1. 为什么我要自己写一个 MCP ServerMCPModel Context Protocol模型上下文协议是 Anthropic 推出的开放标准目标是让大语言模型用统一的方式连接外部数据源和工具。你可以把它理解成「AI 应用的 USB-C 接口」以前每接一个服务就要写一套适配代码现在只要服务端按 MCP 规范暴露能力任何支持 MCP 的客户端都能直接调用。它适合谁适合需要把内部系统、CLI 工具、数据库封装成 AI 可调用能力的后端开发者也适合想搞懂 Agent 工具调用底层到底怎么跑的人。我一开始也以为 MCP 就是个高级 Function Call直到自己动手写 Server 才发现真正难的不是注册工具而是通信层JSON-RPC 消息怎么组、Streamable HTTP 会话怎么建、初始化握手少了哪一步就报错。这篇就聚焦通信层从 JSON-RPC 消息格式讲到 Streamable HTTP 传输给你一份能直接跑的 MCP Server 骨架再用 curl 把握手和会话验证一遍。读完你应该能独立写出一个可被客户端连上的 MCP Server并知道每一步在协议里对应什么。2. 动手前先把 TaoToken 的接入信息准备好写 MCP Server 本身不需要模型但你要验证「模型能不能通过 MCP 调到工具」就得有一个能跑 Function Call 的模型端点。我习惯用 TaoToken 做这一步因为它同时提供 OpenAI 兼容接口和 Claude Code 的接入方式验证 MCP 工具调用链路比较顺。你需要准备两样东西一个 API Key以及对应的接入地址。API 基地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为base_url用。Key 在控制台的 API Keys 页面创建建议单独建一个用于 MCP 调试的 Key方便随时吊销。如果你只是想让模型对话验证工具描述是否合理用模型对话页面就够如果你要长期跑编码类 Agent、反复调 MCP 工具那 Coding Plan 更划算额度模型和调用方式在文档里写得很清楚。接入细节和参数说明都在接入文档里遇到 401 或模型名不对先回去对一遍文档比瞎试快得多。注意MCP Server 的通信层和模型供应商是解耦的。也就是说你完全可以把 Server 跑在本地用任意兼容端点做客户端侧的模型验证。TaoToken 在这里的角色是「提供可调用的模型端点」不是 MCP 协议的一部分别把两者混在一起理解。3. 可复制的 MCP Server 配置骨架先把工程结构定下来后面所有命令都基于这个结构。我用的目录长这样mcp-demo/ ├── config.toml ├── settings.json ├── server.py └── requirements.txtrequirements.txt只有一行核心依赖mcp1.2.0config.toml放服务端自身的运行参数比如监听地址、端口、传输方式、日志级别。这样做的目的是把「协议行为」和「业务逻辑」分开换传输方式时不用改代码[server] name demo-mcp version 1.0.0 transport streamable-http host 127.0.0.1 port 8000 path /mcp [logging] level INFOsettings.json放客户端侧的连接配置也就是客户端怎么找到这个 Server。stdio 和 HTTP 两种写法差别很大这里给 Streamable HTTP 的版本{ mcpServers: { demo: { url: http://127.0.0.1:8000/mcp, transport: streamable_http } } }server.py是核心。我用 FastMCP 封装重点看它怎么把工具注册和传输层解耦from mcp.server.fastmcp import FastMCP mcp FastMCP(demo-mcp) mcp.tool() def add(a: int, b: int) - int: 计算两个整数之和 return a b mcp.tool() def echo(text: str) - str: 原样返回输入文本用于连通性验证 return fecho: {text} if __name__ __main__: mcp.run(transportstreamable-http)启动命令pip install -r requirements.txt python server.py看到日志里出现监听127.0.0.1:8000就说明服务起来了。这里有个容易踩的点mcp.run()的transport参数取值是stdio、sse、streamable-http写错会直接抛异常别凭记忆写。4. 用 curl 验证 JSON-RPC 握手与 Streamable HTTP 会话服务起来之后别急着接客户端先用 curl 把协议层走一遍。MCP 底层是 JSON-RPC 2.0所有消息都是请求-响应或通知。第一步是初始化握手客户端发initialize服务端返回能力协商结果。curl -i -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: 1, method: initialize, params: { protocolVersion: 2025-03-26, capabilities: {}, clientInfo: {name: curl-client, version: 1.0.0} } }这里有两个关键点。第一Accept头必须同时包含application/json和text/event-stream因为 Streamable HTTP 允许服务端根据情况返回普通 JSON 或 SSE 流只写一个可能被拒。第二响应头里通常会带Mcp-Session-Id这个值后面每次请求都要带上否则服务端认不出你是同一个会话。拿到 session id 后发initialized通知确认握手完成。注意通知没有id字段curl -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -H Mcp-Session-Id: 上一步返回的session id \ -d { jsonrpc: 2.0, method: notifications/initialized }接着列出服务端注册的工具验证tools/listcurl -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -H Mcp-Session-Id: session id \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }正常返回里应该能看到add和echo两个工具每个都带name、description、inputSchema。最后真正调用一次工具curl -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -H Mcp-Session-Id: session id \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: add, arguments: {a: 5, b: 3} } }返回结构里result.content是一个数组第一项通常是{type: text, text: 8}。走到这一步说明你的 Server 在协议层已经通了。如果返回的是 SSE 格式你会看到event: message加data:前缀的文本把data:后面的 JSON 解析出来就是同样的结果。5. 本篇常见报错排查报错一406 Not Acceptable。九成是Accept头没写全。Streamable HTTP 要求客户端声明能接受application/json和text/event-stream两种缺一个服务端就可能拒绝。补全即可。报错二400 Bad Request且提示 session 无效。检查Mcp-Session-Id是否带上以及是否在initialize之后才发后续请求。顺序错了服务端会认为你在没有会话的情况下发消息。报错三initialize返回了但tools/list报方法不存在。大概率是notifications/initialized没发。这个通知是握手的一部分少了它服务端不会进入运行阶段能力列表也就查不到。报错四curl 一直挂着不返回。如果你用了GET /mcp建 SSE 长连接它本来就是不主动断开的这是正常行为。验证请求用 POST别用 GET 等响应。报错五本地能跑换端口就 404。检查config.toml里的path和客户端settings.json里的 URL 路径是否一致。Streamable HTTP 默认路径是/mcp改成别的要两边同步改。报错六模型侧调用工具时报 schema 校验失败。这通常不是通信层问题而是工具函数的类型注解和inputSchema对不上。比如参数写了list[float]但客户端传了字符串数组校验就会挂。用tools/list把 schema 打出来对一遍最直接。6. 把链路接起来继续往下走协议层验证通过后下一步就是让真实模型通过 MCP 调你的工具。这时候你需要一个能跑 Function Call 的模型端点把settings.json里的 Server 配置接到客户端再用模型对话发一句「帮我算 5 加 3」看它会不会自动触发add工具。如果模型没调工具先检查工具描述是否清晰描述写得太模糊模型会犹豫。长期跑编码类 Agent、需要反复调 MCP 工具的场景建议直接上 Coding Plan额度模型和调用方式在文档里有完整说明。接入过程中如果遇到 401、模型名不匹配、base_url 写错这类问题先翻接入文档再对照 API Keys 页面确认 Key 状态。把通信层和模型层分开排查问题定位会快很多。
企业数字化 ERP 产品动态
相关推荐
从0到1搭建AI Agent平台:React+Next.js+Python实战指南 1. 为什么我要自己搭一个 AI Agent 平台去年年底我开始认真琢磨一件事:手头重复性的工作太多了。写周报、整理会议纪要、盯竞品更新、回复常见问题、跑数据做初步分析,这些事情单拎出来都不难,但叠在一起每天能吃掉我三四个小时。市面上的 AI… · 2026/9/26 13:35:20
SqlServer批量清理存储过程与表:TaoToken辅助下的查询、判断记录与UPDATE语句实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 13:35:20
Atlas 300V 24G部署YOLO全解析:从CANN环境到OM模型调优 看到“atlas”这个关键词,加上热搜里“atlas 300v 24g 是运算加速卡吗”这个问题,我就知道不少人跟我当初一样,面对华为Atlas产品线时有点蒙。Atlas不是某一块卡的名字,它是一整套AI计算产品家族,从几瓦的模组到上百瓦… · 2026/9/26 13:35:13
Keras + BoxCox 糖尿病风险预测:从数据预处理到可视化交付 简介:面向医疗健康数据研究者、AI竞赛选手及机器学习初学者的糖尿病遗传风险预测系统,源于天池大数据竞赛任务,基于Keras框架实现神经网络预测模型,并采用BoxCox变换优化输入数据分布,配合可视化分析组件,覆… · 2026/9/26 14:10:24
自定义ScrollView+自定义滚动条:TaoToken 统一 Key 接入 AI 工具配置骨架 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:24
Spring AI 智能体通过 MCP 集成本地文件数据:TaoToken 统一 Key 配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:18
西门子TC35模块AT命令定时发短信:TaoToken统一Key接入配置与串口验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:18
mini-swe-agent 模型接入与配置实战指南:从 API Key 到多后端模型类的完整设置 人工智能大模型AI Agent代码智能体 【免费下载链接】mini-swe-agent The 100 line AI agent that solves GitHub issues or helps you in your command line. Radically simple, no huge configs, no giant monorepo—but scores >74% on SWE-bench verified! 项目地址&… · 2026/9/26 14:10:18
Anthropic Agent开发新范式:用代码执行把Token消耗砍到1.3%,TaoToken配置实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 14:10:12
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46