乐于分享
好东西不私藏

MCP 深度解析:AI Agent 工具集成的「万能插座」协议

MCP 深度解析:AI Agent 工具集成的「万能插座」协议
做 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、开源模型…)
N 个工具(数据库、API、文件系统、浏览器…)
每个模型有各自的 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 那套状态码和方法语义的包袱。
2. 双向通信。MCP 支持两种传输方式:
  • 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 生态最痛的问题——工具碎片化
值得投入的场景:
  • 你在构建多工具 Agent,且工具数量 > 5
  • 你的工具需要被多个 Agent/模型复用
  • 你需要在不同环境(本地开发、线上部署)之间切换工具
暂时不用急的场景:
  • 只调一两个简单 API,直接 function calling 就够了
  • 纯内部系统,不需要跨模型兼容
2026年了,MCP的生态已经成熟。Spring AI、LangChain、LlamaIndex 都有一流支持。如果你在做 AI Agent 方向的技术决策,我的建议是:现在就用 MCP 作为工具层标准。不是因为它完美,而是因为它已经是共识,你没必要再造一个轮子。

工具集成的终极形态是「无感」——你写一次工具,所有 Agent 都能用。MCP 在朝这个方向走,而且走得比谁都快。