Let the agent refresh its own tool roster, which needs the first harness-owned tool #371

Closed
opened 2026-08-13 11:14:04 +00:00 by coilyco-ops · 0 comments
Member

Second slice of #163, after #363. This is the half Kai asked for by name: "giving the agent the ability to refresh the MCP registry".

Why it needed its own issue

Every tool Echo offers comes from a rostered MCP server. There is no harness-owned tool, so this is the first one, and that is a seam rather than a wiring change.

The design question resolved itself

I flagged name collision as a real decision on 163: if a rostered server publishes the same name, either the harness tool or the server's tool disappears silently. The answer was already in the code. register treats a roster collision as fatal, with the comment "degrading past it would silently drop whichever tool lost the race." The harness tool is named by the same server__tool rule with harness as the server, so it inherits that rule and a collision is fatal in the same way. No new decision.

What this changed that was not obvious

Registering a tool on every session broke five existing tests, and two of them were telling me something rather than being stale.

TestMCPProviderAllowsEmptyRoster exists because an empty roster is a documented no-tool capability boundary. Offering a refresh there would put a tool in the one configuration meant to have none, which is a capability claim with nothing behind it. The refresh is now offered only when the roster is non-empty.

TestProxyClientDiscoversCallsAndContinuesWithEcoMCP asserts what reaches the model at the wire. That count moving from 1 to 2 is the actual behaviour change in this issue, and it is right that a test noticed.

The four remaining assertions were updated to exact counts including the refresh, not loosened to "contains". An exact count is what fails when a tool nobody intended shows up.

The result text is the part I care about most

A refresh marks servers for re-reading. The listing lands on the next turn. So the result says "This turn still sees the tool list it started with", and the tool description says the same thing, because a model that read otherwise would tell a member a tool is available before it can see one. That is #211 exactly.

Acceptance

  • The model is offered harness__refresh_tools whenever the roster is non-empty.
  • Calling it marks every server and returns text that does not imply the list already changed.
  • The calling turn keeps its list; the next turn re-lists.
  • An empty roster is offered nothing and refuses the call.
  • A server taking the name is a fatal collision.

Delivered in #365's follow-up. Stacked on #363 because it needs the Refresh seam.

Second slice of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/163, after https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/363. This is the half Kai asked for by name: "giving the agent the ability to refresh the MCP registry". ## Why it needed its own issue Every tool Echo offers comes from a rostered MCP server. There is no harness-owned tool, so this is the first one, and that is a seam rather than a wiring change. ## The design question resolved itself I flagged name collision as a real decision on 163: if a rostered server publishes the same name, either the harness tool or the server's tool disappears silently. The answer was already in the code. `register` treats a roster collision as fatal, with the comment "degrading past it would silently drop whichever tool lost the race." The harness tool is named by the same `server__tool` rule with `harness` as the server, so it inherits that rule and a collision is fatal in the same way. No new decision. ## What this changed that was not obvious Registering a tool on every session broke five existing tests, and two of them were telling me something rather than being stale. `TestMCPProviderAllowsEmptyRoster` exists because an empty roster is a documented no-tool capability boundary. Offering a refresh there would put a tool in the one configuration meant to have none, which is a capability claim with nothing behind it. **The refresh is now offered only when the roster is non-empty.** `TestProxyClientDiscoversCallsAndContinuesWithEcoMCP` asserts what reaches the model at the wire. That count moving from 1 to 2 is the actual behaviour change in this issue, and it is right that a test noticed. The four remaining assertions were updated to exact counts including the refresh, not loosened to "contains". An exact count is what fails when a tool nobody intended shows up. ## The result text is the part I care about most A refresh marks servers for re-reading. The listing lands on the **next** turn. So the result says "This turn still sees the tool list it started with", and the tool description says the same thing, because a model that read otherwise would tell a member a tool is available before it can see one. That is https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/211 exactly. ## Acceptance - The model is offered `harness__refresh_tools` whenever the roster is non-empty. - Calling it marks every server and returns text that does not imply the list already changed. - The calling turn keeps its list; the next turn re-lists. - An empty roster is offered nothing and refuses the call. - A server taking the name is a fatal collision. Delivered in https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/365's follow-up. Stacked on https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/363 because it needs the `Refresh` seam.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#371
No description provided.