Was ich beim Bau eines MCP-Servers für ein Entwickler-Tool gelernt habe

MCP

Das Model Context Protocol ist ein Standard, mit dem man einem KI-Agenten eine Reihe von Tools in die Hand gibt. Du beschreibst, was dein Produkt kann, der Client des Agenten verbindet sich, und ab dann ruft der Agent diese Tools mitten im Gespräch auf, so wie er eine Datei liest oder einen Befehl ausführt.

Die Spezifikation ist klein, und die Implementierung ist nicht der schwierige Teil. Ein funktionierender Server ist an einem Nachmittag gebaut. Dass ein Agent ihn richtig benutzt – ohne IDs zu raten, ohne das Falsche abzurufen, ohne aus einer leeren Ausgabe selbstsicher zu schließen, dass es keine Daten gibt –, hat echte Designarbeit gekostet.

Hier sind die Entscheidungen, auf die es ankam, als ich den MCP-Server von BugDump veröffentlicht habe. Sie gelten für jedes Entwickler-Tool, das einen eigenen MCP-Server bekommen soll.

Was MCP überhaupt ändert

Ohne MCP ist der Mensch die Integration. Wer einen Agenten mit deinem Produkt arbeiten lassen will, öffnet dein Dashboard, sucht die passenden Daten, kopiert sie und fügt sie ins Gespräch ein. Jedes Stück Kontext wird von Hand herübergetragen, und so hat der Agent genau so viel Kontext, wie die Person zu kopieren bereit ist.

Mit MCP holt sich der Agent die Daten selbst. Bei BugDump ist das konkret der Unterschied zwischen:

Hier ist ein Fehlerbericht. [fügt 200 Zeilen Console-Ausgabe ein]

und:

Schau dir Aufgabe #42 in BugDump an und behebe sie.

In der zweiten Version holt der Agent die Aufgabe, listet ihre Berichte auf, liest die Console- und Netzwerk-Telemetrie, gleicht den Stack-Trace mit den echten Quelldateien im Repository ab und schlägt eine Änderung vor. Niemand hat das Dashboard geöffnet. Der Agent hatte den ganzen Bericht vor sich, nicht nur den Teil, den ein Mensch für kopierenswert hielt. Und genau dieses Urteil, was kopierenswert ist, soll das Debugging erst liefern, nicht schon voraussetzen.

Darin liegt der Gewinn, und deshalb lautet das Designziel nicht „die API freigeben“, sondern „eine API freigeben, in der sich ein Agent ohne Landkarte zurechtfindet“.

1. Binde den Schlüssel dauerhaft an einen Scope

In meinem ersten Entwurf hatte jedes Tool einen Projekt-Parameter. Das war die naheliegende Übersetzung der REST-API, und sie war gleich doppelt falsch.

Falsch für die Sicherheit. Ein MCP-Schlüssel liegt in einer Konfigurationsdatei und wird von einem autonomen Prozess benutzt. Der Schaden, den dieser Schlüssel anrichten kann, sollte so klein sein, wie es die Aufgabe zulässt.

Falsch für die Bedienbarkeit. Bekommt ein Agent einen Parameter projectId, aber keine Projekt-ID, versucht er trotzdem, ihn zu füllen. Er rät proj_1. Er übergibt den Namen des Projekts. Er erfindet etwas Plausibles, bekommt einen Fehler und probiert die nächste Erfindung. Ein Parameter, der sich raten lässt, wird geraten.

Deshalb ist ein MCP-Schlüssel von BugDump dauerhaft an genau ein Projekt gebunden, und kein Tool nimmt ein Projekt-Argument. Da gibt es nichts zu raten. Fragt jemand nach einem anderen Projekt, kann der Server nur sagen, für welches Projekt dieser Schlüssel gilt. Dafür gibt es das Tool get_current_project: Es existiert nur, damit sich der Agent orientiert, statt zu spekulieren.

Die allgemeine Regel: Jeden Parameter, den ein Agent nicht aus einer vorherigen Ausgabe ableiten kann, wird er halluzinieren. Entferne ihn oder mach ihn auffindbar.

