第20章:MCP 协议——工具的万能接口

如果只有内置工具……

Claude Code 内置了 40 多个工具:读文件、搜索代码、执行命令……但世界上有无数的工具和服务:

  • - 你想让 AI 查询数据库
  • - 你想让 AI 发送 Slack 消息
  • - 你想让 AI 操作 Kubernetes 集群
  • - 你想让 AI 调用你公司内部的 API

不可能把所有这些都内置到 Claude Code 里。那怎么办?

答案是 MCP(Model Context Protocol,模型上下文协议)——一个让 Claude Code 连接任何外部工具的标准协议。

MCP 是什么?

你可以把 MCP 想象成一个"万能插头":


Claude Code ←→ MCP 协议 ←→ 任何工具/服务

就像:
你的手机 ←→ USB-C 接口 ←→ 任何 USB-C 设备

不管外部工具是什么(数据库、消息系统、云服务),只要它实现了 MCP 协议,Claude Code 就能使用它。

MCP 的架构


┌─────────────┐     MCP 协议      ┌─────────────────┐
│  Claude Code │ ←──────────────→ │  MCP 服务器 A     │
│  (客户端)    │                   │  (数据库查询)     │
│              │     MCP 协议      ├─────────────────┤
│              │ ←──────────────→ │  MCP 服务器 B     │
│              │                   │  (Slack 消息)     │
│              │     MCP 协议      ├─────────────────┤
│              │ ←──────────────→ │  MCP 服务器 C     │
│              │                   │  (GitHub API)     │
└─────────────┘                   └─────────────────┘
  • - Claude Code 是 MCP 客户端——它知道怎么发送 MCP 请求
  • - 外部工具 是 MCP 服务器——它们知道怎么响应 MCP 请求
  • - 它们之间通过 MCP 协议通信

MCP 通信方式

MCP 支持三种通信方式:

1. Stdio(标准输入/输出)


Claude Code 启动一个子进程
  → 通过 stdin 发送请求
  → 从 stdout 读取响应

这是最常用的方式。MCP 服务器就是一个普通的程序,Claude Code 在后台运行它。

2. SSE(Server-Sent Events)


Claude Code 连接到一个 HTTP 服务器
  → 通过 HTTP POST 发送请求
  → 通过 SSE 流接收响应

适合远程服务器。

3. WebSocket


Claude Code 建立 WebSocket 连接
  → 双向实时通信

适合需要实时交互的场景。

配置 MCP 服务器

在 Claude Code 的配置文件中添加 MCP 服务器:


{
  "mcpServers": {
    "github": {
      "command": "node",
      "args": ["~/.mcp/github/index.js"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    },
    "database": {
      "command": "python",
      "args": ["~/.mcp/db-server/main.py"],
      "env": {
        "DATABASE_URL": "postgres://localhost/mydb"
      }
    },
    "slack": {
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-slack"],
      "env": {
        "SLACK_TOKEN": "xoxb-xxxxxxxxxxxx"
      }
    }
  }
}

每个 MCP 服务器的配置包括:

  • - command:启动命令
  • - args:命令参数
  • - env:环境变量(通常包含 API 密钥)

MCP 工具的发现

当 Claude Code 启动时,它会连接所有配置的 MCP 服务器,并发现它们提供的工具:


// Claude Code 向 MCP 服务器发送请求
client.request("tools/list")

// MCP 服务器返回工具列表
{
  "tools": [
    {
      "name": "query_database",
      "description": "执行 SQL 查询",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sql": { "type": "string", "description": "SQL 查询语句" }
        }
      }
    },
    {
      "name": "create_table",
      "description": "创建新的数据库表",
      "inputSchema": { ... }
    }
  ]
}

这些工具会被自动添加到 AI 的可用工具列表中。

MCP 工具的命名

MCP 工具在 Claude Code 内部使用特殊的命名格式:


mcp__服务器名__工具名

例如:


mcp__github__create_issue          GitHub 创建 Issue
mcp__database__query_database      数据库查询
mcp__slack__send_message           Slack 发消息

