ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

彻底搞懂 MCP 协议:Agent 工具调用的统一标准,一文讲清原理、架构与落地

彻底搞懂 MCP 协议:Agent 工具调用的统一标准,一文讲清原理、架构与落地 1. 从 Function Calling 到 MCPAgent 工具调用为什么需要统一标准如果你正在做 Agent 开发大概率已经写过不止一套工具定义。给 OpenAI 写一份 JSON Schema换到 Claude 又要调整字段格式再换到某个国产模型平台参数结构又变了。更麻烦的是你在 LangChain 里注册好的工具换到另一个框架时几乎要重写一遍注册逻辑。这不是你代码写得不好而是整个 Agent 工具调用生态长期缺少一套统一标准。MCPModel Context Protocol就是在这个背景下出现的。它是一套开放的、语言无关的通信协议由 Anthropic 牵头推出核心目标是让 Agent 和外部工具、数据源之间的连接方式标准化。你可以把它理解成 Agent 世界的 USB-C 接口一端是各种工具和数据另一端是各种大模型和 Agent 框架中间靠 MCP 协议打通。工具只要实现一次 MCP 服务端所有支持 MCP 的客户端都能直接调用不需要为每个模型或框架单独适配。这篇文章面向正在做 Agent 工具调用的开发者尤其是被 Function Calling 碎片化折磨过的人。我会从 Function Calling 的局限切入拆解 MCP 的协议原理和架构分层然后给出一份可复制的 MCP 服务端配置骨架包含 config.toml 示例和客户端接入验证动作帮你在本地跑通一次完整的工具调用链路。过程中涉及模型调用和 API 接入的部分我会用 TaoToken 作为统一接入层来演示因为它同时支持模型对话和 Coding Plan适合做 Agent 场景的验证。2. Function Calling 的碎片化到底卡在哪里Function Calling 本身不复杂你定义一组工具把名称、描述、参数 Schema 传给模型模型决定调用哪个工具、传什么参数你执行后把结果返回。问题出在“每个模型和框架都有自己的格式”。我试过在一个项目里同时对接三个模型平台工具定义写了三套。OpenAI 用functions字段Anthropic 用tools字段且参数结构不同某个国产平台又要求把工具描述嵌在 system prompt 里。每次新增一个工具三个地方都要改。更头疼的是这些工具定义和框架强绑定LangChain 的 Tool 对象没法直接给另一个框架用。除了格式不统一还有几个真实痛点。工具无法复用你写的数据库查询工具只能在当前项目用换个 Agent 框架就要重写。上下文割裂工具、资源、知识库分散在不同系统每次接入都要写胶水代码。权限管控粗放工具直接暴露给模型没有统一的权限粒度和审计机制。这些问题的根源是Function Calling 只定义了“模型怎么调用工具”没有定义“工具怎么标准化地暴露给所有客户端”。MCP 补的就是这一层。3. MCP 的架构分层与三大核心能力MCP 的架构非常简洁只有两个核心角色。MCP 客户端Client是 Agent 侧也就是大模型应用、Agent 框架或智能体客户端负责向服务端发起请求获取工具、资源、提示词把结果喂给大模型。MCP 服务端Server是工具和数据侧负责对外暴露自己有哪些工具、哪些资源、哪些提示模板接收调用并返回结果。两端只通过标准协议交互互相不需要知道对方的实现细节。你用 Python 写的 MCP 服务Node.js 写的 Agent 可以直接调你用 Go 写的工具Claude 桌面端可以直接用。MCP 定义了三类标准交互能力覆盖了 Agent 上下文注入的主要场景。工具Tools是可执行的动作对应传统的 Function Calling。服务端对外暴露一组可调用的工具每个工具包含名称、描述、参数 Schema客户端调用后获取执行结果。和传统 Function Calling 的区别在于格式标准化一次编写处处可调用。资源Resources是可读取的数据这是 MCP 的特色能力。服务端对外暴露一组可读取的资源用 URI 标识比如file:///path/to/doc或db://user/123客户端可以按需读取内容并自动注入到大模型上下文中。适合知识库、文件内容、数据库记录等只读数据。提示词模板Prompts是可复用的指令模板。服务端可以对外提供标准化的提示词模板客户端调用模板填入参数即可生成高质量 prompt适合沉淀领域专家提示词和固定工作流指令。这三者加起来覆盖了 Agent 从拿数据到用工具再到按指令执行的全流程并且全部标准化。4. 可复制的 MCP 服务端配置骨架下面给出一份最小可跑的 MCP 服务端配置骨架。我用 Python SDK 来演示因为它的装饰器写法最直观。你不需要自己解析协议SDK 会处理消息序列化和交互流程。先安装依赖pip install mcp然后创建一个server.py实现一个最简单的工具服务from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app Server(demo-server) app.list_tools() async def list_tools(): return [ Tool( nameget_weather, description查询指定城市的天气, inputSchema{ type: object, properties: { city: {type: string, description: 城市名称} }, required: [city] } ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name get_weather: city arguments[city] return [TextContent(typetext, textf{city} 今天晴25 摄氏度)] raise ValueError(f未知工具: {name}) async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: import asyncio asyncio.run(main())这份代码做了三件事能力声明list_tools告诉客户端有哪些工具、请求处理call_tool接收调用并执行逻辑、结果返回按标准格式返回TextContent。剩下的协议解析全部由 SDK 搞定。接下来是客户端侧的配置。以 Claude Desktop 为例配置文件通常叫claude_desktop_config.json但很多团队会用config.toml来统一管理多个 MCP 服务。下面是一份config.toml示例[[mcp_servers]] name demo-server command python args [/path/to/server.py] transport stdio [[mcp_servers]] name remote-tools url https://your-mcp-server.example.com/sse transport sse这份配置定义了两个 MCP 服务端一个本地 STDIO 模式一个远程 SSE 模式。STDIO 模式适合本地桌面端 Agent 和开发工具轻量、无网络开销、启动快。SSE 模式基于 HTTP 协议适合部署在服务器上的远程工具服务。两种模式上层的消息格式完全一致业务代码无需修改只换传输层即可。如果你需要让 Agent 调用大模型来完成工具选择可以在客户端侧接入 TaoToken 的模型对话能力。TaoToken 的 API 地址是https://taotoken.net/api支持标准的模型调用格式。你可以在 Agent 的规划环节用它来做工具选择和参数生成然后把结果传给 MCP 客户端执行。5. 验证请求与成功结果配置写好后需要验证整条链路是否跑通。最直接的方式是用 MCP 官方提供的 Inspector 工具或者手动发一条初始化请求。先启动服务端python server.py然后在另一个终端用 MCP 客户端连接。如果你用的是支持 MCP 的 Agent 框架直接在配置里指向server.py即可。手动验证的话可以用 Python 写一个最小客户端from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params StdioServerParameters(commandpython, args[server.py]) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() print(可用工具:, [t.name for t in tools.tools]) result await session.call_tool(get_weather, {city: 北京}) print(调用结果:, result.content[0].text) if __name__ __main__: import asyncio asyncio.run(main())运行后你应该看到类似输出可用工具: [get_weather] 调用结果: 北京 今天晴25 摄氏度这说明整条链路已经跑通客户端初始化、获取工具列表、调用工具、返回结果。整个过程没有写任何协议解析代码全部由 SDK 处理。如果你在 Agent 里接入 TaoToken 做模型规划可以在工具选择环节调用模型对话接口把 MCP 返回的工具列表作为上下文传给模型让模型决定调用哪个工具。TaoToken 的模型对话入口在https://taotoken.net/api接入文档里有完整的请求示例。对于长期做编码和 Agent 开发的场景Coding Plan 会更划算适合需要频繁调用模型做工具规划的项目。6. 本篇常见错排查第一个常见错误是 STDIO 模式下服务端往 stdout 打印了非协议内容。MCP 的 STDIO 模式用 stdout 传输协议消息如果你在代码里print了调试信息客户端会解析失败。解决办法是把调试信息输出到 stderr或者用日志库写到文件。第二个错误是工具参数 Schema 写错。inputSchema必须是合法的 JSON Schemarequired字段要和properties里的键对应。如果模型传参时缺少必填字段call_tool里会抛 KeyError。建议在工具函数里做参数校验返回明确的错误信息。第三个错误是 SSE 模式下 URL 路径不对。MCP 的 SSE 端点通常需要客户端先发一个 GET 请求建立事件流再通过 POST 发送请求。如果你用的框架要求特定路径检查一下是不是少了/sse后缀。第四个错误是客户端初始化超时。STDIO 模式下如果服务端启动慢客户端可能在初始化阶段就超时。可以在配置里增加超时时间或者先手动启动服务端确认能正常运行。第五个错误是把 MCP 当成框架来用。MCP 只解决工具和资源的标准化接入不解决流程编排、记忆、规划、状态管理。这些还是需要 Agent 框架来做。MCP 和框架是互补关系不是替代关系。7. 接入路径与下一步动作如果你已经跑通了上面的最小示例下一步可以把这个模式复制到真实工具上。比如把数据库查询、文件读取、搜索引擎封装成 MCP 服务端然后在 Agent 里通过 MCP 客户端统一调用。这样你的工具就能跨模型、跨框架复用不用再为每个平台写适配层。对于需要模型规划能力的场景可以在 Agent 侧接入 TaoToken 的模型对话接口把 MCP 返回的工具列表作为上下文传给模型做工具选择。API Keys 的获取和接入文档在https://taotoken.net/api里面有完整的请求格式和参数说明。如果你主要做长期编码和 Agent 开发Coding Plan 的调用方式更适合高频场景可以在控制台里查看具体的套餐和额度。MCP 的价值不在于技术有多高深而在于标准化带来的生态效应。当越来越多的工具以 MCP 形式开放Agent 开发者不需要一个个对接插上就能用。你现在就可以从封装第一个 MCP 服务端开始把手里重复写的工具定义收敛成一套标准实现。
返回列表