mcp-gorev-asistani
MCP 任务助手
这是一个教学项目,以单个 Docker Compose 服务运行,将用户消息发送给 Groq 上的 LLM,让 LLM 使用五个 MCP 工具(list_tasks、list_tasks_by_priority、create_task、update_task、delete_task)来管理一个内存中的任务列表。每个任务都有一个 priority(优先级:低/中/高)字段。
它做什么?
你向 POST /chat 端点发送一条自然语言消息(例如"将 Docker 任务标记为已完成")。聊天服务器将该消息连同其拥有的 5 个 MCP 工具的 schema 一起发送给 Groq。模型可以连续调用工具(例如先调用 list_tasks 来查找 id);每次调用都会根据 JSON Schema 进行验证,通过真实的 MCP 服务器执行,并将结果再次展示给模型。最后,自然语言回复和整个过程的可见追踪记录(trace)会一起返回。
Related MCP server: MCP Project Manager
架构
两个独立的 Node.js 进程,在同一个容器内,通过 stdio 上的 JSON-RPC 进行通信:
[app sureci] [mcp-server sureci]
Express (/chat) (child process, stdio ile baslatiliyor)
|- groq/ --HTTP--> Groq API
`- mcp-client/ --stdio/JSON-RPC--> mcp-server/ --> task-store/文件 | 职责 |
| 任务 CRUD,基于 |
| 将 task-store 转换为带 JSON Schema 的 5 个 MCP 工具,监听 stdio+JSON-RPC |
| 以子进程方式启动 mcp-server,保持单一(单例)连接 |
| 向 Groq 发送请求,将 MCP schema 转换为 Groq 工具格式 |
|
|
安装与运行
1) 获取 Groq API 密钥
访问 https://console.groq.com/keys 并登录。
点击"Create API Key"创建新密钥,名称可随意填写(例如
mcp-gorev-asistani)。复制显示的密钥(
gsk_...)——它不会再次显示。
2) 创建 .env 文件
cp .env.example .env打开 .env 文件,将你的密钥粘贴到 GROQ_API_KEY= 行的末尾。
注意:
GROQ_MODEL的值可能会随时间变化——Groq 会不时移除和添加模型。要查看最新列表:curl -s https://api.groq.com/openai/v1/models -H "Authorization: Bearer $GROQ_API_KEY"
3) 使用 Docker Compose 运行
docker compose up --build -d查看日志:
docker compose logs -f看到 Chat sunucusu http://localhost:3000 adresinde calisiyor. 这一行就表示就绪了(容器内端口为 3000,通过 compose.yaml 对外映射为 3001——如果你本机的 3000 端口被占用,可以修改 compose.yaml 中的 ports 行)。
停止运行:
docker compose down测试消息
curl -X POST http://localhost:3001/chat -H "Content-Type: application/json" \
-d '{"message": "Hangi görevlerim var?"}'
curl -X POST http://localhost:3001/chat -H "Content-Type: application/json" \
-d '{"message": "JSON Schema öğrenmek için bir görev ekle."}'
curl -X POST http://localhost:3001/chat -H "Content-Type: application/json" \
-d '{"message": "Docker görevini tamamlandı olarak işaretle."}'
curl -X POST http://localhost:3001/chat -H "Content-Type: application/json" \
-d '{"message": "Tamamlanan görevi sil."}'示例回复(第 3 条消息——注意 id 是先通过 list_tasks 找到,然后传给 update_task 的):
{
"answer": "\"Docker Compose kur\" görevi tamamlandı olarak işaretlendi.",
"trace": [
{ "tool": "list_tasks", "arguments": {}, "validation": "passed",
"result": { "tasks": [ { "id": 1, "title": "MCP sartnamesini oku", "completed": false },
{ "id": 2, "title": "Docker Compose kur", "completed": false },
{ "id": 3, "title": "Groq API anahtarini al", "completed": true } ] } },
{ "tool": "update_task", "arguments": { "completed": true, "id": 2 }, "validation": "passed",
"result": { "id": 2, "title": "Docker Compose kur", "completed": true } }
]
}第 4 条消息("删除已完成的任务。")在测试过程中表现出一个有趣的行为:由于种子数据中已经有一个已完成的任务(id=3),并且在第 5 条消息之后又产生了一个已完成的任务(id=2),模型在两个选项之间犹豫,没有猜测而是询问用户指的是哪一个——没有调用任何工具。这是项目预期/期望的行为(不删除错误的任务),而不是错误。
常见问题
为什么添加一个新工具(例如 list_tasks_by_priority)只需要修改 2 个文件?
因为 app、mcp-client 和 groq 层完全没有硬编码工具——app 在每次请求时通过 listMcpTools() 向 mcp-server 询问"你有哪些工具",并将返回的列表原样传递给 Groq。也就是说,要定义一个新工具,只需 (1) 在 task-store 中添加逻辑,(2) 在 mcp-server 中添加 schema——其余一切都会自动流转。这是第 1 步中"分离职责"决策的具体体现。
为什么没有数据库,而是使用内存数据?
规格说明有意如此要求:该项目旨在教授 MCP 协议和工具调用流程,持久化存储是另一个话题,会带来不必要的复杂性。Map + 种子数据免费提供了"每次启动都从干净状态开始"的行为。
为什么用 Docker Compose,单个 node 命令不够吗?
Docker 消除了"在我机器上能跑"的问题,保证项目在任何机器上都能以相同方式运行。Compose 则让服务(即使这里只有一个服务)能够以标准、单命令的方式启动——更接近真实世界的部署练习。
为什么需要 JSON Schema 验证,信任 Groq 不够吗?
LLM 的输出不是确定性的——模型有时会生成缺失或类型错误的参数。如果不通过 ajv 验证就直接进入 task-store,可能会导致意外错误或数据不一致。验证是"不要信任,要验证"原则的代码体现。
为什么工具定义放在 tools 字段而不是系统消息中?
tools 字段是 Groq/OpenAI API 中的结构化契约——模型将其视为真实、可调用的函数,并以结构化的 tool_calls 格式生成响应。如果我们以纯文本形式写在系统消息中,模型只会将其视为上下文,不会有调用保证或结构。
为什么 mcp-client 不在每次请求时重启 mcp-server? task-store 存在于 mcp-server 进程的 RAM 中。如果每次请求都启动新进程,数据每次都会重置为种子状态——之前消息中做的修改就会丢失。因此,只要 app 进程存活,mcp-client 就保持单一的 mcp-server 连接(单例)。
为什么一次 Groq 调用不够,需要循环?
当用户说"标记 Docker 任务"时,模型不知道它的 id——它需要先调用 list_tasks 找到正确的 id,然后用该 id 调用执行实际操作的工具。这意味着在单个请求中需要多次连续的工具调用;固定的"提问-执行-回答"流程无法支持这一点,需要真正的循环。
已知缺陷 / 尚未达到生产就绪的方面
无持久化:如果容器重启(或崩溃/重新部署),所有任务数据都会丢失。实际使用中需要数据库(Postgres、SQLite 等)。
无多用户/会话隔离:所有用户共享同一个 task-store;没有用户间隔离(多租户)。
无对话记忆:每次
/chat请求都是独立开始的。用户无法引用之前的消息(如"把那个也删了")——只有同一请求内的工具循环期间才保持上下文。单次并发工具调用:即使模型在同一轮中请求多个工具(并行
tool_calls),也只处理第一个。无身份验证/授权:
/chat端点对所有人开放,没有任何访问控制。无输入大小/速率限制:恶意或有缺陷的客户端可以无限发送请求,Groq 账单会相应膨胀。
Ajv schema 在每次请求时重新编译:
ajv.compile(...)本可以缓存以提升性能(在小规模下差别不大)。模型名称可能随时间过时:Groq 的模型目录会变化(在项目期间
llama-3.3-70b-versatile已被移除)——应定期检查GROQ_MODEL。
This server cannot be deployed
Maintenance
Related MCP Connectors
Manage Superlist tasks and lists in plain language from any MCP-compatible AI agent.
Local-first task manager: create, edit, and complete tasks, projects, and checklists via MCP.
Create, list, and complete todo items through MCP.
- DazbenchOAuthapp.dazbench
Task management your AI agents can actually run. One line becomes a context-ready task over MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA simple, powerful Todo list manager for Claude Desktop and other MCP-compatible AI assistants. Organize your tasks across different projects with priorities and never lose track of what needs to be done!15 npm2MIT
- FlicenseAqualityDmaintenanceEnables task management (create, list, update tasks with priority and status) using SQLite storage via MCP tools.3-
- FlicenseNot gradedqualityDmaintenanceA task manager MCP server that demonstrates all three MCP primitives (tools, resources, prompts). Enables users to manage tasks, read task summaries and details, and run structured planning/review prompts through natural language.-
- AlicenseNot gradedqualityAmaintenanceMCP server for Riah To-Do, enabling AI to manage priorities via tools like get_priorities, replace_priorities, add_priority, set_priority_completed, and remove_priority.MIT