2026年最新MCP协议从原理到实战:手写一个MCP Server接入Claude Code全流程踩坑指南
2026年最新MCP协议从原理到实战手写一个MCP Server接入Claude Code全流程踩坑指南 目录一、为什么 2026 年你必须搞懂 MCP 协议二、MCP 协议核心原理5 分钟看懂2.1 一句话理解 MCP2.2 三层架构Host / Client / Server2.3 三类能力Tools / Resources / Prompts2.4 两种传输方式stdio vs SSE三、环境准备3.1 Python 环境与 MCP SDK3.2 安装 Claude Code四、实战第一步手写一个 stdio 版 MCP Server4.1 用 FastMCP 五行代码起一个 Server4.2 定义你的工具增、查、搜索4.3 本地调试MCP Inspector 可视化五、接入 Claude Code 实战5.1 方式一配置文件推荐可版本化5.2 方式二命令行添加适合临时调试5.3 验证工具是否被识别六、进阶升级到 SSE 远程传输6.1 改造代码从 stdio 到 SSE6.2 客户端连接 SSE Server七、踩坑实录我踩过的 7 个坑建议收藏八、MCP vs 传统 Function Calling 横向对比九、总结与互动9.1 本文核心回顾9.2 给你的下一步建议9.3 互动摘要2026 年 6 月微软 Build 大会宣布全面拥抱 MCP 协议Copilot Studio 原生支持 MCP 工具注册。一时间MCP 成了 AI 开发圈的USB 接口标准。但教程要么停在概念科普要么一上来就堆 LangGraph CrewAI 一堆框架对只想先跑通一个自己的工具的开发者极不友好。本文不聊虚的带你从零手写一个 MCP Server接入 Claude Code再把踩过的 7 个坑一次性讲透。读完你就能把自己的任何脚本变成大模型能调用的工具。关键词MCP 协议Model Context ProtocolClaude CodeMCP Serverstdio / SSE 传输Function CallingAI Agent工具调用一、为什么 2026 年你必须搞懂 MCP 协议先说一个很多开发者都遇到过的痛点你给大模型接了一个查询公司数据库的能力用 Function Calling 写得好好的。结果换了个 Agent 框架从 LangChain 换到 CrewAI接口全得重写换了家模型从 GPT 换到 Claude参数格式又对不上想让同事复用你的工具发现他用的框架你压根没听过——工具写了一遍又一遍像个永远调不通的转接头。MCPModel Context Protocol模型上下文协议就是来终结这个混乱的。它由 Anthropic 在 2024 年底提出核心目标用一句话讲清楚让大模型像浏览器访问网页一样用统一协议安全地访问任何外部工具和数据源。写一次 Server所有支持 MCP 的客户端都能用。到 2026 年中局面已经很明朗时间节点事件2024.11Anthropic 发布 MCP 协议规范2025 上半年OpenAI、Google 相继表态支持2025 下半年Cursor、Claude Code、Cline 等 AI 编程工具原生集成2026.06微软 Build 大会宣布 Copilot Studio 全面拥抱 MCP一句话MCP 已经成了连接 AI 和外部工具的事实标准。学会它等于拿到了 2026 年 AI 开发的入场券。二、MCP 协议核心原理5 分钟看懂别被协议两个字吓到MCP 的设计相当克制。底层就是JSON-RPC 2.0你发一段 JSON、收一段 JSON仅此而已。2.1 一句话理解 MCP把大模型想象成一台电脑MCP 就是它的USB 接口。你不用关心接的是硬盘、网卡还是打印机——只要设备符合 USB 规范插上就能用。MCP Server 就是那些USB 设备负责把你的数据库、文件系统、内部 API 包装成统一的接口。2.2 三层架构Host / Client / ServerMCP 的运行时由三个角色组成┌─────────────────────────────────┐ │ Host宿主 │ │ 如 Claude Code / Cursor / Cline │ │ ┌───────────┐ ┌───────────┐ │ │ │ MCP Client│ │ MCP Client│ │ │ └─────┬─────┘ └─────┬─────┘ │ └─────────┼──────────────┼────────┘ │ JSON-RPC │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ MCP Server A │ │ MCP Server B │ │ (你的工具) │ │ (别人的工具) │ └──────┬───────┘ └──────┬───────┘ ▼ ▼ 数据库/文件 GitHub/邮件Host宿主运行大模型的那个程序比如 Claude Code。它负责把模型的工具调用请求转发给对应的 Server。Client客户端嵌在 Host 里每个 Server 对应一个 Client负责协议通信。Server服务端你写的那个程序真正干活的人——读文件、查数据库、调 API 都在它里面。2.3 三类能力Tools / Resources / Prompts一个 MCP Server 可以向外暴露三类东西能力作用谁主动典型场景Tools工具可被模型调用的函数模型决定何时调查天气、发邮件、跑 SQLResources资源可被读取的数据客户端/用户主动拉读文件内容、读配置Prompts提示模板预设的提示词模板用户主动触发代码审查模板、总结模板90% 的实战场景你只需要Tools。本文也以 Tools 为主线展开资源和提示模板留作进阶。2.4 两种传输方式stdio vs SSEServer 和 Client 之间怎么传 JSON-RPC 消息MCP 规范定义了两种主流传输维度stdio标准输入输出SSEServer-Sent Events通信方式子进程的标准输入/输出HTTP 长连接 流式响应部署形态本地Host 启动子进程远程独立 HTTP 服务适用场景本地工具、个人开发团队共享、生产部署配置复杂度低一行命令中需管端口/CORS多客户端共享不行每个 Host 各起一份可以一个 Server 多端连调试难度print 会污染协议见坑1可用浏览器/curl 直接测新手建议先用 stdio 跑通再按需升级到 SSE。本文两种都会手把手演示。三、环境准备3.1 Python 环境与 MCP SDKMCP 官方提供了 Python 和 TypeScript 两套 SDK。本文用 Python因为上手最快。建议用 Python 3.10建个独立虚拟环境# 创建项目目录mkdirmy-mcp-servercdmy-mcp-server# 创建虚拟环境Windows 用 pythonLinux/Mac 用 python3python-mvenv .venv# 激活虚拟环境# Windows (Git Bash):source.venv/Scripts/activate# Linux/Mac:source.venv/bin/activate# 安装 MCP 官方 SDKpipinstallmcp踩坑预警很多人图省事不建虚拟环境直接全局pip install。后面接入 Claude Code 时command字段要写 Python 解释器的绝对路径全局环境的路径一旦变动升级、重装就全崩。永远用虚拟环境的绝对路径别偷懒。3.2 安装 Claude CodeClaude Code 是 Anthropic 官方的命令行 AI 编程助手对 MCP 支持最完整本文以它为接入对象。# 需要 Node.js 18npminstall-ganthropic-ai/claude-code# 验证安装claude--version安装后运行一次claude按提示登录即可。如果你用 Cursor配置思路完全一致只是配置文件位置不同后文会提到。四、实战第一步手写一个 stdio 版 MCP Server需求很实在写一个笔记管理工具让大模型能帮我们增删查改本地笔记。麻雀虽小五脏俱全——查、增、改三种工具都有了足够你举一反三。4.1 用 FastMCP 五行代码起一个 ServerMCP Python SDK 提供了一个高层封装FastMCP用法类似 FastAPI装饰器一挂就能把普通函数变成 MCP 工具。新建note_server.py# note_server.pyimportjsonimportosfrommcp.server.fastmcpimportFastMCP# 笔记存储文件NOTE_FILEnotes.jsondef_load_notes():ifnotos.path.exists(NOTE_FILE):return[]withopen(NOTE_FILE,r,encodingutf-8)asf:returnjson.load(f)def_save_notes(notes):withopen(NOTE_FILE,w,encodingutf-8)asf:json.dump(notes,f,ensure_asciiFalse,indent2)# 创建 MCP Server 实例mcpFastMCP(note-server)if__name____main__:mcp.run(transportstdio)跑起来什么都不干但骨架已经有了。接下来加工具。4.2 定义你的工具增、查、搜索mcp.tool()deflist_notes()-str:列出所有笔记的标题和编号。无笔记时返回空列表提示。notes_load_notes()ifnotnotes:return当前没有任何笔记。returnjson.dumps([{id:i,title:n[title]}fori,ninenumerate(notes)],ensure_asciiFalse)mcp.tool()defadd_note(title:str,content:str)-str:添加一条新笔记。 Args: title: 笔记标题简短概括 content: 笔记正文内容 notes_load_notes()notes.append({title:title,content:content})_save_notes(notes)returnf已添加笔记《{title}》当前共{len(notes)}条。mcp.tool()defsearch_notes(keyword:str)-str:按关键词搜索笔记标题和正文返回匹配结果。 Args: keyword: 搜索关键词 notes_load_notes()results[{id:i,title:n[title],content:n[content]}fori,ninenumerate(notes)ifkeywordinn[title]orkeywordinn[content]]ifnotresults:returnf没有找到包含「{keyword}」的笔记。returnjson.dumps(results,ensure_asciiFalse)注意几个细节这些是新手最容易忽略、却直接决定工具能不能被模型正确调用的关键函数名要语义化模型靠名字猜用途list_notes比get_data好一万倍。docstring 是命根子模型决定要不要调这个工具时主要看 docstring。写得越清楚调用越准。参数要有类型注解title: str比title多了类型信息SDK 会自动转成 JSON Schema 喂给模型。返回值统一用字符串复杂结构用json.dumps别直接返回 dict不同客户端兼容性参差。完整文件保存后本地先验证语法没问题python note_server.py# 没报错、阻塞等待输入说明 stdio 服务已就绪CtrlC 退出4.3 本地调试MCP Inspector 可视化MCP 官方提供了一个调试神器Inspector能在浏览器里直接测试你的工具不用每次都启动 Claude Code。# 一行命令启动会自动拉起一个 Web 界面npx modelcontextprotocol/inspector python note_server.py浏览器打开http://localhost:5173能看到左侧列出所有已注册的 Tools点一个工具右侧填参数点 “Run” 直接调用底部显示完整的 JSON-RPC 请求/响应强烈建议每次改完代码先在 Inspector 里测一遍确认工具行为正常再去接 Claude Code。这能帮你把是 Server 的 bug还是模型没调用对区分开省下大量排查时间。五、接入 Claude Code 实战Server 写好了怎么让 Claude Code 用上它有两种方式任选其一。5.1 方式一配置文件推荐可版本化在项目根目录或用户家目录~/.claude/创建.mcp.json{mcpServers:{note-server:{command:C:\\\\项目路径\\\\my-mcp-server\\\\.venv\\\\Scripts\\\\python.exe,args:[C:\\\\项目路径\\\\my-mcp-server\\\\note_server.py]}}}Windows 路径坑JSON 里反斜杠要转义成\\\\。更省心的做法是用正斜杠/Windows 也认C:/项目路径/my-mcp-server/.venv/Scripts/python.exe。Mac/Linux 用户写正常路径即可。5.2 方式二命令行添加适合临时调试claude mcpaddnote-server -- C:/项目路径/my-mcp-server/.venv/Scripts/python.exe C:/项目路径/my-mcp-server/note_server.py--后面跟的就是启动命令和参数和配置文件里的commandargs完全对应。5.3 验证工具是否被识别在项目目录下启动 Claude Codeclaude进入交互界面后输入/mcp会列出所有已连接的 MCP Server 及其状态。看到note-server: connected且下面列出list_notes、add_note、search_notes三个工具说明接入成功。然后直接用自然语言测试 帮我加一条笔记标题MCP学习计划内容本周跑通stdio版本下周升级SSE 我现在有哪些笔记 搜一下有没有关于SSE的笔记如果模型自主决定调用对应工具并返回正确结果恭喜你已经拥有了一个能被大模型驱动的自定义工具系统。六、进阶升级到 SSE 远程传输stdio 模式有个硬伤每台机器都要装一份 Server没法团队共享。当你想让整个团队用同一个公司内部知识库查询工具时就需要 SSE 模式——把 Server 部署成 HTTP 服务大家远程连。6.1 改造代码从 stdio 到 SSE改动极小FastMCP帮你屏蔽了传输层差异# note_server_sse.py# ... 上面的工具定义完全不变 ...if__name____main__:# 只需把 transport 从 stdio 改成 sse并指定端口mcp.run(transportsse,port8765)运行python note_server_sse.py# 输出类似Uvicorn running on http://0.0.0.0:87656.2 客户端连接 SSE ServerClaude Code 的.mcp.json配置改为 URL 形式{mcpServers:{note-server-remote:{url:http://your-server-ip:8765/sse}}}或命令行claude mcpaddnote-server-remote--transportsse http://localhost:8765/sse这样你的 Server 就能被团队任意成员、任意支持 MCP 的客户端连接了。部署到云服务器后还能配合 nginx 做反向代理和 HTTPS。新协议提醒MCP 规范在 2025 年下半年引入了Streamable HTTP传输逐步取代纯 SSE。它对无状态部署更友好。如果你的 SDK 版本较新可尝试transportstreamable-http。过渡期 SSE 仍广泛兼容本文以 SSE 为例。七、踩坑实录我踩过的 7 个坑建议收藏理论和实战都有了但真正写的时候坑往往在细节里。下面这 7 个坑每一个都让我或社区同学掉过头发。#坑点现象根因解决方案1stdio 下用 print 调试Claude Code 连接后卡死、报协议解析错误stdio 传输靠标准输入输出传 JSON-RPCprint 的内容会被当成协议消息直接污染通道永远用logging输出到 stderrimport logging; logging.basicConfig(streamsys.stderr)2Windows 中文编码乱码工具返回的中文变成???或抛UnicodeDecodeErrorWindows 默认控制台编码是 GBKPython 写文件/输出时编码不一致文件操作显式指定encodingutf-8脚本开头加sys.stdout.reconfigure(encodingutf-8)3command 写了相对路径换个目录启动 Claude Code 就报 “command not found”Host 启动子进程时的工作目录不固定相对路径解析失败command和args一律写绝对路径包括 python.exe 和脚本文件4docstring 太简略模型明明有合适工具却死活不调用或者乱传参数模型选工具主要靠 docstring 理解语义写得太短它不知道这工具干嘛docstring 写清做什么 参数含义 返回什么像给新人写接口文档一样5参数没写类型注解模型把数字传成字符串或参数顺序混乱没有类型注解SDK 生成的 JSON Schema 缺类型信息模型只能猜每个参数都加类型注解name: str、count: int复杂结构用 Pydantic Model6SSE 部署后连不上本机 localhost 能连远程/容器内死活连不上默认监听 127.0.0.1 只接受本机或防火墙没开端口或跨域被拦监听地址设为0.0.0.0开放对应端口跨域时配置 CORS7工具能干危险操作却没护栏模型自作主张删了数据 / 改了不该改的文件给了工具全部权限模型在自主执行时可能越界危险操作删除/覆盖加二次确认参数用 Resources 的只读特性隔离生产环境加操作日志和回滚重点展开坑 1 和坑 4这俩是高频翻车点坑 1 的正确调试姿势importsysimportlogging# 关键输出到 stderr不污染 stdoutstdout 是协议通道logging.basicConfig(levellogging.DEBUG,streamsys.stderr,format%(asctime)s [%(levelname)s] %(message)s)mcp.tool()defadd_note(title:str,content:str)-str:logging.debug(f调用 add_note: title{title})# ... 业务逻辑 ...returnokClaude Code 启动 Server 时可以把 stderr 重定向到文件查看在.mcp.json里没法直接重定向但可以在 Python 脚本里把日志写到文件。坑 4 的 docstring 对比# ❌ 模型大概率不会调用或乱传参mcp.tool()defsearch(keyword):搜索...# ✅ 模型能准确判断何时调用、怎么传参mcp.tool()defsearch_notes(keyword:str)-str:按关键词搜索笔记标题和正文返回所有匹配的笔记。 当用户想查找包含某内容的笔记有没有关于XX的记录时使用。 Args: keyword: 要搜索的关键词单个词或短语 ...八、MCP vs 传统 Function Calling 横向对比写到这里你可能会问我之前用 Function Calling 用得好好的凭什么要换 MCP这张表给你答案维度传统 Function CallingMCP 协议标准化程度各家模型接口不一参数格式各异开放标准模型无关一套规范通吃工具复用换个框架/模型基本要重写写一次 Server所有 MCP 客户端通用工具发现手动在代码里注册每个工具自动发现连上 Server 即可用本地数据访问需自己处理本地文件/数据库对接Server 跑在本地天然能访问本地资源安全控制基本裸奔全靠 prompt 自觉Server 侧可做鉴权、审计、权限隔离调试体验只能看日志黑盒MCP Inspector 可视化调试生态各自为政MCP 工具市场逐渐成型官方/社区 Server 越来越多学习成本低直接写函数中需理解协议和传输适用场景单一模型、简单工具、快速原型多模型/多框架、团队共享、生产级 Agent结论如果你只是个人小打小闹、只用一个模型Function Calling 够用但只要涉及工具复用、团队共享、生产部署MCP 的标准化红利会越来越值。2026 年的趋势已经很明确——新工具按 MCP 规范写老工具逐步迁移。九、总结与互动9.1 本文核心回顾MCP 是什么连接大模型和外部工具的USB 协议2026 年已成事实标准。三层架构Host宿主→ Client客户端→ Server你写的工具服务。三类能力Tools最常用、Resources、Prompts。两种传输stdio本地起步、SSE/Streamable HTTP远程共享。实战路径FastMCP 写工具 → Inspector 调试 → 接入 Claude Code → 按需升级 SSE。7 个坑print 污染、中文编码、相对路径、docstring、类型注解、SSE 监听、安全护栏。9.2 给你的下一步建议本周照着本文把 stdio 版 Note Server 跑通接上 Claude Code。下周把你自己工作中的一个真实脚本比如查日志、跑 SQL、生成报表改造成 MCP Server。进阶研究 Resources 和 Prompts 能力做只读知识库和提示模板。生产化升级到 Streamable HTTP加上鉴权和操作审计。9.3 互动MCP 这套东西还在快速演进坑也还在不断被发现。你在实操中遇到过什么离谱的问题或者有什么好玩的 Server 想法欢迎在评论区交流我会逐条回复。如果这篇对你有帮助点赞 收藏 关注三连是对原创最大的鼓励——下一篇我会写「MCP Server 生产部署鉴权、审计与高可用实战」把这套东西从能跑推进到敢上线别错过。本文所有代码均基于 MCP Python SDK 实测环境为 Windows 11 Python 3.13 Claude Code 最新版。不同版本 SDK API 可能有细微差异以官方文档为准。