MCP 协议、stdio 与 HTTP 传输及客户端配置实战 简介这是一份围绕模型上下文协议MCP整理而成的PDF总结资料面向AI应用开发者、工具链集成人员以及希望理解MCP互操作机制的读者。内容聚焦MCP如何连接AI与外部工具梳理资源管理、提示模板、工具调用、采样等核心能力并汇总支持MCP的桌面应用、编辑器、IDE与框架如Claude桌面、Cursor、Zed、Cline、Continue、Windsurf等同时给出功能支持矩阵与官方文档入口便于快速判断各客户端的能力边界。压缩包内仅含1个PDF文件大小约1.62MB适合作为案头速查与入门概览。目前已有1017人学习下载说明其在AI工具集成领域关注度较高。通过阅读读者可建立MCP的整体知识框架了解不同应用对资源、提示、工具和采样的支持差异把握远程连接、实时交互与多模态等后续方向为后续选型、集成和开发实践提供参考。1. 从一份 MCP 资料开始先分清哪些是协议哪些是配置翻 MCP 资料的时候最让人卡住的往往不是某个 API 看不懂而是把三个层次揉在了一起协议本身、传输层、客户端配置。「mcp是什么」这个问题一句话回答就是——一套让模型应用去发现并调用外部能力的 JSON-RPC 约定。它不是模型不是插件市场也不是某一家客户端的私有扩展。把这三层拆开之后选型、接入、排错都会顺很多协议决定你能暴露什么能力传输层决定这些能力部署在哪台机器上配置决定客户端怎么连上它。后面几章就按这个顺序走先讲清 host、server 和三种原语再看 stdio 与 mcp http 模式怎么取舍然后落到 Claude、Codex、Cursor 的实际配置文件最后用 Spring Boot 起一个自己的 server把本地数据接进模型。2. MCP 协议到底约定了什么host、client、server 三个角色清点 MCP 资料时很容易看到一长串 server 清单却看不到协议本体。先把结论摆出来MCP 规定的是「能力怎么被发现、怎么被调用、结果怎么回传」基于 JSON-RPC 2.0 传输。协议里没有模型、没有推理、没有编排逻辑这些统统在 host 那一侧。2.1 MCP host 和 MCP server 的职责边界host 是承载模型的宿主应用Claude Desktop、Codex、Cursor、Trae 都算。host 内部会为每一个 server 维护一个 client 实例负责拉起进程或建立连接、转发消息、处理权限确认。server 只做一件事把自己的能力按协议描述出来收到调用后执行并返回结果。这个分工决定了几件容易被忽略的事server 不需要知道模型是谁也不持有会话历史它是无状态的执行体一个 host 可以同时挂多个 server工具重名时由 host 决定怎么消歧server 的生命周期归 host 管stdio 模式下 server 就是 host 的子进程。所以排查问题时先定位层进程压根没起来是 host 配置的问题进程起来了但工具列表是空的问题在 server 的注册或描述。2.2 tools、resources、prompts三种原语各管什么协议把服务端能力分成三类原语边界划得比较清楚。这张表比背方法名有用得多。原语发现方法谁决定调用是否只读典型用途toolstools/list模型自主决定否可能有副作用查数据库、发请求、写文件resourcesresources/list应用或用户选取是设计稿、日志、行情快照promptsprompts/list用户主动选择是固定话术、评审模板除了这三类协议里还有 samplingserver 反向请求 host 调用模型、rootshost 声明 server 能访问哪些目录这类可协商能力。整理资料的时候把 tools 当主线就够了另外两类属于补强。2.3 mcp 怎么被调用的一次 tools/call 的完整链路一次成功的调用至少经过三步initialize 握手、tools/list 发现、tools/call 执行。// 1. 客户端握手声明自身能力与协议版本 {jsonrpc:2.0,id:1,method:initialize, params:{protocolVersion:2025-03-26, capabilities:{roots:{listChanged:true}}, clientInfo:{name:my-host,version:0.1.0}}} // 2. 服务端回报自己支持的能力 {jsonrpc:2.0,id:1, result:{protocolVersion:2025-03-26, capabilities:{tools:{listChanged:true}}, serverInfo:{name:stock-local,version:0.1.0}}} // 3. 调用工具arguments 必须匹配 inputSchema {jsonrpc:2.0,id:7,method:tools/call, params:{name:recent_bars,arguments:{code:600519,days:30}}} // 4. 结果按内容数组返回text 类型最常用 {jsonrpc:2.0,id:7, result:{content:[{type:text,text:...}],isError:false}}字段含义说清楚id用来配对请求与响应同一条连接上可以并发多个请求method是固定的命名空间方法工具调用永远是tools/call具体工具名放在params.name里不要往 method 上拼arguments必须匹配tools/list声明的inputSchema类型对不上会被服务端直接拒绝。握手结束后客户端还要发一条notifications/initialized通知这条没有 id 也不需要应答。自研 server 卡死在这一步的情况特别多症状就是客户端一直转圈不报错。2.4 工具描述写得怎么样直接决定调用成功率tools/list返回的每一项包含name、description、inputSchema模型挑工具全靠这三样。几个反复出现的写法问题description 写成「查询数据」模型没法判断该不该用参数名用a、b这种缩写模型只能猜一个工具塞七八个可选参数互相组合出十几种语义。比较稳的写法是一句话讲清「做什么 什么时候用 关键约束」参数层面在 schema 里再解释一遍。required要写全可选参数给默认值——少填一个字段就报错的工具用起来非常难受。3. 传输层怎么选stdio 与 mcp http 模式的取舍协议定完紧跟着的问题就是这些消息走哪条通道。stdio 和 HTTP 这两种模式没有优劣只有适配场景的差别混用或者选错会带来一堆莫名其妙的故障。3.1 stdio 模式本地起进程最省事也最容易踩坑stdio 模式是 host 把 server 当子进程拉起来消息走子进程的 stdin 和 stdout一条消息一行 JSON。不用端口、不用鉴权、不用处理并发本机工具链首选。手工验证比改配置快得多# 直接拉起来灌两条消息看进程是否正常应答 printf %s\n%s\n \ {jsonrpc:2.0,id:1,method:initialize,params:{protocolVersion:2025-03-26,capabilities:{},clientInfo:{name:probe,version:0.1.0}}} \ {jsonrpc:2.0,method:notifications/initialized} \ | node /abs/path/to/server.js每一行是完整的 JSON-RPC 消息用换行分隔不需要 Content-Length 头。跑完能看到一行 result说明进程是活的什么都没有就去看 stderr。最大的坑是 stdout 被污染。不少 server 启动时会打印一行「server started on port xxx」这行日志会把 JSON 流冲乱客户端解析直接失败。所有日志必须走 stderr这条没有商量余地。第二个坑是运行环境GUI 客户端拉起的子进程不一定继承终端里的 PATHnode、npx、python都建议写绝对路径。3.2 mcp http 模式单端点加流式响应远程部署、多人共用、或者环境不允许起子进程时就得用 HTTP 模式。现在主流的是 Streamable HTTP一个端点同时接受 POST 和 GET客户端 POST 一条 JSON-RPC 消息服务端用text/event-stream把响应推回来并在响应头下发 session id后续请求带着它维持会话。# 调试 mcp http 模式Accept 头必须同时声明两种类型 curl -sS -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d {jsonrpc:2.0,id:2,method:tools/list,params:{}}Content-Type必须是application/json写成别的会被拒Accept只写application/json大概率拿到 406服务端可能返回流必须显式声明接受响应头里出现Mcp-Session-Id时后续请求要带上同名请求头。更早的 HTTPSSE 模式走两个端点一个建长连接收事件一个发消息。配置里同时看到/sse和/messages两个路径基本就是这种老模式接旧客户端时会遇到。3.3 两种模式怎么选维度stdiomcp http 模式启动方式host 拉起子进程独立部署客户端连接会话状态进程即会话靠 session id 维持鉴权靠操作系统用户隔离靠令牌与请求头多客户端共享不支持支持调试手段管道灌 JSONcurl 加日志适合场景本机工具链、本地文件团队共享服务、容器环境判断标准很朴素能力只对当前这台机器有意义本地文件、本地数据库、CAD 工程用 stdio能力要被多人或多环境复用设计稿、内部 API、行情服务用 HTTP。3.4 从 stdio 迁到 HTTP 的过渡做法现成的 stdio server 不想改代码常见做法是外面套一层桥接桥接进程把这些 server 以子进程方式拉起来对外暴露一个 HTTP 端点同时维护 session 与子进程的映射关系。这样能快速把本地能力共享出去代价是多一层进程和一份会话表出问题时要先确认桥接层本身还活着。4. 接进 Claude、Codex、Cursor配置写法与排错顺序协议和传输都清楚之后剩下的就是具体的配置文件。不同客户端读的文件不同、字段名不同把这几份配置的差异记住能省掉大量来回试错。4.1 claude 配置 mcp先搞清配置文件的安装范围Claude Desktop 读的是claude_desktop_config.json结构是mcpServers对象每个 key 是一个 server 名。{ mcpServers: { filesystem: { command: /usr/local/bin/npx, args: [-y, modelcontextprotocol/server-filesystem, /Users/me/workspace], env: { NODE_NO_WARNINGS: 1 } } } }command写绝对路径桌面端继承的 PATH 常常和终端不一样args是数组路径带空格也不用加引号env只放这个 server 需要的变量令牌这类敏感值放这里别写进 args进程列表在别的程序里是可见的。改完要完全退出应用再启动配置文件在启动时读取热改不生效。多个客户端可能读不同的文件改完一边没反应先确认改的是哪一份。4.2 codex 配置 mcpTOML 写法与超时参数Codex 用 TOML服务定义放在mcp_servers表下。# ~/.codex/config.toml [mcp_servers.filesystem] command npx args [-y, modelcontextprotocol/server-filesystem, /Users/me/workspace] startup_timeout_ms 20000 [mcp_servers.code_review] command python args [/abs/path/to/review_server.py] [mcp_servers.code_review.env] LOG_LEVEL infostartup_timeout_ms默认值偏短Node 生态里首次启动要装依赖的 server 经常超时调到 20000 以上更稳codex mcp相关的查看命令我一般用来确认 server 有没有被加载、工具列表是不是空输出为空基本就是进程没起来环境变量单独开一张[mcp_servers.name.env]表比塞在 args 里清晰。同一个本地 server 被两个客户端同时拉起时要注意日志文件冲突两个进程写同一个文件会互相覆盖日志里全是残行。4.3 cursor 里比较实用的 mcp 与 figma mcp 的接入顺序Cursor 的 MCP 管理入口支持项目级和全局级两份配置团队工具放项目级个人工具放全局级。比较实用的几类文件系统与搜索、Git 操作、数据库查询、浏览器自动化。figma mcp 的接入顺序经常被搞反。正确顺序是先在 Figma 账号设置里生成个人访问令牌再把令牌放进 server 配置的环境变量最后才在客户端里启用这个 server。{ mcpServers: { figma: { command: npx, args: [-y, figma-mcp-server], env: { FIGMA_ACCESS_TOKEN: 替换成你自己的令牌 } } } }令牌放env不要硬编码进args令牌绑定的是账号权限读不到某个文件通常不是配置问题而是这个账号没被授权接上之后tools/list会多出读取文件、读取节点、导出图片这类工具先用一个简单文件验证再上手。设计协作类工具走的是同一套思路令牌换能力能力再通过 tools 暴露给模型。图层、间距、色值变成可查数据之后前端改样式就不用一遍遍截图比对了。蓝湖 MCP 也是同样的模式取到令牌接上之后标注信息可以直接被模型读到。股票软件本地数据的 MCP 更直接把本地行情库做成工具模型就能按代码查询而不是靠记忆回答。4.4 排错按这个顺序走少绕弯现象优先怀疑验证方式客户端里看不到这个 server配置文件位置或 JSON 语法命令行校验 JSON确认改的是生效的那份server 出现了但工具列表为空进程启动失败或 stdout 被污染手工执行 command 加 args看 stderr调用一直卡住缺少 initialized 通知看服务端是否回复了对应 id 的消息HTTP 模式报 406Accept 头不完整curl 带上 text/event-stream 重试首次调用超时第二次正常冷启动慢加大 startup_timeout_ms 或预热依赖排错的核心动作只有一个把这个 server 从客户端里摘出来用命令行单独跑一遍。客户端里的报错常常只有一句「连接失败」命令行里的异常栈才是真正的原因。5. 自建 MCP server 与本地数据接入很多团队真正需要的不是再装一个现成 server而是把内部系统和本地数据暴露给模型——本地行情库、设计稿、CAD 工程、EDA 工程、日志检索都是这个路子。用 Spring Boot 起步比较省事一个方法就是一个工具。// Spring AI MCP Server方法即工具 Service public class LocalDataTools { Tool(description 按股票代码查询本地日线数据code 为 6 位代码days 为返回天数取值 1-250) public ListBar recentBars(String code, int days) { // 参数在服务端再兜一次底避免模型给出越界值 int safeDays Math.min(Math.max(days, 1), 250); return repo.query(code, safeDays); } }参数说明Tool的description会原样出现在tools/list里是模型选工具的主要依据写得含糊就等于没写方法参数名和类型会自动生成inputSchema别用arg0这类名字返回值被序列化成 content 数组结构太深时先拍平成文本。启动方式按需要选本机自用开 stdio团队共用开 HTTP 端点。验证环节有两个动作值得固定下来。一是用调试客户端连上去看tools/list的原始输出人眼把每一条 description 读一遍自己读不懂就改到读懂为止。二是故意传一次错误参数看返回的是结构化错误还是进程崩溃——崩溃说明服务端没做参数校验这在生产里是隐患。一个容易被忽略的取舍只读数据尽量做成 resource 而不是 tool。行情快照、设计稿、日志片段这类东西做成 resource 由用户或应用决定何时加载模型就不会每个回合都去调一次只有真正带副作用的操作比如写文件、触发构建、提交订单才做成 tool并且把权限确认留在 host 那一侧。最后一个技巧本地数据类 server 建议把「查询」和「导出」拆成两个工具。查询返回摘要导出返回完整数据否则一次调用就把几万行结果灌进上下文后面几轮的推理质量会明显下滑。分页参数不要做成可选强制带上limit能挡掉大部分上下文被撑爆的情况。本文还有配套的精品资源点击获取