做 AI Agent 的人大概都有过这种痛苦:接入一个新工具就要写一套适配代码,换一个模型又要改一遍 function calling 的 schema。工具和模型之间的耦合,让 Agent 开发变成了「胶水工程」。Anthropic 在 2024 年底提出的MCP(Model Context Protocol),就是来解决这个问题的。到 2026 年中,MCP 已经成了事实上的 Agent-Tool 通信标准——OpenAI、Google、各大框架都已支持。如果你还在手写工具适配层,是时候认真看看这个协议了。问题的本质:M×N → M+N
在 MCP 之前,工具集成是典型的 M×N 问题:M 个模型(GPT、Claude、Gemini、开源模型…)每个模型有各自的 function calling 格式,每个工具要为每种模型写适配器。10 个模型 × 50 个工具 = 500 套胶水代码。MCP 的思路很简单:定义一个标准协议,让工具端和模型端各自只对接协议。工具实现一次 MCP Server,所有支持 MCP 的模型都能调用。这就是 M+N 的威力。┌──────────┐ MCP ┌──────────┐│ Claude │◄────────────►│ MCP Server│──► GitHub API│ GPT-4 │◄────────────►│ MCP Server│──► PostgreSQL│ Gemini │◄────────────►│ MCP Server│──► 文件系统└──────────┘ 标准协议 └──────────┘
协议设计:为什么选 JSON-RPC?
MCP 的传输层用了JSON-RPC 2.0,这个选择看起来保守,实际上很聪明:1. 够简单。JSON-RPC 的规范只有几页纸,request/response/notification 三种消息类型,没有 HTTP 那套状态码和方法语义的包袱。- stdio:本地进程通信,Agent 启动 MCP Server 子进程,通过 stdin/stdout 交换 JSON-RPC 消息
- Streamable HTTP(SSE):远程通信,支持服务端推送,适合分布式部署
3. 天然支持流式。LLM 的输出天然是流式的,SSE 传输让工具调用结果也能流式返回,不用等整个响应生成完。// 请求:Agent 调用工具{ ”jsonrpc”: ”2.0”, ”id”: 1, ”method”: ”tools/call”, ”params”: { ”name”: ”query_database”, ”arguments”: { ”sql”: ”SELECT count(*) FROM users WHERE created_at > '2026-07-01'” } }}// 响应:工具返回结果{ ”jsonrpc”: ”2.0”, ”id”: 1, ”result”: { ”content”: [ { ”type”: ”text”, ”text”: ”count: 1,247” } ] }}
核心概念:三个原语
MCP 协议定义了三个核心原语,覆盖了 Agent 与工具交互的全部场景:1. Tools(工具)
最常用的原语。Agent 可以发现和调用工具,每个工具有名称、描述和 JSON Schema 定义的参数。# Python MCP Server 示例from mcp.server import Serverfrom mcp.types import Tool, TextContentserver = Server("my-tools")@server.list_tools()async def list_tools(): return [ Tool( name="search_docs", description="搜索内部文档库", inputSchema={ "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词"}, "limit": {"type": "integer", "default": 10} }, "required": ["query"] } ) ]@server.call_tool()async def call_tool(name: str, arguments: dict): if name == "search_docs": results = await do_search(arguments["query"], arguments.get("limit", 10)) return [TextContent(type="text", text=json.dumps(results, ensure_ascii=False))]
2. Resources(资源)
让 Agent 能读取结构化数据。和 Tools 的区别是:Resources 是被动暴露的数据,Tools 是主动执行的动作。@server.list_resources()async def list_resources(): return [ Resource( uri="config://app/settings", name="应用配置", description="当前应用的配置信息", mimeType="application/json" ) ]@server.read_resource()async def read_resource(uri: str): if uri == "config://app/settings": return json.dumps(get_current_config())
3. Prompts(提示模板)
预定义的 prompt 模板,让 Agent 可以选择合适的模板来处理特定任务。这个原语用得相对少,但在复杂工作流中很有价值。工程落地的关键决策
stdio vs HTTP:怎么选?
我的建议:开发阶段用 stdio 快速迭代,上线切 HTTP。很多人一上来就搞 HTTP 部署,结果调试成本翻倍。stdio 的最大优势是——Agent 进程崩了,Server 也跟着退出,不会有僵尸服务。认证与安全
MCP 协议本身不定义认证机制,这是有意为之的。HTTP 传输下,你有标准的 OAuth2、API Key 等方案可以用。但要注意:// Java MCP Server - 带审计的工具调用@McpTool(name = "execute_query", description = "执行只读SQL查询")public ToolResult executeQuery(@Param("sql") String sql) { // 1. SQL 注入防护:只允许 SELECT if (!sql.trim().toUpperCase().startsWith("SELECT")) { return ToolResult.error("只允许 SELECT 查询"); } // 2. 审计日志 auditLog.info("Query executed by agent: {}", maskSensitive(sql)); // 3. 执行(带超时) var result = jdbcTemplate.queryForList(sql); return ToolResult.text(objectMapper.writeValueAsString(result));}
性能:别让工具调用拖垮 Agent
工具调用是 Agent 链路中最慢的环节。一个典型场景:Agent 思考 2 秒 → 调工具 3 秒 → 再思考 2 秒 → 再调工具 3 秒。10 秒过去了,用户还在等。# Agent 端并行调用示例import asyncioasync def gather_context(query: str): # 同时调用三个工具,不互相依赖 docs, db_results, web_results = await asyncio.gather( mcp_client.call_tool("search_docs", {"query": query}), mcp_client.call_tool("query_db", {"sql": f"SELECT * FROM knowledge WHERE match('{query}')"}), mcp_client.call_tool("web_search", {"query": query, "limit": 5}) ) return merge_results(docs, db_results, web_results)
实战:用 Java 构建 MCP Server
Spring AI 已经内置了 MCP Server 支持,接入成本很低:@Configurationpublic class McpServerConfig { @Bean public McpServer mcpServer(List<McpToolHandler> tools) { return McpServer.builder() .transport(new StdioTransport()) // 或 new HttpTransport(8080) .tools(tools) .build(); }}@Componentpublic class DatabaseTool implements McpToolHandler { @Override public String name() { return "query_database"; } @Override public String description() { return "执行只读SQL查询,返回JSON格式结果。仅支持SELECT语句。"; } @Override public JsonSchema inputSchema() { return JsonSchema.of( Property.string("sql", "SQL查询语句"), Property.integer("limit", "最大返回行数", 100) ); } @Override public McpToolResult execute(JsonNodearguments) { String sql = arguments.get("sql").asText(); int limit = arguments.has("limit") ? arguments.get("limit").asInt() : 100; // 安全校验 + 执行 + 返回 var results = safeExecute(sql, limit); return McpToolResult.text(JsonUtils.toJson(results)); }}
MCP 不是银弹,但它解决了 Agent 生态最痛的问题——工具碎片化。- 你需要在不同环境(本地开发、线上部署)之间切换工具
- 只调一两个简单 API,直接 function calling 就够了
2026年了,MCP的生态已经成熟。Spring AI、LangChain、LlamaIndex 都有一流支持。如果你在做 AI Agent 方向的技术决策,我的建议是:现在就用 MCP 作为工具层标准。不是因为它完美,而是因为它已经是共识,你没必要再造一个轮子。
工具集成的终极形态是「无感」——你写一次工具,所有 Agent 都能用。MCP 在朝这个方向走,而且走得比谁都快。