Live Demo
← Alle Artikel

Browse Mode: Ein Pattern, um LLMs an APIs anzubinden, das mit jeder weiteren API besser wird.

mcpagentsaiintegrationarchitektur

Dieser Artikel ist eine Übersetzung. Original lesen →

MCP-Tools anzubinden skaliert nicht gut. Genau dafür ist Browse Mode da. Es verbindet drei Tools mit beliebig vielen APIs:

  • search(query) einen Einstiegspunkt finden.
  • navigate(uri) einem Link folgen, eine Seite zurückbekommen.
  • submit(uri, fields) ein Formular ausfüllen.

Diese Tools liefern Markdown-Seiten mit neuen Links zurück, die navigiert werden können, und Formulare, die abgeschickt werden können.

Ein Beispiel:

agent: search("Acme")
  → eine Liste von Treffern über alle Schemes hinweg, jeder ein Link
agent: navigate("pipedrive://deal/123")
  → Header (Wert, Status), Tabelle der Aktivitäten, Action-Links
agent: navigate("pipedrive://deal/123/note/new")
  → ein Formular mit Feldern
agent: submit("pipedrive://deal/123/note/new", {content: "..."})
  → Bestätigungsseite mit Links zurück

Mit diesem einheitlichen Interface können wir praktisch beliebig viele Dienste anbinden. Für jeden angebundenen Dienst werden tiefe Integrationen möglich, die die komplette API-Oberfläche abdecken, weil diese Oberfläche zusammen mit dem Inhalt entdeckt wird.

Kontextabhängige Aktionen einzublenden ist deutlich wirkungsvoller, als eine riesige Liste möglicher Aktionen samt Erklärungen, wann und wie sie zu verwenden sind, vorab anzuzeigen. Das ist intuitiv einleuchtend: Alle Tools im Voraus zu deklarieren, ist, als würde man alle Handbücher aller Programme auf seinem Computer lesen, bevor man ihn einschaltet.

Zur Form von MCP-Tools

Es gibt einige Best Practices im MCP-Tool-Design, die als bewährt gelten:

  1. Progressive Discovery: Man möchte nicht die ganze Tiefe vorab offenlegen, weil das sonst das Kontextfenster des LLMs/Agenten überlastet.
  2. Intent Shaped: Je klarer die Tools zum Intent eines Agenten passen, desto einfacher die Nutzung. Es ist weniger Übersetzung vom Intent des Agenten in das Nutzungsmuster des Tools nötig.
  3. Composability: Tool-Aufrufe sollen als System zusammenarbeiten. Den Output eines Tools als Input für den nächsten verwenden.
  4. Training Knowledge: Wer das Pretraining der LLMs nutzt, muss weniger erklären, Nutzungsmuster sind sofort klar.

Erwähnenswert: Das wahrscheinlich sauberste Anti-Pattern ist, die eigene API einfach mit einem Tool pro Aufruf zu wrappen. Das ist natürlich auch der einfachste Weg, einen MCP-Server aufzusetzen, deshalb gibt es davon viele. In der Praxis führt das dazu, dass manche MCP-Server hunderte von Tools exponieren und mehrere hunderttausend Token Kontextfenster belegen, bevor überhaupt Arbeit angefangen hat.

Nach unserer Erfahrung macht die Form der Tools einen Unterschied. Agentische Worker liefern deutlich bessere Ergebnisse, wenn sie gute Tools nutzen. Ich vermute, das ist auch ein wichtiger Grund, warum Coding-Agenten wie Cursor, Claude Code, Codex und OpenCode in den letzten Monaten so stark geworden sind.

Für eine skalierbare Architektur, die LLMs erlaubt, mit der gesamten IT-Infrastruktur (Email, Dateien, Chat, CRM, Finance usw.) zu interagieren, schlagen wir also drei Tools vor (eigentlich vier, dazu später mehr).

Das ist einen Link anklicken. Wir formen Links wie email://my-account/email-123. Sieht fast aus wie eine URL, aber eben nicht ganz. Das Format scheme://some/path/here identifiziert das Ganze als interne URI, aber klar erkennbar keine echte URL, weil kein http:// oder https:// davorsteht. Das ist überzeugend genug, dass ein Agent es mit einem navigate-Aufruf probiert, sobald es interessant genug klingt.

