MCP 调试台(MCP Console)
Rust 编写的 MCP 客户端编译成 WebAssembly,经本地桥接服务连接你的 MCP 服务端和命令行工具
需要本地桥接服务
- 复制示例配置:
cp mcp.config.example.json mcp.config.json,按需加入你自己的 MCP 服务端或命令行工具
- 带上配置启动服务器:
python3 scripts/serve.py 8080 --mcp mcp.config.json
- 在这台电脑上打开
http://localhost:8080/www/mcp/(出于安全考虑,桥接服务只接受本机请求)
- 要从其他电脑通过域名访问:在配置里加
"remote" 一节并设置密码(见 docs/INSTALL.md「通过域名远程访问」)
需要本地桥接服务:python3 scripts/serve.py 8080 --mcp mcp.config.json,然后在本机打开本页 | 工具表单按 inputSchema 自动生成,「原始报文」里能看到每一条 JSON-RPC 消息
📖 原理说明
MCP(Model Context Protocol)是让 AI 应用调用外部工具、读取数据的开放协议:一个 MCP 服务端通过 JSON-RPC 声明自己有哪些「工具」「资源」和「提示词」,客户端(比如 AI 助手)按需调用。这个调试台是一个运行在浏览器里的 MCP 客户端,协议逻辑用 Rust 编写并编译成 WebAssembly;它通过本机的桥接服务连接你用 Go、Rust、Zig 或任何语言写的 MCP 服务端,也能把普通命令行工具当成 MCP 工具来调用。
🧮算法原理
页面(WASM 客户端)→ 桥接服务(本机)→ MCP 服务端 / 命令行工具浏览器不能启动进程,桥接服务只负责搬运消息和执行登记过的程序
- WASM 里的 MCP 客户端
- JSON-RPC 消息的组装与解析、initialize 握手与协议版本协商、分页列表、把工具的 JSON Schema 变成表单、把表单填写的值转换成正确类型的参数并校验,全部在 Rust 里完成(连 JSON 解析器也是手写的)。请求由 WASM 通过浏览器的 fetch 发出,服务端的推送通过 EventSource 接收。网络请求最终都经过浏览器,所以同源、跨域规则照常生效;WASM 能改进的是协议代码的可靠和复用,而不是权限。
- 桥接服务
- 由
scripts/serve.py --mcp 配置文件 启用,只做搬运:stdio 型服务端作为子进程启动,每行一条 JSON-RPC 消息;Streamable HTTP 型服务端直接转发,并处理会话编号和 SSE 格式的响应;子进程的 stderr、服务端主动发来的通知和请求通过事件流推给页面。
- 命令行工具变成 MCP 工具
- 配置文件里登记的每个命令行工具,会被包装成一个「虚拟 MCP 服务端」上的工具:参数表单来自配置里的 input_schema,调用时把参数值填进命令模板的 {占位符},stdout、stderr 和退出码作为结果返回,退出码非 0 就标记为出错。程序直接启动,不经过 shell,所以参数里的 ; | $() 之类的字符只会原样传给程序。参数值单独占一个位置、又以「-」开头时默认拒绝,以免被程序当成选项(比如 --output=…);程序本身也不能由参数决定。
- 服务端反过来请求客户端
- MCP 服务端可以向客户端请求采样、目录或用户输入。调试台不提供这些能力:收到 ping 就回复空结果,其他请求回复「不支持的方法」,并把整个过程记录在「原始报文」里。示例服务端的「反向请求」工具可以演示这一来一回。
- 安全
- 能调用这个接口,就等于能在本机运行配置里的程序,所以桥接服务只接受同时满足以下条件的请求:来自本机回环地址、Host 头是 localhost、没有来自其他网站的 Origin,并带有令牌。令牌只在本机打开本页时通过 HttpOnly、SameSite=Strict 的 Cookie 下发,其他网站既读不到也带不上。浏览器只能按编号使用配置文件里登记的服务端和工具,不能指定程序或参数模板。服务端返回的内容一律当作纯文本显示。服务端的输出按行读取且有长度上限,命令行工具的输出最多保留 1 MB,多出来的读走丢弃;同一时间多个标签页各自的请求编号可能重复,桥接服务会换成自己分配的唯一编号,再把响应换回原编号。
🔄Rust 与 JavaScript 的分工
- JS页面加载后调用
mcp_servers() 取得配置里的服务端;点选一个后 mcp_listen 开始接收推送,mcp_connect 完成握手,再用 mcp_list 取回工具、资源和提示词。
- RustWASM 为每个服务端维护一个会话:分配请求编号、组装 JSON-RPC、经
/api/mcp/<id>/rpc 发出并匹配响应;mcp_form 把工具的 inputSchema 转成表单描述,mcp_call 校验并转换参数后发出 tools/call。
- JSJS 按表单描述生成输入控件,展示结果里的文字、图片和资源;「原始报文」按时间列出所有发出、收到和推送的消息,也可以手写一条 JSON-RPC 直接发送。
⚡性能要点
- 这个页面需要本地服务:部署到静态托管时桥接服务不存在,页面会显示启动方法。只有它不是纯浏览器端的示例。
- 消息往返的开销主要在进程间通信和 HTTP,本机上握手和一次工具调用通常只需几毫秒;超时(默认 30 秒,可在配置里调整)后桥接服务返回 504,子进程退出后下一次请求会自动重启它。
- 这个 .wasm 约 120 KB,比其他示例大:主要是异步请求的状态机、浏览器接口绑定和字符串处理,因此用了体积优先的优化级别。
源码crates/tools/mcp/src/mcp.rscrates/tools/mcp/src/web.rsscripts/mcp_bridge.pyscripts/mcp_shell.pyscripts/mcp_demo_server.pycrates/tools/mcp/examples/demo_server.rsexamples/mcp-servers/go/main.goexamples/mcp-servers/zig/demo_server.zigwww/mcp/index.js