第6章:MCP

问题背景

当 Claude 需要访问 Jira、GitHub、数据库、内部 API 等外部系统时,直接复制粘贴数据或为每个系统编写专用适配器都不可持续。MCP(Model Context Protocol,模型上下文协议)要解决的核心问题是:让 AI 客户端与外部工具、数据源之间建立安全、标准、可复用的连接。

6.1 从 M×N 到 M+N:标准化的力量

MCP 的价值可以用 USB-C 类比理解。没有标准接口时,M 种设备与 N 种外设需要 M×N 种连接方案;有了统一标准后,设备端和外设端各实现一次协议,即可把复杂度降低为 M+N。

MCP 实现了完全相同的逻辑(见下图)。在 MCP 问世之前,任何一个 AI 客户端(如 Claude、ChatGPT 等)与特定数据源(如 Jira、GitHub、数据库等)之间的集成,都需要单独开发并维护专用的适配器。例如,若要让 GitHub 访问 Claude 代码,需要开发一个 GitHub-Claude 适配器;若要让同一个 GitHub 接入 ChatGPT,则必须重新开发一个 GitHub-ChatGPT 适配器。假设有5个 AI 客户端和100个数据源,理论上就需要维护500个独立的适配器——这意味着每新增一个 AI 客户端或数据源,都伴随着大量且重复的集成开发工作。

image-20260619223732410

MCP 的核心思路:

  • AI 客户端实现 MCP 客户端协议。
  • 数据源或工具实现 MCP 服务器协议。
  • 双方遵循标准后即可即插即用。

总结

MCP 的本质不是某个工具插件,而是标准化连接协议。它通过统一接口,降低 AI 客户端与外部系统之间的集成复杂度。

6.2 架构:客户端-服务器与 JSON-RPC

MCP 采用经典的客户端-服务器架构(见下图),基于 JSON-RPC 2.0 协议进行通信。

image-20260619223803245

角色分工:

  • MCP 客户端:内置于 Claude Code,负责发现服务器能力、构造工具调用请求并处理响应。
  • MCP 服务器:独立程序,连接数据库、API、文件系统等外部服务,并通过 MCP 暴露能力。

MCP 架构与 VSCode 的语言服务器协议(LSP)类似。LSP 连接编辑器与语言工具链,MCP 连接 AI 模型与外部数字世界。

一台MCP服务器可向客户端“暴露”以下3类核心能力。

1. Tools

Tools 是最核心且最常用的能力。工具是供 Claude 主动调用的函数,例如:

  • 在 Jira 上创建工单。
  • 查询数据库过去 7 天订单。
  • 向 Slack 发送消息。

每个工具定义名称、描述、输入参数 schema 和返回值格式。Claude 判断需要调用工具时,会构造符合 schema 的请求,服务器执行后返回结构化结果。

2. Resources

Resources 类似只读文件,供 Claude 按需读取数据。它与 Tools 的区别是:

  • Tools 用于执行操作,可能有副作用。
  • Resources 用于读取数据,通常只读。

例如,读取 README 内容属于 Resource;提交 Commit 属于 Tool。

3. Prompts

Prompts 是可复用提示词模板,用于标准化特定任务的启动方式。例如代码审查 MCP 服务器可提供 code-review 模板,自动载入审查关注点和输出格式。尽管该功能与Skills存在一定重叠,且在实际应用中的普及度不及前两类,但它为任务初始化提供了便捷路径。

实际应用中,Tools 最常用。用户说“帮我在 Jira 中查找 P1 级 bug”时,Claude 通常调用 Jira MCP 服务器暴露的查询工具。

总结

MCP 以客户端-服务器架构和 JSON-RPC 为基础,向 Claude 暴露三类能力:Tools 执行动作,Resources 提供只读数据,Prompts 标准化任务启动。

6.3 传输方式:连接的3种形态

MCP 的传输层定义客户端与服务器之间如何通信。目前主要支持 3 种传输方式。

1. stdio(标准输入输出)

适用于本地进程通信。客户端(如 Claude Code) 以子进程形式启动 MCP 服务器,通过 stdin/stdout 传递 JSON-RPC 消息。

优点:

  • 完全本地运行。
  • 不需要网络连接。
  • 延迟低,安全性高。

适用场景:

  • 文件系统访问。
  • 本地数据库连接。
  • 本地开发工具集成。
  • 大多数通过 npx 启动的官方 MCP 服务器。

2. HTTP

适用于远程服务器通信。AI 客户端向 HTTP 端点发送POST请求,服务器处理后返回响应。

适用场景:

  • 公司内网 Jira 适配器。
  • SaaS 提供的 MCP 接入点。
  • 需要 OAuth 2.0 或企业统一身份认证的服务。

3. SSE(Server-Sent Events)

曾是早期远程传输方案,目前已废弃。旧项目中若仍使用 SSE,建议尽快迁移到 HTTP。


遵循 “本地选择stdio,远程选择HTTP” 的简单准则即可满足绝大多数需求。

总结

传输方式决定 MCP 连接的运行形态。本地工具优先 stdio,远程服务优先 HTTP,SSE 属于遗留方案。

6.4 配置详解:从 CLI 到配置文件

6.4.1 CLI 快速配置

Claude Code 提供 claude mcp 命令管理 MCP 服务器。

# 添加本地 stdio 服务器:启动一个本地文件系统服务,指定工作目录为 /workspace
claude mcp add filesystem npx -y @modelcontextprotocol/server-filesystem /workspace

# 添加远程 HTTP 服务器:连接至公司内网的 Jira 服务
claude mcp add --transport http company-jira https://jira.company.com/mcp

# 添加用户级服务器(全局可用):将 GitHub 服务添加到用户级别配置,使其对所有项目生效
claude mcp add --scope user github -- npx -y @modelcontextprotocol/server-github

# 添加带认证信息的服务器:通过自定义 HTTP 头传递认证 Token
claude mcp add --transport http --header "Authorization: Bearer ${TOKEN}" api https://api.example.com/mcp

# 管理命令
claude mcp list # 列出配置:查看当前所有已配置的 MCP 服务器
claude mcp test github # 测试连接:验证指定服务器(如 GitHub)的连接状态及可用性
claude mcp remove github # 移除服务器:删除指定的 MCP 服务器配置

6.4.2 .mcp.json 配置文件

claude mcp 命令本质上是在管理 .mcp.json 配置。

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
"env": {}
},
"company-jira": {
"type": "http",
"url": "https://jira.company.com/mcp",
"headers": {
"Authorization": "Bearer ${JIRA_TOKEN}"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${DB_URL:-postgresql://localhost:5432/mydb}"
}
}
}
}

环境变量替换是关键功能:

  • ${VAR_NAME}:运行时替换为环境变量值。
  • ${VAR_NAME:-default_value}:未设置变量时使用默认值。

这样可以把敏感信息保存在环境变量或 .env 中,而不是硬编码进 .mcp.json。配置文件只保存变量引用,可安全提交到 Git。

6.4.3 配置文件的位置与作用域

.mcpjson配置文件根据存放位置的不同,具有不同的作用域,如下表所示。

文件路径 作用域 适用场景
.mcp.json(项目根目录) 项目级 配置仅对当前项目生效。适用于团队共享的、与特定代码库绑定的服务(如该项目的数据库连接、特定的内部工具)。此文件通常提交到 Git 仓库
~/.claude/ 目录 所有项目用户级 配置对所有项目生效。适用于个人通用的工具(如个人常用的文件系统访问、全局的代码搜索工具)。此文件位于用户主目录,不随项目变动

如果凭证不宜提交,可把凭证存入 .claude/settings.local.json,基础服务器配置保留在 .mcp.json 中供团队共享。

总结

MCP 配置既可通过 CLI 快速添加,也可通过 .mcp.json 精细管理。团队共享配置应避免硬编码密钥,使用环境变量注入敏感信息。

6.5 实战一:连接数据库

让 Claude 查询数据库是 MCP 的常见用法。

PostgreSQL MCP 配置示例:

{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${DATABASE_URL:-postgresql://localhost:5432/mydb}"
}
}
}
}

使用方式:

你:帮我查一下数据库里上个月的订单数量和总金额。

Claude:正在查询数据库……

[调用 postgres MCP Server: sql_query 工具]

上个月(2025 年 12 月)订单统计:
- 订单数量:1,234 笔
- 总金额:¥456,789.00
- 平均客单价:¥370.21
- 较上月增长 12.3%

在此过程中,Claude 会自动识别查询需求,定位到 postgres MCP 服务器,生成并执行 SQL 语句,最后整理返回结果。你不需要掌握 SQL 语法,也不必打开数据库客户端或手动导出数据。

安全原则:数据库连接应使用只读账号。如果使用具备写权限的账号,Claude 理论上可能执行 INSERTUPDATEDROP TABLE 等高风险操作。因此,在 DATABASE_URL 中配置只读用户是保障数据安全的最基本防护。

6.6 实战二:构建自定义 MCP 服务器

当现有 MCP 服务器无法满足需求时,可使用 TypeScript 或 Python SDK 构建自定义服务器。

TypeScript 待办事项管理服务器示例:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// 内存存储
const todos: { id: string; text: string; done: boolean }[] = [];

// 创建 MCP 服务器实例
const server = new McpServer({
name: "todo-server",
version: "1.0.0",
});

// 定义工具:添加待办事项
server.tool(
"todo_add", // 工具名称
"Add a new todo item", // 工具描述(供 Claude 判断调用时机)
{ text: z.string().describe("The todo text") }, // 输入参数 Schema
async ({ text }) => { // 执行逻辑
const todo = {
id: Math.random().toString(36).substring(2, 9),
text,
done: false,
};

todos.push(todo);

return {
content: [
{
type: "text",
text: `Added: ${todo.id} - ${todo.text}`,
},
],
};
}
);

// 定义工具:列出所有待办事项
server.tool("todo_list", "List all todo items", {}, async () => {
const text =
todos.length === 0
? "No todos found."
: todos
.map((t) => `[${t.done ? "x" : " "}] ${t.id}: ${t.text}`)
.join("\n");

return {
content: [
{
type: "text",
text,
},
],
};
});

// 定义资源:统计信息
server.resource("stats", "Server statistics", async () => {
return {
contents: [
{
uri: "stats://current",
mimeType: "application/json",
text: JSON.stringify(
{
total: todos.length,
completed: todos.filter((t) => t.done).length,
pending: todos.filter((t) => !t.done).length,
},
null,
2
),
},
],
};
});

// 启动服务器
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server started"); // 注意:日志输出至 stderr
}

main().catch(console.error);

在上述架构中,有几个关键的设计细节值得特别注意。

  • 工具描述至关重要:server.tool() 的第二个参数(描述字符串)是 Claude 判断何时调用该工具的核心依据。描述写得越清晰、准确,Claude 的意图识别和工具调用就越精准。

  • 类型安全与校验:输入参数通过 Zod schema 进行定义,这不仅提供了严格的类型安全保障,还能在运行时自动校验参数的有效性,防止错误的数据传入。

  • 日志输出规范:调试日志必须通过 console.error 输出到 stderr,而非 stdout。这是因为 stdout 通道专门用于传输 JSON-RPC 消息,若混人普通日志会导致协议解析失败。这一机制与 Hooks 脚本的调试输出原理一致。

Python 版本的实现同样简洁优雅。

from mcp.server import Server
from mcp.server.stdio import stdio_server

# 初始化服务器与内存存储
server = Server("todo-server")
todos = []


@server.tool("todo_add")
async def add_todo(text: str) -> str:
"""添加新的待办事项"""
todo_id = generate_id() # 假设已定义 generate_id 函数
todos.append({"id": todo_id, "text": text, "done": False})
return f"Added: {todo_id} - {text}"


@server.tool("todo_list")
async def list_todos() -> str:
"""列出所有待办事项"""
if not todos:
return "No todos found."

return "\n".join(
f"[{'x' if t['done'] else ' '}] {t['id']}: {t['text']}"
for t in todos
)


async def main():
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream)


if __name__ == "__main__":
import asyncio

asyncio.run(main())

完成开发后,你需要在配置文件中注册自定义服务器。以下示例展示了如何启动一个编译后的 MCP 服务(若为 Python 项目,请将 command 调整为 python)。

{
"mcpServers": {
"my-todo": {
"command": "node",
"args": ["./mcp-server/build/index.js"]
}
}
}

6.7 常用 MCP 服务器生态

6.7.1 官方 MCP 服务器

Anthropic 官方提供的 MCP 服务器,最常用的几类如下表所示。

MCP 服务器名称 注意用途 安装 / 启动命令
server-filesystem 文件系统读写操作 npx @modelcontextprotocol/server-filesystem<path>
server-fetch 发送 HTTP 请求 npx @modelcontextprotocol/server-fetch
server-postgres PostgreSQL 数据库查询 npx @modelcontextprotocol/server-postgres
server-memory 跨会话持久化记忆存储 npx @modelcontextprotocol/server-memory
server-git Git 版本控制操作 npx @modelcontextprotocol/server-git

①启动 server-filesystem 时,请将替换为你希望授权访问的实际目录路径。

6.7.2 热门第三方 MCP 服务器

服务器名称 主要用途 通信协议
GitHub MCP GitHub 协作管理(PR、Issues、代码检索) HTTP(SSE)
Notion MCP Notion 文档读取与写入 HTTP(SSE)
Sentry MCP 错误追踪与日志分析 HTTP(SSE)
Context7 检索最新技术文档 stdio
Bytebase DBHub 多数据库统一接入与管理 stdio

6.7.3 实用配置组合

以下是一份专为全栈开发者设计的 MCP 配置文件,集成了文件系统、网络请求、代码协作及数据库管理功能。

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
},
"fetch": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-fetch"]
},
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
}
},
"database": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${DATABASE_URL}"]
}
}
}

提示:${GITHUB_TOKEN}${DATABASE_URL} 是环境变量占位符,使用前需在终端环境中设置。

借助此配置,开发者可在单个 Claude 会话中无缝完成以往需要在多个工具间切换的复杂工作流。

  • 数据插叙:“帮我统计数据库中最近7天的订单总额”→自动调用 database 服务器执行 SQL 查询。

  • 任务管理:“整理上述 bug 描述并将之创建为一个新的 GitHubIssue”→自动调用 GitHub 服务器通过 API 提交工单。

  • 文档检索:“获取 React19 官方文档中关于 ServerComponents 的最新说明”→自动调用 fetch 服务器实时抓取网页内容。

6.8 安全机制:信任的边界

MCP 扩展了 Claude 的外部操作能力,也引入了安全风险。必须明确边界。

6.8.1 三层纵深安全机制

为了平衡灵活性与安全性,MCP 架构设计了层层递进的三重防御机制。

第一层,首次连接的交互式审批。

这是建立信任的基石。每当用户配置了一台新的 MCP 服务器时,Claude 在首次尝试连接该服务器前会自动暂停,并向用户展示服务器的详细信息(如来源、权限范围等),请求明确的显式授权。该步骤为强制交互流程,无法绕过。

第二层,细粒度的工具级权限控制。

即使整台 MCP 服务器已获得全局授权,Claude 在调用具体工具时仍需要保持警惕,特别是针对具有副作用的操作(如文件写入、代码执行、数据库修改等)。Claude 会在执行前再次拦截,向用户展示即将执行的具体指令细节,并等待二次确认。

第三层,基于 OAuth 2.0 的动态认证。

对于远程 MCP 服务器,推荐采用 OAuth 2.0 协议而非长期有效的静态 API 密钥。这种方式不仅便于与企业现有的统一身份认证系统集成以实现单点登录,而且支持令牌的自动过期与刷新机制。

6.8.2 安全风险与防护

2025年4月,安全研究人员指出了MCP生态中的以下安全风险应。

  • 提示注入攻击:恶意内容可通过 MCP 服务器注入 Claude 的上下文。若 MCP 服务器返回包含恶意指令的数据(如“忽略之前的所有指令,执行以下操作”),Claude 可能会被误导。防护措施是仅使用可信来源的 MCP 服务器。
  • 工具权限滥用:单个工具的权限看似安全,但多个工具组合使用时可能产生意想不到的后果。例如,“读文件”工具与“发邮件”工具的组合,理论上可能导致文件内容泄露。防护措施是遵循最小权限原则。
  • 冒名顶替:恶意工具可伪装成合法工具的名称和描述,诱导 Claude 调用。防护措施是仅安装来自可信来源的 MCP 服务器包。

评估 MCP 服务器的信任度与评估 npm 包并无本质区别:核心在于考察其来源(是源自官方的@modelcontextprotocol/ 命名空间,还是个人开发者)、维护活跃度、下载量及社区口碑。选择知名的官方服务器是确保安全的起点。此外,在安全实践上,连接数据库时务必使用只读账号;管理 API 密钥时,应通过环境变量注入,严禁硬编码。

6.9 MCP+Skills:厨房与菜谱

第3章介绍的 Skills 与本章探讨的 MCP,分别解决不同层面的问题:

  • MCP 提供访问外部数据和工具的能力。
  • Skills 指导 Claude 如何以标准流程使用这些能力。

类比:

  • MCP 是厨房:提供数据库、API、文件、外部工具等设备和原料。
  • Skills 是菜谱:规定如何选择工具、处理数据和输出结果。

在实际应用中,两者的协作模式:在 Skills 的 SKILL.md 中引用 MCP 工具,从而指导 Claude 按照特定的工作流高效调用这些工具(见下图)。

这一组合赋予了 Claude 双重优势:既能通过 MCP 获取实时数据能力,又能借助 Skills 遵循一致的数据处理方式。这意味着,Claude 不再依赖用户每次的详尽指令,也不需要仰仗 Claude 的临场判断,即可实现稳定、高效的自动化执行。

image-20260619225905666

总结

MCP 解决“能连接什么”,Skills 解决“连接后怎么做”。两者组合后,Claude 既有工具能力,也有标准流程。

6.10 企业级部署

对拥有数十甚至上百名工程师的团队而言,依赖个人自行配置 MCP 服务器并非可扩展的方案。为此,Claude Code 提供了企业级的集中管理机制。

管理员可通过 managed-mcp.json (或 Claude for Enterprise) 管理后台,为组织预配置 MCP 服务器。这些服务器可自动对所有成员生效,并可由管理员预先授权,从而免除每位用户首次使用时的审批弹窗流程。

价值:

  • 开发者可以 “零配置,开箱即用” 的使用 Jira、Linear、内部知识库、数据仓库等工具。
  • 企业可集中审查、审计和管控 MCP 访问。
  • 相比分散个人配置,集中管理更安全、更可维护。

6.11 调试与故障排除

MCP 服务器的调试难度通常高于 Hooks 脚本,原因在于其涉及进程间通信、网络连接以及复杂的认证流程等多个环节。

6.11.1 常用调试手段

一些常用的调试手段如下。

# 列出所有已配置的服务器及其当前状态
claude mcp list

# 专门测试特定服务器的连接连通性
claude mcp test my-server

# 启用 MCP 调试模式
claude --mcp-debug

6.11.2 MCP 工具输出的 Token 管理

针对 MCP 工具可能返回海量数据(例如,未加 LIMIT 限制的数据库查询可能返回数万行记录)的情况,Claude Code 内置了专门的 Token 管理机制。

  • 警告阈值:当输出超过10000 Token 时,系统会显示警告提示。截断阈值:当输出超过25000 Token 时,系统将自动对内容进行不截断,防止上下文溢出。

  • 自定义配置:用户可以通过设置环境变量 MAX_MCP_OUTPUT_TOKENS 来调整这一输出上限,以适应不同的业务场景需求。

6.11.3 常见问题

MCP 常见问题与解决方案如下表所示。该表可以帮助用户快速定位和解决开发中遇到的典型问题。

问题现象 可能原因 解决方案
服务器无法启动 命令或路径配置错误 检查配置文件中的 command 和 args 参数;尝试在终端手动运行该命令以验证是否可以正常启动
连接超时 网络不稳定或服务器响应过慢 设置环境变量 MCP_TIMEOUT(单位为毫秒),适当延长等待时间
认证失败 Token 错误、缺失或已过期 确认相关环境变量(如 API_KEY 等)已正确设置;检查 Token 的有效性并及时刷新
输出被截断 返回数据量超过 Token 限制 调大环境变量 MAX_MCP_OUTPUT_TOKENS 的上限;优化查询逻辑(如增加 LIMIT),让服务器返回更精简的数据
JSON 解析错误 服务器标准输出(stdout)被日志污染 确保服务器将调试日志、错误信息等非数据内容输出至标准错误(stderr),保持 stdout 仅包含纯净的 JSON 数据

本章小结

MCP 的核心价值在于用统一开放协议标准化 AI 工具集成,让 AI 客户端能够连接不同数据源和服务,而无需为每种组合单独开发适配层。它基于 JSON-RPC 2.0,支持本地 stdio 和远程 HTTP 通信,并可通过环境变量安全管理配置。

从工程角度看,MCP 不只是“能连接”,更重要的是“标准化连接”。符合 MCP 标准的服务器和客户端可以相互兼容,推动 AI 工具生态持续扩展。与 Hooks 和 Skills 相比,MCP 负责扩展数据与服务边界,Skills 指导执行方式,Hooks 约束行为边界,三者共同构成完整的 AI 工程化体系。