mcp-gorev-asistani
MCP Aufgabenassistent
Ein lehrreiches Projekt, das als einzelner Docker-Compose-Dienst läuft: Es sendet Benutzernachrichten an ein LLM bei Groq, das mithilfe von fünf MCP-Tools (list_tasks, list_tasks_by_priority, create_task, update_task, delete_task) eine In-Memory-Aufgabenliste verwaltet. Jede Aufgabe hat ein priority-Feld (Dringlichkeit: niedrig/mittel/hoch).
Was macht es?
Du sendest eine Nachricht in natürlicher Sprache an den Endpunkt POST /chat (z. B. „Docker-Aufgabe als erledigt markieren"). Der Chat-Server sendet diese Nachricht zusammen mit den Schemata der 5 verfügbaren MCP-Tools an Groq. Das Modell kann bei Bedarf nacheinander Tools aufrufen (z. B. zuerst list_tasks, um die ID zu finden); jeder Aufruf wird gegen das JSON-Schema validiert, über den echten MCP-Server ausgeführt und das Ergebnis dem Modell erneut angezeigt. Am Ende werden die Antwort in natürlicher Sprache und eine sichtbare Spur (trace) des gesamten Ablaufs gemeinsam zurückgegeben.
Related MCP server: MCP Project Manager
Architektur
Zwei separate Node.js-Prozesse kommunizieren im selben Container über JSON-RPC per stdio:
[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/Datei | Verantwortung |
| Aufgaben-CRUD, |
| Wandelt task-store in 5 MCP-Tools mit JSON-Schema um, lauscht auf stdio+JSON-RPC |
| Startet mcp-server als Child-Prozess, hält eine einzige (Singleton-)Verbindung |
| Sendet Anfragen an Groq, Konvertierung MCP-Schema → Groq-Tool-Format |
|
|
Installation und Ausführung
1) Groq-API-Schlüssel besorgen
Gehe auf https://console.groq.com/keys und melde dich an.
Erstelle mit „Create API Key" einen neuen Schlüssel und gib ihm einen beliebigen Namen (z. B.
mcp-aufgabenassistent).Kopiere den angezeigten Schlüssel (
gsk_...) – er wird nicht noch einmal angezeigt.
2) .env-Datei erstellen
cp .env.example .envÖffne die .env-Datei und füge deinen Schlüssel am Ende der Zeile GROQ_API_KEY= ein.
Hinweis: Der Wert von
GROQ_MODELkann sich im Laufe der Zeit ändern – Groq entfernt und fügt regelmäßig Modelle hinzu. So siehst du die aktuelle Liste:curl -s https://api.groq.com/openai/v1/models -H "Authorization: Bearer $GROQ_API_KEY"
3) Mit Docker Compose ausführen
docker compose up --build -dSo verfolgst du die Logs:
docker compose logs -fSobald du die Zeile Chat-Server läuft auf http://localhost:3000 siehst, ist alles bereit (Container-Port 3000, nach außen über compose.yaml als 3001 geöffnet – falls Port 3000 auf deinem Rechner belegt ist, kannst du die ports-Zeile in compose.yaml ändern).
Zum Beenden:
docker compose downTestnachrichten
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."}'Beispielantwort (3. Nachricht – beachte, dass die ID zuerst mit list_tasks ermittelt und dann an update_task übergeben wird):
{
"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 } }
]
}Die 4. Nachricht („Lösche die erledigte Aufgabe.") zeigte während des Tests ein interessantes Verhalten: Da in den Seed-Daten bereits eine erledigte Aufgabe existierte (id=3) und nach der 5. Nachricht eine weitere erledigte Aufgabe (id=2) hinzukam, stand das Modell vor zwei Optionen und fragte den Benutzer, welche gemeint sei, statt zu raten – ohne ein einziges Tool aufzurufen. Das ist ein erwartetes/gewünschtes Verhalten des Projekts (nicht die falsche Aufgabe löschen), kein Fehler.
Häufig gestellte Fragen
Warum musste ich für ein neues Tool (z. B. list_tasks_by_priority) nur 2 Dateien ändern?
Weil die Schichten app, mcp-client und groq die Tools überhaupt nicht fest verdrahten (hardcoden) – app fragt bei jeder Anfrage mit listMcpTools() beim mcp-server nach, „was hast du", und übergibt die zurückgegebene Liste unverändert an Groq. Um ein neues Tool zu definieren, genügt es also, (1) die Logik in task-store und (2) das Schema in mcp-server zu ergänzen – alles andere fließt automatisch. Das ist die konkrete Umsetzung der Entscheidung „Verantwortlichkeiten trennen" aus Schritt 1.
Warum gibt es keine Datenbank, sondern In-Memory-Daten?
Die Spezifikation verlangt das bewusst: Das Projekt soll das MCP-Protokoll und den Tool-Aufruf-Ablauf vermitteln; persistente Speicherung ist ein separates Thema und hätte unnötige Komplexität hinzugefügt. Map + Seed-Daten liefern das Verhalten „bei jedem Start mit einem sauberen Zustand beginnen" kostenlos mit.
Warum Docker Compose – hätte nicht ein einzelner node-Befehl gereicht?
Docker beseitigt das „bei mir funktioniert es"-Problem und garantiert, dass das Projekt auf jeder Maschine identisch läuft. Compose macht die Dienste (auch wenn es hier nur einer ist) standardmäßig mit einem einzigen Befehl startbar – eine Übung, die realen Installationen nahekommt.
Warum gibt es eine JSON-Schema-Validierung – hätte man Groq nicht vertrauen können?
Die LLM-Ausgabe ist nicht deterministisch – das Modell kann manchmal unvollständige oder falsch typisierte Argumente erzeugen. Ohne Validierung mit ajv direkt auf task-store zuzugreifen, könnte zu unerwarteten Fehlern oder inkonsistenten Daten führen. Die Validierung ist die Code-Entsprechung des Prinzips „traue dem LLM nicht, prüfe es".
Warum stehen die Tool-Definitionen im tools-Feld und nicht in der Systemnachricht?
Das tools-Feld ist ein strukturierter Vertrag in der Groq/OpenAI-API – das Modell behandelt es als echte, aufrufbare Funktionen und erzeugt die Antwort im strukturierten tool_calls-Format. Würden wir sie als Klartext in die Systemnachricht schreiben, würde das Modell sie nur als Kontext lesen, ohne Garantie oder Struktur für den Aufruf.
Warum startet mcp-client den mcp-server nicht bei jeder Anfrage neu? task-store lebt im RAM des mcp-server-Prozesses. Würde bei jeder Anfrage ein neuer Prozess gestartet, würden die Daten jedes Mal auf den Seed-Zustand zurückgesetzt – Änderungen aus früheren Nachrichten gingen verloren. Deshalb hält mcp-client, solange der app-Prozess läuft, genau EINE mcp-server-Verbindung (Singleton).
Warum reicht ein einziger Groq-Aufruf nicht – warum ist eine Schleife nötig?
Wenn der Benutzer „Markiere die Docker-Aufgabe" sagt, kennt das Modell deren ID nicht – es muss zuerst list_tasks aufrufen, um die richtige ID zu finden, und dann das Tool, das die eigentliche Aktion ausführt, mit dieser ID aufrufen. Das bedeutet mehrere aufeinanderfolgende Tool-Aufrufe in einer einzigen Anfrage; der starre Ablauf „fragen–ausführen–erklären" unterstützt das nicht, eine echte Schleife ist nötig.
Bekannte Einschränkungen / nicht produktionsreife Punkte
Keine Persistenz: Wenn der Container neu gestartet wird (oder abstürzt/neu deployed wird), gehen alle Aufgabendaten verloren. Für den echten Einsatz wäre eine Datenbank (Postgres, SQLite usw.) nötig.
Keine Mehrbenutzer-/Sitzungstrennung: Alle Benutzer teilen sich denselben task-store; es gibt keine Isolierung zwischen Benutzern (Multi-Tenancy).
Kein Gesprächsgedächtnis: Jede
/chat-Anfrage startet unabhängig. Der Benutzer kann nicht auf frühere Nachrichten Bezug nehmen (z. B. „lösche auch die") – Kontext bleibt nur innerhalb der Tool-Schleife derselben Anfrage erhalten.Nur ein gleichzeitiger Tool-Aufruf: Selbst wenn das Modell in derselben Runde mehrere Tools anfordert (parallele
tool_calls), wird nur der erste verarbeitet.Keine Authentifizierung/Autorisierung: Der
/chat-Endpunkt ist für alle offen, ohne jegliche Zugriffskontrolle.Keine Eingabegrößen-/Ratenbegrenzung (Rate Limiting): Bösartige oder fehlerhafte Clients können unbegrenzt Anfragen senden; die Groq-Rechnung kann entsprechend ansteigen.
Das Ajv-Schema wird bei jeder Anfrage neu kompiliert:
ajv.compile(...)könnte für die Leistung zwischengespeichert werden (im kleinen Maßstab fällt es nicht auf).Der Modellname kann mit der Zeit veralten: Der Modellkatalog von Groq ändert sich (während dieses Projekts wurde
llama-3.3-70b-versatileentfernt) –GROQ_MODELsollte regelmäßig überprüft werden.
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