## 什么是 MCP?

MCP(Model Context Protocol,模型上下文协议)是连接 AI 助手与外部工具、数据源和服务的开放标准。你的服务器暴露"工具" — 具有名称、描述和输入模式的函数 — AI 模型在对话中决定何时调用它们。MCP 由 Anthropic 在 2024 年末创建,现在被 Claude、ChatGPT、IDE 插件和不断增长的代理框架列表支持,它对 AI 起到的作用与 USB 对硬件起到的作用相同:一根电缆,适用于任何设备。

## 为什么 MCP 重要

在 MCP 之前,每个 AI 助手通过自定义"插件"或"function calling"代码连接到每个外部服务。每个 AI 供应商都有自己的格式。每个工具集成都必须按供应商重新编写 — 一次为 Claude,再一次为 ChatGPT,再一次为 Cursor,再一次为自定义代理。

MCP 标准化了接口。一个 MCP 服务器适用于所有兼容 MCP 的客户端。这意味着:

- 工具构建者写一次集成,而不是 N 次
- AI 客户端在新工具发布时立即拾取,无需更新客户端
- 代理可以在运行时发现、列出和调用工具 — 无需编译时配线
- 开源服务器可以被审计、分叉和自托管

就像专有打印机驱动程序和 IP 标准的区别。协议很无聊。在它上面标准化解锁了一个生态系统。

## 工作原理

所有通信都使用 **JSON-RPC 2.0** 通过 HTTP POST 到单个端点(例如 `/mcp`):

1. 客户端发送 `initialize` 来建立会话
2. 服务器以其名称、版本和功能响应
3. 客户端发送 `tools/list` 来发现可用工具
4. 服务器返回带描述和输入模式的工具列表
5. 客户端发送 `tools/call` 带有工具名称和参数
6. 服务器执行工具并返回结果

## MCP 与替代方案

| 方面 | OpenAI function calling | [OpenAPI](/kb/zh/openapi) / Swagger | MCP |
|---|---|---|---|
| 供应商范围 | 单一供应商 | 供应商中立 | 供应商中立 |
| 设计目的 | LLM 工具调用 | REST API | AI 代理 |
| 发现 | 客户端硬编码 | 静态规范文件 | 通过 `tools/list` 运行时 |
| 流式传输 | 有限 | 无原生支持 | 内置(SSE / Streamable HTTP) |
| 有状态会话 | 否 | 否 | 是(initialize → 调用) |
| 认证 | 客户端密钥 | API 密钥、OAuth | OAuth、bearer、自定义 |
| 生态系统 | 仅 OpenAI | 成熟、广泛 | 新但快速增长 |

OpenAPI 在设计时描述 REST API。MCP 在运行时描述*活动*工具表面。两者互补 — 许多 MCP 服务器包装现有的 OpenAPI 服务并将其作为代理可调用工具公开。

## 实现示例

```javascript
app.post('/mcp', (req, res) => {
  const { method, params, id } = req.body;

  if (method === 'initialize') {
    return res.json({ jsonrpc: '2.0', id, result: {
      protocolVersion: '2024-11-05',
      capabilities: { tools: {} },
      serverInfo: { name: 'my-service', version: '1.0' }
    }});
  }

  if (method === 'tools/list') {
    return res.json({ jsonrpc: '2.0', id, result: {
      tools: [{
        name: 'search',
        description: 'Search for items',
        inputSchema: {
          type: 'object',
          properties: { query: { type: 'string' } },
          required: ['query']
        }
      }]
    }});
  }

  if (method === 'tools/call') {
    const { name, arguments: args } = params;
    return res.json({ jsonrpc: '2.0', id, result: {
      content: [{ type: 'text', text: 'Search results...' }]
    }});
  }

  res.json({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found' }});
});
```

## 传输选项

MCP 支持三种传输 — 根据客户端运行位置选择:

- **Streamable HTTP** *(远程服务器推荐)*:普通 HTTP POST 到一个端点。服务器返回 JSON 响应或为发出进度的工具返回 SSE 流。通过 CDN、负载均衡器和防火墙工作。这是 claude.ai web 和大多数托管客户端所期望的。
- **SSE(Server-Sent Events)**:使用长连接 GET 用于服务器→客户端和 POST 用于客户端→服务器的较旧传输。仍受支持但 Streamable HTTP 在新服务器中取代了它。
- **stdio**:进程管道 — 客户端将你的服务器作为子进程启动并通过 stdin/stdout 通信。Claude Desktop 和 CLI 代理使用。无网络,无 CORS,但客户端必须能够在本地运行你的代码。

