github / github/copilot-cli

Concurrent MCP OAuth token-refresh for two servers cancels one reconnect (self-heals, but surfaces a false hard-failure error)

未关闭
#4,842 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

triage
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

Describe the bug

When two remote HTTP MCP servers (atlassian-mcp and ado-remote-mcp) both receive a 401 OAuth
challenge at nearly the same moment, the concurrent background token-refresh/reconnect for one of
them gets cancelled (quit_reason":"Cancelled"), producing a foreground-facing error:

Failed to refresh foreground session after MCP OAuth: Error: MCP server "ado-remote-mcp" failed to
reconnect: MCP server "ado-remote-mcp" connection was cancelled

The CLI self-heals a few seconds later (Successfully authenticated with ado-remote-mcp), so the
server ends up usable, but the error surfaces to the user as an alarming failure
(Failed to connect to MCP server "ado-remote-mcp": ... connection was cancelled. Execute '/mcp show ado-remote-mcp' to inspect or check the logs.) for a condition that isn't actually a lasting failure.

This looks related to (but distinct from) #4753, #4084, and #3706 — those involve session-resume
handover, OAuth routed to the wrong handler, and reconnect fan-out across many hosts, respectively.
This report is specifically about two servers hitting an expired-token 401 at the same time,
where the reconnect task for one server is cancelled — apparently pre-empted by the other server's
concurrent OAuth flow — and only recovers via a fully independent retry moments later.

Affected version

1.0.83

Steps to reproduce
  1. Configure two remote HTTP MCP servers with OAuth (e.g. atlassian-mcp and an Azure DevOps
    remote MCP server) such that both access tokens expire around the same time.
  2. Start (or resume) a session after both tokens have expired.
  3. Both servers receive a 401 at nearly the same timestamp and each begins a background
    OAuth refresh/reconnect.
  4. One server's reconnect task is cancelled mid-flight; the CLI logs an ERROR and (in this
    instance) also surfaces Failed to refresh foreground session after MCP OAuth: ... connection was cancelled to the user.
  5. ~3 seconds later, a fresh authentication attempt for the same server succeeds
    (Successfully authenticated with <server>), and the server becomes usable — but only after
    the alarming error has already been shown.
Actual log excerpt (redacted server URLs)
23:12:43.336Z [ERROR] [rust:rmcp::transport::worker] worker quit with fatal: Transport channel closed,
  when Client(OAuthChallenge { ... "https://mcp.atlassian.com/.well-known/oauth-protected-resource/v2/mcp" ...
  response: McpOAuthHttpResponse { status_code: 401, ... } })
23:12:43.535Z [ERROR] Refreshing authentication for atlassian-mcp...
23:12:43.972Z [ERROR] Successfully authenticated with atlassian-mcp
23:12:44.106Z [ERROR] [rust:rmcp::transport::worker] worker quit with fatal: Transport channel closed,
  when Client(OAuthChallenge { ... "https://mcp.dev.azure.com/.well-known/oauth-protected-resource/<org>" ...
  response: McpOAuthHttpResponse { status_code: 401, ... } })
23:12:45.148Z [ERROR] [rust:rmcp::transport::worker] worker quit with fatal: Transport channel closed, ... (atlassian, again)
23:12:45.327Z [INFO]  [rust:rmcp::service] task cancelled
23:12:45.327Z [INFO]  [rust:rmcp::service] task cancelled
23:12:45.327Z [WARNING] [rust:copilot_runtime::session::mcp::agent_host] MCP background reconnect after
  OAuth still needs auth {"server":"ado-remote-mcp"}
23:12:45.327Z [INFO]  [rust:rmcp::service] serve finished {"quit_reason":"Cancelled"}
23:12:45.752Z [ERROR] Failed to refresh foreground session after MCP OAuth: Error: MCP server
  "ado-remote-mcp" failed to reconnect: MCP server "ado-remote-mcp" connection was cancelled
23:12:48.220Z [ERROR] Successfully authenticated with ado-remote-mcp
Expected behavior
  • Concurrent token refreshes for independent MCP servers should not cancel one another's
    reconnect task.
  • If a reconnect is transiently cancelled but recovers within a few seconds, that should not be
    surfaced to the user as a hard failure (or should be labeled as transient/retrying, not as an
    actionable error pointing at /mcp show).
  • Ideally the retry/backoff for concurrent OAuth refreshes across multiple servers should be
    serialized or otherwise made non-cancelling of sibling in-flight reconnects.
Environment
  • OS: Windows 11 (build 26200)
  • CLI version: 1.0.83 (exe built 2026-09-04)
  • MCP servers involved: atlassian-mcp (remote HTTP, OAuth), ado-remote-mcp (remote HTTP, OAuth,
    Azure DevOps)
  • Both servers configured as type: "http" with OAuth in .copilot/mcp-config.json / repo
    .github/mcp.json
Additional context

Ruled out as a cause: duplicate/conflicting MCP server definitions across repo (.github/mcp.json)
and local (~/.copilot/mcp-config.json) scopes for the same server name — the cancellation occurs
during the concurrent-401 OAuth refresh path itself (rmcp::service/agent_host logs), independent
of which scope's config won. Removing the local duplicate did not change this behavior on retest;
it's a config hygiene fix but not the root cause of the cancellation.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先通过名为 copilot_runtime::session::mcp::agent_host 和 rmcp::service 的日志跟踪并发 OAuth 重连路径,重点关注取消和前台错误传播。重现两个同时发生的 401 响应,并验证一个服务器的重连不会取消另一个服务器的重连,且暂时性恢复不会被报告为严重失败。

由索引模型根据 Issue 内容生成。

评估

技术栈
rust
领域
authentication, cli
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
48/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。