Repository navigation
Cloud agent: "Registry only" MCP policy blocks all repo-configured MCP servers — proxy-bridged configs can't be fingerprinted ("unable to compute fingerprint from local configuration") #5155
Description
Describe the bug
Describe the bug
With the org MCP policy set to Registry only, the Copilot cloud agent silently drops every repo-configured MCP server, even when the server is present in the configured registry with a matching package identity. Only the platform defaults (github-mcp-server, playwright) reach the session.
The CLI log inside the session (~/.copilot/logs/process-*.log) shows:
[DEBUG] Registry <org-registry>: servers will be verified against this registry
[ERROR] MCP server "mcp-server-A" filtered: Could not verify server "mcp-server-A" against registry <org-registry>: unable to compute fingerprint from local configuration
[ERROR] MCP server "mcp-server-B" filtered: Could not verify server "mcp-server-B" against registry <org-registry>: unable to compute fingerprint from local configuration
With the policy switched to Allow all, the same servers mount and their tools work.
Root cause (from reading the shipped runtime)
In the cloud agent, the CLI never sees the repo's MCP config. cca-engine (dist-cca-v3/index.js) replaces every proxy-discovered server with a bridge config:
// ~line 80361
discoveredServers[name] = toBridgedMcpServerConfig(name, void 0, mcpProxyUrl);// ~line 79716
function toBridgedMcpServerConfig(serverName, serverConfig, mcpProxyUrl, customAgentName, customAgentVersion) {
const args = [BRIDGE_SCRIPT_PATH, `--proxy-url=${mcpProxyUrl}`, `--server-name=${serverName}`];
if (serverConfig) {
args.push(`--config=${Buffer.from(JSON.stringify(serverConfig)).toString("base64")}`);
}
...
return { type: "local", command: process.execPath, args, ..., tools: ["*"] };
}So for every third-party server the CLI receives node <bridge-script> --proxy-url=… --server-name=…. The CLI derives a stdio server's identity from its command (npx→npm, uvx→pypi, dotnet→nuget, docker, mcpb; see the explanation in mindovermachine-dev/product-cli#20). node maps to nothing, so no fingerprint can be computed and the server is filtered.
- At line 80361
serverConfigisvoid 0, so even the base64--configarg is omitted. The original config is not available to the CLI at all. - Built-in servers pass only because they are marked runtime-authored (
markRuntimeAuthoredServer, gated bycopilot_swe_agent_mcp_builtin_provenance) and are exempt from third-party policy. - From code reading (not tested end-to-end): remote/HTTP configs are bridged the same way when
mcpProxyUrlis set (toSdkMcpServerConfig, ~line 79741), so switching to anhttpserver does not avoid this in the cloud agent.
Net effect: under "Registry only", no repo-configured (or custom-agent) MCP server can ever pass verification in the cloud agent.
Steps to reproduce
- Org settings → Copilot → Policies: MCP servers in Copilot = Enabled; MCP registry URL = a spec-compliant registry; registry access = Registry only.
- Registry entry named
mcp-server-A:
{
"name": "mcp-server-A",
"version": "0.0.2",
"packages": [{
"registryType": "oci",
"identifier": "<registry-host>/<path>/mcp-server-A",
"version": "0.0.2",
"transport": { "type": "stdio" }
}]
}Verified: GET <org-registry>/v0.1/servers/mcp-server-A/versions/latest returns 200 with server.name == "mcp-server-A".
3. Repo → Settings → Copilot → coding agent → MCP configuration:
{
"mcpServers": {
"mcp-server-A": {
"type": "local",
"command": "docker",
"args": ["run", "-i", "--rm", "<registry-host>/<path>/mcp-server-A:0.0.2"],
"tools": ["*"]
}
}
}- Assign a task to the cloud agent.
- Observe:
- cca-engine logs
Discovered MCP server: mcp-server-AandMCP servers configured for session: …, mcp-server-A, …. - No
MCP server 'mcp-server-A': pending/connectedlifecycle events appear. - The CLI log shows the
unable to compute fingerprinterror above.
- cca-engine logs
What we ruled out
- Registry reachability/auth: Cloud Run access logs show 200s for the CLI's requests during the session.
- Name lookup: before aliasing, the error was
Not found in registry. After making the registry resolve the config key, the error moved to the fingerprint stage. - Local config shape:
type: localvsstdio,-e VARvs--env=VAR, and minimal args all gave the identical error. - Package type:
registryTypeocivsdockergave the identical error. - Policy fetch: succeeds (
servers will be verified against this registry). This is not the fail-closed family in Cloud agent: MCP registry policy fetch fails with 401/403 on GHEC data residency, silently blocking all user-configured MCP servers #4378 / All MCP servers blocked by policy when GHE returns 404 on /copilot/mcp_registry #2498 / MCP registry policy fetch returns 403 for Actions GITHUB_TOKEN, blocking all non-default MCP servers in CI #4346.
Expected behavior
Repo-configured servers that match a registry entry should be verified against their original configuration. Options include passing serverConfig into the bridge and fingerprinting from it, or running the registry check in cca-engine/the MCP proxy before bridging. Registry-matching servers should then mount under "Registry only".
Affected version
- Surface: Copilot cloud agent (Copilot Business,
api.business.githubcopilot.com) - Runtime:
runtime-cca-vendored-06412f43e9f392ebb48daa02136895268f688937(also seen on47b2e066…) - Feature flags present:
copilot_swe_agent_new_out_proc_mcp,copilot_swe_agent_mcp_builtin_provenance - Date observed: 2026-10-15
Related
- fix(author): launch Copilot sessions over HTTP so the MCP passes the enterprise allowlist mindovermachine-dev/product-cli#20: same error in the local CLI; documents the command→identity mapping.
- Cloud agent: MCP registry policy fetch fails with 401/403 on GHEC data residency, silently blocking all user-configured MCP servers #4378: cloud agent silently dropping user-configured MCP servers (different trigger: policy fetch 401/403).
- Separate but adjacent: the registry lookup uses the config key as the server name, but config keys can't contain
.. Spec-style reverse-DNS registry names (e.g.io.example/server) are therefore unmatchable from repo config without registry-side aliasing. Happy to file this separately.
Activity