如果你想要一个 MCP 服务器同时与 Claude Desktop *和* Claude web 应用 *和* ChatGPT *和* Cursor 工作,请发布 Streamable HTTP。现在几乎所有人都说它。

## CORS — 基于浏览器的代理所需

越来越多的 MCP 客户端在*浏览器中*运行:Claude.ai web、ChatGPT 浏览器、浏览器扩展和嵌入式聊天小部件。当 `claude.ai` 上运行的 JavaScript 调用 `fetch('https://yourdomain.com/mcp')` 时,浏览器自己做两件事:

1. 它实际上将请求发送到你的服务器。
2. 它拒绝将响应交给请求它的 JavaScript — *除非*你的服务器响应包含命名 `claude.ai`(或 `*`)的 `Access-Control-Allow-Origin` 头。

因此没有 CORS 头时,你的服务器运行良好并返回 200,但浏览器选项卡中的 MCP 客户端看到网络错误,永远无法读取正文。这是浏览器在保护用户。像 Claude Desktop 或 MCP CLI 这样的服务器端客户端不受此限制。

为支持基于浏览器的 MCP 客户端,在每个 `/mcp` 响应上发送这些头,并处理 OPTIONS 预检:

```javascript
app.use('/mcp', (req, res, next) => {
  res.set('Access-Control-Allow-Origin', '*');
  res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization');
  if (req.method === 'OPTIONS') return res.sendStatus(204);
  next();
});
```

### 通配符 vs 特定来源

`Access-Control-Allow-Origin: *` 适用于**公开、只读**的 MCP 端点。如果你的 MCP 端点需要认证或为工具调用收费,返回特定来源(或将请求的 `Origin` 头与允许列表对比并回显)并设置 `Access-Control-Allow-Credentials: true`。根据 CORS 规范,通配符来源不能与凭证一起使用。

### 为什么预检很重要

对于"简单"请求 — 普通 `GET` 或 `Content-Type: text/plain` 的 `POST` — 浏览器只是发送它,只有响应被阻止。但是 MCP 使用 `Content-Type: application/json` 的 `POST`,浏览器认为这足够危险以*先检查*。在发送实际 POST 之前,浏览器发送 `OPTIONS` 请求询问:"你会接受来自此来源带这些头的 POST 吗?"

如果你的服务器没有用 2xx 状态和正确的 CORS 头响应 OPTIONS,浏览器完全取消 POST — 它永远不到达你的服务器。这就是为什么 CORS 中间件必须处理两者:OPTIONS 预检*和*实际 POST。

## 认证

对于公开只读服务器,无认证就可以。对于私有或付费工具,MCP 支持:

- **Bearer 令牌**在 `Authorization` 头中(最简单)
- **OAuth 2.1** 与 PKCE — 用户委托访问的标准;MCP 规范在 `/.well-known/oauth-authorization-server` 定义元数据端点,以便客户端自动发现你的 OAuth 流程
- **按请求付款** 通过 [x402](/kb/zh/x402) — 返回带支付指令的 HTTP 402 而不是事先认证

如果是人类代表自己授权,OAuth 是正确的默认值。Bearer 令牌适合服务到服务。x402 适合付费且无状态的调用。

## 谁在使用 MCP

- **Anthropic Claude** — Claude Desktop、Claude.ai web 和 Claude API 中的原生 MCP 客户端
- **OpenAI ChatGPT** — 在 2025 年添加了 MCP 支持
- **IDE 集成** — Cursor、Zed、Windsurf 和 JetBrains 插件都说 MCP
- **代理框架** — LangChain、LlamaIndex 和大多数代理 SDK 包含 MCP 传输
- **官方 MCP 注册表** `registry.modelcontextprotocol.io` 列出数百个公开服务器
- **Smithery** `smithery.ai` 是最大的社区维护 MCP 市场

agentgrade 发布自己的 MCP 服务器(`com.agentgrade/mcp-server`),用于希望从 MCP 感知客户端内部扫描站点的代理。

## 常见错误和调试

