Skip to content

agent-mcp-manager-v0.0.2

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Jun 21:07
· 7 commits to main since this release
0349e4a

Closes two production bug reports surfaced while installing remote MCP servers (BrowserOS) across coding agents. Both are rooted in the same gap: upstream docker/mcp-gateway writes one stdio entry per client by Go-type, so it never modelled per-agent transport capability. This library had generalised to "write any transport per caller spec" without adding the per-agent gate, which let it produce shapes some agents reject.

What changes by agent

Agent What changes
claude-desktop link() with an http/sse spec now throws UnsupportedTransportError at the API boundary instead of writing a {url, headers} block Claude Desktop will silently skip on next launch with "not a valid MCP server configuration." stdio specs unchanged.
codex Same typed enforcement, for parity. Codex was already stdio-only via the TOML emitter; the rejection is now a typed error you can catch in a fan-out loop.
claude-code system (~/.claude.json) Unchanged. Still accepts stdio, sse, and http with no type tag.
claude-code project (.mcp.json) Now stdio-only AND injects type: "stdio", matching upstream Docker's set: .mcpServers[$NAME] = $JSON+{"type":"stdio"}. Newer Claude Code releases require this tag; the library was silently producing entries those releases would skip.
vscode Was hardcoding type: "stdio" on every entry (wrong for http/sse). Now writes type: matching spec.transport. Stdio callers see no change.
cursor, gemini, zed Unchanged.

What changes library-wide

  • UnsupportedTransportError (new typed error). Includes agent, transport, details.supported, and an mcp-remote shim hint. Exported from the package root.
  • McpTransport (new public type, just 'stdio' | 'sse' | 'http').
  • link({ allowOverwrite: true }) (new opt-in). Bypasses the foreign-entry guard, takes ownership of an existing on-disk entry, and records it in the manifest. Default false. Does NOT bypass the transport-capability check.
  • getCatalogEntry and resolveAgentSurface newly exported. Use resolveAgentSurface(id, scope).supportedTransports to pre-filter agents by transport capability before linking; it honours scope-specific overrides (Claude Code project scope is stdio-only, system is not).

Recovering from ForeignEntryError

If link() throws Cannot replace a user-edited entry. Please remove <name> from this agent's config manually and try again, it means the on-disk config already has an entry under that name the workspace manifest did not write. Two options:

// Take ownership and rewrite with your spec:
await mgr.link({
  serverName: 'BrowserOS',
  agent: 'claude-code',
  allowOverwrite: true,
})

// Or remove manually and retry without the flag.

Registering a remote MCP server in a stdio-only agent

claude-desktop, codex, and claude-code project scope only accept stdio entries. Wrap the URL with mcp-remote:

await mgr.add({
  name: 'browseros',
  spec: {
    transport: 'stdio',
    command: 'npx',
    args: [
      '-y',
      'mcp-remote',
      'https://browseros.example.com/mcp',
      '--header',
      `Authorization: Bearer ${process.env.BROWSEROS_TOKEN}`,
    ],
  },
})

for (const a of (await detectInstalledAgents()).filter((a) => a.installed)) {
  await mgr.link({ serverName: 'browseros', agent: a.id })
}

The library does not auto-shim through mcp-remote in this release. Auto-shim is on the v0.2 roadmap so the manifest stays a faithful record of intent.

Pre-filter pattern (scope-aware)

import { resolveAgentSurface, type AgentScope, type McpTransport } from 'agent-mcp-manager'

const scope: AgentScope = 'system'
const supports = (id, t: McpTransport) =>
  resolveAgentSurface(id, scope).supportedTransports.includes(t)

for (const a of (await detectInstalledAgents()).filter((a) => a.installed)) {
  if (!supports(a.id, 'http')) continue
  await mgr.link({ serverName: 'github', agent: a.id })
}

Upstream Docker conformance

Now matches the per-agent on-disk shape upstream docker/mcp-gateway writes for every agent in our catalog. Three known deltas remain by design or are deferred:

  • VS Code: we write three transports; upstream writes one. Intentional (VS Code accepts all three when tagged correctly).
  • Zed spread order (defaults vs caller-supplied): deferred to v0.2.
  • Missing agents (Cline, Continue.dev, Goose, LM Studio, OpenCode, Sema4, Crush, Kiro): planned for v0.2.

Out of scope for 0.0.2 (planned)

  • Auto-shim http/sse via mcp-remote for stdio-only agents.
  • Case-insensitive name matching (manifest schema change).
  • adopt() primitive that preserves the on-disk shape verbatim instead of rewriting.

Links