Model Context Protocol(MCP)超全解析:从 JSON-RPC 原理到 SDK 实战,一篇就够!
发布时间:2026/10/2 6:05:21来源:尧图网络
1. 为什么你需要亲手写一个 MCP Server如果你正在做 AI 应用大概率遇到过这个场景模型本身很聪明但它不知道你本地的文件长什么样、查不了你数据库里的订单、也调不动你内部那套工单系统。你想给它接上这些能力于是写了一个又一个 function calling 的适配层每换一个模型厂商就要重写一遍参数格式维护成本高得离谱。Model Context Protocol简称 MCP就是来解决这件事的。它是一套基于 JSON-RPC 2.0 的开放协议把「AI 应用怎么安全、实时地拿到外部数据和工具」这件事标准化了。你可以把它理解成 AI 世界的 USB-C 接口Host比如 Claude Desktop、Cursor、各类 IDE 插件是电脑Server 是你插上去的 U 盘、键盘、显示器只要双方都遵守接口规范插上就能用不需要为每个设备单独写驱动。这篇文章面向的是想自建 MCP Server 的开发者。我会从 JSON-RPC 的通信原理讲起然后带你用官方 SDK 写一个能跑通的 Server给出可复制的配置片段最后完成一次完整的请求-响应验证。看完你就能自己动手让大模型真正「长出手脚」。适合谁看有 Python 或 TypeScript 基础、想给 AI 应用接外部能力的后端/全栈开发者正在做 Agent 产品、被 function calling 适配层折磨的工程师以及想搞清楚 MCP 底层到底怎么通信的技术爱好者。不需要你事先了解 MCP但需要你会用命令行、能看懂 JSON。整篇的节奏是先讲清楚协议分层和 JSON-RPC 报文长什么样再进入 SDK 实战中间穿插配置和排障。技术部分我会尽量给全命令和参数你可以边看边敲。2. MCP 的 JSON-RPC 通信原理与协议分层要自建 Server先得搞明白 MCP 到底在传什么。MCP 的协议栈分成两层数据层和传输层。数据层定义「传什么内容」传输层定义「怎么传」。数据层用的就是 JSON-RPC 2.0。这是一个非常轻量的远程调用协议一条请求报文只有四个关键字段jsonrpc固定为2.0id用来匹配请求和响应method是要调用的方法名params是参数对象。响应报文则带result或error。就这么简单没有复杂的头信息也没有强制的序列化格式要求。MCP 在 JSON-RPC 之上定义了三类核心 Primitive这是你写 Server 时最常打交道的类型作用关键方法Tools可被模型调用的函数tools/list枚举、tools/call执行Resources只读数据源类似文件resources/list、resources/readPrompts可复用的提示词模板prompts/list、prompts/get连接建立后第一件事是握手initialize。客户端发一条initialize请求带上自己支持的协议版本和 capabilitiesServer 回一条响应说明自己的名称、版本和能力。握手完成后客户端会发一条notifications/initialized通知表示准备就绪。这个流程和 TCP 三次握手思路类似目的是让双方在正式干活前先对齐能力边界。握手报文长这样你可以对照着理解字段含义{ jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2025-06-18, capabilities: { elicitation: {} }, clientInfo: { name: csdn-client, version: 1.0.0 } } }传输层有两种选择。stdio 用于本地进程通信Host 直接把你写的 Server 当子进程启动通过标准输入输出收发报文零网络开销适合本地工具类 Server。Streamable HTTP 用于远程 Server支持 SSE 流式回包、Bearer Token 和 OAuth 2.0适合部署在服务器上给多个客户端共用。还有一个容易被忽略但很重要的机制通知Notifications。Server 可以在运行中主动推送状态变化比如工具列表更新了就发一条{ jsonrpc: 2.0, method: notifications/tools/list_changed }Host 收到后会自动重新调用tools/list刷新工具列表不需要重启。这意味着你的 Server 可以动态增删工具模型侧无感知。这个设计在需要热更新能力的场景里非常实用。理解了这两层你就知道写一个 MCP Server 本质上就是实现若干 JSON-RPC 方法选一种传输方式把它们暴露出去。剩下的交给 SDK。3. 用官方 SDK 写一个可复制的 MCP Server原理讲完进入动手环节。官方提供了 Python、TypeScript、Java、Go 等多语言 SDK我这里用 Python 演示因为它的异步写法最直观也最容易和现有后端服务集成。先装依赖。建议用虚拟环境避免污染全局python -m venv mcp-env source mcp-env/bin/activate pip install mcp[cli]装完后新建一个weather_server.py。这个 Server 提供一个查询天气的工具工具本身返回模拟数据重点是让你看清 SDK 的注册和调用链路from mcp.server.fastmcp import FastMCP mcp FastMCP(weather-server) mcp.tool() def weather_current(location: str, units: str metric) - dict: 查询指定城市的当前天气。 Args: location: 城市名称例如 San Francisco units: 单位metric 或 imperial fake_data { San Francisco: {temp: 18, condition: foggy}, Beijing: {temp: 26, condition: clear}, } data fake_data.get(location, {temp: 20, condition: unknown}) if units imperial: data[temp] round(data[temp] * 9 / 5 32) return {location: location, units: units, **data} if __name__ __main__: mcp.run(transportstdio)这里有几个关键点。FastMCP是 SDK 提供的高层封装mcp.tool()装饰器会把函数自动注册成一个 Tool函数的 docstring 会成为工具描述参数类型注解会成为 JSON Schema。模型看到的就是这份 Schema所以 docstring 写清楚很重要它直接影响模型会不会正确调用你的工具。mcp.run(transportstdio)表示用标准输入输出通信。如果你要部署成远程服务改成transportstreamable-http并指定端口即可。接下来是 Host 侧的配置。以 Claude Desktop 为例配置文件路径在 macOS 上是~/Library/Application Support/Claude/claude_desktop_config.jsonWindows 上是%APPDATA%\Claude\claude_desktop_config.json。写入以下内容{ mcpServers: { weather: { command: /absolute/path/to/mcp-env/bin/python, args: [/absolute/path/to/weather_server.py] } } }注意command一定要写虚拟环境里 Python 的绝对路径不要写python否则 Host 启动子进程时找不到你的依赖。这是新手最常踩的坑之一。如果你用的是 Cline 这类支持 MCP 的编辑器插件配置结构类似但字段名可能不同通常是mcpServers下配command和args远程 Server 则配url和headers。Cline 的 MCP 配置里如果要接远程服务需要同时写全三件套Base URL、API Key、Model ID缺一个都会连不上。配置保存后重启 Host你的工具就会出现在工具列表里。整个过程不需要你手写任何 JSON-RPC 报文SDK 全帮你处理了。4. 一次完整的请求-响应验证与结果解读配置写完怎么确认真的跑通了最直接的办法是用官方调试工具 MCP Inspector。它是个可视化界面能列出你的工具、资源、提示词还能一键发请求。启动方式npx modelcontextprotocol/inspector python /absolute/path/to/weather_server.py命令跑起来后终端会打印一个本地地址通常是http://localhost:6274浏览器打开就能看到界面。左侧会显示连接状态中间是工具列表你应该能看到weather_current。点开这个工具填入参数{location: San Francisco, units: imperial}点执行。右侧会返回结果{ location: San Francisco, units: imperial, temp: 64, condition: foggy }看到这个返回说明整条链路通了Inspector 作为 Client 发tools/call你的 Server 执行函数并回包JSON-RPC 的id匹配正确结果解析无误。如果你想看底层报文Inspector 的日志面板会显示原始 JSON-RPC 消息。你会看到类似这样的请求{ jsonrpc: 2.0, id: 2, method: tools/call, params: { name: weather_current, arguments: {location: San Francisco, units: imperial} } }以及对应的响应{ jsonrpc: 2.0, id: 2, result: { content: [ {type: text, text: {\location\: \San Francisco\, ...}} ] } }注意result.content是个数组这是 MCP 的标准返回结构支持文本、图片等多种内容类型。你的函数返回的 dict 会被 SDK 序列化成文本塞进content里。在真实 Host 里验证也很简单。重启 Claude Desktop 后直接问它「旧金山现在天气怎么样」模型会自动发现weather_current工具并调用。如果模型没调用多半是 docstring 描述不够清晰或者工具名和参数名让模型难以理解。实测下来从零到跑通这条链路熟练的话半小时内能搞定。真正花时间的是把工具逻辑写扎实以及处理各种边界情况。5. 常见报错排查401、local proxy failed 与 OAuth跑通过程中你大概率会遇到几个典型报错这里集中说一下。401 Unauthorized。这个通常出现在远程 Server 场景。如果你用 Streamable HTTP 传输并开了鉴权Client 请求头里必须带Authorization: Bearer token。检查你的 Host 配置里有没有正确填 API Key。如果是接第三方模型服务Key 填错、过期、或者复制时带了空格都会报 401。建议把 Key 单独存环境变量配置里用引用而不是硬编码。local proxy failed / connection refused。这个报错说明 Host 启动子进程失败或者连不上你指定的地址。排查顺序第一command路径是不是绝对路径、文件有没有执行权限第二虚拟环境里的依赖是否装全手动跑一遍python weather_server.py看会不会报 ImportError第三如果是远程 Server确认端口没被占用、防火墙没拦。stdio 模式下这个错基本都是路径问题。reading choices 相关报错。这类错误一般不是 MCP 协议本身的问题而是模型服务返回结构不符合预期。常见于你用了非标准接口或者请求参数里model字段填了服务端不认识的 Model ID。检查三件套是否齐全Base URL 指向正确的 API 端点、API Key 有效、Model ID 是服务端支持的型号。三者缺一不可。OAuth 授权失败。远程 MCP Server 如果用 OAuth 2.0Client 需要先走授权码流程拿到 token。报错通常是回调地址不匹配、scope 没申请对、或者 token 过期没刷新。调试阶段可以先用 Bearer Token 绕过 OAuth把链路跑通再上完整授权。工具列表为空。Host 连上了但看不到工具先确认tools/list能不能正常返回。用 Inspector 连一下就知道。如果 Inspector 能看到而 Host 看不到多半是 Host 缓存了旧列表重启一下。如果 Server 是动态注册工具的确认注册逻辑在mcp.run()之前执行完毕。排障的核心思路是分层定位先确认进程能不能起来再确认 JSON-RPC 握手成不成功最后确认具体方法调用有没有问题。Inspector 在这三步里都能帮你看到原始报文比盲猜高效得多。6. 把 MCP 接入你的日常开发流Server 跑通只是起点。真正让它产生价值是把它接进你每天用的工具里。如果你用 Claude Code 做日常编码可以把 MCP Server 配到它的配置里让模型在写代码时能直接查你的内部文档、读数据库 schema、调测试环境接口。配置方式和前面 Claude Desktop 类似找到对应的配置文件在mcpServers下加一段就行。对于需要长期跑 Agent 任务的场景建议把 Server 部署成远程服务用 Streamable HTTP 传输这样多个客户端可以共用也方便做鉴权和限流。部署时记得把 Base URL、API Key、Model ID 这三件套在客户端配全任何一环缺失都会导致连接失败。如果你还没决定用哪套模型服务来驱动这些 MCP 调用可以先去 https://taotoken.net/api 看看接入文档把 API Key 申请好再对照 https://taotoken.net/api-keys 配置。想先验证模型对话效果可以直接在 https://taotoken.net/chat 里试如果是长期编码或 Agent 场景Coding Plan 会更合适地址是 https://taotoken.net/coding-plan。文档里对 MCP 相关的接入方式有说明照着配能少走弯路。写 MCP Server 这件事门槛比想象中低。协议本身不复杂SDK 把脏活都干了你真正要花心思的是工具设计参数怎么定、描述怎么写、错误怎么返回这些才决定模型用起来顺不顺手。先把一个最简单的工具跑通再逐步加功能比一上来就设计大而全的 Server 靠谱得多。
网站建设高端定制企业官网