【AI原生开发实战】4.2 MCP协议深度解析:模型上下文协议
学习目标
- 理解MCP协议的核心定位和解决的问题
- 掌握MCP的架构设计和核心组件
- 理解MCP与Function Calling的区别
- 能够构建简单的MCP服务器和客户端
- 了解MCP的生态系统和发展趋势
一、MCP协议的诞生背景
1.1 AI集成的"N×M"困境
在MCP出现之前,每个AI应用连接每个数据源都需要独立的定制化开发:
AI应用1 ─┬─► 数据源A ├─► 数据源B └─► 数据源C AI应用2 ─┬─► 数据源A(需要重新开发) ├─► 数据源B(需要重新开发) └─► 数据源C(需要重新开发) AI应用3 ─┬─► 数据源A(需要重新开发) ├─► 数据源B(需要重新开发) └─► 数据源C(需要重新开发)这是典型的"N×M"问题:N个AI应用 × M个数据源 = N×M个定制连接器。
1.2 Anthropic的解决方案
2024年11月25日,Anthropic发布了Model Context Protocol(MCP),这是一个开放标准,旨在成为AI应用的"USB接口":
┌──────────────────────────────────────────────────────────────┐ │ MCP:AI的通用连接协议 │ ├──────────────────────────────────────────────────────────────┤ │ │ │ AI应用1 ─┬─► MCP服务器A ─┬─► 数据源A │ │ │ ├─► 数据源B │ │ │ └─► 数据源C │ │ │ │ │ AI应用2 ─┼─► MCP服务器A(无需重新开发!) │ │ │ │ │ AI应用3 ─┴─► MCP服务器A(无需重新开发!) │ │ │ └──────────────────────────────────────────────────────────────┘1.3 MCP的核心价值
| 价值 | 说明 |
|---|---|
| 标准化 | 统一的协议规范,一次实现到处运行 |
| 互操作性 | 任何MCP客户端可连接任何MCP服务器 |
| 简化集成 | 开发者只需关注业务逻辑 |
| 安全可控 | 标准化的权限管理和审计 |
二、MCP协议架构
2.1 核心组件
MCP采用经典的客户端-服务器架构,包含五个核心组件:
┌──────────────────────────────────────────────────────────────┐ │ MCP架构图 │ ├──────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Host │ │ Server │ │ │ │ (AI应用) │◄──────────►│ (数据源) │ │ │ └──────┬──────┘ JSON-RPC └──────┬──────┘ │ │ │ │ │ │ │ ┌─────────────┐ │ │ │ └─►│ Client │ │ │ │ │ (协议实现) │◄─────────┘ │ │ └─────────────┘ │ │ │ │ ┌───────────────────────────────────────────────────────┐ │ │ │ 通信传输层 (Transport) │ │ │ │ stdio (本地) │ SSE (远程) │ Streamable HTTP │ │ │ └───────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────┘2.2 组件详解
Host(主机):
- AI应用本体,如Claude Desktop、Cursor IDE
- 包含一个或多个MCP客户端
- 决定何时需要访问外部上下文
Client(客户端):
- 运行在Host内的协议实现
- 与Server保持1:1连接
- 处理协议协商、消息路由
Server(服务器):
- 提供特定能力的轻量级程序
- 通过标准化的MCP协议暴露工具、资源和提示
- 例子:GitHub服务器、Slack服务器、数据库服务器
2.3 三大原语
MCP定义了三种核心能力抽象:
| 原语 | 控制方 | 说明 | 示例 |
|---|---|---|---|
| Resources | 应用控制 | AI可读取的数据资源 | 文件内容、数据库schema、API文档 |
| Tools | 模型控制 | AI可调用的函数 | 查询数据库、发送消息、创建Issue |
| Prompts | 用户控制 | 预定义的提示模板 | SQL生成助手、代码review模板 |
三、MCP与Function Calling的对比
3.1 功能定位不同
| 维度 | MCP | Function Calling |
|---|---|---|
| 定位 | AI应用与数据源的连接协议 | LLM输出结构化工具调用的能力 |
| 层次 | 系统架构层 | 模型能力层 |
| 范围 | 整个AI应用生态 | 单次模型调用 |
| 标准化 | 跨平台、跨厂商 | 厂商特定 |
3.2 互补关系
MCP内部使用Function Calling:
用户请求 │ ▼ ┌─────────────────────────────────────────┐ │ MCP Host (Claude) │ │ │ │ ┌─────────────────────────────────┐ │ │ │ MCP Client │ │ │ │ │ │ │ │ MCP Server A (数据库) │ │ │ │ └──► Tools (SQL查询) │ │ │ │ └──► Function Calling │ │ │ │ │ │ │ │ MCP Server B (GitHub) │ │ │ │ └──► Tools (API调用) │ │ │ │ └──► Function Calling │ │ │ └─────────────────────────────────┘ │ └─────────────────────────────────────────┘3.3 选择建议
| 场景 | 选择MCP | 选择Function Calling |
|---|---|---|
| 连接外部数据源 | ✅ | ❌ |
| 定义单个工具行为 | ❌ | ✅ |
| 标准化AI应用集成 | ✅ | ❌ |
| 快速添加单个工具 | ❌ | ✅ |
四、MCP协议规范
4.1 通信协议
MCP基于JSON-RPC 2.0构建,支持两种传输方式:
stdio(标准输入输出):
- 适用于本地通信
- 简单、可靠
- Claude Desktop默认使用
SSE(Server-Sent Events):
- 适用于远程通信
- 支持服务器推送
- 企业部署常用
4.2 消息格式
// 请求消息{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"query_database","arguments":{"sql":"SELECT * FROM users LIMIT 10"}}}// 响应消息{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"[{\"id\": 1, \"name\": \"Alice\"}, ...]"}],"isError":false}}4.3 核心能力
初始化握手:
// 客户端请求{"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"roots":{"listChanged":true},"sampling":{}},"clientInfo":{"name":"claude-desktop","version":"1.0"}}}// 服务器响应{"protocolVersion":"2024-11-05","capabilities":{"tools":{"listChanged":true},"resources":{"subscribe":true}},"serverInfo":{"name":"github-mcp-server","version":"1.0"}}五、MCP服务器开发
5.1 Python SDK示例
frommcp.server.fastmcpimportFastMCP# 创建MCP服务器mcp=FastMCP("数据库助手")# 添加工具@mcp.tool()defquery_database(sql:str,limit:int=100)->str:""" 执行SQL查询 参数: sql: SQL查询语句(必须是SELECT) limit: 返回结果上限 返回: JSON格式的查询结果 """# 实际查询逻辑result=db.execute(sql,limit=limit)returnjson.dumps(result,default=str)# 添加资源@mcp.resource("database://schema")defget_schema()->str:"""获取数据库schema"""returnjson.dumps(db.get_schema())# 添加提示模板@mcp.prompt()defsql_generation_helper(table:str,question:str):returnf"""你是一个SQL专家。用户想要从表'{table}'中获取信息。 用户问题:{question}请生成对应的SQL查询语句。"""5.2 TypeScript SDK示例
import{McpServer}from"@modelcontextprotocol/sdk/server";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio";constserver=newMcpServer({name:"filesystem-server",version:"1.0.0"});// 注册工具server.tool("read_file","读取文件内容",{path:{type:"string",description:"文件路径"}},async({path})=>{constcontent=awaitfs.readFile(path,"utf-8");return{content:[{type:"text",text:content}]};});// 启动服务器consttransport=newStdioServerTransport();server.run(transport);六、实战:构建MCP服务器
6.1 项目结构
my-mcp-server/ ├── src/ │ ├── __init__.py │ ├── server.py # MCP服务器主文件 │ ├── tools/ # 工具实现 │ │ ├── __init__.py │ │ ├── search.py │ │ └── database.py │ └── resources/ # 资源实现 │ ├── __init__.py │ └── documents.py ├── pyproject.toml └── README.md6.2 完整示例:Slack MCP服务器
frommcp.server.fastmcpimportFastMCPfromslack_sdkimportWebClientfromslack_sdk.errorsimportSlackApiError mcp=FastMCP("Slack助手")# 初始化Slack客户端slack_client=WebClient(token=os.getenv("SLACK_BOT_TOKEN"))@mcp.tool()defsend_message(channel:str,text:str)->str:""" 发送Slack消息 参数: channel: 频道ID或名称 text: 消息内容 返回: 发送结果 """try:response=slack_client.chat_postMessage(channel=channel,text=text)returnf"消息已发送至{channel},时间戳:{response['ts']}"exceptSlackApiErrorase:returnf"发送失败:{e.response['error']}"@mcp.tool()defsearch_messages(query:str,channel:str=None,limit:int=20)->str:""" 搜索Slack消息 参数: query: 搜索关键词 channel: 可选的频道过滤 limit: 返回结果数量 返回: 匹配的搜索结果 """try:response=slack_client.search_messages(query=query,channel=channel,count=limit)results=response["messages"]["matches"]returnjson.dumps(results,indent=2)exceptSlackApiErrorase:returnf"搜索失败:{e.response['error']}"@mcp.resource("slack://channels")deflist_channels()->str:"""获取所有可见频道"""response=slack_client.conversations_list()channels=[{"id":c["id"],"name":c["name"]}forcinresponse["channels"]]returnjson.dumps(channels)6.3 配置文件
// ~/.claude-desktop/mcp.json{"mcpServers":{"slack":{"command":"python","args":["/path/to/slack-mcp-server/main.py"],"env":{"SLACK_BOT_TOKEN":"xoxb-..."}}}}七、MCP生态系统
7.1 官方服务器
Anthropic提供了多个预构建的MCP服务器:
| 服务器 | 功能 |
|---|---|
| GitHub | 创建Issue、PR,读取代码库 |
| Slack | 发送消息、搜索历史 |
| Google Drive | 读取文档、表格 |
| PostgreSQL | SQL查询 |
| Puppeteer | 网页抓取 |
7.2 社区生态
| 类型 | 资源 |
|---|---|
| 服务器集合 | awesome-mcp-servers |
| AWS集成 | AWS MCP Servers |
| 工具平台 | PulseMCP |
7.3 企业采用
MCP已被多家科技巨头采用:
- OpenAI:2025年3月正式支持MCP
- Google:DeepMind产品集成
- Microsoft:Semantic Kernel支持
- Cloudflare:MCP服务器部署平台
八、安全考虑
8.1 安全威胁
| 威胁 | 描述 | 缓解措施 |
|---|---|---|
| Prompt注入 | 恶意指令通过工具参数注入 | 输入验证,权限控制 |
| 工具链攻击 | 组合工具执行恶意操作 | 最小权限原则 |
| 伪装服务器 | 恶意服务器替换合法服务器 | 签名验证,来源认证 |
8.2 安全最佳实践
# 1. 参数验证@mcp.tool()defexecute_sql(sql:str)->str:# 验证SQL安全性sql_upper=sql.upper().strip()ifnotsql_upper.startswith("SELECT"):raiseValueError("Only SELECT queries are allowed")if"; DROP"insql_upper:raiseValueError("Potential SQL injection detected")# 2. 权限控制@mcp.tool()defdelete_file(path:str,require_confirm:bool=True):ifrequire_confirm:raisePermissionError("Deletion requires explicit confirmation")# 3. 审计日志defaudit_log(tool_name:str,args:dict,user_id:str):logger.info(f"[AUDIT]{user_id}called{tool_name}with{args}")九、总结与展望
核心要点
- MCP解决N×M集成问题:通过标准化协议实现AI应用与数据源的解耦
- 三大原语:Resources(应用控制)、Tools(模型控制)、Prompts(用户控制)
- 开放生态:跨厂商支持,活跃的社区发展
- 安全第一:标准化的权限管理和审计机制
未来发展
- 协议演进:持续的功能扩展和性能优化
- 生态系统:更多官方和社区服务器
- 标准化:有望成为AI集成的行业标准
选型建议
| 场景 | 推荐 |
|---|---|
| 构建AI应用生态 | 使用MCP |
| 连接多种外部数据源 | 使用MCP |
| 定义单个工具行为 | 使用Function Calling |
| 快速原型开发 | 使用Function Calling |
参考文献
- Anthropic. “Introducing the Model Context Protocol”. 2024-11-25.
- Model Context Protocol Specification. https://modelcontextprotocol.io
- MCP Python SDK. https://github.com/modelcontextprotocol/python-sdk
- MCP TypeScript SDK. https://github.com/modelcontextprotocol/typescript-sdk
