如果最近你在写 MCP Server(FastMCP、官方 SDK,或者自己撸 JSON-RPC),这篇文章大概能帮你省掉一半的调试时间。
省流 :直接在IDEA、Pycharm等软件中点击设置-插件-搜索MCP Debugger,安装即可使用

目录
- [一、先聊痛点:调试 MCP Server 的体验是真的差](#一、先聊痛点:调试 MCP Server 的体验是真的差)
- [二、MCP Debugger 是什么](#二、MCP Debugger 是什么)
- 三、安装
- 四、五分钟上手
- [五、重点:HTTP 模式的完整实操](#五、重点:HTTP 模式的完整实操)
- [六、报文日志:MCP 的「网络面板」](#六、报文日志:MCP 的「网络面板」)
- 七、获取方式
一、先聊痛点:调试 MCP Server 的体验是真的差
MCP(Model Context Protocol)现在火得很,但开发侧的工具链明显没跟上。翻一翻你调试 MCP Server 时的日常:
- 想看一眼
tools/list返回了什么 ------得先写个客户端 demo,把initialize→notifications/initialized→tools/list这三步握手按顺序拼一遍。顺序错了服务端直接不理你。 - 工具调不通 ------报的是一句
-32602 Invalid params,不告诉你哪个参数错了、期望什么类型。 - 参数长什么样全靠猜 ------schema 里明明写了
default、enum,还是得自己手抄一份到请求体里。 - 换个传输方式就换一套代码 ------今天
stdio起子进程,明天服务端部署成 HTTP,客户端得重写。 - 服务端起不来只能靠 curl 猜------报错信息在 TCP 层和框架层之间来回跳,看不到真正的报文。
写业务逻辑的时间,一多半花在「造一个能看见协议的工具」上。
而这套活儿,本来就是 Postman 该干的------只不过 MCP 用的是 JSON-RPC over stdio / HTTP,Postman 管不了握手和会话。
所以我把 Postman 那套体验搬进了 IDE。
二、MCP Debugger 是什么
JetBrains 全家桶插件:把 MCP 调试台装进 PyCharm / IDEA / WebStorm / GoLand 的右侧边栏。
核心就一件事:让 MCP 调试变得和调 REST 接口一样顺手。
你熟悉的 Postman 操作,在这里一一对应:
| Postman 里 | MCP Debugger 里 |
|---|---|
| 环境 / Collection | MCP 服务器(下拉框切换) |
| 接口列表 | 工具 / 资源 / 资源模板 / 提示词(自动拉取,不用手写) |
| Params / Body | 参数 JSON (按工具 schema 自动预填) |
| Send | 调用 (或 Ctrl+Enter) |
| Response | 结果 JSON(原样展示,可滚动、可复制) |
| Network / Console | 报文日志(请求 / 响应 / 通知 / 子进程 stderr,按方向着色) |
能力清单:
| 能力 | 说明 |
|---|---|
| 三种传输 | stdio(本地子进程)、Streamable HTTP 、旧版 HTTP + SSE 。协议版本协商、Mcp-Session-Id 会话、能力声明全部自动处理 |
| 工具自动识别 | 工具列表来自 tools/list,游标翻页会自动翻到底 ;资源、资源模板、提示词一并列出。服务端发 tools/list_changed 通知时自动刷新 |
| 参数自动预填 | 按工具的 JSON Schema 生成一份完整可解析的参数 JSON,不是空白编辑器 |
| 定义随时可查 | 一个「定义」页签就是工具原始 JSON(含 annotations、outputSchema),类型 / 必填 / 说明 / 默认值都在 |
| 报文级日志 | 按方向与时间着色,长报文可折叠,带请求 / 响应 / 错误计数 |
| 导入现成配置 | 自动扫描本机与工程内的 MCP 配置文件,也能直接粘贴 mcpServers JSON |
| 一份包通吃 | 只依赖平台基础模块,同一个 zip 装进所有 JetBrains IDE |

三、安装
插件是自研的,目前通过发行包 或源码安装。
方式一:发行包(推荐)
bash
# 仓库根目录执行,产物在 build/distributions/
./gradlew buildPlugin
# → build/distributions/mcp-debug-idea-plugin-1.0.0.zip
Windows 上直接双击 package.bat 等价。
然后 IDE 里:Settings → Plugins → ⚙ → Install Plugin from Disk... 选中这个 zip,重启。
方式二:源码运行(开发调试用)
bash
./gradlew runIde
会拉起一个已经装好本插件的沙箱 IDE。
环境要求:JDK 17。本工程的 Gradle Wrapper jar 未随仓库提交,若
./gradlew报
找不到主类 GradleWrapperMain,直接用本机 Gradle 发行版调用即可。
四、五分钟上手
重启后,在 IDE 右侧边栏 找到 MCP Debugger 工具窗口(找不到就去 View → Tool Windows 里翻)。
- 点工具栏的 ➕ 新建服务器,或者 管理 ▾ → 粘贴 JSON 导入... 把现成的
mcpServers配置贴进去。 - 选好服务器,点 连接。
- 状态点变绿、工具树开始填充 → 握手成功、目录已就绪。
- 左侧点开任意工具 → 右侧参数区已经预填好 JSON → 改几个值点 调用 (
Ctrl+Enter更快)。 - 结果 JSON 显示在下方,状态条右侧的 复制 拿走同一份内容;底部 报文日志 是协议流水。
界面长这样(窄边栏会自动改成上下堆叠,不用管):
┌──────────────────────────────────────────────────────────────────────┐
│ [ 服务端 ▾ ......................... ] │ 工具栏
│ ➕ ↻ ✏️ ⚙️ ▤ ● 已连接 · 12 工具 │
├───────────────────────────┬──────────────────────────────────────────┤
│ 目录树 │ 详情 / 调用区 │
│ ├ 工具 (12) │ ┌────────────────────────────────────┐ │
│ │ ├ add │ │ 名称 · 描述 · 来源 │ │
│ │ ├ search_docs │ ├────────────────────────────────────┤ │
│ │ └ ... │ │ JSON │ 定义 │ │
│ ├ 资源 (3) │ │ ┌────────────────────────────────┐ │ │
│ ├ 资源模板 (1) │ │ │ { │ │ │
│ │ │ │ │ "keyword": "", │ │ │
│ │ │ │ │ "top_k": 5 │ │ │
│ │ │ │ │ } │ │ │
│ │ │ │ └────────────────────────────────┘ │ │
│ │ │ │ [ 调用 ] │ │
│ │ │ ├────────────────────────────────────┤ │
│ │ │ │ ● 完成 · 12 ms [复制] │ │
│ │ │ │ { │ │
│ │ │ │ "content": [ ... ] │ │
│ │ │ └────────────────────────────────────┘ │
├───────────────────────────┴──────────────────────────────────────────┤
│ Console 10:42:01.113 ← {"jsonrpc":"2.0","id":3,"method":"tools/call"...│
│ 10:42:01.115 → {"jsonrpc":"2.0","id":3,"result":{"content"... │
└──────────────────────────────────────────────────────────────────────┘
注意上面参数区那两行:"keyword": "" 和 "top_k": 5------这是插件照着服务端的 schema 替你填的 ,5 就是那个参数的 default。下一节展开讲。
五、重点:HTTP 模式的完整实操
stdio 模式大家用得最多(本地起个子进程),但真正坑最多、最需要工具辅助的是 HTTP 模式:
- 你没法像 stdio 那样直接把子进程拉起来看输出,服务端的状态是黑盒;
- 握手、会话 id、
Accept头、协议版本,任何一处不对,服务端给的都是一句没头没尾的报错; - 服务端可能跑在容器里、跑在远端测试环境,甚至是你同事的机器上。
所以这一节把 HTTP 模式从头到尾走一遍。
5.1 准备一个 HTTP 端点的 MCP 服务端
拿 FastMCP 起一个最小服务端(真实项目里就是你正在写的那个):
python
# server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("demo", host="127.0.0.1", port=8000)
@mcp.tool()
def add(a: int, b: int) -> int:
"""两数相加"""
return a + b
@mcp.tool()
def search_docs(keyword: str, top_k: int = 5) -> list[str]:
"""按关键词检索文档"""
return [f"doc-{i}" for i in range(top_k)]
if __name__ == "__main__":
# Streamable HTTP,默认端点 /mcp
mcp.run(transport="streamable-http")
bash
python server.py
# 端点:http://127.0.0.1:8000/mcp
5.2 在插件里新建一个 HTTP 服务器
点 ➕,在「新建 MCP 服务器」对话框里:
| 字段 | 填什么 |
|---|---|
| 名称 | 随便起,例如 demo-http,下拉框里显示这个名字 |
| 传输方式 | http (Streamable HTTP,MCP 2025-03-26 起);旧版服务端选 sse |
| 地址 | http://127.0.0.1:8000/mcp ------ Streamable HTTP 要填完整端点,不是根地址 |
| 请求头 | 需要鉴权就填,例如 Authorization: Bearer xxx。Content-Type 与 Accept 插件会自己带 |
stdio 和 http 的字段在同一个对话框里、用传输方式切换卡片------临时改主意「还是走 HTTP 吧」不用重开一遍。
「高级」页签里还有两个有用的:
- 协议版本 :默认
2025-06-18。很旧的服务端可以试2024-11-05;服务端返回哪个版本插件都接受,不会硬校验。 - 超时(秒) :默认
60,跑得慢的工具(比如大模型推理、批量抓取)调到300。

5.3 先「测试连接」,通过了再保存
这是我觉得最省心的一个设计:对话框里的 测试连接 按钮会按当前表单内容真的连一次,跑完整套握手,然后把结果打回来:
✔ 连接成功:example-server 1.2.0,工具 2,资源 0,提示词 0
失败也会明确告诉你卡在哪一步,而不是等你保存完、连不上、再回来改。测试用的会话结束时会立刻关掉(stdio 的子进程也会被收掉),不会留着占资源。
配置写完先点一下它,比什么都快。
5.4 连接成功后:工具自己就来了
点 连接,剩下的事全是自动的:
- 发
initialize(带协议版本和能力声明); - 按规范补一条
notifications/initialized通知------少了这一条,很多服务端会直接拒绝后续请求; - 拉
tools/list,如果有nextCursor就自动翻页翻到底; - 顺手拉
resources/list、resources/templates/list、prompts/list。
状态栏变成 ● 已连接 · N 个工具 ,左侧树里工具 / 资源 / 资源模板 / 提示词四个分组就位(空分组不显示,免得一堆 0)。
HTTP 模式下额外做的两件事:
- 会话 id 自动接管 :服务端在握手响应里通过
Mcp-Session-Id头下发会话 id,插件拾取后每个后续请求都会带回去。这是 Streamable HTTP 最容易漏的一环,漏了就是「第一次能连,第二次 400」。 - 响应两种形态都能解 :服务端回
application/json还是text/event-stream(SSE 流),插件都能读。
还有一个躺赢的:服务端发 notifications/tools/list_changed 时(比如你热重载了代码),工具树会自动刷新,不用手点。

5.5 点开工具,参数已经填好了
点 search_docs,右侧参数区的 JSON 页签里不是空白,而是:
json
{
"keyword": "",
"top_k": 5
}
注意两点:
keyword没有default,按类型给了空字符串""------参数名照样出现,你不用去猜它叫什么;top_k的5是从 schema 的default里带出来的。
换个 add,参数区就是 {"a": 0, "b": 0}。
参数的类型、哪些必填、每个字段的说明,切到旁边的 「定义」页签 看------那就是工具的原始 JSON 定义(含 annotations、outputSchema),不用另开文档。
改哪个值就改哪个,多余的键删掉即可 ,然后 Ctrl+Enter。

5.6 调用与结果
点「调用」(或 Ctrl+Enter),结果直接摊成一份 JSON:
- 编辑器级高亮、可滚动、可全选复制;
- 状态条右侧 复制 按钮复制的就是这份 JSON 原文;
- 状态条上有耗时:● 完成 · 12 ms;
- 服务端返回
isError = true时会明确标出来,不会让你误以为是成功的。
结果区只显示 JSON,不做任何二次渲染。 这是刻意的------调试台最重要的是「界面上看到的就是协议里回的那一份」,中间加一层美化反而会让你怀疑数据被改过。

5.7 旧版 HTTP + SSE 怎么填
老服务端(MCP 2024-11-05 那套)用的是 HTTP + SSE 两段式:
json
{
"mcpServers": {
"legacy": {
"type": "sse",
"url": "https://example.com/sse"
}
}
}
插件的处理流程:
- 先 GET 地址建 SSE 长连接;
- 从
endpoint事件里拿到回传地址; - 之后所有请求 POST 到那个回传地址,响应从 SSE 流里读回来。
对应服务端就是 mcp.run(transport="sse"),端点默认 /sse。
三种传输的配置对照:
| 传输 | type |
关键字段 | 适用 |
|---|---|---|---|
| stdio | 默认 | command / args / env / cwd |
本地起子进程,npx / uvx / docker / 任意可执行文件 |
| Streamable HTTP | http |
url + headers |
现代 HTTP 服务端,填完整端点如 .../mcp |
| 旧版 SSE | sse |
url |
老服务端,如 .../sse |
六、报文日志:MCP 的「网络面板」
对调试 MCP 来说,这个面板的价值不低于调用面板本身。
大多数「工具调不通」其实是协议层的问题:没发 initialized、方法名拼错、返回 -32602、子进程 stderr 里在报错------这些从报文里一眼就能看出来,但从上层报错信息里完全看不出来。
日志按来源分开着色:
- 出站报文 (
←) - 入站报文 (
→) - 子进程 stderr / 传输层提示
- 插件自身的错误
标题栏有几个实用的小控件:
- 报文体 勾选框:关掉后日志只留方法名,看长响应清爽很多;
- 清空:只清日志,不断连接;
- 计数在中间(请求 12 · 响应 12 · 错误 1),窄了会被省略号截断,但完整内容挂在标题的 tooltip 上。
底部日志区可以折叠 ------工具栏的 报文日志 开关,或者日志标题栏左侧的 ▼ 都能折叠/展开,折叠状态会被记住。

七、获取方式
直接在IDEA、Pycharm等软件中点击设置-插件-搜索MCP Debugger,安装即可使用

如果这篇对你有用,点个赞让更多写 MCP 的人看到 👍