🧠 前置阅读:建议先了解 LLM 工具调用与 Function Calling(LLM Agent 工具调用指南),在此基础上理解 MCP 的演化意义。
1. 为什么要发明 MCP?
2024 年,Anthropic 推出了 Model Context Protocol(MCP)——一个开放的协议标准,目标是让 LLM 应用能够像 USB-C 连接外设一样,即插即用地接入数据、工具和上下文。
1.1 MCP 解决的核心痛点
Function Calling 时代的问题:
├── 每个应用都要单独集成 N 个 API(Slack、Notion、GitHub...)
├── 每个工具的描述格式不同(OpenAI vs Claude vs Gemini)
├── 上下文拼接靠 Prompt 工程,没有标准层级
├── 安全权限细粒度控制靠代码硬编码
└── 工具调用链无法共享、复用、交换
MCP 时代的目标:
├── 一次开发,处处可用(write once, connect anywhere)
├── 统一的协议层,不同 LLM 共享同一套工具
├── 标准的上下文原语:Resources / Prompts / Tools / Sampling
├── 声明式权限与安全边界
└── 工具生态可交换、可组合、可版本控制
2. MCP 四大核心原语
2.1 Resources(资源)
Resources 是只读的数据源,为 LLM 提供上下文。例如文件内容、数据库查询结果、API 响应。
{
"uri": "file:///data/sales_report_2024.pdf",
"mimeType": "application/pdf",
"name": "2024 Annual Sales Report",
"description": "公司年度销售报告",
"size": 2457600
}
与 RAG 的区别:RAG 是隐式的(把知识库切分索引后自动检索),Resources 是显式的(模型明确知道哪些数据源可用,由用户或工具选择性订阅)。
2.2 Prompts(提示模板)
Prompts 是可复用的对话模板,由 MCP Server 提供给客户端。
{
"name": "analyze_csv",
"description": "分析 CSV 文件内容并给出洞察",
"arguments": [
{
"name": "file_path",
"description": "CSV 文件路径",
"required": true
}
],
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "请分析以下 CSV 文件,找出关键趋势:{{file_path}}"
}
}
]
}
2.3 Tools(工具)
Tools 是可执行的操作,与 Function Calling 中的工具概念一致,但标准化了生命周期(注册、发现、调用、返回)。
{
"name": "hello_world",
"description": "向指定用户打招呼",
"inputSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
2.4 Sampling(采样)
Sampling 是让 Server 反向请求 LLM 的能力——当一个 MCP Server 需要模型推理时(如 “请帮我总结一下用户输入”),它可以通过 Sampling 向客户端提交一个 LLM 调用请求。
{
"modelHints": ["claude-3-5-sonnet"],
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "请总结以下内容:..."
}
}
],
"maxTokens": 500
}
3. MCP 协议架构
┌──────────────────────────────────────────┐
│ AI 应用(客户端) │ ← Claude Desktop / Cline / Continue / Cursor
├──────────────────────────────────────────┤
│ MCP Client(协议适配层) │ ← 处理 JSON-RPC 2.0 消息
├──────────────────────────────────────────┤
│ STDIO / SSE │ ← 传输层:本地进程或 HTTP 流
├──────────────────────────────────────────┤
│ MCP Server(服务提供方) │ ← 暴露 Resources / Tools / Prompts
├──────────────────────────────────────────┤
│ FileSystem / DB / API / IDE / 浏览器 │ ← 实际数据源/能力
└──────────────────────────────────────────┘
3.1 传输层
| 方式 | 适用场景 | 特性 |
|---|---|---|
| stdio | 本地 Server | 最简单,Python/Node 脚本直接运行 |
| SSE | 远程 Server | HTTP Server-Sent Events,支持跨网络 |
| WebSocket | 实时双向 | 高交互场景(如 IDE 实时编码) |
3.2 消息协议
MCP 基于 JSON-RPC 2.0:
// 请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
// 响应
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "read_file",
"description": "读取文件内容",
"inputSchema": { ... }
}
]
}
}
4. MCP 与 Function Calling 的对比
| 维度 | Function Calling | MCP |
|---|---|---|
| 标准化程度 | 各平台不同(OpenAI/Claude/Gemini) | 统一协议 |
| 上下文管理 | Prompt 中硬编码 | Resources / Prompts 标准化 |
| 能力发现 | 静态声明,初始化时传入 | 运行时动态发现(list tools) |
| 生命周期 | 单次调用 | 连接 → 初始化 → 调用 → 断开 |
| 组合复用性 | 单一应用内部 | 跨应用共享 Server |
| 安全模型 | 应用级控制 | Server 级权限声明 |
| 适用场景 | 简单单次工具调用 | 复杂、持久、共享的 Agent 环境 |
不是替代关系,是互补:Function Calling 是 LLM 的"能力调用接口",MCP 是这个接口的"标准化协议层"。
5. 一个最小 MCP Server 示例
# 安装:pip install mcp
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
from mcp.server.stdio import stdio_server
import mcp.types as types
import asyncio
server = Server("hello-mcp")
@server.list_resources()
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri="file:///greeting.txt",
name="问候语",
mimeType="text/plain",
description="一个简单的问候资源",
)
]
@server.read_resource()
async def read_resource(uri: str) -> str:
if uri == "file:///greeting.txt":
return "你好!欢迎使用 MCP。"
raise ValueError(f"未知的资源: {uri}")
@server.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="hello_world",
description="向指定用户名打招呼",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "用户名"}
},
"required": ["name"],
},
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "hello_world":
return [types.TextContent(type="text", text=f"你好, {arguments['name']}!")]
raise ValueError(f"未知的工具: {name}")
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="hello-mcp",
server_version="0.1.0",
capabilities=server.get_capabilities(),
),
)
if __name__ == "__main__":
asyncio.run(main())
在 Claude Desktop 中配置:
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"hello-mcp": {
"command": "python",
"args": ["/path/to/hello_mcp.py"]
}
}
}
重启 Claude Desktop 后即可在对话中看到 hello_world 工具。
6. MCP 生态工具概览
| 工具 | 类型 | 说明 |
|---|---|---|
| Claude Desktop | 官方客户端 | 第一个支持 MCP 的完整产品 |
| Cline | VSCode 插件 | 集成 MCP 的 AI 编码助手 |
| Continue | VSCode 插件 | 开源 MCP 客户端 |
| Cursor | IDE | 通过插件支持 MCP |
| filesystem | Server | 文件系统读写 |
| postgres | Server | PostgreSQL 查询 |
| github | Server | GitHub API 对接 |
| slack | Server | Slack 消息发送/读取 |
| brave-search | Server | Brave API 搜索 |
7. 从 Function Calling 迁移到 MCP 的思路
现有 Function Calling 代码
├── 提取工具函数 → MCP Server utils
├── 提取 Schema → MCP Tool definitions
├── 提取上下文 → MCP Resources
├── 替换 API 调用层 → MCP Client SDK
└── 配置文件注册 → claude_desktop_config.json / .cursor/mcp.json
8. 设计要点与安全建议
- 最小权限:每个 MCP Server 只暴露必要的资源和工具
- 请求确认:敏感操作(写文件、发邮件)弹窗让用户确认
- 审计日志:记录每次 MCP 调用的参数和结果
- 超时控制:MCP Server 响应设 30s 超时,防止挂死
FAQ
Q: MCP 能替代直接调用 API 吗?
A: 不能简单说替代。对于频繁复用的工具(文件系统、数据库、GitHub),MCP 极大降低集成成本。对于一次性专用接口,直接调用可能更简单。
Q: MCP 和 LangChain 的 Tool 有什么区别?
A: LangChain Tool 是应用内部的函数封装,MCP 是跨应用的标准协议。LangChain 可以消费 MCP Server(通过 mcp-adapters),两者的关系是互补。
Q: 非 Anthropic 模型能用 MCP 吗?
A: 可以。MCP 是协议标准,与模型无关。OpenAI、Google 的模型同样可以通过 MCP Client 连接 MCP Server。目前生态中大量 Server 已经与 GPT-4o、Gemini 做过兼容性测试。
📂 继续阅读:
- MCP 服务端开发实战 — 从 SQLite RPC 到完整 Server
- MCP 客户端集成指南 — Claude Desktop、Cline、Continue 配置详解
- MCP 工具生态与最佳实践 — 20+ 官方/社区 Server 速查表
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。