先读概念篇(推荐):MCP 到底是什么?六大能力,每个讲清「怎么用」
系列回顾:主循环 · 代码库工具 · REPL · 项目上下文 · Skills · 权限 + Write
概念篇把 MCP 六大能力讲完了。本篇只谈一件事:
react-agent-mini 如何在不改 query() 的前提下,把外部 stdio MCP Tools 接进 ReAct 循环。
mini 只实现了 Tools + Stdio(Resources / Prompts / Sampling 等见概念篇;本仓库概念演示在 examples/mcp-tour-server)。
mini 接的是哪一块?
概念篇里的能力 mini
Tools ✅ 连接、发现、适配、门卫、转发
Resources ❌
Prompts ❌
Sampling / Roots / Elicitation ❌
传输 ✅ 仅 stdio
策略:先打通「动态工具表」这条主干——和内置 Echo / Read 走同一条 runToolUse。
一张图看清链路
.mcp.json(配置:连哪些 server,用什么命令启动)
↓
loadMcpTools() → stdio 启动子进程 → list_tools
↓
adaptMcpTool():每个 MCP tool → 内部 Tool 形状
↓
sessionTools() = builtin(Echo/Read/…)+ mcp__* 工具
↓
模型 tool_use → runToolUse → 门卫(第六篇)→ 转发 call_tool
↓
tool_result 回注 → query() 继续
对 query() 来说,MCP 工具和普通 Read 没区别。 变化只在 启动接线 和 适配层。
动手:5 分钟接上计算器
仓库示例:examples/mcp-calc-server(只暴露 add / multiply)。
Step 0:先确认 Server 能跑
node examples/mcp-calc-server/smoke.mjs
期望:
tools: add, multiply
add(17,25): {"content":[{"type":"text","text":"17 + 25 = 42"}]}
Step 1:写配置
cp .mcp.json.example .mcp.json
{
"mcpServers": {
"calc": {
"command": "node",
"args": ["examples/mcp-calc-server/server.js"]
}
}
}
| calc | server id → 工具名前缀 |
| command + args | 如何拉起 stdio Server |
| 无配置文件 | 跳过 MCP,零开销 |
Step 2:启动 Agent
bun run dev
REPL 里问:
用计算器工具算一下 17 加 25,必须调用 MCP 工具,不要心算
Step 3:对照链路
启动 → list_tools → 注册 mcp__calc__add / mcp__calc__multiply
模型 → tool_use mcp__calc__add { a: 17, b: 25 }
门卫 → Allow? (y/N) → y
转发 → call_tool → "17 + 25 = 42" → tool_result → 自然语言回答
headless:
ALLOW_WRITE=1 bun run dev — "用 mcp__calc__add 计算 17+25"
Step 4:自己加 subtract
在 server.js 的 list / call 各加一项,重启 Agent(不热重载),再问「100 减 37」。
实现要点
工具名:mcp__<server>__<tool>
避免和内置 Read / Write 冲突:
mcp__calc__add
模型看到的是全名;适配层映射回 Server 原始名再 call_tool。
适配器:伪装成内部 Tool
adaptMcpTool 做四件事:起名、描述、宽松 Zod + 出站 JSON Schema、call() 转发 MCP。
adaptMcpTool('calc', { name: 'add', description: '…' }, callTool)
// → { name: 'mcp__calc__add', call: () => 转发 MCP, … }
之后与 Echo 同一条流水线:查找 → 校验 → 门卫 → call → tool_result。
权限:复用第六篇门卫
MCP 默认 isReadOnly: false:
| REPL | y/N |
| headless | 默认拒绝,除非 ALLOW_WRITE=1 |
readOnlyHint: true 时映射为只读、自动放行。
启动接线
const [{ systemPrompt, skills }, mcp] = await Promise.all([
loadSessionContext(),
loadMcpTools(),
])
const tools = sessionTools(mcp.tools)
// …
finally { await closeMcp?.() }
连接有超时(list 15s、call 30s);单个 server 失败则 stderr 警告并跳过。
和主循环的关系
L1 CLI → .mcp.json、合并 tools、门卫
L2 query() → 不变
L3 runToolUse → 不变
L4 适配 → services/mcp/
MCP 不改变 ReAct 循环,只改变「工具表从哪来」。
刻意没做什么?
| Resources / Prompts / … | 见概念篇 + examples/mcp-tour-server |
| Streamable HTTP / OAuth | 仅本地 stdio |
| 热重载 | 改配置需重启 |
完整版 Claude Code / Cursor 会做全能力;mini 验证的是:
配置 → 连接 → list_tools → 适配 Tool → 合并 → 复用 runToolUse
系列拼图
| 1–6 | 循环 → 代码库 → REPL → 上下文 → Skills → 门卫 |
| 7 | MCP 概念与六大能力 Demo |
| 8 | 本篇:mini 接线实现 |
带走什么?
仓库与链接
- GitHub:react-agent-mini
- 概念篇:mcp-concepts.md
- 计算器(接 Agent):examples/mcp-calc-server
- 概念 tour:examples/mcp-tour-server
- 配置模板:.mcp.json.example
- MCP 规范
欢迎 Star、Issue 和 PR。
本文基于 react-agent-mini 变更 v3-mcp(stdio MCP + 工具适配)撰写。


