github / github/copilot-cli

Prerelease CLI builds can block non-default MCP servers after registry policy fetch fails

Abierto
#2,552 2 comentarios 0 reacciones 0 asignados Ver en GitHub
area:mcp
Lenguaje dominante
Shell
Estrellas
11.2k
Forks
1.9k
Merge medio
14 h 16 min
PR fusionados (30 d)
6

Descripción

# Bug Report: Prerelease CLI builds can block non-default MCP servers after registry policy fetch fails

## Related Issues

- **#2498** — "All MCP servers blocked by policy when GHE returns 404 on /copilot/mcp_registry" — Same GHES 404 symptom on stable v1.0.17. Our report adds the prerelease-specific trigger mechanism, root cause analysis of the update channel logic, and a complete workaround including pkg cache cleanup.
- **#2479** — "Failed to fetch MCP registry policy for individual user (404)" — Original report for individual/Pro users on stable 1.0.14–1.0.15, marked fixed in 1.0.16/1.0.19.
- **#2486** — "1 MCP server was blocked by policy" — Personal Pro+ user, same registry 404, documents the auto-update pkg cache override behavior independently.

This report documents the same 404 failure pattern re-emerging specifically in prerelease builds (1.0.20-x) within a GHES enterprise environment, via a distinct trigger: certain config states cause the CLI to default to the prerelease update channel, which installs builds with a different client audience parameter that the registry does not recognize.

## Summary

Copilot CLI prerelease builds (tested: 1.0.20-0, 1.0.20-1) receive HTTP 404 when fetching MCP policy from the enterprise registry during startup. The CLI then blocks all non-default MCP servers. The tested stable build (1.0.19) did not block non-default servers.

## Environment

- **OS**: Windows 11 (x64)
- **Node**: v22.16.0
- **CLI broken versions**: `@github/copilot` 1.0.20-0 and 1.0.20-1 (prerelease channel)
- **CLI working version**: `@github/copilot` 1.0.19 (stable/latest channel)
- **Deployment**: GitHub Enterprise Server (GHES) environment

## Reproduction Steps

1. Configure `~/.copilot/config.json` with a config state that selects the prerelease update channel by default (e.g., no explicit `"update_channel"` set, with internal flags that default to prerelease)
2. Allow auto-update to run (or run `copilot update`)
3. The CLI selects the prerelease update channel and installs a prerelease build (e.g., 1.0.20-0)
4. On next startup, the MCP registry policy fetch returns HTTP 404
5. Debug logs show: `"Non-default MCP servers will be blocked until the policy can be fetched"`
6. All non-default/plugin-contributed MCP servers are blocked
7. Only the built-in default `github-mcp-server` loads

**Alternative repro**: Directly install a prerelease build via `npm install -g @github/copilot@prerelease` and start the CLI in a GHES environment.

**To observe**: Enable debug logging via `"logLevel": "all"` in `~/.copilot/config.json` and check logs in `~/.copilot/logs/`.

## Observed Root Cause

### Update channel logic (from published npm package `sdk/index.js`):

The update channel selection logic can default to `"prerelease"` based on certain config states. The prerelease channel fetches all GitHub releases (including prereleases), while the stable channel fetches only `/releases/latest`.

### Observed correlation

The tested prerelease binaries (1.0.20-0, 1.0.20-1) contain a different client-side audience parameter value than the tested stable binary (1.0.19). The registry policy fetch fails (404) with the prerelease audience value and succeeds or is skipped with the stable audience value. **Server-side gating logic was not directly verified** — this is an observed correlation between the client audience value and the registry response.

### npm dist-tags (as of 2026-04-07):
- `latest`: 1.0.19 — non-default MCP servers load ✅
- `prerelease`: 1.0.20-1 — registry fetch returns 404, servers blocked ❌

## Impact

- All observed non-default/plugin-contributed MCP servers in the GHES environment were blocked
- Skills depending on plugin MCP servers become non-functional
- In our testing, the failure was only evident in debug logs; we did not observe a clear user-facing remediation message
- Users whose config defaults to the prerelease update channel are disproportionately affected

## Workaround

1. **Fully exit the CLI** (stop any running Copilot session)
2. Add `"update_channel": "stable"` to `~/.copilot/config.json`
3. Run `npm install -g @github/copilot@latest` to reinstall the stable version
4. Delete any prerelease entries from the auto-update cache at `~/.copilot/pkg/universal/` (e.g., directories named `1.0.20-0`, `1.0.20-1`). In our testing, a cached prerelease binary took precedence over the npm-installed version at startup.
5. Restart the CLI
6. **Verify**: Confirm the running version is stable (check `/version`) and that non-default MCP servers load (check debug logs for `servers_blocked_count=0`)

## Expected Behavior

1. Prerelease builds should not break MCP server loading for GHES users
2. The registry should handle the client values emitted by supported CLI builds gracefully (not return 404)
3. OR: The CLI should not fail closed on registry 404 — it should fall back to a permissive default or allow previously-loaded servers
4. Users should receive a visible warning when auto-updating to a prerelease that may change client behavior

## Verified Evidence

| Observation | Status | Method |
|---|---|---|
| Prerelease binaries contain different audience value than stable | ✅ Verified | Binary string extraction |
| Registry returns 404 with prerelease binary | ✅ Verified | Debug log analysis |
| Stable binary did not block non-default MCP servers | ✅ Verified | Debug log analysis |
| Config state causes prerelease channel default | ✅ Verified | SDK source code inspection |
| `update_channel: "stable"` overrides the default | ✅ Verified | Config change + restart |
| Auto-update pkg cache can override npm-installed version | ✅ Verified | Observed after npm reinstall |
| ALL prerelease builds have the different audience value | ❓ Unverified | Only tested 1.0.20-0 and 1.0.20-1 |
| Registry is explicitly audience-gated server-side | ❓ Inferred | Correlation between client value and response |

## Log Evidence

### Stable (1.0.19) — non-default servers allowed:
```
mcp_allowlist_policy_check: outcome="no_registries", registry_count=0
custom_mcp_allowed=true, servers_blocked_count=0
```
Note: The stable build's log shows `outcome="no_registries"` — this may indicate the registry was not queried rather than a successful fetch. Either way, non-default servers were not blocked.

### Prerelease (1.0.20-0) — non-default servers blocked:
```
mcp_policy_check: registry fetch 404
"Non-default MCP servers will be blocked until the policy can be fetched"
custom_mcp_allowed=false, servers_blocked_count=4
```

## Caveat

This bug report has been reviewed and sanitized to remove any personally identifiable information, proprietary details, and organization-specific data. As a result, certain environment details, configuration values, and reproduction specifics have been generalized or omitted. Some gaps in this report may be a consequence of that redaction rather than a lack of investigation. The original findings were more detailed but could not be disclosed publicly for privacy and security reasons. The CLI team may request additional context privately if needed to fully reproduce or diagnose the issue.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.