深度解析 MCP:为什么一串 JSON 就能让 Agent 接入外部世界?

发布时间:2026/7/15 21:33:28
深度解析 MCP:为什么一串 JSON 就能让 Agent 接入外部世界? 在 AI Agent 快速普及的今天MCPModel Context Protocol模型上下文协议正在成为大模型连接本地工具、云端服务、数据库、文件系统和企业 API 的重要标准。很多人第一次使用 MCP 时都会被它的轻量感震住在 Cursor、Qoder、CherryStudio 或其他 Agent Host 里只要粘贴一段不到10行的JSON代码手动方式更方便的是通过token一键同步但底层都是JSONAgent 似乎立刻就学会了查天气、调浏览器、连数据库、调 API它到底是怎么工作的本文将以一个查询城市天气的例子为主线拆解 MCP 从配置加载、服务启动、能力发现、工具调用到结果返回的完整链路并解释为什么一串 JSON 就能成为 Agent 连接外部世界的钥匙。一、重新认识 MCP JSON不是代码而是连接契约有些人会把 MCP 配置理解成一种插件导入语句Agent 读取 JSON 后就会自动 import 某个 Python 包或 JavaScript 模块然后把里面的函数注册进大模型这个理解并不准确。MCP 配置更像一张“连接说明书”。它告诉 Agent Host如果你想接入某个能力应该执行什么命令传什么参数连接哪个远程地址。至于这个 MCP Server 到底提供哪些工具、每个工具需要什么参数、返回什么结果MCP配置JSON通常不涉及而是由 Server 在启动后通过 MCP 协议动态声明。用一句话概括你粘贴的MCP配置文件是一把钥匙它打开的是 Agent 和外部工具之间的标准化通道。下面我们以具体的案例来进行说明。二、核心机制拆解Agent 如何通过 MCP 学会新能力假设我们有一个 MCP 服务叫mcp-server-weather。它的作用很简单根据城市名称查询实时天气。我们给 Agent Host 导入的MCP配置长这样{mcpServers:{weather-helper:{command:uvx,args:[mcp-server-weather,--api-key,YOUR_WEATHER_API_KEY]}}}当用户添加这个MCP服务时后台经历了两个大的阶段连接阶段让 Agent 知道有哪些工具可用和调用阶段实际执行工具并返回结果。其中连接阶段又细分为三个步骤下面逐一拆解。2.1 连接阶段让 Agent 知道有哪些工具2.11 第一阶段启动 MCP Server建立传输通道Agent Host 首先解析 MCP配置JSON发现这里配置了一个名为weather-helper的 MCP Server。它需要执行的命令是uvx参数是mcp-server-weather --api-key YOUR_WEATHER_API_KEY。连起来就是uvx mcp-server-weather --api-key YOUR_WEATHER_API_KEYClaude Code通过命令行添加mcp也是这样执行的Claude mcp add weather-helper uvx mcp-server-weather --api-key YOUR_WEATHER_API_KEY于是Agent Host 会调用操作系统的子进程机制在后台启动这个服务。用伪代码表示大致类似这样processsubprocess.Popen([uvx,mcp-server-weather,--api-key,YOUR_WEATHER_API_KEY],stdinsubprocess.PIPE,stdoutsubprocess.PIPE)这里有一个关键点对 Agent Host 来说mcp-server-weather并不是内置模块它只是一个可以被操作系统启动的外部进程。Agent Host 不需要理解天气 API也不需要知道这个包内部怎么实现。它只负责把这个进程拉起来并和它建立通信。在本地 stdio 通信模式下Agent 和 MCP Server 之间通常通过标准输入输出通信。你可以把它理解成一根“传声筒”Agent 往 Server 的 stdin 写入 JSON-RPC 消息Server 再从 stdout 写回 JSON-RPC 响应。它们不一定需要开放网络端口也不一定要走 HTTP本地进程之间就能完成协议交互。2.12 第二阶段握手与能力发现MCP Server 启动后Agent Host 并不知道它能做什么。此时双方先进行一次标准的初始化握手initialize handshake确认彼此的身份和能力Agent 发送initialize请求声明自己支持的 MCP 协议版本如2024-11-05和客户端能力如是否支持 sampling、roots 等特性。Server 收到后返回自身的协议版本、服务端能力集以及服务名称和版本号。双方确认后连接状态标记为initialized。这一步可以理解为 Agent 和 Server 在正式合作前先对一下暗号——确认都说同一种语言、都遵守同一套规则。握手完成后Agent 才正式开始探索 Server 提供了哪些工具。它会发送tools/list请求Agent 问 MCP Server“你都提供哪些工具每个工具怎么用”MCP Server 返回自己的能力声明。例如天气服务可能返回如下结构{jsonrpc:2.0,id:2,result:{tools:[{name:get_weather,description:获取指定城市的实时天气,inputSchema:{type:object,properties:{city:{type:string,description:城市名称例如 Beijing}},required:[city]}}]}}这才是 MCP 的“魔法时刻”。Agent 并不是从配置 JSON 里知道get_weather的存在而是在运行时通过tools/list动态发现了这个工具。通常MCP不只返回一个工具而是多个工具。这份工具声明里至少包含三类信息工具名称例如get_weather工具描述例如“获取指定城市的实时天气”输入参数的 JSON Schema例如必须传入一个字符串类型的city。这些信息共同构成了 Agent 可理解的工具契约。2.13 第三阶段Schema 注入让大模型知道自己有了工具发现工具后MCP SDK 或 Agent Host 会完成一个关键动作把 MCP Server 返回的工具 Schema转换成 LLM 原生支持的 Tool Use / Function Calling 格式然后注入到后续对话上下文中。为什么需要这一步转换因为 LLM 并不理解 MCP 协议——它只认识自己的 Function Calling 接口规范。MCP SDK 在这里扮演了翻译官的角色// ← MCP tools/list 原始响应JSON-RPC 格式{jsonrpc:2.0,id:2,result:{tools:[{name:get_weather,description:获取指定城市的实时天气,inputSchema:{type:object,properties:{city:{type:string,description:城市名称}},required:[city]}}]}}// → 转换后注入 LLM 的 Function Calling 格式{type:function,function:{name:get_weather,description:获取指定城市的实时天气,parameters:{type:object,properties:{city:{type:string,description:城市名称}},required:[city]}}}可以看到inputSchema被映射为parameters其余结构一一对应。MCP 的价值正在于此——不管后端接的是天气 API、数据库还是文件系统只要 Server 返回标准 SchemaSDK 就能自动完成格式转换LLM 看到的始终是统一的 Function Calling 接口。这一步很重要因为真正做决策的是 LLM。LLM 本身不会直接读操作系统管道也不会自己启动子进程。它看到的是 Agent Host 提供给它的上下文当前有哪些工具、工具名称是什么、每个工具适合什么场景、调用时应该传哪些参数。至此连接阶段完成MCP 服务已就绪等待用户触发调用。2.2 调用阶段实际执行工具并返回结果第四阶段工具调用闭环意图变成真实执行当用户问“北京今天天气怎么样”时大模型会判断这是一个实时信息问题单靠模型参数无法回答当前上下文里有一个get_weather工具这个工具需要city参数用户提到的城市是“北京”对应参数可以是Beijing或北京。当 LLM 决定调用工具后Agent Host 会把这个意图封装成 MCP 的 JSON-RPC 请求发送给 MCP Server。例如{jsonrpc:2.0,id:3,method:tools/call,params:{name:get_weather,arguments:{city:Beijing}}}随后真正的执行发生在mcp-server-weather这个进程里。它会解析参数拿到city Beijing然后调用真实的天气 API例如 OpenWeather、和风天气或企业内部气象服务。拿到结果后MCP Server 再把结构化结果写回通信通道。Agent Host 接收到结果后会把结果交回给 LLM。LLM 再根据工具返回内容组织自然语言回答例如“北京今天晴气温约 25℃适合外出但早晚温差较大。”到这里一个完整闭环就完成了用户提出需求LLM 判断是否需要工具Agent Host 按协议发起调用MCP Server 执行真实业务逻辑结果返回给 LLM最终以自然语言呈现给用户。总体流程如下MCP Server独立子进程传输层MCP ProtocolAI 推理层MCP HostClaude / Cursor【mcp-server-weather】【MCP Server SDK】【JSON-RPC 2.0 / Stdio】【大脑LLM】【MCP Client SDK】【Agent Host】【mcp-server-weather】【MCP Server SDK】【JSON-RPC 2.0 / Stdio】【大脑LLM】【MCP Client SDK】【Agent Host】第一阶段启动与建立通道读取 mcp_config.json通过子进程拉起 Server subprocess.Popen([uvx, mcp-server-weather, ...])第二阶段握手与能力发现第三阶段Schema 注入与模型决策LLM 判断需要调用工具 get_weather(cityBeijing)第四阶段工具调用闭环与执行调用外部天气 API\n获取北京实时天气数据【用户】发送发现请求tools/list1传输 JSON-RPC 请求2返回能力声明含 get_weather Schema3传输 JSON-RPC 响应4注册 get_weather 工具契约5提问帮我看看北京今天天气怎么样6注入上下文用户问题 get_weather Schema7返回工具调用意图Tool Use8发起工具调用9封装请求tools/call(nameget_weather, cityBeijing)10传输 JSON-RPC 请求11解析参数并执行真实业务逻辑12返回结果temp25℃, conditionSunny13封装 JSON-RPC 响应14传输 JSON-RPC 响应15提取结构化天气结果16回填工具结果北京 25℃ 晴17生成自然语言回答18呈现最终答案北京今天晴约 25℃19【用户】补充调用失败了怎么办以上展示的是成功路径。如果天气 API 超时、鉴权失败或返回异常MCP Server 并不会直接崩溃而是通过 JSON-RPC 的error对象返回结构化错误信息包含错误码和描述。Agent Host 再将错误注入 LLM 上下文LLM 可以据此向用户解释失败原因、建议替代方案、甚至自动重试。这正是协议的价值——不仅定义了正常交互也定义了异常处理的标准路径。三、MCP 的架构精髓三层解耦MCP 之所以能用一串 JSON 撬动庞大的工具生态核心在于它做到了三层解耦。3.1 传输解耦JSON Config 只负责描述如何建立通道可以是 stdio、本地命令、Docker也可以是 HTTP/SSE 远程地址。Agent Host 不需要为每个工具写专门适配器。3.2 能力解耦Agent 并不需要提前知道工具有哪些Server 会在运行时通过tools/list动态声明自己的能力。工具名称、描述、参数 Schema 都由 Server 提供再由 Agent Host 转换成 LLM 可理解的工具上下文。3.3 分发解耦MCP Server 的代码可以通过 PyPI、npm、GitHub、Docker、企业内网或云服务交付。MCP 协议并不绑定某个包仓库也不强迫开发者走统一发布平台。这三层解耦让 Agent 生态从为每个工具写一套硬编码插件转向用统一协议连接任意工具。开发者只要实现 MCP Server声明工具 Schema处理tools/call就可以让不同 Agent Host 以相似方式接入自己的能力。MCP vs 原生 Function Calling差异到底在哪维度MCP原生 Function Calling工具定义Server 运行时动态声明开发者硬编码在代码中新增工具粘贴 JSON 即可改代码 重新部署跨 Host 复用同一 Server多 Host 通用每个 Host 单独写一套工具执行独立子进程隔离运行Host 进程内调用协议标准JSON-RPC 2.0 统一协议各平台私有格式一句话总结Function Calling 是把工具写死在代码里MCP 是把工具变成可插拔的标准化服务。这也是为什么你在 Cursor 里配好的 MCP Server换到 Claude Code 里粘贴同一段 JSON 照样能跑——工具逻辑和 Agent Host 彻底解耦了。四、MCP 服务的四种分发与运行方式理解了前面的流程再回头看“一串 JSON 接入万物”就会发现它并不神秘。JSON 的作用不是承载能力本身而是告诉 Agent Host 如何找到 MCP Server并建立与它的通信通道。至于 MCP Server 的代码从哪里来、运行在哪里、如何分发则有不同形态。4.1 场景一PyPI / npm 分发本地 stdio 运行最常见的配置是这样的{command:uvx,args:[mcp-server-weather]}或者 Node.js 生态中常见的{command:npx,args:[mcp-server-weather]}uvx和npx都是包运行工具。它们的作用是根据包名去 PyPI 或 npm 等包仓库下载代码准备依赖环境然后把对应程序作为本地进程启动。这类方式对使用者很友好因为很多时候不需要手动安装包也不需要关心代码放在哪里。只要本机有对应运行环境Agent Host 执行这条命令就能把 MCP Server 拉起来。但要注意PyPI 或 npm 只是代码分发渠道不是 MCP 协议的注册中心。开发者把 MCP Server 发布到包平台是为了方便别人下载和运行MCP 协议本身并不要求所有服务都注册到某个官方中心。这种模式适合需要访问本地资源的工具例如本地文件系统、本地数据库、浏览器自动化、命令行工具、开发环境操作等。因为 MCP Server 就运行在用户机器上所以它天然更容易接触本地上下文。4.2 场景二GitHub 或本地脚本直接启动开发调试或企业内部工具中也常见这样的配置{command:python,args:[/Users/username/github/my-mcp-weather/server.py]}这种方式完全不需要把代码发布到 PyPI 或 npm。开发者可以把代码放在 GitHub使用者git clone到本地后把脚本路径写进 JSON也可以干脆是一个从未公开的企业内部脚本。Agent Host 不关心这个脚本来自哪里。它只负责执行python /path/to/server.py然后按 MCP 协议和这个进程通信。只要这个脚本实现了 MCP Server 所需的协议响应它就能被 Agent 当作工具服务使用。这种方式适合个人原型、内部系统集成、私有 API 封装和快速调试。它的优点是灵活不需要发布流程缺点是使用者必须自己准备代码、依赖和本地路径。4.3 场景三远程 HTTP/SSE 服务连接云端有些 MCP Server 并不运行在用户电脑上而是部署在云端。这时配置里可能没有command和args而是一个远程地址{mcpServers:{cloud-weather:{url:https://api.example.com/mcp/weather}}}在这种模式下Agent Host 不再启动本地子进程而是通过 HTTP、SSEServer-Sent Events或其他 MCP 支持的远程传输方式连接云端服务。Server 运行在开发者或企业的服务器上Agent 通过网络与它完成初始化、工具发现和工具调用。这种方式对非技术用户更友好因为用户本地不需要 Python、Node.js、Docker 等环境也不用下载代码。它也适合 SaaS 产品和企业共享服务因为服务提供方可以集中维护能力、统一鉴权、统一升级。但它也带来新的要求服务端需要处理认证授权、访问控制、限流、日志、安全审计和可用性。尤其当工具涉及用户隐私数据或企业内部系统时远程模式必须认真设计 OAuth2、API Key、权限隔离和数据边界。4.4 场景四Docker 容器化分发隔离复杂环境还有一种常见方式是通过 Docker 启动 MCP Server{command:docker,args:[run,-i,--rm,my-weather-mcp:latest]}这种方式的本质仍然是本地 stdio 模式只不过 MCP Server 被封装在容器里运行。Agent Host 执行 Docker 命令Docker 拉起容器容器内的进程通过标准输入输出与 Agent Host 通信。Docker 模式适合依赖复杂系统库、需要环境隔离或希望降低本机污染的场景。例如某个 MCP Server 依赖特定版本的浏览器、数据库客户端、图像处理库或系统二进制工具直接要求用户本地安装会很麻烦用容器封装后运行环境就更可控。不过Docker 并不会自动消除安全问题。容器权限、挂载目录、网络访问和密钥传入方式都需要谨慎配置。MCP 提供的是通信标准不是万能安全沙箱。3.5 四类方式的核心差异对比从上面几个场景可以看出MCP 的分发与运行方式并不只有一种。它可以通过 PyPI、npm、GitHub、本地脚本、远程服务或 Docker 镜像交付。这些方式的差异主要体现在三个问题上代码从哪里来Server 在哪里运行以及 Agent 如何建立通信。如果使用uvx或npx代码来自包管理器Server 通常在本地作为子进程运行适合社区工具和本地能力扩展。如果使用本地脚本代码来自用户文件系统适合私有工具和调试。如果使用远程 URL代码运行在云端适合 SaaS 和企业共享服务。如果使用 Docker代码来自镜像仓库运行在容器中适合依赖复杂或需要隔离的工具。但无论哪种方式有一点是不变的MCP 协议本身不负责分发代码也不要求服务注册到某个中心。它只规定 Agent 和 Server 之间如何说话。4.6 MCP 服务目录网站给人看的应用商店既然 MCP 不要求官方注册中心为什么网上还有很多 MCP 服务目录网站比如魔搭MCPmcp.so是目前全球最大的 MCP 服务市场收录超过 2 万个 MCP 服务器、客户端和集成支持按类别浏览和搜索是发现和挑选 MCP 工具的首选一站式目录lobehub通过活跃度、稳定性、社区反馈三个维度对 MCP 服务器进行评分帮你筛选可信赖的服务支持中英文这些网站更像“给人看的应用商店”而不是 Agent 必须访问的注册中心。它们通常承担三类作用帮助开发者展示自己的 MCP Server帮助用户发现可用工具提供一键复制配置或托管部署能力。但 Agent 在运行时并不会自动去这些网站搜索工具。它只认当前 Host 配置里写明的 MCP Server。你粘贴了某段 JSON它就按那段 JSON 去启动进程或连接 URL你没有配置的服务它通常不会凭空知道。这也是 MCP 去中心化设计的一部分。MCP 规范关注的是协议互通而不是把所有工具纳入一个中心化市场。五、安全边界MCP 不是魔法也不是免审计通道MCP 让工具接入变得简单但简单不等于没有风险。6.1 本地 stdio 模式的风险在本地 stdio 模式下MCP Server 运行在用户电脑上理论上可以访问它被授予的本地资源。因此用户在粘贴配置时本质上是在允许 Agent Host 启动某个外部程序。这个程序来自哪里、是否可信、是否会读取敏感文件、是否会把数据发往外部网络都需要审慎判断。6.2 远程 HTTP/SSE 模式的风险在远程 HTTP/SSE 模式下数据会通过网络传给云端 MCP Server。此时更要关注鉴权、隐私、日志留存和权限边界。对于企业场景最好使用最小权限原则明确哪些工具可以访问哪些系统、哪些数据可以被返回给模型、哪些操作需要用户确认。因此MCP 的安全性来自协议设计、Host 权限控制、Server 实现质量和用户授权机制的共同作用而不是只靠“用了 MCP”这件事本身。六、结语一串 JSON 背后的真实含义当你下一次在 Agent 里粘贴一段 MCP 配置时可以把它理解成一张“工具接入说明书”。它没有把代码塞进 Agent也没有让大模型瞬间学会某个 API 的内部实现它只是告诉 Agent去哪里找到一个 MCP Server如何和它建立连接。真正让 Agent 获得能力的是连接建立之后的一系列标准化交互Server 通过tools/list声明工具Agent Host 把工具 Schema 注入 LLM 上下文LLM 根据用户意图选择工具Host 再通过tools/call请求 Server 执行业务逻辑最后把结果交给 LLM 组织成自然语言。这就是 MCP 的关键价值它把 AI 能力扩展从“硬编码集成”变成了“协议化连接”把工具生态从“每个 Agent 各写一套插件”推向“一个 Server 可被多个 Host 理解”。所以一串 JSON 并没有施魔法。它只是打开了一扇门。门后是 MCP 用标准协议搭建起来的外部世界。