← Zum Blog
Blog

Zwei Wochen mit mcp_tool Hooks im Daily Driver

Bash-Wrapper-Hooks waren bis April der Standard. Seit Claude Code 2.1.118 gibt es type mcp_tool. Was wir umgestellt haben, was geknallt hat, was hilft.

29. Mai 2026
Memory-Hooks hatte ich im April durchverdrahtet. Bash-Wrapper-Script, das dem Modell einen Hint in den Context schreibt, "ruf nex_summarize bevor Du gehst". 47 Sessions über zwei Wochen. 38 OK. 6 vom Modell ignoriert. 3 mit falschem Tool-Call, er rief nex_search statt nex_summarize. Macht 19 Prozent Failure-Rate. Bei einem System das Memory-Persistenz garantieren soll ist 19 Prozent zu hoch. Am 23. April kam Claude Code 2.1.118 mit einem neuen Hook-Type, `mcp_tool`. Statt das Modell zu bitten, ruft Claude Code den Tool-Call selbst. Kein Bash, kein Hint, keine Modell-Latenz. Wenn der Server antwortet ist die Sache durch. Wenn nicht, log und weiter. In den zwei Wochen seit dem Switch hab ich die fünf Hook-Bundles für unsere SaaS-MCPs umgestellt. Memory, CRM, GEO, Crew, Academy. Hier ist was geblieben ist. ## Das Konzept in fünf Zeilen JSON Statt einem Bash-Script mit Heredoc-Hint schreibst Du das in `~/.claude/settings.json`: ```json { "type": "mcp_tool", "server": "studiomeyer-memory", "tool": "nex_summarize", "input": { "session_id": "${session_id}" }, "timeout": 60 } ``` Fünf Felder. `${session_id}` wird zur Laufzeit substituiert. Claude Code feuert den Tool-Call selbst gegen den schon connecteten MCP-Server. Das Tool-Result kommt nicht zurück ins Modell, der Hook ist best-effort. Genau wie ein Bash-Hook nur ohne den Bash-Wrapper. ## Was uns das gelöst hat Die 19 Prozent Failure-Rate ist auf 0 gefallen. Nicht weil die MCP-Tools besser geworden sind, sondern weil das Modell nicht mehr im Loop ist. Bei 23 Sessions seit dem Umstieg keine einzige fehlende Summary mehr. Latenz ist auch runter. Bash-Hooks brauchten 800ms bis 2 Sekunden, weil das Modell den Prompt sehen, parsen und einen Tool-Call generieren musste. Der `mcp_tool` Hook ist ein direkter Call auf den schon laufenden Server, median 380ms in unserem Setup. Die schönste Konsequenz, Latenz-Budgets sind planbar. Du setzt `timeout: 60`, der Hook scheitert lautlos wenn der Server hängt und blockiert nichts. Beim Bash-Wrapper musste ich vorher manuell Trace-Logs schreiben um zu wissen ob das Modell überhaupt zugehört hat. ## Was geknallt hat Drei Sachen die ich falsch gemacht hab. Erstens, ich hab `crm_create_company` in einen Hook gesteckt. PostToolUse(Write) sollte automatisch eine neue Firma anlegen wenn ich eine Datei mit Firmenname schreibe. Klang clever. Wurde 14 Mal innerhalb von zwei Stunden gefeuert, weil ich die gleiche Datei mehrfach editiert habe. 14 Duplikate in der CRM-DB, alle mit den gleichen Daten. `crm_create_company` ist nicht idempotent. Hooks brauchen idempotente Tools, sonst kumulieren Side-Effects. In der Lesson L4-10 steht das als Punkt 1 von fünf, in der Praxis hab ich es ignoriert. Zweitens, ich hab UserPromptSubmit auf `nex_search` geschickt ohne Trigger-Phrase. Bei jeder User-Eingabe wurde Memory durchsucht. 380ms Median, aber bei 200 Prompts pro Tag macht das 76 Sekunden Overhead nur für "guten Morgen" und "ja danke" Eingaben. Lösung war ein `if`-Filter auf "@memory" als Schlüsselwort. Jetzt feuert der Hook nur wenn ich explizit Memory will. 12 Aufrufe pro Tag statt 200. Drittens, der `${tool_input.file_path}` Bug. Bei PostToolUse(Edit) wollte ich `${tool_input.file_path}` in `crm_log_interaction` einfliessen lassen. Hat zwei Tage nicht funktioniert weil ich das Feld in einem Tool-Schema falsch gelesen hatte. Hook hat lautlos ein leeres String-Field reingeschrieben und ich hab die leeren CRM-Logs erst gesehen als ich nach einer alten Kunden-Mail gesucht habe. Lesson, jeder neue Hook braucht einen Probe-Lauf mit einem echo-MCP-Tool das nur den Input zurückspiegelt, bevor das echte Tool drin steht. ## Was ich jetzt anders mache Vier Regeln die seit dem Umstieg gehalten haben. Jedes Tool das in einen Hook soll, muss die Fünf-Punkte-Prüfung bestehen die in der Lesson [L4-10 mcp_tool Hooks](/levels/4/10-mcp-tool-hooks) steht, idempotent, schnell, deterministisch, side-effect-frei ohne expliziten User-Trigger, DSGVO-bewusst. Punkt 1 hatte ich beim CRM-Hook ignoriert. Macht man nicht zweimal. Jeder neue Hook geht in eine 24-Stunden Observation-Phase. Telegram-Alert wenn er feuert, aber kein scharfer Tool-Call. Erst wenn ich sehe dass die Felder stimmen und der Trigger nicht zu oft zieht, kommt das echte Tool rein. Trigger-Phrasen auf UserPromptSubmit. Nicht jeder Prompt soll Memory triggern. `@memory`, `@crm`, `@geo` als explizite Schlüsselwörter. Saubere Trennung zwischen "ich rede mit Claude" und "ich rede mit der Memory-Schicht". Recipe-Dokumentation Pflicht. Jeder Hook in `settings.json` hat einen Verweis auf das passende Recipe in `/recipes/16.x-...`, das dokumentiert was der Hook macht, warum, und wann Du ihn abschaltest. Sonst sammelt sich ein Settings-Friedhof an. ## Was als nächstes In Phase 16 haben wir fünf Hook-Bundles fertig, jeweils ein Recipe pro SaaS-MCP. Memory war der erste, CRM und GEO sind seit gestern live. Crew und Academy folgen diese Woche. Wenn Du selber gerade von Bash-Wrapper auf `mcp_tool` umsteigst, der Playbook [hooks-debuggen-wenn-nichts-feuert](/playbooks/hooks-debuggen-wenn-nichts-feuert) deckt die häufigsten Fallen ab. Die offizielle Anthropic-Doku zum Hook-Type steht auf [code.claude.com/docs/en/hooks](https://code.claude.com/docs/en/hooks), das ist meine Pflicht-Lektüre bevor ich ein neues Hook-Bundle aufsetze. Bash-Wrapper-Hooks haben noch ihre Berechtigung. Wenn Du mehrere Tool-Calls verketten musst oder das Result inspizieren willst, führt kein Weg am `command` Hook vorbei. Aber für den 80-Prozent-Fall, ein einzelner deterministischer Tool-Call auf ein Lifecycle-Event, ist `mcp_tool` der neue Default. Zwei Wochen, 0 Failures auf der Memory-Schicht, planbare Latenz-Budgets. Den Rückweg würde ich nicht mehr gehen.
← Weitere Blog-Posts