MCP协议详解:让AI连接万物的标准接口
# MCP 协议详解:让 AI 连接万物的标准接口
MCP(Model Context Protocol,模型上下文协议)是 Anthropic 于 2024 年 11 月推出的开放协议,用于标准化 AI 模型与外部数据源、工具之间的连接方式。可以把它理解为 AI 时代的"USB-C 接口"——一个统一标准,让任何 AI 模型都能以一致的方式接入数据库、文件系统、API、企业内部工具等各类外部资源。本文从概念、架构、原理到实战开发,全面讲清楚 MCP。
# 一、为什么需要 MCP
# 1.1 之前的痛点
在 MCP 出现之前,让 AI 接入外部工具是一件"重复造轮子"的事:
- 每个工具都要单独对接:想接 GitHub,就写一套 GitHub 适配;想接数据库,又写一套数据库适配。N 个模型 × M 个工具 = N×M 种集成。
- 协议不统一:OpenAI 用 Function Calling,Anthropic 早期用 Tool Use,各家格式不同,工具无法跨平台复用。
- 上下文割裂:AI 只能看到对话里的内容,无法主动读取本地文件、查询数据库、调用企业内部 API,能力被"困在"聊天窗口里。
# 1.2 MCP 解决了什么
MCP 用一个统一协议把上面的 N×M 问题变成 N+M:
没有 MCP: 有 MCP:
┌──────┐ ┌──────┐
│模型 A │──┐ │模型 A │──┐
└──────┘ │ ┌────────┐ └──────┘ │
┌──────┐ ├──│GitHub │ ┌──────┐ ├──┌──────────┐
│模型 B │──┤ └────────┘ │模型 B │──┤ │MCP 协议 │──┬──GitHub
└──────┘ │ ┌────────┐ └──────┘ │ └──────────┘ ├──数据库
┌──────┐ ├──│数据库 │ ┌──────┐ │ ├──文件系统
│模型 C │──┘ └────────┘ │模型 C │──┘ └──企业API
└──────┘ (N×M 种集成) └──────┘ (N+M 种集成)
2
3
4
5
6
7
8
9
10
- 对模型方:只要支持 MCP 协议,就能接入所有 MCP Server,无需逐个适配。
- 对工具方:只要实现一次 MCP Server,就能被所有支持 MCP 的 AI 客户端使用。
- 对用户:配置一次,AI 就能读文件、查数据库、调 API,能力大幅扩展。
类比:USB-C 出现前,每个设备配一种充电线;USB-C 出现后,一根线充所有设备。MCP 就是 AI 世界的 USB-C。
# 二、核心概念
MCP 采用客户端-服务器架构,涉及三个角色:
┌──────────────────────────────────────────────────────────┐
│ Host(宿主) │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ AI 模型 │ │ Client A │ │ Client B │ │
│ │ │ └─────┬──────┘ └─────┬──────┘ │
│ │ Claude/ │ │ 1:1 │ 1:1 │
│ │ CodeFree-O │ │ │ │
│ └────────────┘ ▼ ▼ │
└────────────────────────┬───────────────┬─────────────────┘
│ │
stdio/SSE stdio/SSE
│ │
┌──────▼──────┐ ┌─────▼───────┐
│ MCP Server A│ │MCP Server B │
│ (文件系统) │ │ (数据库) │
└─────────────┘ └─────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2.1 三个角色
| 角色 | 说明 | 举例 |
|---|---|---|
| Host(宿主) | 运行 AI 模型的应用程序,负责管理 Client 的生命周期 | Claude Desktop、Claude Code、CodeFree-O、Cursor |
| Client(客户端) | 嵌在 Host 内部,与单个 Server 保持 1:1 连接,负责协议通信 | Host 自动创建,用户通常不直接操作 |
| Server(服务器) | 暴露具体能力和数据的轻量级程序,按协议提供 Tools / Resources / Prompts | filesystem-server、github-server、mysql-server |
关键点:一个 Host 可以同时连接多个 Server(通过多个 Client),每个 Client 与一个 Server 是 1:1 的关系。
# 2.2 三大原语(Primitives)
Server 通过三种"原语"向 AI 暴露能力:
| 原语 | 类比 | 谁控制 | 说明 |
|---|---|---|---|
| Tools(工具) | 函数调用 | 模型决定调用 | 模型可主动调用的函数,如"查询订单""创建 Issue"。类似 Function Calling。 |
| Resources(资源) | 文件 / 数据 | 应用控制(用户或 Host 决定何时读取) | 模型可读取的数据,如文件内容、数据库记录、日志。用 URI 标识,如 file:///config.json。 |
| Prompts(提示模板) | 快捷指令 | 用户控制 | 预定义的提示模板,用户可主动选择触发,如"代码审查模板""SQL 优化模板"。 |
区分控制权:Tools 是模型自主调用的,Resources 是应用决定提供的,Prompts 是用户主动触发的。三者各司其职。
# 三、通信原理
# 3.1 协议基础
MCP 通信基于 JSON-RPC 2.0,消息格式是标准的 JSON。
一个完整的 MCP 交互生命周期:
1. 初始化握手 2. 能力发现 3. 正常调用 4. 关闭
┌─────────┐ ┌──────────┐ ┌──────────────┐ ┌────────┐
│initialize│ → │tools/ │ → │tools/call │ → │shutdown│
│ │ ← │list │ ← │ │ │ │
└─────────┘ └──────────┘ └──────────────┘ └────────┘
协商版本、 列出 Server 模型决定调用 断开连接
声明能力 提供的工具/ 某个工具,传入
资源/提示 参数,拿到结果
2
3
4
5
6
7
8
# 3.2 消息示例
模型调用工具(tools/call):
// 请求:模型想调用 "query_order" 工具
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "query_order",
"arguments": {
"orderId": "ORD-20261013-001"
}
}
}
// 响应:Server 返回查询结果
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "订单 ORD-20261013-001,金额 ¥299.00,状态:已发货"
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
列出工具(tools/list):
// 请求
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
// 响应:Server 声明自己提供哪些工具
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "query_order",
"description": "根据订单号查询订单详情",
"inputSchema": {
"type": "object",
"properties": {
"orderId": { "type": "string", "description": "订单号" }
},
"required": ["orderId"]
}
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3.3 传输层(Transport)
MCP 支持两种传输方式:
| 传输方式 | 通信方式 | 适用场景 | 特点 |
|---|---|---|---|
| stdio | 标准输入/输出 | 本地 Server(与 Host 同一台机器) | Host 启动子进程,通过 stdin/stdout 通信,最常用 |
| Streamable HTTP | HTTP + SSE | 远程 Server(跨网络) | Server 部署在远端,Host 通过 HTTP 调用,支持长连接推送 |
早期版本使用 SSE(Server-Sent Events)传输,2025 年规范升级为 Streamable HTTP,兼容性更好。本地开发优先选 stdio,简单且无需端口管理。
# 四、配置和使用 MCP Server
以 Claude Code / CodeFree-O 为例,配置 MCP Server 只需编辑配置文件。
# 4.1 配置文件位置
| 范围 | 文件路径 | 作用域 |
|---|---|---|
| 项目级 | .mcp.json(项目根目录) | 仅当前项目生效,可提交到 Git 共享给团队 |
| 用户级 | ~/.claude.json 或 ~/.codefree-o/config.json | 当前用户所有项目生效 |
# 4.2 配置示例
配置一个本地文件系统 Server(stdio 传输):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/yourname/projects"
]
}
}
}
2
3
4
5
6
7
8
9
10
11
12
command:启动 Server 的命令,这里是npx。args:传给命令的参数,这里用@modelcontextprotocol/server-filesystem这个官方包,并指定可访问的目录为/Users/yourname/projects。
配置一个远程 Server(HTTP 传输):
{
"mcpServers": {
"company-api": {
"url": "https://mcp.company.com/api",
"headers": {
"Authorization": "Bearer your-token-here"
}
}
}
}
2
3
4
5
6
7
8
9
10
同时配置多个 Server:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
},
"mysql": {
"command": "npx",
"args": ["-y", "@benborla29/mcp-server-mysql"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "your-password",
"MYSQL_DATABASE": "mydb"
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
env字段用于给 Server 进程注入环境变量,常用于传递 API Token、数据库连接信息等。注意不要把密钥提交到公开仓库。
# 4.3 验证配置
配置完成后,在 Claude Code 中输入:
/mcp
会列出所有已连接的 Server 及其状态、提供的工具数量。看到 ✓ connected 即表示连接成功。
# 五、常用 MCP Server
社区和官方已经提供了大量开箱即用的 Server:
| Server | 能力 | 安装包 |
|---|---|---|
| filesystem | 读写本地文件、目录列表 | @modelcontextprotocol/server-filesystem |
| github | 搜索仓库、管理 Issue/PR、读取代码 | @modelcontextprotocol/server-github |
| gitlab | GitLab 仓库、MR、Issue 管理 | @modelcontextprotocol/server-gitlab |
| sqlite | 查询本地 SQLite 数据库 | @modelcontextprotocol/server-sqlite |
| postgres | 查询 PostgreSQL 数据库 | @modelcontextprotocol/server-postgres |
| mysql | 查询 MySQL 数据库 | @benborla29/mcp-server-mysql |
| fetch | 抓取网页内容并转为 Markdown | @modelcontextprotocol/server-fetch |
| memory | 跨会话的知识图谱记忆 | @modelcontextprotocol/server-memory |
| puppeteer | 浏览器自动化、截图、爬取 | @modelcontextprotocol/server-puppeteer |
| sequential-thinking | 结构化分步推理 | @modelcontextprotocol/server-sequential-thinking |
完整列表见官方仓库:https://github.com/modelcontextprotocol/servers
# 六、开发一个 MCP Server
当现成 Server 不满足需求时,可以自己开发。以 Python 为例,用官方 SDK 实现一个"查询订单"的 Server。
# 6.1 安装 SDK
pip install mcp
# 6.2 最小示例
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("order-server")
@mcp.tool()
def query_order(order_id: str) -> str:
"""根据订单号查询订单详情
Args:
order_id: 订单号,格式如 ORD-YYYYMMDD-NNN
"""
orders = {
"ORD-20261013-001": "订单金额 ¥299.00,状态:已发货",
"ORD-20261013-002": "订单金额 ¥1280.00,状态:待付款",
}
return orders.get(order_id, f"未找到订单 {order_id}")
@mcp.tool()
def create_order(product_name: str, quantity: int) -> str:
"""创建新订单
Args:
product_name: 商品名称
quantity: 购买数量
"""
order_id = f"ORD-20261013-{quantity:03d}"
return f"订单创建成功,订单号:{order_id},商品:{product_name} × {quantity}"
if __name__ == "__main__":
mcp.run(transport="stdio")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
代码说明:
FastMCP是官方提供的高层封装,用装饰器@mcp.tool()把普通函数注册为 MCP 工具。- 函数的docstring 会自动作为工具描述传给模型,写清楚参数含义很重要。
mcp.run(transport="stdio")以 stdio 模式启动,等待 Host 连接。
# 6.3 配置使用
将开发好的 Server 配置到 Host:
{
"mcpServers": {
"order": {
"command": "python",
"args": ["/path/to/order_server.py"]
}
}
}
2
3
4
5
6
7
8
重启 Host 后,AI 就能调用 query_order 和 create_order 了。
# 6.4 暴露 Resources 和 Prompts
除了 Tools,还可以暴露 Resources(数据)和 Prompts(提示模板):
@mcp.resource("order://list")
def list_orders() -> str:
"""返回所有订单列表(应用可读取的资源)"""
return "ORD-001 已发货\nORD-002 待付款\nORD-003 已完成"
@mcp.prompt()
def review_order(order_id: str) -> str:
"""订单审查提示模板(用户可主动触发)"""
return f"请审查订单 {order_id} 的金额、状态和物流信息,给出风险评估。"
2
3
4
5
6
7
8
9
10
# 七、MCP vs Function Calling
很多人会问:MCP 和 Function Calling 有什么区别?
| 对比维度 | Function Calling | MCP |
|---|---|---|
| 本质 | 模型厂商的私有 API 能力 | 开放的标准协议 |
| 标准化 | 各家格式不同(OpenAI、Anthropic 各写各的) | 统一的 JSON-RPC 2.0 规范 |
| 复用性 | 一个工具适配要绑定具体模型 | 一次开发,所有支持 MCP 的客户端通用 |
| 运行位置 | 工具逻辑通常在应用内或通过 HTTP 调用 | Server 是独立进程,可本地可远程 |
| 能力范围 | 主要是"调用函数" | Tools + Resources + Prompts 三类能力 |
| 状态管理 | 通常无状态 | Server 可保持状态(如数据库连接池) |
一句话总结:Function Calling 是"模型能调函数"的能力,MCP 是"如何调、调什么、在哪调"的统一标准。MCP 底层仍然可以用 Function Calling 实现,但把集成方式标准化了。
# 八、最佳实践
# 8.1 工具设计
- 描述要精准:
description和 docstring 是模型理解工具的唯一依据,写清楚"做什么"和"参数含义"。 - 粒度要适中:太细(一个 CRUD 拆四个工具)模型容易选错;太粗(一个工具干所有事)模型不好传参。按业务动作划分。
- 参数要明确:用
required标注必填参数,给枚举值用enum,减少模型猜测。
# ❌ 描述模糊,模型不知道何时用
@mcp.tool()
def do_something(data: str) -> str:
"""处理数据"""
...
# ✅ 描述清晰,参数有约束
@mcp.tool()
def refund_order(order_id: str, reason: str) -> str:
"""对指定订单发起退款
Args:
order_id: 要退款的订单号
reason: 退款原因
"""
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 8.2 安全注意事项
| 风险 | 建议 |
|---|---|
| 密钥泄露 | Token、密码用 env 注入,不要硬编码到 Server 代码或配置文件中;.mcp.json 含密钥时加入 .gitignore |
| 越权访问 | filesystem Server 限定可访问目录;数据库 Server 用只读账号;遵循最小权限原则 |
| 注入攻击 | 工具参数要做校验和转义,尤其是拼接 SQL、Shell 命令时 |
| 敏感数据外泄 | Server 返回内容会进入模型上下文,避免返回密码、密钥等敏感字段 |
# 8.3 性能优化
- 本地优先用 stdio:避免 HTTP 的网络开销,进程间通信更快。
- 大数据分页:查询结果可能很大时,工具支持
limit/offset参数,避免一次性塞满上下文。 - 按需暴露工具:一个 Server 不要注册太多工具,模型在几十个工具中选择容易出错,按场景拆分多个 Server。
# 九、总结
| 要点 | 说明 |
|---|---|
| 是什么 | AI 连接外部数据源和工具的开放标准协议,类比"AI 的 USB-C" |
| 架构 | Host → Client → Server,Client 与 Server 1:1 连接 |
| 三大能力 | Tools(模型调用)、Resources(应用提供数据)、Prompts(用户触发模板) |
| 通信 | JSON-RPC 2.0,stdio(本地)或 Streamable HTTP(远程) |
| 价值 | 把 N×M 集成问题变成 N+M,工具一次开发处处可用 |
| 上手 | 配置 .mcp.json 即可使用现成 Server;用 Python/TS SDK 可快速开发自定义 Server |
MCP 正在成为 AI 工具生态的事实标准。掌握 MCP,就能让你的 AI 助手真正"长出手脚",从聊天窗口走向连接真实世界的智能体。