2. Entwirf die Drill-down-Kette ausdrücklich

Meine Tools bilden eine bewusst gewählte Reihenfolge:

Plain Text
list_tasks            → find a task, get its taskId
get_task              → read one task
list_reports_for_task → list a task's reports, get each reportId
get_report            → read one report
get_report_telemetry  → page through everything in that report

Jede ID, die ein Tool bekommt, muss aus einer vorherigen Antwort stammen. Genau so steht es in den Server-Instruktionen, zusammen mit dem ausdrücklichen Verbot, IDs selbst zu bauen.

Der Fehler, den das verhindert, ist subtil und teuer. Agenten parallelisieren aggressiv, und meistens zu Recht. Aber ein Agent, der get_report-Aufrufe parallel absetzt, bevor er auch nur eine Berichts-ID hat, erfindet die IDs, bekommt sieben Fehler zurück und verbrennt eine Menge Kontext, um sich davon zu erholen. Behoben wird das durch den Satz: Parallele Aufrufe sind nur mit IDs sicher, die du schon hast.

3. Akzeptiere die IDs, die Menschen wirklich benutzen

Aufgaben in BugDump haben eine UUID und eine öffentliche ID, die als #42 angezeigt wird. Menschen sagen „Aufgabe 42“. Niemand hat je „Aufgabe 9f8c1a4e-...“ gesagt.

get_task akzeptiert beides. Ein kleines Entgegenkommen mit unverhältnismäßig großer Wirkung, weil es eine ganze Klasse gescheiterter erster Versuche beseitigt. Der Agent probiert, was der Mensch gesagt hat, und es klappt.

Schau, welche ID in deinem Team in Slack getippt wird. Genau die sollte dein Tool akzeptieren.

4. Liefere standardmäßig Zusammenfassungen, aber sag, was du gekürzt hast

Ein einzelner Fehlerbericht kann Tausende Console-Einträge enthalten, Hunderte Netzwerk-Requests mit Bodys, Screenshots und ein Session-Replay. Käme das alles standardmäßig zurück, wäre der Kontext des Agenten schon nach dem ersten Aufruf voll, und für die eigentliche Arbeit bliebe kein Platz.

Deshalb liefert get_report standardmäßig eine kompakte Zusammenfassung: die letzten Console-Einträge und die Metadaten der Netzwerk-Requests, ohne Bodys.

Entscheidend ist der nächste Satz in der Antwort. Die Zusammenfassung sagt, was gekürzt wurde. Nicht stillschweigend, sondern ausdrücklich, im Payload selbst.

Stilles Abschneiden ist das Schlimmste, was ein Tool tun kann, weil dabei kein Fehler entsteht. Es entsteht eine selbstsichere falsche Antwort. Ein Agent, der ein gekürztes Netzwerk-Log ohne jeden Hinweis auf die Kürzung bekommt, meldet, es habe keine fehlgeschlagenen Requests gegeben. Dass das falsch war, merkt erst viel später jemand.

Das ist dieselbe Disziplin wie --max-count bei einem Suchwerkzeug: Melde das Limit, an das du gestoßen bist. Wenn dein Tool irgendetwas begrenzt, gehört die Grenze in die Ausgabe.

5. Gib dem Agenten einen Weg zum Rest

Eine Zusammenfassung ist nur dann in Ordnung, wenn es auch einen vollständigen Abruf gibt. Dafür gibt es get_report_telemetry: Es blättert in chronologischen Abschnitten durch die Console, das Netzwerk mit Bodys oder die Interaktionen, mit offset und nextOffset und einem Flag hasMore, das auf false springt, wenn der Stream zu Ende ist.

Zwei Eigenschaften machen das für einen Agenten brauchbar, nicht nur für ein Programm.

Chronologische Abschnitte statt beliebiger. Weil nach Zeit sortiert wird, ergibt auch ein teilweiser Abruf Sinn. Ein Agent, der die ersten beiden Seiten holt, kennt den Anfang der Geschichte, keine zufällige Stichprobe daraus.

