MCP-learning
一个包含 MCP 客户端与示例 MCP Server 的学习型仓库(monorepo)。
mcp-client-typescript/: TypeScript 编写的 MCP 客户端(CLI),调用 Azure OpenAI 的 Chat Completions(function calling)能力,并通过 MCP 协议与外部工具交互。weather/: TypeScript 编写的示例 MCP Server,向客户端暴露工具(tools)。
目录结构
./
├─ README.md
├─ mcp-client-typescript/
│ ├─ src/index.ts
│ ├─ build/index.js
│ ├─ package.json
│ └─ tsconfig.json
└─ weather/
├─ src/index.ts
├─ build/index.js
├─ package.json
└─ tsconfig.json快速开始
1) 安装依赖并构建
cd weather && npm i && npm run build
cd ../mcp-client-typescript && npm i && npm run build2) 配置 Azure OpenAI 环境变量(mcp-client-typescript/.env)
AZURE_ENDPOINT="https://"
AZURE_API_KEY="" # 或设置 AZURE_OPENAI_API_KEY
AZURE_MODEL="" # 如 gpt-4o, gpt-4o-mini 等对应的部署名3) 启动客户端,连接示例 Server(以 weather 为例)
# 终端 A:直接运行客户端(会在 CLI 中提示输入 Query)
node /Users/Desktop/mcp-learning/mcp-client-typescript/build/index.js \
/Users/Desktop/mcp-learning/weather/build/index.js提示:客户端内部会启动一个基于 stdio 的 MCP 连接(StdioClientTransport)。serverScriptPath 传入的就是 Server 的可执行脚本(上例为 weather/build/index.js)。
mcp-client-typescript 工作原理(与 @index.ts 同步)
mcp-client-typescript/src/index.ts 的核心逻辑:
- 连接 MCP Server,获取其
tools列表,并将其转化为 Chat Completions 的函数调用工具描述(tools)。 - 会话循环
while (true)中:
- 将当前 messages 发给 Azure OpenAI 的 Chat Completions。 - 取得 assistant 响应: - 无论有无 tool_calls,先把该 assistant 消息完整(含 content 与 tool_calls 字段)追加进 messages。 - 若不存在任何 tool_calls,说明不需要再调用工具,本轮对话结束,直接返回。 - 若存在 tool_calls: - 逐个解析工具名与参数,调用 MCP Server 提供的对应工具。 - 工具调用成功:把结果以 role: "tool"、并带上对应的 tool_call_id 追加到 messages。 - 工具调用失败:把结构化错误也以 role: "tool"、并带上对应的 tool_call_id 追加到 messages。 - 继续下一轮 while (true),把最新的 messages(包含工具返回)再次发送给模型,让模型阅读工具结果进行二次推理或生成最终答案。
这样实现后,满足了 OpenAI/Azure 的函数调用协议约束:
- 任意
tool消息必须紧跟在包含tool_calls的assistant消息之后。 - 每条
tool消息必须携带与其对应的tool_call_id,供模型对齐。
错误信息 push 到 messages 的理念与格式
将“工具失败”视为一种“可供模型进一步思考的中间观测值”。因此:
- 工具失败时,不中断对话;将错误以
role: "tool"的消息推送回模型,模型可基于错误复盘、调整参数或更换策略,形成自修复闭环。 - 错误负载采用结构化 JSON,便于模型检索关键信息与制定下一步动作。
推荐错误负载结构:
{
"ok": false,
"toolName": "",
"args": { "...调用参数..." },
"error": {
"name": "Error",
"message": "具体错误信息",
"stack": "堆栈(如可用)"
},
"timestamp": "2025-10-20T08:00:00.000Z"
}工具调用与错误回传流程(中文流程图)
用户输入 Query
│
▼
Azure OpenAI Chat Completions(附 tools)
│
▼
返回 assistant(可能包含 tool_calls)
│
├─ 无 tool_calls → 追加 assistant 到 messages → 返回结果(对话回显/结束)
│
└─ 有 tool_calls → 追加完整 assistant(含 tool_calls)到 messages
│
├─ 遍历每个 tool_call:
│ ├─ 调用 MCP 工具(传入解析后的参数)
│ ├─ 成功 → 以 role:"tool" + tool_call_id 追加结果到 messages
│ └─ 失败 → 以 role:"tool" + tool_call_id 追加结构化错误JSON到 messages
│
▼
将更新后的 messages 再次发送给模型(形成“读工具结果→继续推理”的闭环)自修复与“自进化”建议
- 会话内自修复:上述闭环让模型能基于工具错误继续思考与重试,快速收敛到可行方案。
- 真正自进化:需要把“错误—修复”经验沉淀到会话之外(测试、文档、规则库、默认参数模板,或自动生成 PR ),从而长期提升能力。
- 建议为错误引入分级与策略:
- 可重试(网络/限流)→ 指数退避、限制最大重试次数 - 可修复(参数/权限)→ 自动校正参数、请求权限或切换工具 - 不可修复(缺资源/策略)→ 直接反馈用户与记录
常见问题(Troubleshooting)
- 报错:
Invalid parameter: messages with role 'tool' must be a response to a preceeding message with 'tool_calls'.
- 处理:确保先将包含 tool_calls 的 assistant 消息追加到 messages,随后再追加对应的 tool 消息。
- 工具错误对象被串成
[object Object]
- 处理:对错误进行结构化序列化(name/message/stack),并以 JSON 字符串化后写入 content。
运行与开发小贴士
weather是一个示例 MCP Server,你可以按需扩展其工具集合。mcp-client-typescript的processQuery采用永真循环,仅当当前轮assistant不再包含tool_calls时返回,避免过早终止导致工具结果无法被模型消费。- 本仓库使用 ESM(
"type": "module")。
若你在本仓库上继续扩展,请优先更新本 README 的“目录结构”和“工作原理”章节,保持文档与实现同步。
