MCP协议详解:AI Agent的标准化工具调用接口
·
原创技术解读 | 深入理解Model Context Protocol
摘要Model Context Protocol(MCP)是Anthropic于2024年底推出的开放协议,旨在为AI模型与外部工具、数据源之间建立标准化的通信接口。本文深入解析MCP的架构设计、核心组件以及在实际项目中的应用实践。## 一、为什么需要MCP?### 1.1 工具调用的碎片化问题在AI应用开发的实践中,一个普遍存在的痛点是工具调用的碎片化。每个模型提供商、每个框架都有自己的工具调用方式:- OpenAI的Function Calling- LangChain的Tools接口- LlamaIndex的Query Engine- 各类自定义的API封装这种碎片化导致了严重的生态割裂:为GPT-4开发的工具无法直接在Claude上使用,基于LangChain的代码难以迁移到LlamaIndex。### 1.2 MCP的解决方案MCP的出现正是为了解决这一问题。它定义了一套统一的协议规范,让AI模型可以像"USB接口"一样,即插即用地连接各种工具和数据源。MCP的核心价值:┌─────────────────────────────────────────┐│ 统一接口层(MCP) │├─────────────────────────────────────────┤│ Claude │ GPT-4 │ Llama │ 其他模型 │├─────────────────────────────────────────┤│ 代码搜索 │ 数据库 │ API │ 文件系统 ││ 浏览器 │ 计算器 │ 天气 │ 邮件服务 │└─────────────────────────────────────────┘## 二、MCP核心架构解析### 2.1 协议层次结构MCP采用客户端-服务器架构,主要包含三个层次:┌─────────────────────────────────────┐│ MCP Host ││ (Claude Desktop, IDE, etc.) │├─────────────────────────────────────┤│ MCP Client ││ (Protocol implementation) │├─────────────────────────────────────┤│ MCP Server ││ (Tool/Data source provider) │└─────────────────────────────────────┘### 2.2 核心组件#### 2.2.1 Resources(资源)资源代表服务器可以向客户端提供的只读数据,类似于REST API中的GET端点:json{ "uri": "file:///project/README.md", "mimeType": "text/markdown", "name": "项目说明文档", "description": "项目的README文件", "metadata": { "lastModified": "2024-12-01T10:00:00Z", "size": 2048 }}#### 2.2.2 Tools(工具)工具是可执行的操作,模型可以调用它们来完成特定任务:json{ "name": "search_code", "description": "在代码库中搜索特定内容", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "搜索关键词" }, "path": { "type": "string", "description": "搜索路径" }, "fileType": { "type": "string", "enum": ["py", "js", "ts", "java"], "description": "文件类型过滤" } }, "required": ["query"] }}#### 2.2.3 Prompts(提示模板)预定义的提示模板,帮助模型更好地使用特定功能:json{ "name": "code_review", "description": "代码审查提示模板", "arguments": [ { "name": "code", "description": "需要审查的代码", "required": true }, { "name": "language", "description": "编程语言", "required": false } ]}## 三、MCP Server开发实战### 3.1 基础Server实现下面是一个完整的MCP Server示例,展示如何实现一个代码搜索工具:python# server.pyfrom mcp.server import Serverfrom mcp.types import Resource, Tool, TextContentimport subprocessimport json# 初始化MCP服务器app = Server("code-search-server")@app.list_resources()async def list_resources() -> list[Resource]: """列出可用资源""" return [ Resource( uri="docs://usage", name="使用文档", description="代码搜索工具的使用说明", mimeType="text/markdown" ) ]@app.read_resource()async def read_resource(uri: str) -> str: """读取资源内容""" if uri == "docs://usage": return """ # 代码搜索工具使用说明 该工具支持在项目中搜索代码内容。 ## 使用方法 1. 提供搜索关键词 2. 可选指定搜索路径 3. 获取匹配结果 ## 示例 json { “query”: “def main”, “path”: “./src”, “fileType”: “py” } """ raise ValueError(f"未知资源: {uri}")@app.list_tools()async def list_tools() -> list[Tool]: """列出可用工具""" return [ Tool( name="search_code", description="使用ripgrep搜索代码", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "搜索关键词" }, "path": { "type": "string", "description": "搜索路径,默认为当前目录", "default": "." }, "fileType": { "type": "string", "description": "文件类型过滤,如py,js等", "default": "*" } }, "required": ["query"] } ) ]@app.call_tool()async def call_tool(name: str, arguments: dict) -> list[TextContent]: """执行工具调用""" if name == "search_code": query = arguments["query"] path = arguments.get("path", ".") file_type = arguments.get("fileType", "*") # 构建ripgrep命令 cmd = ["rg", "-n", "--color", "never", query] if file_type != "*": cmd.extend(["-t", file_type]) try: result = subprocess.run( cmd, cwd=path, capture_output=True, text=True, timeout=30 ) # 格式化结果 lines = result.stdout.strip().split("\n")[:20] # 限制结果数量 formatted_results = [] for line in lines: if ":" in line: file_path, line_num, content = line.split(":", 2) formatted_results.append({ "file": file_path, "line": int(line_num), "content": content.strip() }) return [ TextContent( type="text", text=json.dumps(formatted_results, ensure_ascii=False, indent=2) ) ] except subprocess.TimeoutExpired: return [TextContent(type="text", text="搜索超时")] except Exception as e: return [TextContent(type="text", text=f"搜索出错: {str(e)}")] raise ValueError(f"未知工具: {name}")if __name__ == "__main__": app.run()### 3.2 数据库查询Server示例python# db_server.pyfrom mcp.server import Serverfrom mcp.types import Resource, Tool, TextContentimport sqlite3import jsonapp = Server("database-server")class DatabaseManager: def __init__(self, db_path: str): self.db_path = db_path def get_schema(self) -> str: """获取数据库Schema""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # 获取所有表 cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") tables = cursor.fetchall() schema = [] for (table_name,) in tables: cursor.execute(f"PRAGMA table_info({table_name})") columns = cursor.fetchall() schema.append({ "table": table_name, "columns": [{"name": col[1], "type": col[2]} for col in columns] }) conn.close() return json.dumps(schema, indent=2) def execute_query(self, query: str) -> list: """执行SQL查询""" conn = sqlite3.connect(self.db_path) conn.row_factory = sqlite3.Row cursor = conn.cursor() try: cursor.execute(query) rows = cursor.fetchall() result = [dict(row) for row in rows] conn.close() return result except Exception as e: conn.close() raise edb_manager = DatabaseManager("./data.db")@app.list_resources()async def list_resources() -> list[Resource]: return [ Resource( uri="db://schema", name="数据库Schema", description="数据库表结构信息", mimeType="application/json" ) ]@app.read_resource()async def read_resource(uri: str) -> str: if uri == "db://schema": return db_manager.get_schema() raise ValueError(f"未知资源: {uri}")@app.list_tools()async def list_tools() -> list[Tool]: return [ Tool( name="query_database", description="执行SQL查询(仅支持SELECT)", inputSchema={ "type": "object", "properties": { "sql": { "type": "string", "description": "SQL查询语句" } }, "required": ["sql"] } ) ]@app.call_tool()async def call_tool(name: str, arguments: dict) -> list[TextContent]: if name == "query_database": sql = arguments["sql"] # 安全检查:只允许SELECT if not sql.strip().lower().startswith("select"): return [TextContent(type="text", text="仅支持SELECT查询")] try: results = db_manager.execute_query(sql) return [ TextContent( type="text", text=json.dumps(results, ensure_ascii=False, indent=2) ) ] except Exception as e: return [TextContent(type="text", text=f"查询失败: {str(e)}")] raise ValueError(f"未知工具: {name}")## 四、MCP Client使用### 4.1 Python Client示例python# client.pyfrom mcp.client import Clientimport asyncioasync def main(): # 连接到MCP Server client = Client() await client.connect("./server.py") # 列出可用资源 resources = await client.list_resources() print("可用资源:") for r in resources: print(f" - {r.name}: {r.uri}") # 读取资源 schema = await client.read_resource("db://schema") print(f"\n数据库Schema:\n{schema}") # 列出可用工具 tools = await client.list_tools() print("\n可用工具:") for t in tools: print(f" - {t.name}: {t.description}") # 调用工具 result = await client.call_tool( "search_code", {"query": "def main", "path": "./src"} ) print(f"\n搜索结果:\n{result}")if __name__ == "__main__": asyncio.run(main())## 五、MCP生态与工具### 5.1 官方工具| 工具 | 功能 | 链接 ||------|------|------|| Claude Desktop | MCP Host | anthropic.com || MCP Inspector | Server调试工具 | github.com/modelcontextprotocol/inspector || MCP SDK | Python/TypeScript SDK | github.com/modelcontextprotocol/python-sdk |### 5.2 社区Server- 文件系统:文件读写、目录遍历- 浏览器:网页抓取、内容提取- Git:代码仓库操作- Slack:消息发送、频道管理- PostgreSQL:数据库查询## 六、最佳实践### 6.1 Server设计原则1. 单一职责:每个Server专注于一类工具或数据源2. 清晰描述:工具和资源描述要准确、详细3. 错误处理:提供友好的错误信息4. 安全性:验证输入,防止注入攻击5. 性能优化:避免长时间阻塞操作### 6.2 安全性考虑python# 输入验证示例@app.call_tool()async def call_tool(name: str, arguments: dict) -> list[TextContent]: if name == "execute_command": command = arguments.get("command", "") # 危险命令过滤 dangerous_commands = ["rm -rf", "format", "del /f"] for dangerous in dangerous_commands: if dangerous in command.lower(): return [TextContent( type="text", text=f"命令包含危险操作,已阻止执行" )] # 执行命令...## 七、总结MCP协议为AI Agent与外部工具的交互提供了标准化方案,有望解决当前工具生态碎片化的痛点。对于开发者而言,掌握MCP Server的开发和集成,将成为构建强大AI应用的重要技能。随着生态的发展,我们可以期待更多标准化的MCP Server出现,让AI Agent真正具备"即插即用"的工具使用能力。—参考资源:- MCP官方文档:modelcontextprotocol.io- MCP规范:github.com/modelcontextprotocol/specification- Awesome MCP Servers:github.com/modelcontextprotocol/servers标签:#MCP #AIAgent #工具调用 #协议标准 #Anthropic
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)