- **`Method not found`**(-32601):客户端调用了你的服务器未实现的方法。始终为未知方法返回优雅的错误而不是抛出。
- **CORS 预检失败**:OPTIONS 返回 404 或 405。添加上面所示的中间件。
- **客户端 UI 中工具列表为空**:你的 `tools/list` 响应格式良好,但客户端期望非空 `tools` 数组。确认至少注册了一个工具。
- **`Invalid params`**(-32602):客户端发送的参数与你的 `inputSchema` 不匹配。查看 JSON Schema — 缺少必需字段或类型错误是通常的元凶。
- **Desktop 中工作,web 中失败**:几乎总是 CORS。浏览器阻止响应;服务器日志显示 200s,但客户端看不到任何东西。

## 关键概念

- **Tools**:你的服务器暴露的函数(例如 "search"、"create_invoice")
- **inputSchema**:描述每个工具接受什么参数的 JSON Schema
- **Resources**:你的服务器可以交给模型的只读数据(文件、片段、查询结果)
- **Prompts**:服务器发布供客户端使用的可重用提示模板
- **Streamable HTTP**:推荐的传输 — 所有消息通过 POST 到一个端点
- **SSE**:Server-Sent Events — 较旧传输,为向后兼容保留

## FAQ

### MCP 是 Anthropic 协议还是开放标准?

它由 Anthropic 创建并作为开放规范发布。参考实现采用 MIT 许可。OpenAI、IDE 供应商和代理框架独立于 Anthropic 采用了它 — 它现在是社区标准,不是单一供应商协议。

### MCP 与 OpenAI 的 function calling 有什么区别?

Function calling 是一个供应商 API 的特性。MCP 是任何客户端都可以说的传输层协议。使用 function calling,模型和工具定义存在于同一个 OpenAI 请求中;使用 MCP,模型存在于客户端,工具存在于你的服务器,它们通过定义的通信格式通信。

### 我应该将现有 REST API 公开为 MCP,还是只给 AI 我的 OpenAPI 规范?

两者都有效,但针对不同客户端。具有原生 MCP 支持的模型(Claude、Cursor)直接通过 MCP 调用工具。如果你只有时间做一个,发布 MCP — 大多数代理客户端更喜欢它用于运行时发现。

### MCP 需要 WebSocket 吗?

不。当前标准是 Streamable HTTP — 到一个端点的普通 POST,内部可选 SSE 流。早期草案使用 WebSocket;那条路被放弃了,因为普通 HTTP 无需配置就能穿越 CDN、负载均衡器和企业防火墙。

### MCP 服务器可以为工具调用收费吗?

可以。协议本身不包括支付,但你可以在上面叠加 x402:让你的服务器从 `tools/call` 返回 HTTP 402,直到代理附加有效的支付收据。这是代理生态系统中最活跃的模式之一。

### 我如何在注册表中列出我的 MCP 服务器?

向 [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) 提交清单。Smithery.ai 镜像注册表并添加发现功能。列表是免费的,审核队列很短。

### 为什么我的 MCP 服务器很慢?

协议本身很便宜 — HTTP 上的 JSON-RPC。慢几乎总是(a)工具实现,或(b)无服务器冷启动。在责怪传输之前先分析 `tools/call` 处理程序。

### 我需要每个工具一个单独的服务器,还是一个带多个工具的服务器?

一个带多个工具的服务器是标准。按逻辑服务分组工具(例如,所有 GitHub 操作在一个服务器中)。客户端可以同时连接到多个服务器,所以只有当权限管理或托管需求不同时分割才有意义。

## 规范成熟度

**正式规范。** MCP 由 Anthropic 维护,具有版本化规范。当前协议版本:`2024-11-05`。Claude、ChatGPT、Cursor 和大多数代理框架原生支持。Streamable HTTP 传输稳定,并被所有主要客户端使用。

## 了解更多

- [modelcontextprotocol.io](https://modelcontextprotocol.io) — 官方规范
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) — 参考实现
- [官方 MCP 注册表](https://registry.modelcontextprotocol.io) — MCP 服务器的公开目录
- [Smithery](https://smithery.ai) — 最大的社区市场
- [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) — 跨源资源共享参考
- [代理就绪度](/agent-readiness) — MCP 如何融入更广泛的代理 Web 格局

## 相关

- [SKILL.md](/kb/zh/skills)
- [A2A](/kb/zh/a2a)
- [WebMCP](/kb/zh/webmcp)
- [llms.txt](/kb/zh/llms-txt)
