mcp_tool Hooks, der direkte Draht in deinen MCP-Server
Claude Code v2.1.118 erlaubt Hooks die MCP-Tools direkt aufrufen. Was sich aendert, wann es passt, wann nicht.
Das Problem mit Bash-Wrapper-Hooks
In Lektion 4 hast Du gelernt wie Hooks funktionieren. Du schreibst einen Bash-Hook der dem Modell einen Hinweis gibt: "ruf jetzt nex_summarize auf bevor Du gehst". Das funktioniert, aber nur weil das Modell zuhoert. Manchmal ignoriert es den Hinweis. Manchmal ruft es das falsche Tool auf. Und Du merkst es erst Tage spaeter wenn Memory Luecken hat.
Am 23. April 2026 hat Claude Code in Version 2.1.118 einen neuen Hook-Type bekommen, der dieses Problem deterministisch loest: type: "mcp_tool".
Was der mcp_tool Hook ist
Statt Bash-Reminder schreibt Du den Tool-Call direkt in ~/.claude/settings.json:
{
"type": "mcp_tool",
"server": "studiomeyer-memory",
"tool": "nex_summarize",
"input": { "session_id": "${session_id}" },
"timeout": 60,
"statusMessage": "Memory: Auto-Summary..."
}
Fuenf Felder. Claude Code feuert den Tool-Call selbst, ohne dass das Modell beteiligt ist. Wenn der Server da ist und das Tool antwortet, ist die Sache erledigt. Wenn nicht, log und weiter. Hooks sind best-effort, nie kritischer Pfad.
Was Du substituieren kannst
In input kannst Du Werte aus dem Lifecycle einfliessen lassen:
${cwd}, current working directory${session_id}, UUID der aktuellen Session${tool_input.feld}, bei PostToolUse das Feld aus dem Tool-Input (z.B.${tool_input.file_path})${tool_name}, der Tool-Name (Pre/PostToolUse)${duration_ms}, Tool-Execution-Zeit (PostToolUse)${user_prompt}, der User-Prompt (UserPromptSubmit)
Damit feuerst Du nex_search mit { "query": "${user_prompt}" } auf jedem User-Input. Oder crm_log_interaction mit { "summary": "Edited ${tool_input.file_path}" } nach jedem File-Edit. Aus Reminder wird Aktion.
Die Fuenf-Punkte-Pruefung VOR dem Hook
Hooks feuern automatisch ohne explizite User-Zustimmung pro Aufruf. Bevor Du ein Tool in einen Hook steckst, MUSS es alle fuenf erfuellen:
- Idempotent. Mehrfacher Aufruf mit gleichem Input erzeugt das gleiche Ergebnis ohne kumulative Side-Effects.
nex_summarizeist idempotent.crm_create_companyist NICHT idempotent (erzeugt Duplikate). - Schnell. Default-Timeout ist 60 Sekunden, empfohlen unter 30 Sekunden bei synchronen Hooks (Stop, PreCompact). Wenn Dein Tool bei kalter DB-Connection 90 Sekunden braucht, scheitert der Hook lautlos.
- Deterministisch. Gleicher Input, gleiches (oder benigne-aequivalentes) Ergebnis. Kein
Math.random()ohne Snapshot. Keine "aktuelle Uhrzeit" als Output ausser Du gibst die Zeit explizit als Input. - Side-Effect-frei ohne expliziten User-Trigger. Read-Tools auf UserPromptSubmit duerfen nichts persistent veraendern. Schreib-Operationen nur wenn der User implizit zugestimmt hat (Edit/Write triggert log, das ist OK).
- DSGVO-bewusst. Der Hook feuert auf jedem matching Event. Wenn das Tool Daten an Drittparteien schickt (LLM-API, Logging), MUSS das im Recipe-README dokumentiert sein.
Ein Tool das einen der fuenf Punkte verletzt, kommt nicht in einen Hook. Punkt.
Wann mcp_tool, wann Bash
Nicht jede Workflow passt zu mcp_tool. Nutze Bash-Hooks (type: "command") wenn:
- Du mehrere Tool-Calls mit Logik dazwischen brauchst
- Du etwas aufrufen willst das kein MCP-Tool ist (CLI, curl, eigenes Script)
- Du das Result als JSON-Object brauchst das Claude Code aktiv nutzt
Nutze mcp_tool wenn:
- Du genau einen MCP-Tool-Call mit deterministischem Input willst
- Das Tool existiert, ist idempotent und schnell
- Du das Tool-Result nicht inspizieren oder modifizieren musst
Fuenf konkrete Bundles fuer unsere SaaS-MCPs
Wir haben 5 Hook-Bundles vorbereitet, eines pro StudioMeyer-SaaS-MCP:
| MCP | Was der Hook macht | Recipe |
|-----|---------------------|--------|
| Memory (studiomeyer-memory) | Stop -> nex_summarize + nex_session_end. PreCompact -> nex_summarize. UserPromptSubmit -> nex_search. SubagentStop -> nex_learn. | /recipes/16.2-memory-hook-bundle |
| CRM (studiomeyer-crm) | UserPromptSubmit -> crm_search bei Kunden-Namen. PostToolUse(Edit|Write) mit if-Filter -> crm_log_interaction bei E-Mail-Drafts. | /recipes/16.3-crm-hook-bundle |
| GEO (studiomeyer-geo) | Stop mit if=Edit(*.md) -> geo_check (auto-Audit nach Content-Edit). | /recipes/16.4-geo-crew-hook-bundle |
| Crew (studiomeyer-crew) | SessionStart -> crew_activate (Default-Persona je nach cwd). Stop -> crew_feedback. | /recipes/16.4-geo-crew-hook-bundle |
| Academy (mcp-academy) | SessionStart -> academy_stats + academy_next_lesson. UserPromptSubmit mit Trigger-Phrase -> academy_concept_search. | /recipes/16.5-academy-hook-bundle |
Jedes Bundle ist eine Recipe in Phase 16 der Academy. Du klickst Dich durch die Recipe, kopierst den JSON-Block in Deine ~/.claude/settings.json, und der Hook ist live.
Distribution: das ganze als Plugin installieren
Ab Phase 9 (Distribution) lernst Du wie Du eigene MCP-Server packagest. Das gleiche Prinzip gilt fuer Hook-Bundles: wir veroeffentlichen die fuenf SaaS-Hook-Bundles als Plugins im studiomeyer-io/studiomeyer-marketplace. Ein claude plugin install studiomeyer-memory-hooks und Du hast alle vier Memory-Hooks auf einmal aktiviert. Manuelle settings.json-Edits sind dann nur noch fuer Power-User die customizen wollen.
Anti-Pattern: alles automatisieren
Die Versuchung ist gross, jeden Lifecycle-Event mit einem Hook zu fuellen. Macht das nicht. Hooks sind best-effort und feuern still. Wenn 8 Hooks parallel Memory-Operations ausloesen und einer davon fehlerhaft ist, suchst Du im Dunkeln. Die Faustregel: ein Hook pro klar definiertem Use-Case. Memory braucht 4 Hooks, CRM braucht 2, GEO braucht 1, Crew braucht 2, Academy braucht 2. Das sind 11 Hooks insgesamt, mehr ist Overkill.
Naechste Lektion
In Lektion 11 (kommt) gibts die Fortsetzung: Plugin-Distribution. Wie Du aus Deinen eigenen Hook-Bundles ein installierbares Plugin machst. Das Pattern ist identisch zu MCP-Server-Distribution aus Phase 8.
Quellen
- Claude Code Hooks Reference (offiziell, inklusive
mcp_toolSchema seit v2.1.118) - Recipe 16.1: mcp_tool hook intro
- Recipe 16.2: Memory hook bundle