Skip to content
源码分析手册

MCP 认证与 OAuth:连接远程能力的“钥匙”

对于需要访问 Google Calendar、GitHub 或内部系统的远程 MCP 服务,Claude Code 提供了一套标准化的认证流程。它支持工业级的 OAuth 2.0 授权码流,同时提供了灵活的 headersHelper 来处理自定义认证。

先搞清楚这是什么

MCP 认证本质上是 跨进程的凭证交换与令牌生命周期代理 (OAuth Proxy & Token Broker)

它解决了子进程(MCP Server)无法直接弹出 UI 授权的问题。Claude Code 扮演了“守门人”的角色:它拦截 Server 抛出的认证请求,启动本地回调监听器(OAuth Port),引导人类在浏览器中完成操作,最后将换取的令牌安全地注入 Server 进程。其目标不是让面板显示“已登录”,而是让一个 needs-auth 状态的连接恢复成真实的工具集。

实现细节

认证流程被拆分为配置、执行和重连三个阶段:

  1. OAuth 核心流程 (src/services/mcp/auth.ts)

    • metadata 发现:通过 authServerMetadataUrl 识别远程服务的授权端点。
    • 本地回调服务:利用 src/services/mcp/oauthPort.ts 开启 127.0.0.1 上的临时端口。
    • 令牌管理saveTokens 将 Access Token 和 Refresh Token 写入安全存储(Secure Storage),而不是普通的 .mcp.json 配置文件。
    • 自动续期ClaudeAuthProvider.tokens() 会定期检查并自动刷新即将过期的令牌。
  2. 伪工具占位与恢复 (src/tools/McpAuthTool/McpAuthTool.ts)

    • 当 Server 尚未认证时,Claude 会在模型侧暴露一个 mcp__<server>__authenticate 伪工具。
    • 一旦用户完成 OAuth,该工具会调用 reconnect(),把这个 Server 真正的 tools/commands 整体“热替换”进来。
  3. 动态请求头 (src/services/mcp/headersHelper.ts)

    • 如果远程服务不走 OAuth,而是需要短期令牌或内部 SSO,可以使用 headersHelper 字段。
    • 它是受 Workspace Trust 约束的 shell 命令。在连接建立前,Claude 会运行此命令并捕获其 stdout 中的 JSON,将其作为 HTTP Headers 并入 SSE 连接请求中。
    • 源码逻辑确保了每次连接都会执行,无本地缓存,这正好适配了“每次请求换取新 token”的短寿命认证场景。
  4. XAA 一键登录 (src/services/mcp/xaaIdpLogin.ts)

    • 针对高度集成的合作伙伴(如 claude.ai 本身),系统支持 XAA IdP 流程,实现无缝的身份识别与令牌交换。

实战注意事项

  • 存储隔离clientIdauthUrl.mcp.json,但 clientSecret 和具体 tokens 永远留在安全存储中。
  • Transport 限制:OAuth 机制目前主要服务于 HTTP 和 SSE 连接。对于 Stdio 类型的本地进程,它默认被禁用。
  • Helper 容错headersHelper 的执行超时被硬编码为 10 秒。如果命令执行失败,Claude 会记录日志但可能尝试带空头继续连接,而不是立刻抛出 fatal error。
  • 无图形化环境:在纯 SSH 会话中,由于无法自动打开本地浏览器,OAuth 流程会退化为“手动粘贴回调 URL”模式。

相关主题

源码锚点

  • claude-code-opensource/src/services/mcp/auth.ts — OAuth 授权、发现与令牌交换的中枢。
📄 src/services/mcp/auth.ts — OAuth 授权、发现与令牌交换的中枢。L3-9 of 2466
typescript
  discoverOAuthServerInfo,
  type OAuthClientProvider,
  type OAuthDiscoveryState,
  auth as sdkAuth,
  refreshAuthorization as sdkRefreshAuthorization,
} from '@modelcontextprotocol/sdk/client/auth.js'
import {
  • claude-code-opensource/src/services/mcp/headersHelper.ts — 动态 Headers 获取与 shell 命令执行入口。
📄 src/services/mcp/headersHelper.ts — 动态 Headers 获取与 shell 命令执行入口。L30-59 of 139
typescript
 * @returns Headers object or null if not configured or failed
 */
export async function getMcpHeadersFromHelper(
  serverName: string,
  config: McpSSEServerConfig | McpHTTPServerConfig | McpWebSocketServerConfig,
): Promise<Record<string, string> | null> {
  if (!config.headersHelper) {
    return null
  }

  // Security check for project/local settings
  // Skip trust check in non-interactive mode (e.g., CI/CD, automation)
  if (
    'scope' in config &&
    isMcpServerFromProjectOrLocalSettings(config as ScopedMcpServerConfig) &&
    !getIsNonInteractiveSession()
  ) {
    // Check if trust has been established for this project
    const hasTrust = checkHasTrustDialogAccepted()
    if (!hasTrust) {
      const error = new Error(
        `Security: headersHelper for MCP server '${serverName}' executed before workspace trust is confirmed. If you see this message, post in ${MACRO.FEEDBACK_CHANNEL}.`,
      )
      logAntError('MCP headersHelper invoked before trust check', error)
      logEvent('tengu_mcp_headersHelper_missing_trust', {})
      return null
    }
  }

  try {
  • claude-code-opensource/src/services/mcp/oauthPort.ts — 本地回调服务器管理。
📄 src/services/mcp/oauthPort.ts — 本地回调服务器管理。L9-11 of 79
typescript
const REDIRECT_PORT_RANGE =
  getPlatform() === 'windows'
    ? { min: 39152, max: 49151 }
  • claude-code-opensource/src/tools/McpAuthTool/McpAuthTool.ts — 衔接模型与认证流程的伪工具实现。
📄 src/tools/McpAuthTool/McpAuthTool.ts — 衔接模型与认证流程的伪工具实现。L23-23 of 216
typescript
const inputSchema = lazySchema(() => z.object({}))
  • claude-code-opensource/src/services/mcp/types.ts — 远程 Server 的 OAuth 配置模型。
📄 src/services/mcp/types.ts — 远程 Server 的 OAuth 配置模型。L4-6 of 259
typescript
  ServerCapabilities,
} from '@modelcontextprotocol/sdk/types.js'
import { z } from 'zod/v4'

基于 Claude Code v2.1.88 开源快照的深度分析