MCP 是 Claude 的 什么? - claude-10

16 阅读12分钟

Command、Agent、Skill 这些都还是 Claude Code 内部的事情。

虽然 Claude Code 已经很厉害了 —— 能读本地文件、能跑 bash、能 fetch URL。

但公司的 Jira、团队的 Slack、DB、你的 Figma 设计稿——这些东西,Claude Code 不认识,至少你不教它不会认识。

MCP(Model Context Protocol) 就是让这些东西插进来的机制。这一篇把它讲透。这是系列文章第10篇。


目录概要

  1. 为什么要有一个新协议,而不是每个工具直接写 plugin
  2. MCP 的协议模型:server / client / transport
  3. 三种 transport:stdio / http / sse
  4. 配置文件的三层 scope
  5. 权限系统:mcp__<server>__<tool> 的由来
  6. 5 个真正日常用的 MCP server
  7. "MCP 泛滥"是一个真实问题
  8. 小结

一、为什么不直接写插件

先解一个认知疑问——Claude 是个 LLM 客户端,VSCode 是个编辑器客户端,为什么 VSCode 的扩展机制是"VSCode 自己定义的插件 API",而 Claude Code 选了"一个开放协议 + 协议实现者"?

1.1 一个反向推演

假设 Anthropic 跟 Microsoft 当年一样,定义一套自己的 plugin API——每个扩展实现 ClaudePlugin 接口,打包成某种格式、在一个 registry 里管理。那会怎么样?

问题 1:每个客户端都要各自造轮子。Claude Code 有自己的插件格式、Cursor 有自己的、Cline 有自己的——一个 GitHub MCP 的作者要给五个客户端各写五份。

问题 2:协议被绑死在实现者手里。Anthropic 想改 API 语义,得推着全部插件迁移;插件作者想加新能力,得等 Anthropic 放行。

问题 3:和模型耦合。不同模型对"工具调用"的理解方式不一样(OpenAI 的 function calling、Claude 的 tool use 都有自己的 JSON schema),如果插件协议绑定到模型 API,换模型就废。

1.2 MCP 的解法

Anthropic 2024 年末放出 MCP1,思路是——把"工具定义"这件事独立成一个协议

graph LR
  subgraph Clients
    C1[Claude Desktop]
    C2[Claude Code]
    C3[Cursor]
    C4[Zed]
  end

  subgraph Protocol[MCP Protocol]
    P[标准化的 JSON-RPC]
  end

  subgraph Servers
    S1[GitHub MCP]
    S2[Slack MCP]
    S3[Playwright MCP]
    S4[你自己写的 MCP]
  end

  C1 -->|MCP| P
  C2 -->|MCP| P
  C3 -->|MCP| P
  C4 -->|MCP| P
  P --> S1
  P --> S2
  P --> S3
  P --> S4

  style P fill:#ff9
  style S1 fill:#afa
  style S2 fill:#afa
  style S3 fill:#afa
  style S4 fill:#afa
  • 客户端(Claude Code、Cursor 等)只需要实现 MCP 协议
  • 服务端(GitHub MCP、Slack MCP 等)只需要实现 MCP 协议
  • 中间的协议是开放的——谁都能读规范、谁都能实现

这样一来:

  • 一个 GitHub MCP 写一次,所有支持 MCP 的客户端都能用
  • 换模型不影响 MCP server——协议层在客户端里做 tool use 翻译
  • Anthropic 不需要当"插件审核员"——社区自己维护 registry

设计哲学上:MCP 更像 USB 而不是插件系统——定义接口形状,不关心接口两端是谁

1.3 跟 VSCode 扩展的对比

维度VSCode ExtensionMCP
协议Microsoft 自定义 APIJSON-RPC 2.0 开放协议
执行位置在 VSCode 进程里(Extension Host)独立进程 / 远程服务
客户端绑 VSCode任意 MCP 客户端
授权VSCode 的安装权限每个 server 单独控制
生态市场(microsoft.com 管理)社区 + 官方 registry 并存

关键洞察:VSCode Extension 是"住在编辑器里的租客";MCP server 是"经过协议通信的独立服务"——它的执行环境跟客户端完全隔离

这一层隔离带来巨大好处:MCP server 可以用任何语言写、可以跑在任何机器上、可以做任何只要它愿意做的事——客户端根本不关心。


二、MCP 的协议模型

