mcp

Every agent tool reads its MCP servers from a different file in a different shape. brigade mcp keeps one canonical catalog and merges it into each tool’s native config, so the same servers are wired everywhere from a single source.

It is the one place Brigade writes runtime config into tool-owned files, so it stays bounded: explicit (never automatic), dry-run by default, merges by server key (servers you added by hand are preserved), and it never inlines secrets - env values are written as ${VAR} references.

The canonical catalog

.brigade/mcp.json is tracked and shared. Ownership of which server keys Brigade manages in each tool file is tracked in the gitignored .brigade/mcp/state.json.

{
  "version": 1,
  "servers": {
    "github": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": { "ref": "GITHUB_TOKEN" } },
      "timeout": 60,
      "targets": null
    }
  }
}

Supported tools

ToolFileShape
Claude Code.mcp.jsonJSON mcpServers
Cursor.cursor/mcp.jsonJSON mcpServers
Codex CLI.codex/config.tomlTOML [mcp_servers.*], surgical merge
VS Code.vscode/mcp.jsonJSON servers + inputs[] for secrets
OpenCodeopencode.jsonJSON mcp, command-array shape
Antigravity~/.gemini/config/mcp_config.jsonJSON mcpServers, serverUrl for remote (user-scoped)

Commands

brigade mcp init                       # scaffold the catalog + sidecar, update .gitignore
brigade mcp add --name github \
  --command npx --args "-y @modelcontextprotocol/server-github" \
  --env GITHUB_TOKEN=ref:GITHUB_TOKEN --timeout 60
brigade mcp list
brigade mcp plan                       # preview (read-only)
brigade mcp sync                       # dry-run across every configured tool
brigade mcp sync --write               # merge into each tool's config
brigade mcp sync --write --user-scope  # also write Antigravity's user-global config
brigade mcp doctor
brigade mcp import --harness cursor --merge   # read an existing config into the catalog
brigade operator sync-mcp --write      # validate -> sync -> summary, one receipt

Merge and ownership

Brigade owns only the server keys it recorded. A server you added to a tool config yourself is preserved untouched. A server Brigade manages but you then edited is a conflict, skipped unless you pass --force. Servers removed from the catalog are deleted only with --prune, and only when they still match what Brigade wrote. If the sidecar is lost (a fresh clone), a live server identical to what Brigade would write is reconciled back to owned, so re-syncing does not spuriously conflict.

Secrets are written as references, never values: ${VAR} for most tools, a ${input:VAR} plus a top-level inputs[] entry for VS Code. brigade mcp import demotes any literal-looking secret in an existing config to a reference and never copies the value into the catalog.