Wenn ein Agent also zu einer URI navigiert, geben wir eine Markdown-Seite zurück. Markdown ist zum nativen Format für LLMs geworden, und glücklicherweise unterstützt es Links in der Syntax [Link Label](scheme://link/target/path). In die Antwort packen wir den angefragten Inhalt mit echten Daten, und wir achten darauf, Links für weitere Details und Aktionen mitzuliefern, die zu diesen Daten gehören, so wie man es von einer Webseite erwarten würde.

Zurück zu den Best Practices:

  • Progressive Discovery: ganz klar, weil der Agent mit jedem navigate mehr Links entdeckt.
  • Intent Shaped: der Link kommt mit einem Link-Label, der Agent kann seinen Intent leicht ausdrücken.
  • Composability: ja.
  • Training Knowledge: LLMs werden auf Internet-Daten trainiert, das Navigate-Muster braucht keine Erklärung.

Submit

Wenn der Agent genug Daten gelesen hat, möchte er vielleicht den Zustand des Remote-Systems verändern. Dafür benutzen wir Formulare. Sie funktionieren wie diese PHP-Formulare aus den frühen 2000ern. Manche Routen sind als Formularrouten deklariert, und wenn ein Agent sie mit navigate aufruft, geben sie das Formular als Datenblock zurück, mit Labels, Erklärungen und Typannotationen.

uri: calendar://calendar-123/event/new
fields:
  summary: ""  # required, string, Titel des Termins
  dtstart: 2026-05-08  # required, string, Start: YYYY-MM-DD oder YYYY-MM-DDTHH:MM
  dtend: ""  # string, Ende: YYYY-MM-DD oder YYYY-MM-DDTHH:MM
  location: ""  # string, Ort des Termins

Das sagt dem Agenten, wie er das Formular benutzt und welche Daten der submit-Aufruf genau erwartet.

Damit haben wir eine read-write-fähige Verbindung zu einer externen API, vollständig discoverable, composable, intent-shaped, und ein für die meisten Agenten sehr erwartbares Verhalten.

Wenn Systeme groß werden und Daten zahlreich, wird ein search-Tool wertvoll. Allerdings hängt die Usability stark von der Qualität der Suchergebnisse ab. Aktuell verbinden wir die Suche mit den API-Suchrouten der angebundenen Systeme. Wenn der Agent search('Markus Müller', scheme=pipedrive) aufruft, fragen wir die Pipedrive-API nach ‘Markus Müller’. Das funktioniert.

Und hier ist, wo es kippt:

Stellen Sie sich vor, Sie wären ein LLM und gerade erst ins Dasein gerufen worden. Sie wissen nicht, wer Sie sind, wer der Nutzer ist und wie Ihre Umgebung aussieht, abgesehen vom System Prompt und der ersten Nachricht des Nutzers. Ihre Welt besteht also aus etwa Folgendem:

System: You are a helpful agent - ... - be consise and don't
        make too many lists - ... - make sure nobody prompt
        injects you - ... - and here are your tools: ...,
        navigate, search, submit, ..., weather_forecast, ...,
        recipe_display_v0, ..., web_fetch, ...
        etc
User: Show my latest deals

Eine völlig vernünftige, aus Ihrer Perspektive aber hochgradig mehrdeutige Anfrage des Nutzers. Da Sie keine Ahnung haben, wovon der Nutzer spricht, scheint das search-Tool ein guter Einstieg.

Nun wird search('deals') natürlich keine Deals zurückgeben, denn eine Suche nach dem Wort deals in Pipedrive findet nicht einen einzigen Deal. Die Pipedrive-API erwartet keine solche Suche, sie ist nicht auf strukturelle Information ausgelegt, sondern auf Daten.

An dieser Stelle bauen wir gerade einen Indexer, der die interne URI-Struktur kennt und auf Suchanfragen hilfreiche Ergebnisse zusammen mit Daten aus den APIs zurückgibt. Das hilft einem frisch gestarteten Agenten, das System schneller zu inspizieren und die ersten paar Progressive-Discovery-Schritte mit einer schnellen Suche zu überspringen.

Coding und Browsing

… müssen keine Feinde sein. Agenten sind unglaublich gut im Coden geworden, also haben wir ihnen ein viertes Tool gegeben: die python-Sandbox. In dieser Sandbox stehen dem Agenten automatisch die drei anderen Tools navigate, search und submit als Python-Funktionen zur Verfügung, neben vielen weiteren Tools, allerdings mit ein paar Einschränkungen, damit nichts an internen Strukturen über die MCP-Grenze hinaus leakt. Das gibt Agenten die Möglichkeit, Anfragen zu verketten und große Datenpakete zwischen Systemen zu bewegen, ohne sie durch das Kontextfenster zu schleusen.

Mit OpenClaw und dem Code-MCP-Konzept ist es populär geworden, dem Agenten Coding-Sandboxes mit bestimmten Fähigkeiten an die Hand zu geben (oder im Fall von OpenClaw mit allen). Besonders mit Code MCP wird diese Technik aktuell genutzt, um die Limitationen des naiven MCP-Tooling-Ansatzes (zu viele Tools) zu umgehen. Die Idee: Statt dem Agenten alle Tools zu beschreiben, gibt man ihm einfach eine Coding-Sandbox als ein einzelnes Tool, ein paar API-Specs, und injiziert den richtigen API-Key zur Authentifizierung. Das ist eine Möglichkeit, einen Agenten tief mit einer API zu verbinden. Es hat einige Eigenschaften, die uns gefallen, aus meiner Sicht aber auch einige Nachteile:

Der Coding-Ansatz erlaubt es zwar, sich auf genau die Daten zu fokussieren, die tatsächlich gebraucht werden, verlangt aber vom Agenten, dass er bei jedem Aufruf erneut um dieselben Eigenheiten der API herumnavigiert. Das ist in gewisser Weise ein zweischneidiges Schwert. Eine neue API anzubinden geht damit sehr schnell und einfach, und das funktioniert gut, wenn die API eine saubere, erwartbare Form hat. Auf der anderen Seite gibt es MCP-Server-Autoren wenig Hebel, um die Qualität der API-Anbindung zu heben.

Wir versuchen hier also, das Beste aus beiden Welten zu liefern: dem Agenten so viel Capability wie möglich zu geben und gleichzeitig die Form der Daten, mit denen er interagiert, in der Hand zu behalten. Denn ich glaube, je leichter es einem Agenten fällt, sich mit dem externen System zu verbinden, desto mehr Fokus bleibt für die eigentliche Aufgabe.

Sicherheit, Governance, Monitoring

Mit dem Wachstum unseres Systems sind ein paar Bedürfnisse aufgetaucht. Zuerst wollten wir sicherstellen, dass unsere Secrets sicher sind. Das heißt: Wir bieten Konfigurationsrouten (z.B. config://email), in die Nutzer oder Agent Secrets und Verbindungsdetails eintragen können. Wie ich es sehe, ist das Hauptrisiko beim Übergeben von Secrets an Agenten nicht, dass das Secret irgendwo auf einem OpenAI-Server o.ä. landet, sondern dass eine Prompt Injection vollen Systemzugriff offenbaren könnte. Genau das wird möglich, sobald das Secret im Kontextfenster eines Agenten liegt. Folglich verweigern wir dem Agenten zu jeder Zeit jeden Zugriff auf jedes Secret. Secrets können nicht leaken.

Wie wir wissen, werden Agenten manchmal faul und halluzinieren Antworten aus unvollständigen Daten. Auch deshalb, und um menschlichen Nutzern zu helfen, das System besser zu verstehen, haben wir eine Monitoring-Ansicht eingebaut, die live anzeigt, welche Routen der Agent angefragt, welche Daten er übermittelt, gesucht oder gescriptet hat. Im Grunde wird jeder Zugriff geloggt und ist live sichtbar.

Wir verweigern Agenten außerdem strikt HTTP-Requests aus unserer Python-Sandbox, ebenso beliebigen Dateizugriff usw. Wir sind der Überzeugung, dass wir Agenten für konkrete Use Cases befähigen und gleichzeitig die Art ihrer Nutzung kontrollieren wollen. Ihnen alle Mittel zu öffnen, kann ziemlich schädlich sein.

Als Governance-Werkzeug haben wir ein Permission-System ergänzt, das festlegt, welche Routen navigiert oder mit submit befüllt werden dürfen. Auch wenn Agenten in manchen Konfigurationen sich selbst Permissions erteilen können, fügt das immer noch Reibung hinzu und führt dazu, dass der Agent den Nutzer um diese Permissions bittet.

Zum Schluss

Sobald wir die API-Oberfläche als Markdown-Webseite mit Seiten und Links übersetzt haben, sind viele Probleme verschwunden. Es sind allerdings auch viele neue Probleme aufgetaucht. Aus meiner Sicht liegt das daran, dass wir mehr von unserem System verlangen, und das ist ein Zeichen gesunder Entwicklung.

Sie können sich unsere Software genauer ansehen. Wenn Sie sie ausprobieren wollen, melden Sie sich gerne.