# OAuth 支持

## 核心亮点
- 覆盖上游 MCP 服务器的 OAuth 2.0 授权码（PKCE）全流程。
- 支持从 `WWW-Authenticate` 响应和 RFC 8414 元数据自动发现。
- 实现动态客户端注册（RFC 7591）以及资源指示（RFC 8707）。
- 会将客户端凭据与令牌持久化到 `mcp_settings.json`，重启后直接复用。

## MCPHub 何时启用 OAuth
1. MCPHub 调用需要授权的 MCP 服务器并收到 `401 Unauthorized`。
2. 响应通过 `WWW-Authenticate` header 暴露受保护资源的元数据（`authorization_server` 或 `as_uri`）。
3. MCPHub 自动发现授权服务器、按需注册客户端，并引导用户完成一次授权。
4. 回调处理完成后，MCPHub 使用新令牌重新连接并继续请求。

> MCPHub 会在服务器详情视图和后端日志中记录发现、注册、授权链接、换取令牌等关键步骤。

## 按服务器类型快速上手

### 支持动态注册的服务器
部分服务器会公开完整的 OAuth 元数据，并允许客户端动态注册。例如 Vercel 与 Linear 的 MCP 服务器只需配置 SSE 地址即可：

```json
{
  "mcpServers": {
    "vercel": {
      "type": "sse",
      "url": "https://mcp.vercel.com"
    },
    "linear": {
      "type": "sse",
      "url": "https://mcp.linear.app/mcp"
    }
  }
}
```

- MCPHub 会自动发现授权服务器、完成注册，并处理整个 PKCE 流程。
- 所有凭据与令牌会写入 `mcp_settings.json`，无须在控制台额外配置。

### 需要手动配置客户端的服务器
另有一些服务端并不支持动态注册。GitHub 的 MCP 端点（`https://api.githubcopilot.com/mcp/`）就是典型例子，接入步骤如下：

1. 在服务提供商控制台创建 OAuth 应用（GitHub 路径为 **Settings → Developer settings → OAuth Apps**）。
2. 将回调/重定向地址设置为 `http://localhost:3000/oauth/callback`（或你的部署域名）。同时请确保 **设置 → 安装 → 基础地址** 与该域名一致，用于 MCP 请求与 OAuth 回调。
3. 复制生成的 Client ID 与 Client Secret。
4. 通过 MCPHub 控制台或直接编辑 `mcp_settings.json` 写入如下配置。

```json
{
  "mcpServers": {
    "github": {
      "type": "sse",
      "url": "https://api.githubcopilot.com/mcp/",
      "oauth": {
        "clientId": "${GITHUB_OAUTH_APP_ID}",
        "clientSecret": "${GITHUB_OAUTH_APP_SECRET}",
        "scopes": ["replace-with-provider-scope"],
        "resource": "https://api.githubcopilot.com"
      }
    }
  }
}
```

- MCPHub 会跳过动态注册，直接使用你提供的凭据完成授权流程。
- 凭据轮换时需要同步更新控制台或配置文件。
- 将 `scopes` 替换为服务端要求的具体 Scope。

## 配置方式
大多数场景可依赖自动检测，也可以在 `mcp_settings.json` 中显式声明 OAuth 配置。只填写确实需要的字段。

### 自动检测（最小配置）
```json
{
  "mcpServers": {
    "secured-sse": {
      "type": "sse",
      "url": "https://mcp.example.com/sse",
      "oauth": {
        "scopes": ["mcp.tools", "mcp.prompts"],
        "resource": "https://mcp.example.com"
      }
    }
  }
}
```
- MCPHub 会根据挑战头自动发现授权服务器，并引导用户完成授权。
- 令牌（包含刷新令牌）会写入磁盘，重启后自动复用。

### 静态客户端凭据（自带 Client）
```json
{
  "oauth": {
    "clientId": "mcphub-client",
    "clientSecret": "replace-me-if-required",
    "authorizationEndpoint": "https://auth.example.com/oauth/authorize",
    "tokenEndpoint": "https://auth.example.com/oauth/token",
    "redirectUri": "http://localhost:3000/oauth/callback"
  }
}
```
- 适用于需要手动注册客户端的授权服务器。
- `redirectUri` 会覆盖该服务器从 **设置 → 安装 → 基础地址** 推导出的回调地址。
- 如果未配置 `redirectUri`，MCPHub 会依次回退到 `${Base URL}/oauth/callback`，再回退到 `http://localhost:3000/oauth/callback`。
- 同时确保 **设置 → 安装 → 基础地址** 与部署域名一致，以保证默认回调地址正确。

### 动态客户端注册（RFC 7591）
```json
{
  "oauth": {
    "dynamicRegistration": {
      "enabled": true,
      "issuer": "https://auth.example.com",
      "metadata": {
        "client_name": "MCPHub",
        "redirect_uris": [
          "http://localhost:3000/oauth/callback",
          "https://mcphub.example.com/oauth/callback"
        ],
        "scope": "mcp.tools mcp.prompts",
        "grant_types": ["authorization_code", "refresh_token"]
      },
      "initialAccessToken": "optional-token-if-required"
    },
    "scopes": ["mcp.tools", "mcp.prompts"],
    "resource": "https://mcp.example.com"
  }
}
```
- MCPHub 会通过 `issuer` 发现端点、完成注册，并持久化下发的 `client_id`/`client_secret`。
- 如果配置了 `oauth.redirectUri`，MCPHub 会优先使用它作为回调地址，并把它加入动态注册的 `redirect_uris`。
- 只有当注册端点受保护时才需要提供 `initialAccessToken`。

## 授权流程
1. **初始化**：启动时遍历服务器配置，发现元数据并在启用 `dynamicRegistration` 时注册客户端。
2. **用户授权**：建立连接时自动打开系统浏览器，携带 PKCE 参数访问授权页。
3. **回调处理**：内置路径 `/oauth/callback` 校验 `state`、完成换取令牌，并通过 MCP SDK 保存结果。
4. **令牌生命周期**：访问令牌与刷新令牌会缓存于内存，自动刷新，并写回 `mcp_settings.json`。

## 提示与排障
- 确保授权过程中使用的回调地址与已注册的 `redirect_uris` 完全一致。
- 若部署在 HTTPS 域名下，请对外暴露 `/oauth/callback` 或通过反向代理转发。
- 如无法完成自动发现，可显式提供 `authorizationEndpoint` 与 `tokenEndpoint`。
- 授权服务器吊销令牌后，可手动清理 `mcp_settings.json` 中的旧令牌，MCPHub 会在下一次请求时重新触发授权。