这种前缀防止了名字冲突——如果两个 MCP 服务器都有一个叫 search 的工具,它们会变成 mcp__serverA__searchmcp__serverB__search

MCP 的实际使用

当 AI 需要使用 MCP 工具时,流程和内置工具完全一样:


1. AI 决定使用工具
   { "name": "mcp__database__query_database",
     "input": { "sql": "SELECT * FROM users WHERE active = true" } }

2. Claude Code 收到请求
   → 识别出这是 MCP 工具(前缀 "mcp__")
   → 找到对应的 MCP 服务器("database")

3. 转发给 MCP 服务器
   client.request("tools/call", {
     name: "query_database",
     arguments: { sql: "SELECT * FROM users WHERE active = true" }
   })

4. MCP 服务器执行查询
   → 连接数据库
   → 执行 SQL
   → 返回结果

5. 结果返回给 AI
   { "content": [{ "text": "找到 42 个活跃用户..." }] }

6. AI 根据结果继续回复

MCP 的权限控制

MCP 工具同样受权限系统管控:


{
  "permissions": {
    "alwaysAllow": [
      "mcp__github__list_issues",
      "mcp__github__get_issue"
    ],
    "alwaysDeny": [
      "mcp__database__drop_table"
    ],
    "alwaysAsk": [
      "mcp__slack__send_message"
    ]
  }
}

你也可以用通配符一次性管理整个服务器的工具:


{
  "alwaysDeny": ["mcp__dangerous_server__*"]
}

MCP 的意义

MCP 的设计非常聪明,它解决了几个关键问题:

1. 无限扩展性

任何人都可以写一个 MCP 服务器,提供任何功能。Claude Code 不需要为每种服务都写适配代码。

2. 语言无关

MCP 服务器可以用任何编程语言写——Python、JavaScript、Go、Rust……只要遵循 MCP 协议就行。

3. 安全隔离

MCP 服务器在独立的进程中运行。即使它崩溃了,也不会影响 Claude Code 本身。

4. 标准化

所有 MCP 工具都有统一的接口(JSON Schema 定义输入输出),AI 不需要学习每种工具的特殊用法。

本章小结

  • - MCP 是让 Claude Code 连接外部工具的标准协议
  • - 支持三种通信方式:Stdio、SSE、WebSocket
  • - 工具通过配置文件注册,启动时自动发现
  • - MCP 工具命名格式:mcp__服务器名__工具名
  • - 权限系统同样适用于 MCP 工具
  • - MCP 实现了无限扩展、语言无关、安全隔离和标准化

思考题

  1. 1. 如果你要为你学校的图书馆系统写一个 MCP 服务器,它应该提供哪些工具?
  2. 2. MCP 的三种通信方式各适合什么场景?
  3. 3. 为什么 MCP 服务器在独立进程中运行很重要?

动手实验:写一个简单的 MCP 服务器

如果你想亲手体验 MCP,可以试试写一个最简单的 MCP 服务器。只需要一个 Node.js 文件:


// simple-mcp-server.js
// 一个返回当前时间的 MCP 服务器

const readline = require('readline')

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
})

rl.on('line', (line) => {
  const request = JSON.parse(line)

  if (request.method === 'tools/list') {
    // 告诉客户端我们有哪些工具
    const response = {
      id: request.id,
      result: {
        tools: [{
          name: 'get_time',
          description: '获取当前时间',
          inputSchema: { type: 'object', properties: {} }
        }]
      }
    }
    console.log(JSON.stringify(response))
  }

  if (request.method === 'tools/call') {
    // 执行工具
    const response = {
      id: request.id,
      result: {
        content: [{ type: 'text', text: `当前时间: ${new Date().toLocaleString()}` }]
      }
    }
    console.log(JSON.stringify(response))
  }
})

这个服务器只有一个工具——获取当前时间。但它展示了 MCP 的核心思想:通过标准输入/输出通信,用 JSON 交换数据。

下一章,我们将了解 Hook 系统——用户自定义的"触发器"。


本书由 everettjf 使用 Claude Code 分析泄露源码编写 | 保留出处即可自由转载