Skip to content

feat(mcp-sync): sync GitHub Copilot CLI's MCP servers too - #581

Merged
Ark0N merged 1 commit into
Ark0N:masterfrom
opticon454:feat/mcp-sync-copilot
Oct 10, 2026
Merged

Ark0N merged 1 commit into
Ark0N:masterfrom
opticon454:feat/mcp-sync-copilot

Conversation

@opticon454

Copy link
Copy Markdown
Contributor

Summary

MCP server sync (#521) copies MCP servers between the agent CLIs' own config files. GitHub Copilot CLI keeps its list too (~/.copilot/mcp-config.json), so it was left out. This adds it.

Copilot is not a Codeman run mode, so it has no CLI-registry entry (and giving it one would drag in launch, discovery and install). It is declared as plain data in src/mcp-sync-targets.ts (MCP_SYNC_ONLY_TOOLS) and joins the registry CLIs as a sync target, after them, so a registry CLI's definition wins a same-name difference. It takes part when copilot is installed or its config file exists, otherwise it is reported absent and never created. The same rules apply as for the others: additive only, switched-off servers are not copied, nothing unparseable is written, secrets keep the file 0600, results carry names only.

The dialect (copilot-json), checked against Copilot CLI 1.0.94

  • File ~/.copilot/mcp-config.json, moved by COPILOT_HOME (verified: COPILOT_HOME=<dir> copilot mcp list reads <dir>).
  • mcpServers, each entry with tools (["*"] = all), type local | http | sse, and command/args/env or url/headers. Copied servers are written with tools: ["*"]; an existing server's tool filter is never touched.
  • copilot mcp disable does not mark the entry. It lists the name under disabledMcpServers in settings.json beside the config. Sync reads that list (never writes it), so a disabled server is not copied. If settings.json is not valid JSON the target is unreadable rather than guessed at.

Round trip checked with the real CLI: a file written by addServers('copilot-json', ...) is listed by copilot mcp list as fs (local), web (http), live (sse), and copilot mcp get fs shows the command, the masked env and Tools: * (all).

Tests

  • test/mcp-sync.test.ts (+10): output captured from copilot mcp add; the written shape; existing server and tool filter kept; both directions between Copilot and Claude (sse expressed) and idempotent; a server disabled in settings.json is not copied (and the file is only read); a server disabled in Copilot but live elsewhere is still synced; invalid settings.json leaves the target unreadable without quoting the file; COPILOT_HOME; neither installed nor configured is absent; env values stay out of the result and the file is private.
  • test/mcp-sync-targets.test.ts (+5): the declaration, the binary probe, yielding to a registry id, order in the route's targets, binaryOnPath.
  • 537 tests across the registry, docs, guard, structure, schema and MCP suites pass; tsc --noEmit clean.

Docs: docs/cli-registry.md (new "Tools that are not run modes" paragraph), docs/api-reference.md, docs/wiki/Settings-Reference.md, the Settings text.

Copilot CLI keeps its user MCP list in ~/.copilot/mcp-config.json (COPILOT_HOME moves it) but is
not a Codeman run mode, so it has no registry entry. Add the copilot-json dialect (mcpServers,
tools ["*"], type local/http/sse, checked against `copilot mcp add` 1.0.94) and declare Copilot as
a sync-only target in src/mcp-sync-targets.ts, listed after the registry CLIs. A server switched
off with `copilot mcp disable` is recorded in settings.json (disabledMcpServers), not on the
entry: sync reads that list so it is not copied, and reports the target unreadable if the file
is not valid JSON instead of guessing.
@Ark0N
Ark0N merged commit 92e5416 into Ark0N:master Oct 10, 2026
2 checks passed
Ark0N pushed a commit that referenced this pull request Oct 10, 2026
…opilot (#581)

The route test cleared only the registry CLIs' relocation vars, so with
COPILOT_HOME exported it wrote its fixture into that real Copilot config.
It now clears the sync-only tools' vars too, and Copilot's install probe goes
through the test's own installed set instead of the machine's PATH.

Docs: CLAUDE.md, the API reference and the Settings reference name COPILOT_HOME
and the sync-only table; a missing comma in docs/cli-registry.md; the
mcp-sync.ts overview and the Sync confirm mention Copilot.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ark0N pushed a commit that referenced this pull request Oct 10, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ark0N pushed a commit that referenced this pull request Oct 10, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@opticon454
opticon454 deleted the feat/mcp-sync-copilot branch October 10, 2026 05:16
@Ark0N

Ark0N commented Oct 10, 2026

Copy link
Copy Markdown
Owner

Merged and shipped in 1.41.0, thanks @opticon454! MCP server sync now includes GitHub Copilot CLI as a sync target, with all the same safety rules. One fix at merge: the route test didn't clear COPILOT_HOME, so on a machine with that set it wrote its fixture into the real Copilot config. It now clears the sync-only tools' relocation vars too, and Copilot's install probe in that test goes through the test's own installed set. I also added COPILOT_HOME to the docs that list the relocation vars. A per-target opt-out for Copilot would be a nice follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants