MCP
1. MCP 是什么
1.1 定义与起源
MCP(Model Context Protocol,模型上下文协议)是 Anthropic 于 2024 年 11 月推出的开放协议,旨在标准化大语言模型(LLM)应用程序与外部数据源、工具之间的集成方式。官方将其比喻为"AI 世界的 USB-C 接口"——如同 USB-C 统一了各类电子设备的连接标准,MCP 试图统一 AI 应用与外部世界的通信方式。
在 MCP 出现之前,如果你想让 AI 访问某个数据源,需要为每个 AI 工具单独编写适配层:给 Claude 写一个插件,给 Cursor 写一个扩展,给 Windsurf 再写一个……复杂度是 N x M(N 个数据源 x M 个 AI 工具)。有了 MCP 之后,你只需要编写一次 MCP Server,所有支持 MCP 的客户端都能直接调用,复杂度降到了 N + M。
MCP 的设计深受 LSP(Language Server Protocol,语言服务器协议)的启发。LSP 标准化了如何在各种开发工具中添加编程语言支持,而 MCP 则标准化了如何将额外的上下文和工具集成到 AI 应用生态中。
1.2 设计哲学
MCP 基于以下核心设计原则:
| 原则 | 含义 |
|---|---|
| 服务器应极其易于构建 | 宿主应用处理复杂的编排职责,服务器专注于特定、明确定义的能力 |
| 服务器应高度可组合 | 每个服务器提供隔离的聚焦功能,多个服务器可无缝组合 |
| 服务器不应读取整个对话 | 服务器仅接收必要的上下文信息,完整对话历史保留在宿主 |
| 功能可逐步添加 | 核心协议提供最低限度的必需功能,可根据需要协商额外能力 |
1.3 解决的问题
MCP 主要解决三个核心问题:
- 集成碎片化:每个 AI 工具都需要为每个数据源编写自定义集成代码
- 上下文传递困难:LLM 难以获取实时、私有、领域特定的数据
- 工具发现不一致:不同平台对"工具"的定义和调用方式各不相同
2. 核心架构
2.1 三层组件模型
MCP 采用客户端-宿主-服务器架构,其中每个宿主可以运行多个客户端实例:
+-------------------------------------------------------------+
| MCP Host |
| (Claude Desktop / Claude Code / Cursor / Windsurf ...) |
| |
| +----------------+ +----------------+ |
| | MCP Client 1 | | MCP Client 2 | ... |
| | (连接 Server A)| | (连接 Server B)| |
| +-------+--------+ +-------+--------+ |
+----------|-------------------|------------------------------+
| |
v v
+-------------+ +-------------+
| MCP Server A| | MCP Server B|
| (GitHub API)| | (PostgreSQL)|
+-------------+ +-------------+
宿主(Host):LLM 应用本身,作为容器和协调者。它创建并管理多个客户端实例,控制连接权限和生命周期,执行安全策略和同意要求,处理用户授权决策,协调 AI/LLM 集成和采样。
客户端(Client):由宿主创建,维护一个与特定服务器的一对一连接。每个客户端建立一个有状态的会话,处理协议协商和能力交换,双向路由协议消息,管理订阅和通知,在服务器之间维护安全边界。
服务器(Server):提供专门的上下文和能力。通过 MCP 原语暴露资源、工具和提示,独立运行并承担明确职责,通过客户端接口请求采样,必须遵守安全限制,可以是本地进程或远程服务。
2.2 协议规范:基于 JSON-RPC 2.0
MCP 基于 JSON-RPC 2.0 构建,提供了一种有状态的会话协议。它定义了三种核心消息类型:
| 消息类型 | 特征 | 用途 |
|---|---|---|
| 请求(Request) | 具有 id、method 和 params,期望响应 | 调用工具、列出资源、获取提示 |
| 响应(Response) | 匹配特定请求 id 的成功 result 或 error | 返回操作结果 |
| 通知(Notification) | 无需响应的单向消息,无 id 字段 | 状态变更、初始化完成信号 |
2.3 生命周期:从握手到关闭
MCP 定义了严格的三阶段连接生命周期:
阶段一:初始化(Initialization)
初始化是客户端与服务器的第一次交互,必须在任何其他操作之前完成。
步骤 1:客户端发送 initialize 请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": { "listChanged": true },
"sampling": {}
},
"clientInfo": {
"name": "ClaudeCode",
"version": "2.1.0"
}
}
}
步骤 2:服务器响应其能力和信息
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"logging": {},
"prompts": { "listChanged": true },
"resources": { "subscribe": true, "listChanged": true },
"tools": { "listChanged": true }
},
"serverInfo": {
"name": "github-server",
"version": "1.0.0"
},
"instructions": "Optional instructions for the client"
}
}
步骤 3:客户端发送 initialized 通知确认就绪
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
阶段二:运行(Operation)
双方根据协商的能力交换消息。客户端可以请求工具列表、调用工具、读取资源、获取提示;服务器可以发送能力变更通知。
阶段三:关闭(Shutdown)
- stdio 传输:客户端关闭输入流,等待服务器退出,必要时发送
SIGTERM或SIGKILL - HTTP 传输:关闭关联的 HTTP 连接
2.4 能力协商
MCP 使用基于能力的协商系统,客户端和服务器在初始化期间显式声明支持的功能:
| 类别 | 能力 | 描述 |
|---|---|---|
| 客户端 | roots | 提供文件系统根目录的能力 |
| 客户端 | sampling | 支持 LLM 采样请求 |
| 服务器 | prompts | 提供提示模板 |
| 服务器 | resources | 提供可读资源 |
| 服务器 | tools | 暴露可调用的工具 |
| 服务器 | logging | 发送结构化日志消息 |
| 服务器 | completions | 支持参数自动补全 |
2.5 三种核心原语
MCP Server 通过三种原语暴露功能:
| 原语 | 类型 | 用途 | 示例 |
|---|---|---|---|
| Tools(工具) | 可执行 | 执行操作、副作用 | 查询数据库、发送消息、创建文件 |
| Resources(资源) | 只读 | 提供数据、上下文 | 文件内容、API 返回、配置信息 |
| Prompts(提示) | 模板 | 预定义对话模板 | 代码审查模板、日报生成模板 |
Tools 是 AI 可以调用的"函数",执行某个动作并返回结果。Resources 是 AI 可以读取的"数据源"。Prompts 是帮助 AI 更快理解任务的"模板"。
2.6 传输方式
MCP 支持两种传输方式:
| 传输方式 | 适用场景 | 特点 |
|---|---|---|
| stdio | 本地进程通信 | 通过标准输入输出传输,适合本地工具,安全性高 |
| HTTP / SSE | 远程服务通信 | 基于 HTTP 或 Server-Sent Events,适合云端服务,需处理认证 |
3. 内置 MCP Server 列表
MCP 生态已发展出数百个 Server,覆盖开发、数据、通信、自动化等多个领域。以下是官方和社区维护的核心 Server:
3.1 官方参考实现
| Server | 功能 | 安装方式 |
|---|---|---|
| Everything | 参考测试服务器,包含 prompts、resources、tools 完整示例 | npx -y @modelcontextprotocol/server-everything |
| Fetch | Web 内容获取和转换,优化 LLM 使用效率 | npx -y @modelcontextprotocol/server-fetch |
| Filesystem | 安全文件操作,支持可配置访问控制 | npx -y @modelcontextprotocol/server-filesystem /allowed/path |
| Git | 读取、搜索和操作 Git 仓库 | uvx mcp-server-git |
| Memory | 基于知识图谱的持久化记忆系统 | npx -y @modelcontextprotocol/server-memory |
| Sequential Thinking | 动态反思式问题求解 | npx -y @modelcontextprotocol/server-sequentialthinking |
| Time | 时间和时区转换 | npx -y @modelcontextprotocol/server-time |
3.2 常用第三方 Server
| 类别 | Server | 功能 | 安装方式 |
|---|---|---|---|
| 代码托管 | GitHub | 仓库管理、PR、Issue、代码搜索 | 远程 HTTP Server,需 GitHub PAT |
| 代码托管 | GitLab | GitLab API、项目管理 | npx -y @modelcontextprotocol/server-gitlab |
| 数据库 | PostgreSQL | 只读数据库访问、Schema 检查 | npx -y @modelcontextprotocol/server-postgres <dsn> |
| 数据库 | SQLite | 数据库交互和商业智能 | npx -y @modelcontextprotocol/server-sqlite |
| 数据库 | MySQL | SQL 查询执行 | 社区实现 |
| 浏览器 | Puppeteer | 浏览器自动化和网页抓取 | npx -y @modelcontextprotocol/server-puppeteer |
| 通信 | Slack | 频道管理和消息功能 | 远程 HTTP Server,OAuth 认证 |
| 通信 | Email (Gmail) | 邮件发送和搜索 | OAuth 2.0 认证 |
| 搜索 | Brave Search | Web 和本地搜索 | 需 Brave Search API Key |
| 监控 | Sentry | 检索和分析 Sentry 问题 | 远程 HTTP Server |
| 地图 | Google Maps | 位置服务、路线、地点详情 | 需 Google Maps API Key |
| 网盘 | Google Drive | 文件访问和搜索 | OAuth 2.0 认证 |
| 文档 | Notion | 页面、数据库、块操作 | 远程 HTTP Server,OAuth 认证 |
| 设计 | Figma | 设计文件访问 | 社区实现 |
| 支付 | Stripe | 支付操作和管理 | 远程 HTTP Server |
3.3 Server 生态发现
社区维护的 Server 目录:
- MCP Registry — 官方示例和参考实现
- Awesome MCP Servers — 社区精选 Server 集合
- MCPHub — 带用户评价的 Server 目录
- MCPpedia — 17000+ Server 的安全评分和比较
- PulseMCP — 社区中心和每周 newsletter
4. 在 Claude Code 中安装与配置 MCP Server
4.1 三种安装方式
Claude Code 支持三种方式添加 MCP Server:
方式一:远程 HTTP Server(推荐)
适合连接云端服务,是最广泛支持的传输方式:
# 基本语法
claude mcp add --transport http <name> <url>
# 连接 Notion
claude mcp add --transport http notion https://mcp.notion.com/mcp
# 带 Bearer Token 的认证
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
方式二:远程 SSE Server
# 基本语法
claude mcp add --transport sse <name> <url>
# 连接 Asana
claude mcp add --transport sse asana https://mcp.asana.com/sse
方式三:本地 stdio Server
适合需要直接系统访问或自定义脚本的工具:
# 基本语法
claude mcp add [options] <name> -- <command> [args...]
# 连接 Airtable
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
-- npx -y airtable-mcp-server
# 连接 PostgreSQL 数据库
claude mcp add --transport stdio db -- npx -y @modelcontextprotocol/server-postgres \
"postgresql://user:pass@localhost:5432/mydb"
# 连接文件系统(限制访问目录)
claude mcp add --transport stdio fs -- npx -y @modelcontextprotocol/server-filesystem \
/Users/lionad/projects /Users/lionad/documents
4.2 三种配置作用域
Claude Code 支持三个配置作用域:
| 作用域 | 加载范围 | 团队共享 | 存储位置 |
|---|---|---|---|
| Local(默认) | 仅当前项目 | 否 | ~/.claude.json |
| Project | 仅当前项目 | 是(通过版本控制) | .mcp.json(项目根目录) |
| User | 所有项目 | 否 | ~/.claude.json |
# Local 作用域(默认)
claude mcp add --transport http stripe https://mcp.stripe.com
# Project 作用域(团队共享)
claude mcp add --transport http paypal --scope project https://mcp.paypal.com/mcp
# User 作用域(跨项目)
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
Project 作用域的配置文件 .mcp.json 示例:
{
"mcpServers": {
"shared-server": {
"command": "/path/to/server",
"args": [],
"env": {}
}
}
}
4.3 管理命令
# 列出所有配置的 Server
claude mcp list
# 查看特定 Server 详情
claude mcp get github
# 移除 Server
claude mcp remove github
# 重置项目作用域的批准选择
claude mcp reset-project-choices
# 在 Claude Code 内检查 Server 状态
/mcp
4.4 环境变量扩展
.mcp.json 支持环境变量扩展,方便团队共享配置同时保护敏感信息:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}
支持的语法:
${VAR}— 展开为环境变量VAR的值${VAR:-default}— 若VAR已设置则使用其值,否则使用默认值
4.5 常用 Server 配置示例
GitHub
# 使用 GitHub Personal Access Token
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
配置后可直接使用自然语言操作:
Review PR #456 and suggest improvements
Create a new issue for the bug we just found
Show me all open PRs assigned to me
PostgreSQL
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"
配置后可直接查询:
What's our total revenue this month?
Show me the schema for the orders table
Find customers who haven't made a purchase in 90 days
Sentry
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
配置后可调试生产问题:
What are the most common errors in the last 24 hours?
Show me the stack trace for error ID abc123
Which deployment introduced these new errors?
4.6 高级功能
动态工具更新:Claude Code 支持 MCP list_changed 通知,Server 可动态更新可用工具而无需重新连接。
自动重连:HTTP/SSE Server 断开后,Claude Code 会自动以指数退避重连(最多 5 次,从 1 秒开始翻倍)。
输出限制:默认最大输出 25000 tokens,可通过环境变量调整:
export MAX_MCP_OUTPUT_TOKENS=50000
claude
工具搜索:默认启用工具延迟加载,只有 Claude 实际使用的工具才会进入上下文,减少对上下文窗口的占用。
5. 自定义 MCP Server:从零开发
5.1 环境准备
# 创建项目目录
mkdir mcp-weather-server && cd mcp-weather-server
# 初始化(使用 Bun 或 npm)
bun init -y
# 或 npm init -y
# 安装 MCP TypeScript SDK 和 Zod
bun add @modelcontextprotocol/sdk zod
# 或 npm install @modelcontextprotocol/sdk zod
TypeScript 配置要点:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"strict": true
}
}
5.2 创建 Server 骨架
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 创建服务器实例
const server = new McpServer({
name: "weather-service",
version: "1.0.0",
});
// 注册工具(Tools)
server.tool(
"get_weather",
"获取指定城市的当前天气信息",
{
city: z.string().describe("城市名称,如:北京、上海"),
},
async ({ city }) => {
// 工具实现见下文
return { content: [{ type: "text", text: `查询 ${city} 的天气...` }] };
}
);
// 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Weather Server 已启动,等待连接...");
5.3 实现工具(Tools)
// 天气查询工具实现
server.tool(
"get_weather",
"获取指定城市的当前天气信息",
{
city: z.string().describe("城市名称,如:北京、上海"),
},
async ({ city }) => {
const API_KEY = process.env.OPENWEATHER_API_KEY;
const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${API_KEY}&units=metric&lang=zh_cn`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`API 请求失败:${response.status}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify({
city: data.name,
temperature: `${data.main.temp}°C`,
feels_like: `${data.main.feels_like}°C`,
description: data.weather[0].description,
humidity: `${data.main.humidity}%`,
wind_speed: `${data.wind.speed} m/s`,
}, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `查询失败:${error instanceof Error ? error.message : '未知错误'}`,
},
],
isError: true,
};
}
}
);
5.4 添加资源(Resources)
// 提供服务器状态信息
server.resource(
"server-status",
"status://server",
async (uri) => ({
contents: [
{
uri: uri.href,
text: JSON.stringify({
name: "Weather Service",
version: "1.0.0",
status: "running",
timestamp: new Date().toISOString(),
}, null, 2),
},
],
})
);
// 提供 API 文档
server.resource(
"api-docs",
"docs://api",
async (uri) => ({
contents: [
{
uri: uri.href,
text: `
# Weather MCP Server API
## Tools
- get_weather(city: string): 获取指定城市天气
## Resources
- status://server - 服务器状态
- docs://api - API 文档
`.trim(),
},
],
})
);
5.5 添加提示模板(Prompts)
// 预定义的天气报告模板
server.prompt(
"weather_report",
"生成一份格式化的天气报告",
{
city: z.string().describe("城市名称"),
include_tips: z.boolean().optional().describe("是否包含穿衣建议"),
},
({ city, include_tips }) => ({
messages: [
{
role: "user",
content: {
type: "text",
text: `请为${city}生成一份天气报告。${include_tips ? "同时提供穿衣建议。" : ""}`,
},
},
],
})
);
5.6 完整入口文件
// src/index.ts(完整版)
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "weather-service",
version: "1.0.0",
});
// ===== Tools =====
server.tool("get_weather", /* ... */);
// ===== Resources =====
server.resource("server-status", /* ... */);
server.resource("api-docs", /* ... */);
// ===== Prompts =====
server.prompt("weather_report", /* ... */);
// ===== 错误处理 =====
process.stdin.on("error", (err) => {
console.error("标准输入错误:", err);
process.exit(1);
});
process.stdout.on("error", (err) => {
console.error("标准输出错误:", err);
process.exit(1);
});
// 优雅退出
process.on("SIGINT", async () => {
await server.close();
process.exit(0);
});
// 启动
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Weather Server 已启动,等待连接...");
5.7 配置 Claude Code 使用自定义 Server
# 使用绝对路径配置
claude mcp add --transport stdio weather -- bun run /absolute/path/to/mcp-weather-server/src/index.ts
或在 .mcp.json 中配置:
{
"mcpServers": {
"weather": {
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-weather-server/src/index.ts"],
"env": {
"OPENWEATHER_API_KEY": "your-api-key"
}
}
}
}
5.8 生产环境部署选项
| 部署方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 本地 stdio | 个人使用、开发测试 | 简单、安全 | 无法共享 |
| HTTP/SSE | 团队共享、多用户 | 可远程访问 | 需处理认证 |
| Serverless | 生产环境 | 自动扩缩容 | 冷启动延迟 |
生产环境注意事项:
// 认证检查
const apiKey = request.headers.get("Authorization");
if (apiKey !== `Bearer ${process.env.API_KEY}`) {
return new Response("Unauthorized", { status: 401 });
}
// 日志记录
import pino from "pino";
const logger = pino();
server.tool("get_weather", /* ... */, async ({ city }) => {
logger.info({ city }, "查询天气");
// ...
});
6. MCP 与 Function Call 的区别和关系
6.1 核心区别
| 维度 | Function Call | MCP |
|---|---|---|
| 本质 | 模型内置能力(如 OpenAI 的 JSON 格式指令) | 跨模型协议标准(独立于具体模型) |
| 定位 | 单模型调用外部工具的实现方式 | 多模型调用工具的通信规范 |
| 发起方 | 由大模型主动生成调用指令 | 由标准化客户端/服务器架构传递指令 |
| 依赖关系 | 深度绑定特定模型 | 模型无关(兼容 Claude/GPT/通义等) |
| 工具热插拔 | 需重新部署模型 | 工具可动态注册/卸载 |
| 跨设备调用 | 限于本地环境 | 支持远程/云工具调用 |
6.2 简单比喻
- Function Call = 手机的语音助手(只能控制本机 App)
- MCP = 蓝牙协议(让任何手机连接任何耳机)
6.3 协同工作模式
二者实际可形成互补的上下游关系:
用户请求 → 大模型生成 Function Call → 转换为 MCP 请求 → 调用工具 → 结果返回模型
具体协作流程:
- 模型通过 Function Call 解析用户意图
- 将函数调用参数转换为 MCP 标准报文
- MCP 客户端分发给对应工具服务器
- 结果通过 MCP 返回模型生成回答
优势:保留 Function Call 的意图解析能力,获得 MCP 的工具生态扩展性。
6.4 技术演进趋势
- Function Call 将作为模型原生基础能力持续进化
- MCP 正在成为企业 AI 基础设施的事实标准协议
- 二者边界逐渐模糊,最终形成"模型解析 → 协议传输 → 工具执行"分层架构
- OpenAI 等厂商已支持 Function Call 转 MCP 网关
7. 实际案例
7.1 案例一:连接 PostgreSQL 数据库
场景:让 Claude 用自然语言查询数据库。
配置:
claude mcp add --transport stdio postgres -- npx -y \
@modelcontextprotocol/server-postgres \
"postgresql://readonly:pass@localhost:5432/analytics"
使用:
> 本月总收入是多少?
[Claude 自动调用 MCP 工具查询数据库]
> 显示 orders 表的 Schema
[Claude 自动调用 schema 查询工具]
> 找出 90 天内未购买的客户
[Claude 生成并执行 SQL 查询]
最佳实践:
- 使用只读账号连接生产数据库
- 提供数据库 Schema 文件帮助 AI 理解表结构
- 准备示例查询文件提升生成质量
7.2 案例二:操作 GitHub
场景:在 Claude Code 中直接管理代码仓库。
配置:
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
使用:
> Review PR #456 并给出改进建议
[Claude 读取 PR diff、评论、CI 状态,生成审查报告]
> 为刚发现的 bug 创建一个新 Issue
[Claude 自动创建 Issue,包含复现步骤和堆栈跟踪]
> 显示分配给我的所有开放 PR
[Claude 查询并列出 PR 列表]
> 实现 JIRA 工单 ENG-4521 描述的功能并在 GitHub 创建 PR
[Claude 读取工单 → 编写代码 → 提交 → 创建 PR]
7.3 案例三:读取 Slack 消息
场景:将 Slack 消息作为上下文输入 Claude。
配置:
claude mcp add --transport http slack https://mcp.slack.com/mcp
Slack 官方远程 Server 使用 OAuth 认证,尊重现有权限。
使用:
> 总结 #engineering 频道今天的讨论
[Claude 读取频道消息并生成摘要]
> 根据 Slack 中发布的新 Figma 设计更新邮件模板
[Claude 读取 Slack 中的设计链接 → 获取 Figma 内容 → 更新代码]
> 给参与讨论的 10 位用户发送反馈会议邀请
[Claude 提取用户列表 → 生成邮件草稿]
7.4 案例四:多 MCP 串联工作流
场景:将多个 MCP Server 串联完成复杂任务。
用户: "实现 JIRA 工单 ENG-4521 的功能,基于我们的设计规范,
然后创建 PR 并通知团队"
Claude 的执行流程:
1. [JIRA MCP] 读取 ENG-4521 的详细描述
2. [Figma MCP] 获取相关设计稿
3. [Git MCP] 检查当前分支状态
4. [Filesystem MCP] 读取项目代码规范
5. 编写代码实现功能
6. [Git MCP] 提交代码
7. [GitHub MCP] 创建 PR
8. [Slack MCP] 在 #engineering 频道通知团队
8. 安全考量
8.1 核心安全风险
MCP 引入了全新的攻击面:AI 代理基于自然语言动态执行工具,访问敏感系统。OWASP 已发布专门的 MCP 安全速查表,识别出以下关键风险:
| 风险 | 描述 |
|---|---|
| Tool Poisoning(工具投毒) | 恶意指令隐藏在工具描述、参数 Schema 或返回值中,操纵 LLM 行为 |
| Rug Pull 攻击 | Server 在初始用户批准后更改工具定义,将可信工具变为恶意工具 |
| Tool Shadowing | 恶意 Server 的工具描述操纵代理对其他可信 Server 工具的行为 |
| Confused Deputy(混淆代理) | MCP Server 使用自身(往往过于宽泛的)权限执行操作,而非请求用户的权限 |
| 数据外泄 | 通过提示注入将敏感数据编码到看似正常的工具调用中 |
| 供应链攻击 | 从公共注册表安装不受信任或已被攻破的 MCP Server 包 |
| 沙箱逃逸 | 本地 MCP Server 以完整主机权限运行,导致文件系统遍历或任意代码执行 |
8.2 安全最佳实践
1. 最小权限原则
- 为每个 MCP Server 授予其功能所需的最低权限
- 使用按 Server 隔离的凭证,绝不跨 Server 共享 Token
- 请求窄范围的 OAuth 作用域(如
mail.readonly而非mail.full_access) - 优先使用短期临时 Token 而非长期 PAT
2. 工具描述完整性校验
- 批准前检查所有工具描述、参数名、类型和返回 Schema
- 将整个工具 Schema 视为潜在的注入面
- 使用加密哈希固定工具定义,变更时告警(防止 rug pull)
- 使用
mcp-scan等工具自动检测投毒描述和跨 Server 阴影
3. 沙箱隔离
- 在沙箱环境(容器、chroot、应用沙箱)中运行本地 MCP Server
- 将文件系统访问限制为仅所需目录
- 除非明确需要,否则禁用网络访问
- 将敏感 Server(支付、认证、PII)与普通 Server 分离
4. 敏感操作人工确认
- 对破坏性、财务或数据共享操作要求显式用户确认
- 向用户显示完整的工具调用参数,而非仅摘要名称
- 切勿自动批准工具调用,尤其在多 Server 设置中
5. 输入输出验证
- 将所有输入视为不受信任(源自可能被恶意上下文影响的 LLM 输出)
- 防范注入攻击(SQL、OS 命令、路径遍历)
- 在返回 LLM 上下文前验证和清理工具输出
- 切勿传递原始 Shell 命令或未经清理的文件路径
6. 传输层安全
- 对所有远程 MCP Server 端点强制执行认证
- 使用 OAuth 2.0 with PKCE 进行远程 Server 授权
- 始终对远程传输使用 TLS
- 将 MCP HTTP/SSE Server 绑定到特定接口(如
127.0.0.1),而非0.0.0.0 - 使用操作系统原生安全凭证存储(macOS Keychain、Windows Credential Manager)
7. 监控、日志与审计
- 记录所有 MCP 工具调用,包含完整参数、用户上下文和时间戳
- 将 MCP 日志输入 SIEM 进行异常检测
- 对异常模式告警:新工具被调用、管理员级查询、异常调用频率
- 从日志中脱敏密钥和 PII
8. 供应链安全
- 仅从可信、已验证的来源安装 MCP Server
- 安装前审查 Server 源代码和工具定义
- 使用校验和或代码签名验证包完整性
- 仔细检查包名再安装——拼写仿冒(typosquatting)是常见攻击向量
8.3 Claude Code 的安全机制
Claude Code 内置了多层安全保护:
- 项目作用域 Server 需批准:
.mcp.json中配置的 Server 首次使用时需要用户批准 - 作用域隔离:Local/Project/User 三层作用域确保配置不会意外泄露
- Denylist 优先:
managed-mcp.json中的拒绝列表绝对优先于允许列表 - 输出限制:默认 25000 tokens 的输出上限防止上下文被淹没
- 工具搜索:延迟加载工具定义,减少上下文暴露面
企业级管理配置示例:
// /Library/Application Support/ClaudeCode/managed-mcp.json (macOS)
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/"
},
"sentry": {
"type": "http",
"url": "https://mcp.sentry.dev/mcp"
}
},
"deniedMcpServers": [
{ "serverUrl": "https://*.untrusted.com/*" },
{ "serverCommand": ["npx", "-y", "unapproved-package"] }
]
}
9. 参考来源
- Model Context Protocol 官方文档 — MCP 协议规范、示例和指南的权威来源
- MCP Specification 2025-03-26 — 协议规范的权威定义
- MCP 中文文档 — 社区翻译的中文版文档
- modelcontextprotocol/servers — 官方参考实现和社区 Server 集合
- Claude Code MCP 文档 — Claude Code 中配置和使用 MCP 的完整指南
- OWASP MCP Security Cheat Sheet — MCP 安全的权威速查表
- MCP Server 开发入门:从零搭建你的第一个 MCP 服务 — TypeScript SDK 实战教程
- MCP with Postgres - Querying my data in plain English — PostgreSQL MCP 实战案例
- 12 MCP Server Examples Every AI Engineer Should Know — 生产环境常用 Server 概览
- 大模型应用开发中 MCP 与 Function Call 的关系与区别 — 阿里云开发者社区的技术对比分析
- MCP Server Security Best Practices — 企业级 MCP 安全部署指南