简单看一下 MCP 底下的样子。你不需要背细节,但理解层级很重要。

2.1 三个角色

sequenceDiagram
    participant H as Host (Claude Code)
    participant C as MCP Client
    participant S as MCP Server

    H->>C: 启动 MCP client
    C->>S: initialize (能力协商)
    S-->>C: 返回 tools / resources / prompts 列表
    C-->>H: 注册工具到主会话

    Note over H,S: 用户提问 / Claude 决定用工具

    H->>C: 调用 mcp__github__create_issue
    C->>S: tools/call
    S-->>C: 返回结果
    C-->>H: 结果进 Claude 上下文
  • Host:Claude Code 本身,是承载一切的进程
  • Client:Host 里为每个 server 起的一个 MCP client,负责协议通信
  • Server:真正干活的进程(或者远程服务)

2.2 Server 能暴露的东西

MCP server 能向客户端暴露 三种 东西:

类型作用举例
Tools可以被 Claude 调用的函数github.create_issueslack.send_message
Resources可以被 Claude 读取的数据数据库 schema、配置文件内容
Prompts可以被用户 / Claude 展开的模板"写一份 bug 报告" 的套路

绝大多数 MCP server 只用了 tools——把一个外部服务的每个 API 方法包成一个 tool 暴露给 Claude。但 resources 和 prompts 的设计空间其实更有意思,只是目前还没被普遍用起来。

2.3 协议层是 JSON-RPC 2.0

MCP 本质上是包了一层特定 schema 的 JSON-RPC 2.0——用标准的 request / response / notification 三种消息类型,走标准的 id / method / params 字段。

这个选择很务实。JSON-RPC 是成熟、简单、多语言生态都有的协议。Anthropic 没发明轮子,只是在它上面约定了"initialize"、"tools/list"、"tools/call" 这些方法名和参数结构。


三、三种 transport:stdio / http / sse

协议层统一了,但消息怎么传还是有选择。MCP 支持三种 transport:

3.1 stdio——本地进程

最常见的模式。Claude Code 用 spawn 起一个子进程,通过 stdin / stdout 传 JSON-RPC 消息:

{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp"]
    }
  }
}

适合:本地工具——Playwright、Context7、本地数据库客户端。

优点:简单、无需网络、权限清晰。 缺点:只能本机跑、启动有冷启动开销。

3.2 http——远程服务

用标准 HTTP POST JSON-RPC:

{
  "mcpServers": {
    "remote-api": {
      "type": "http",
      "url": "https://mcp.example.com/mcp"
    }
  }
}

适合:公司内 MCP 网关SaaS 服务共享给多人的 server

优点:跨机器共享、中心化管理。 缺点:需要网络、需要 auth。

3.3 sse——长连接流

Server-Sent Events。在 http 基础上用长连接推消息,适合需要 server 主动 push 的场景(比如"文件发生变化通知 Claude")。

目前这种用法比较少,绝大多数场景 stdio 够用。

3.4 对照表

transport典型场景本地/远程启动开销
stdio本地工具、开发期本地每会话一次
http企业网关、公共 API远程每调用一次
sse实时数据流、监听远程建立连接时一次

四、配置文件的三层 scope

跟 settings 一样,MCP 的配置也是分层的——三层 scope

graph TD
  subgraph User[User Scope: ~/.claude.json]
    U["mcpServers: { context7, playwright }"]
  end

  subgraph Project[Project Scope: .mcp.json]
    P["mcpServers: { postgres-prod, sentry }"]
  end

  subgraph Subagent[Subagent Scope: agent frontmatter]
    A["mcpServers: { internal-api }"]
  end

  Session[当前 Session 能用的 MCP]
  U --> Session
  P --> Session
  A --> Session

  style U fill:#aaf
  style P fill:#afa
  style A fill:#ff9

4.1 Project 级:.mcp.json

放在 repo 根。团队共享,入 git。典型内容:

{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp"]
    },
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp"]
    }
  }
}

所有这个项目的人都自动拿到这些 server。

4.2 User 级:~/.claude.jsonmcpServers 字段

个人 home 目录的全局配置。对所有项目生效——我个人习惯的 MCP,放这里最合适。

4.3 Subagent 级:agent frontmatter 的 mcpServers

这个是 06 篇讲 subagent 时提过的字段。可以精确控制"这个 subagent 只能用某些 MCP server":

