一、MCP 是什么?
Model Context Protocol (MCP) 是 Anthropic 推出的开源标准协议,用于连接 AI 应用与外部系统。如果用一个形象的比喻,MCP 就像是 AI 应用的 USB-C 接口——提供了一个标准化的连接方式,让 AI 应用能够与各种数据源、工具和工作流无缝集成。
1.1 为什么需要 MCP?
当前 AI 应用面临的核心挑战:
- 信息孤岛问题:每个数据源都需要单独的集成方案
- 开发复杂度高:为每个 AI 应用构建定制化的数据连接器
- 缺乏标准化:不同厂商的集成方案互不兼容
- 上下文丢失:AI 在不同工具间切换时难以保持上下文连续性
MCP 通过提供统一的协议标准,将这些碎片化的集成方案替换为单一的标准协议,从根本上解决了这些问题。
二、核心架构设计
2.1 架构组件
MCP 采用经典的客户端-服务器架构:
1 2 3 4 5 6 7 8 9 10
| ┌─────────────────┐ │ MCP Host │ ← AI 应用(如 Claude Desktop) │ (协调者) │ └────────┬────────┘ │ ├─── MCP Client 1 ──→ MCP Server A (数据库) │ ├─── MCP Client 2 ──→ MCP Server B (文件系统) │ └─── MCP Client 3 ──→ MCP Server C (API 服务)
|
各组件职责:
- MCP Host:AI 应用本身,负责协调多个 MCP 客户端
- MCP Client:维护与 MCP 服务器的连接,处理协议通信
- MCP Server:提供具体的上下文数据和能力(工具、资源、提示)
2.2 协议设计
MCP 基于 JSON-RPC 2.0 构建,包含两个核心层:
数据层 (Protocol Layer)
- 定义通信协议格式
- 管理连接生命周期
- 处理能力协商机制
传输层 (Transport Layer)
- 管理通信信道
- 支持 stdio(本地进程)和 HTTP with SSE(远程服务器)
三、三大核心原语
3.1 Resources(资源)
类似文件系统的只读数据源,供客户端读取。
1 2 3 4 5 6
| { "uri": "file:///path/to/document.txt", "name": "项目文档", "mimeType": "text/plain", "description": "项目需求文档" }
|
LLM 可调用的可执行函数,实现具体操作。
1 2 3 4 5 6 7 8
| from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
@mcp.tool() async def get_weather(city: str, state: str) -> str: """获取指定城市的天气信息""" return f"{city}, {state} 的天气是晴天,温度 25°C"
|
3.3 Prompts(提示模板)
预编写的任务模板,用于标准化常见操作。
1 2 3 4 5 6 7 8 9 10 11
| { "name": "code_review", "description": "代码审查提示模板", "arguments": [ { "name": "language", "description": "编程语言", "required": true } ] }
|
四、实战:构建 MCP 服务器
4.1 Python 实现(FastMCP)
1 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
| from mcp.server.fastmcp import FastMCP import sqlite3
mcp = FastMCP("database-server")
@mcp.tool() async def query_users(limit: int = 10) -> str: """查询用户列表""" conn = sqlite3.connect('app.db') cursor = conn.cursor() cursor.execute('SELECT * FROM users LIMIT ?', (limit,)) results = cursor.fetchall() conn.close() return str(results)
@mcp.tool() async def create_user(name: str, email: str) -> str: """创建新用户""" conn = sqlite3.connect('app.db') cursor = conn.cursor() cursor.execute( 'INSERT INTO users (name, email) VALUES (?, ?)', (name, email) ) conn.commit() user_id = cursor.lastrowid conn.close() return f"用户创建成功,ID: {user_id}"
if __name__ == "__main__": mcp.run()
|
4.2 TypeScript/Node.js 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server( { name: "file-server", version: "1.0.0" }, { capabilities: { tools: {} } } );
server.setRequestHandler("tools/call", async (request) => { if (request.params.name === "read_file") { const fs = await import("fs/promises"); const content = await fs.readFile(request.params.arguments.path, "utf-8"); return { content: [{ type: "text", text: content }] }; } throw new Error("未知工具"); });
const transport = new StdioServerTransport(); await server.connect(transport);
|
4.3 最佳实践
- 日志处理:stdio 服务器永远不要写入 stdout,使用 stderr 或文件日志
- 错误处理:实现完善的异常处理和错误信息返回
- 类型安全:使用类型提示和输入验证
- 安全控制:实现适当的访问控制和参数验证
五、构建 MCP 客户端
1 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
| from anthropic import Anthropic from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client
class MCPClient: def __init__(self): self.anthropic = Anthropic() self.session = None
async def connect_to_server(self, server_script_path: str): server_params = StdioServerParameters( command="python", args=[server_script_path], ) stdio_transport = await stdio_client(server_params) self.stdio, self.write = stdio_transport self.session = ClientSession(self.stdio, self.write) await self.session.initialize()
async def process_query(self, query: str) -> str: tools = await self.session.list_tools() response = self.anthropic.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=4096, messages=[{"role": "user", "content": query}], tools=[{ "name": tool.name, "description": tool.description, "input_schema": tool.inputSchema } for tool in tools.tools] ) return response.content[0].text
|
六、生态系统
6.1 官方参考服务器
| 服务器 |
功能描述 |
| filesystem |
安全的文件系统操作 |
| git |
Git 仓库读取、搜索和操作 |
| github |
GitHub API 集成 |
| fetch |
Web 内容抓取和转换 |
| memory |
基于知识图谱的持久化记忆 |
6.2 企业级应用
已集成 MCP 的公司:Block、Apollo、Zed、Replit、Codeium、Sourcegraph、Microsoft 等。
6.3 官方 SDK
Python、TypeScript、Kotlin、Java、C#、Ruby
七、MCP vs 传统方案
| 维度 |
传统方式 |
MCP 方式 |
| 开发成本 |
每个数据源需单独实现 |
一次实现,到处复用 |
| 维护难度 |
多套代码分别维护 |
统一协议标准 |
| 扩展性 |
添加新数据源需重写 |
实现 MCP 服务器即可 |
| 互操作性 |
厂商方案互不兼容 |
开放标准,跨平台 |
八、安全与最佳实践
访问控制
1 2 3 4 5
| @mcp.tool() async def read_file(path: str) -> str: if not is_path_allowed(path): raise PermissionError("路径访问被拒绝") return read_file_content(path)
|
参数验证
1 2 3 4 5 6 7 8 9 10
| from pydantic import BaseModel, validator
class QueryParams(BaseModel): limit: int
@validator('limit') def validate_limit(cls, v): if v > 1000: raise ValueError('limit 不能超过 1000') return v
|
性能优化
- 连接池管理
- 缓存策略(lru_cache)
- 并发控制(asyncio.Semaphore)
九、三大 Host 对比
Codex CLI(OpenAI)
- 优势:安全治理彻底,审批流和沙箱最完整
- 劣势:可视化和多窗口体验有限
Claude Code(Anthropic)
- 优势:IDE 深度集成,上下文回放最强
- 劣势:CLI 自动化较弱
Genim CLI
- 优势:自动化友好,易嵌入 CI/CD 流水线
- 劣势:交互式体验偏弱,无图形界面
选型建议:
| 需求 |
推荐 |
| 安全高可信、命令行驱动 |
Codex CLI |
| IDE 即时回馈、开发体验优先 |
Claude Code |
| 上下文拼装纳入自动化流水线 |
Genim CLI |
十、未来展望
- 更丰富的传输层:WebSocket、gRPC、云原生部署
- 智能能力发现:基于语义的工具推荐,自动化能力组合
- 企业级特性:细粒度 RBAC、审计事件流、多租户隔离
- 多代理协作:多个 MCP Host/Server 串联共享上下文
总结
MCP 代表了 AI 应用集成的范式转变:
- ✅ 标准化:统一的协议规范,替代碎片化集成
- ✅ 开放性:开源协议,任何人都可以实现和扩展
- ✅ 可组合性:模块化设计,灵活组合不同能力
- ✅ 跨平台:多语言支持,适应不同技术栈
参考资源