MCP计算器(TypeScript)
现场演示 --不安装任何东西就尝试一下
为什么存在
大多数AI教程都用幻灯片或伪代码解释概念。这个项目采取了不同的方法: 你通过阅读一个可用的应用程序来学习.
该领域故意简单(计算器),因此您可以完全专注于AI模式。每个函数都以它所教授的概念命名。这段代码读起来像教科书一样自上而下。
我构建这个是因为当我开始构建人工智能应用程序时,我想要一个小的代码库,展示所有部分是如何组合在一起的——MCP、工具调用、代理循环、思维链、即时工程——用真正的HTTP请求、真正的LLM调用和真正的工具执行端到端地连接起来。这就是代码库。
你将学到什么
五个AI工程概念,都在代码中可见:
| # | 概念 | 代码中的位置 |
|---|---|---|
| 1 | MCP(模型上下文协议) --LLM如何发现和调用外部工具 | calculator-server.ts, initializeMcp() |
| 2 | 工具调用 --LLM选择一个函数和参数,代码运行它 | convertMcpToolsToOpenAiFormat(), executeSingleToolCall() |
| 3 | 代理循环 --LLM是一个循环:思考、行动、观察、重复 | runAgenticLoop() |
| 4 | 思维链 --法学硕士在选择工具之前“大声思考” runAgenticLoop(),寻找 llm_chain_of_thought | |
| 5 | 提示工程 --系统提示如何塑造LLM行为 | buildConversation() |
这是给谁的
- 学习MCP的工程师 --查看握手、发现和工具执行端到端工作
- 人们正在构建他们的第一个人工智能代理 --这里的代理循环与生产代理使用的模式相同,只是更小
- 任何对工具调用感兴趣的人 --观察LLM决定调用哪个函数以及使用什么参数
- TypeScript开发人员 --严格的类型,每个边界的Zod验证,干净的项目结构
不需要AI经验。如果你能阅读TypeScript并理解HTTP请求,你就可以遵循这段代码。
5分钟快速入门
先决条件: Node.js>=20,一个OpenAI API密钥
# 1. Clone
git clone https://github.com/madhusudankapoor/mcpcal.git
cd mcpcal
# 2. Install and build
npm install
npm run build
# 3. Add your OpenAI key
echo 'OPENAI_API_KEY=sk-...' > .env
# 4. Start (backend auto-spawns MCP server)
npm run start:client试试这三件事:
- 点击
5 + 3 =--观看学习控制台显示MCP阶段(握手→ 发现→ 执行) - 类型
what is 5 + 3?在聊天中——单轮代理循环(LLM调用一个工具,得到答案) - 类型
what is 4 * 4 * 4?在聊天中——多轮代理循环(LLM调用在3轮中加倍)
底部的学习控制台显示了每一步:发送到LLM的内容、返回的内容、选择的工具以及循环如何收敛到答案。
或者完全跳过设置,使用 现场演示.
建筑
┌─────────────────────────────────────────────────────────────────┐
│ YOUR MACHINE │
│ │
│ ┌──────────────┐ HTTP ┌───────────────────────────┐ │
│ │ Browser UI │ ────────────> │ Express Backend │ │
│ │ │ │ (client-backend.ts) │ │
│ │ Calculator │ POST /chat │ │ │
│ │ buttons │ ────────────> │ 1. Receives user message │ │
│ │ │ │ 2. Talks to OpenAI │ │
│ │ Chat input │ │ 3. Executes MCP tools │ │
│ │ │ JSON response│ 4. Talks to OpenAI again │ │
│ │ Chat output │ │ (same server, │
│ same tools, │
Chat message: │ same result) │
LLM picks tool │ │
─────────────────>│ │
└─────────────────────────┘MCP生命周期
第一阶段:启动握手
启动时,后端将MCP服务器作为子进程生成,并通过stdio连接:
Backend MCP Server
│ spawn process + connect │
│ ────────────────────────────> │
│ handshake + capabilities │
│ │
│ [add, subtract, multiply, │
│ divide] with JSON Schemas │
│ type: "function",
description: "Add function: {
two numbers", name: "add",
inputSchema: { description: "Add two numbers",
properties: { parameters: {
a: {type:"number"}, properties: {
b: {type:"number"} a: {type:"number"},
} b: {type:"number"}
} }
} }
}如果MCP服务器明天添加了一个新工具,LLM将自动访问它。无需更改代码。
第3阶段:工具执行
对于按钮点击:
Browser Backend MCP Server
│ POST /calculate │ │
│ {tool:"add", │ │
│ args:{a:5, b:3}} │ │
│ ──────────────────────> │ callTool("add",{a:5,b:3})│
│ │ ──────────────────────> │
│ │ {ok:true, result:8} │
│ │ .envAPI终点
GET /tools
返回发现的工具:
{
"tools": [
{
"name": "add",
"description": "Add two numbers together",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number", "description": "First number" },
"b": { "type": "number", "description": "Second number" }
},
"required": ["a", "b"],
"additionalProperties": false
}
}
]
}POST /calculate
{ "tool": "divide", "args": { "a": 5, "b": 2 } }成功: { "result": 2.5, "expression": "5 / 2" }
错误: { "error": "Division by zero is not allowed.", "details": "Provide a non-zero divisor." }
POST /chat
{ "message": "what is 10 times 5?" }成功:
{
"response": "10 times 5 equals 50.",
"toolCalls": [
{
"tool": "multiply",
"args": { "a": 10, "b": 5 },
"result": { "ok": true, "result": 50 }
}
]
}GET /healthz
退货 { "status": "ok" }.
GET /mcp-events
返回跟踪历史快照。
GET /mcp-events/stream
实时服务器发送的跟踪事件流。
贡献
欢迎捐款。这是一个教育项目,所以清晰比聪明更重要。
如何做出贡献:
- 分叉回购
- 创建分支(
git checkout -b my-change) - 进行更改
- 确保
npm run build通过 - 打开拉取请求
良好的首次贡献:
- 添加新的MCP工具(例如。,
modulo,power)--服务器、类型和UI都需要更新 - 改进学习控制台解释
- 添加测试
- 修复代码注释或README中的拼写错误或措辞不清楚
指导方针:
- 保持代码简单易读——这是一个教学工具
- 每个函数都应该以它的作用命名
- 对JSDoc长篇论文的简短评论
- 如果您添加了功能,请更新README
许可证
麻省理工学院
为什么选择MCP作为计算器?
对于真正的数学,MCP是多余的。这个项目具有教育意义。
当工具是远程的、异构的,或者需要跨多个客户端和服务器进行标准化发现时,MCP变得很有用。这个计算器显示了一个足够小的代码库中的所有模式(握手、发现、执行、代理循环),可以一次读取。