---
name: deploy-agent
mcpServers:
  - kubernetes-prod
  - aws-deploy
---

优先级:subagent > project > user。subagent 定义的如果和 project 的同名,subagent 的覆盖。

4.4 环境变量注入

重要:API token 这种东西不要写进 .mcp.json(入 git 会泄露)。用环境变量插值:

{
  "mcpServers": {
    "remote-api": {
      "type": "http",
      "url": "https://mcp.example.com/mcp?token=${MCP_API_TOKEN}"
    }
  }
}

Claude Code 启动时从环境变量读 MCP_API_TOKEN,替换到 URL 里。token 走 shell env 或 .env,不入 git。


五、权限系统——mcp__<server>__<tool> 的由来

MCP server 接入 Claude Code 之后,它暴露的每个 tool 会按 mcp__<server>__<tool> 命名注册到 Claude。

举例:

  • GitHub MCP 的 create_issuemcp__github__create_issue
  • Context7 MCP 的 resolve-library-idmcp__context7__resolve-library-id
  • Playwright MCP 的 browser_snapshotmcp__playwright__browser_snapshot

5.1 为什么这样命名

一个 Claude Code session 里可能同时连着 5 个 MCP server。不同 server 可能都有一个叫 search 的工具——必须加前缀做命名空间隔离

mcp__ 是系统前缀,<server> 是你 .mcp.json 里起的名字,<tool> 是 server 自己定义的。

5.2 权限规则

所有 07 / 08 篇讲过的 permission 语法对 MCP 工具一样适用:

{
  "permissions": {
    "allow": [
      "mcp__*",                              // 放行所有 MCP(慎用)
      "mcp__context7__*",                    // 放行整个 context7
      "mcp__playwright__browser_snapshot"    // 只放行特定 tool
    ],
    "deny": [
      "mcp__dangerous-server__*",            // 禁用整个 server
      "mcp__github__delete_*"                // 禁 github 的删除类工具
    ]
  }
}

完整 regex支持,跟 hook matcher 的语法一样。

5.3 Server 级开关

.claude/settings.json 里还有三个 server 级的 bool 字段,用来控制"哪些 MCP 自动启用":

字段行为
enableAllProjectMcpServers自动批准 .mcp.json 里所有 server,不弹确认
enabledMcpjsonServers白名单,列出的 server 自动启用
disabledMcpjsonServers黑名单,列出的 server 禁用

一个新克隆下来的仓库第一次跑 Claude Code,默认会逐个弹确认:"是否启用这个 MCP server?"——避免恶意 .mcp.json 偷偷接入外部服务。想直接全批准,就设 enableAllProjectMcpServers: true


六、5 个真正日常用的 MCP server

市面上 MCP server 已经几百个了,但绝大多数不值得装。有一条来自 r/mcp 的扎心评论2说得很到位:

"Went overboard with 15 MCP servers thinking more = better. Ended up using only 4 daily."

作者反复筛过之后,留在日常用的就下面这 5 个

6.1 Context7——防 API 幻觉

npx -y @upstash/context7-mcp

解决什么问题:Claude 训练数据是有 cutoff 的。你用 React Server Component 最新 API、Next.js 15 的新路由、某个 library 最近才加的方法——训练里根本没有,Claude 只能瞎编。

Context7 实时把最新版官方文档塞进 Claude 的 context。你问"React 最新的 useActionState 怎么用",Context7 现场把最新文档的相关段落拉过来,Claude 基于真实文档回答。

最大杀手:从根本上消除"Claude 给的代码 API 不存在"这种 bug。一旦装上就离不开。

6.2 Playwright——浏览器自动化

npx -y @playwright/mcp

解决什么问题:前端功能做完了,Claude 能帮你测吗?以前只能手动打开浏览器测。

Playwright MCP 让 Claude 直接操作浏览器——截图、点击、填表单、读 DOM、验证视觉。它能自己打开 localhost:3000、登录、走一遍注册流程、验证邮件发送——全自动。

实战价值:前端功能的"实现 → 测试 → 验证" 闭环,Claude 一个人搞定。

6.3 Claude in Chrome——调试真实浏览器

解决什么问题:Playwright 是 headless 或者无痕模式——看不到你真实用户看到的那个页面。Claude in Chrome 接的是你日常打开的 Chrome——包含 cookie、缓存、登录态、插件。