Eine ausdrückliche Abbruchbedingung. hasMore: false ist eine Tatsache, nach der der Agent handeln kann. „Das Array kam kürzer zurück als das Limit“ ist eine Schlussfolgerung, und bei Schlussfolgerungen am Ende langer Tool-Schleifen werden Agenten kreativ.

6. Schreib die Instruktionen für den Agenten, nicht für Menschen

MCP-Server bringen einen Block mit Instruktionen mit, der im Kontext des Agenten landet. Die Versuchung ist groß, dort Werbetext unterzubringen. Viel besser nutzt du den Platz für das, was sich aus den Tool-Schemas nicht ableiten lässt:

  • In welcher Reihenfolge die Tools aufgerufen werden müssen

  • Das Verbot, IDs zu erfinden

  • Welche Aufrufe sich parallelisieren lassen und welche nicht

  • Was „die Zusammenfassung zeigt nichts“ bedeutet und was nicht

Der letzte Punkt hat sich seinen Platz verdient. Meine Instruktionen sagen sinngemäß: Die Zusammenfassung sagt dir, was gekürzt wurde, also nimm nicht an, dass „die Zusammenfassung zeigt nichts“ heißt „da ist nichts“. Dieser eine Satz verhindert einen ganz bestimmten Fehlschluss, den ich Agenten habe ziehen sehen.

Behandle den Instruktionsblock wie eine Notiz für ein fähiges Teammitglied, das mitten in einer Aufgabe dazukommt. Die Typsignaturen kann es selbst lesen. Es braucht das, was man sonst erst lernt, wenn man es falsch gemacht hat.

7. Reiner Lesezugriff ist ein Feature

Der MCP-Server von BugDump bietet sieben Tools, und alle sieben lesen. Keins legt eine Aufgabe an, schließt eine oder schreibt einen Kommentar.

Das war eine bewusste Entscheidung, keine offene Baustelle. Der Workflow, für den der Server da ist, ist die Untersuchung: Belege holen, mit dem Code abgleichen, einen Fix vorschlagen. Die schreibende Hälfte des Workflows – entscheiden, ob ein Bug echt ist, ob er ein Duplikat ist, ob er erledigt ist – ist die Stelle, an der menschliches Urteil die eigentliche Arbeit leistet.

Dazu kommt ein einfacheres Argument. Ein Lese-Schlüssel, der leakt, ist ein Problem der Offenlegung. Ein Schlüssel mit Schreibrechten, der leakt und bei einem autonomen Prozess liegt, ist ein Problem der Datenintegrität. Bei der Wahl zwischen beidem, und weil der Workflow, auf den ich abzielte, keinen Schreibzugriff brauchte, hat sich die Entscheidung von selbst ergeben.

Fang mit reinem Lesezugriff an. Schreibzugriff kommt dazu, wenn ein Workflow ihn verlangt, und solche Schlüssel bekommen einen eigenen Scope.

Die unbequeme Voraussetzung

Unter all dem liegt eine Voraussetzung, die mit Protokolldesign nichts zu tun hat.

Ein Agent kann nicht nachfragen. Er kann der Person, die den Bug gemeldet hat, keine Nachricht schicken und fragen, welchen Browser sie benutzt hat. Er hat genau einen Versuch mit den Belegen, die es gibt, und wenn die dünn sind, liefert er eine flüssige, sauber gegliederte und komplett spekulative Antwort.

Der Wert eines MCP-Servers ist also durch die Qualität der Daten dahinter begrenzt. Meiner funktioniert, weil ein BugDump-Bericht schon die Console, das Netzwerk-Log, das Session-Replay, die Interaktionen und die komplette Umgebung enthält, automatisch erfasst in dem Moment, in dem der Bug passiert ist. Das Protokoll transportiert das nur.

Wenn du über einen MCP-Server für dein eigenes Tool nachdenkst, beantworte zuerst diese Frage: Sind die Daten dahinter vollständig genug, um ohne Rückfrage damit zu arbeiten? Wenn ja, ist MCP eine dünne Schicht, die sich lohnt. Wenn nicht, macht das Protokoll die Lücken nur leichter erreichbar.

Mehr zum Thema