Move the MCP roster to deploy so Echo names no specific MCP in config or code #117

Closed
opened 2026-08-11 23:05:05 +00:00 by coilyco-ops · 0 comments
Member

Today a definition owns its roster in tracked sirens-echo source. Definition.MCPServers carries MCPServerDefinition{Name, URL, URLEnv} (internal/community/config.go:61-65 at 3812935), and the agent/*.yaml definitions name each server and each *_MCP_URL environment variable. Adding an MCP to a lane is therefore an edit to this repo.

That is the wrong layer. Deploy owns rollout and ingress, which makes the roster deployment tuning, and config belongs at the layer that fully determines it rather than one above. coilyco-bridge/deploy should be able to register an MCP for a lane with no config or code reference to that MCP anywhere in sirens-echo.

Target shape

  • Echo reads its roster from a deployment-owned source at startup, mirroring how SIRENS_ECHO_ACCESS_POLICY already names a deployment-owned tracked file (Config.AccessPolicyPath). A mounted roster file is the closest precedent and keeps the value out of argv.
  • Echo keeps the schema, validation, and name rules for a roster. mcpServerNamePattern, the duplicate check, and the exactly-one-of-url-or-url_env rule are Echo's, because they are protocol and safety constraints rather than fleet values.
  • Echo keeps zero server names, URLs, and *_MCP_URL variable names. Those move to deploy, per lane. The two lanes already differ, so per-lane roster fits the existing split.
  • An absent roster stays a valid no-tool boundary, which is already the contract.

Prose stays, and is the point

Echo's skills and docs may keep describing capabilities narratively, so the model has framing for what it might be holding. Prose is not a reference the code resolves, so it does not re-create the coupling. docs/sirens-echo-tools.md currently states that "each source-controlled definition owns its own MCP roster", which becomes false and needs rewriting to describe the boundary instead of the list.

Accepted tradeoff: prose can drift from what a lane actually registers. Prose describing a surface that is not mounted is a documentation bug rather than a runtime one, and the runtime already tells the model only about tools it actually discovered.

Restraint is preserved

The tools doc's restraint about mutation is not weakened by this. Adding a surface is still an explicit tracked edit by a human, it just lands in the repo that owns the deployment. This is not self-service or dynamic registration by the model or by Echo.

Companion work

Deploy needs the matching side: per-lane roster content and the mount. Worth filing there once the Echo-side shape is settled, since a deploy issue is not actionable before then.

Relates to #116, which changes what supervises the roster once it is long-lived.

Today a definition owns its roster in tracked sirens-echo source. `Definition.MCPServers` carries `MCPServerDefinition{Name, URL, URLEnv}` (`internal/community/config.go:61-65` at `3812935`), and the `agent/*.yaml` definitions name each server and each `*_MCP_URL` environment variable. Adding an MCP to a lane is therefore an edit to this repo. That is the wrong layer. Deploy owns rollout and ingress, which makes the roster deployment tuning, and config belongs at the layer that fully determines it rather than one above. `coilyco-bridge/deploy` should be able to register an MCP for a lane with **no config or code reference to that MCP anywhere in sirens-echo**. ## Target shape * Echo reads its roster from a deployment-owned source at startup, mirroring how `SIRENS_ECHO_ACCESS_POLICY` already names a deployment-owned tracked file (`Config.AccessPolicyPath`). A mounted roster file is the closest precedent and keeps the value out of argv. * Echo keeps the **schema, validation, and name rules** for a roster. `mcpServerNamePattern`, the duplicate check, and the exactly-one-of-url-or-url_env rule are Echo's, because they are protocol and safety constraints rather than fleet values. * Echo keeps **zero** server names, URLs, and `*_MCP_URL` variable names. Those move to deploy, per lane. The two lanes already differ, so per-lane roster fits the existing split. * An absent roster stays a valid no-tool boundary, which is already the contract. ## Prose stays, and is the point Echo's skills and docs may keep describing capabilities narratively, so the model has framing for what it might be holding. Prose is not a reference the code resolves, so it does not re-create the coupling. `docs/sirens-echo-tools.md` currently states that "each source-controlled definition owns its own MCP roster", which becomes false and needs rewriting to describe the boundary instead of the list. Accepted tradeoff: prose can drift from what a lane actually registers. Prose describing a surface that is not mounted is a documentation bug rather than a runtime one, and the runtime already tells the model only about tools it actually discovered. ## Restraint is preserved The tools doc's restraint about mutation is not weakened by this. Adding a surface is still an explicit tracked edit by a human, it just lands in the repo that owns the deployment. This is not self-service or dynamic registration by the model or by Echo. ## Companion work Deploy needs the matching side: per-lane roster content and the mount. Worth filing there once the Echo-side shape is settled, since a deploy issue is not actionable before then. Relates to #116, which changes what supervises the roster once it is long-lived.
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#117
No description provided.