适合:调生产问题。用户在线上看到的 bug,Claude 打开 DevTools、查 console、看 network 请求——站在用户的视角看问题。

6.4 DeepWiki——吃透 GitHub 仓库

解决什么问题:你要接入一个陌生仓库,自己读代码要几小时。DeepWiki 给你一份结构化 wiki:架构图、核心模块、API 表、关键 dependency。

用法套路:用 DeepWiki 问"这个 repo 的架构长啥样" → 拿结论指导你后续提问 → 碰到具体 API 细节时再用 Context7 查官方文档。两个工具配合最好用。

6.5 Excalidraw——从 prompt 生成架构图

解决什么问题:写架构文档时要画图。自己画慢、mermaid 美观有限。Excalidraw MCP 从 prompt 直接生成手绘风格的架构图/流程图——贴进 PR、贴进文档都好看。


6.6 一个推荐的工作流

把上面 5 个组合起来,形成一个研发闭环

graph LR
  R[研究陌生 repo/库<br>DeepWiki + Context7] --> I[实现代码]
  I --> D[调试<br>Playwright / Claude in Chrome]
  D --> DOC[画架构图<br>Excalidraw]
  DOC --> PR[交付]

  style R fill:#aaf
  style D fill:#ff9
  style DOC fill:#afa

研究 → 实现 → 调试 → 写文档——四个环节都有 MCP 加持。


七、"MCP 泛滥"是一个真实问题

前面引用的那条 reddit 评论不是孤例。"装太多 MCP 反而让 Claude 变慢变笨"是个普遍吐槽。原因有三条:

7.1 每个 MCP 都往 system prompt 塞 tool schema

MCP server 暴露 10 个 tool,那就是 10 个 tool schema 被注入到主上下文。装 15 个 MCP、每个平均 10 个 tool——150 个工具描述占着 context。Claude 每次决策前都要浏览这个巨大的工具清单。

后果:

  • context 被吃掉大头(本来该留给业务的)
  • Claude 选 tool 时更容易误选——选择空间大了就容易选错
  • 响应变慢

7.2 冷启动成本叠加

每个 stdio MCP 启动要几百毫秒到几秒。你在 .mcp.json 里开 15 个 server——会话起步 10 秒起步,每次都要重来一遍。

7.3 安全面扩大

每接一个第三方 MCP 就多一个信任边界。这个 server 拿到你的 Claude 请求、它拿到什么数据、它回传什么 prompt 注入——都要审计。接入的越多审计越松。

7.4 实用经验

经过几轮迭代,作者的取舍原则是:

  1. 每个 MCP 都要有一个明确的"不可替代点"——Context7 无法用别的替代(实时文档),Playwright 无法用别的替代(真浏览器)
  2. 能用 built-in 工具的不要上 MCP——读文件用 Read 不用 filesystem MCP,搜代码用 Grep 不用 code-search MCP
  3. "3 个常用、2 个偶尔用"比"15 个都装上"强

八、从单机到中枢

MCP 这套东西,开始看着又一个新协议、又一堆新术语。但拆开看本质——

它解决的问题是"让 AI 客户端能接上任意外部服务,而不需要每个客户端都为每个服务写一遍 plugin"。解法是把接口形状标准化,执行位置留给 server 自己决定。

对 Claude Code 用户来说的价值是两条:一是真实时性(Context7 让 Claude 摆脱训练 cutoff),二是真世界动作(Playwright 让 Claude 真能操作东西,不只是回答问题)。

最大的坑是贪多——装上 15 个 MCP 结果每次都慢、每次都选错工具。选型时先问"不可替代性在哪",不能回答的就别装。

写完这篇,Claude Code 这个"单机工具"就真的升格成"工作中枢"了——内部有 command / agent / skill 的编排,外部有 MCP 接入世界。

但讲了这么多理论、写了这么多配置,真正让新手 / 老手差距拉开的还是那些"书上没写、文档没讲、用久了才会知道"的小技巧。下一篇把作者这段时间攒下来的实用技巧和冷知识列一下——快捷键、隐藏命令、效率套路、/compact 的时机、--agent 的妙用——都是能马上用上的东西。


参考资料

外部链接

Footnotes

  1. Model Context Protocol Specification — MCP 官方协议规范

  2. MCP Server Overload Discussion — r/mcp — 社区关于"装太多 MCP"的讨论