Hört auf, REST-API-Wrapper für MCP nachzubauen
Jeder REST-zu-MCP-Wrapper beginnt gleich. Man sucht sich eine API aus, öffnet die Doku und fängt an, Glue-Code zu schreiben. Authentifizierung, Parameter-Mapping, Error-Handling, Pagination, Retries, Response-Aufbereitung. Zweihundert Zeilen später hat man eine Integration. Dann fängt man bei der nächsten API von vorn an.
Die eigentlichen Kosten sind nicht die 200 Zeilen. Es ist die Tatsache, dass man Execution Policy — Credential-Handling, Zugriffskontrolle, Audit Logging — um jeden einzelnen Wrapper herum neu implementiert. Diese Arbeit ist teuer, repetitiv und schwer zu skalieren.
DADL geht einen anderen Weg: Statt für jede REST-API einen eigenen Wrapper zu schreiben, beschreibt man die API deklarativ. ToolMesh verwandelt diese Beschreibung in Tools und übernimmt die Laufzeitbelange — auch die, die die meisten Wrapper stillschweigend ignorieren: Credential-Isolation, Autorisierung und Audit Logging.
Der Wrapper, den man immer wieder neu baut
Abschnitt betitelt „Der Wrapper, den man immer wieder neu baut“Hier ist ein minimaler MCP-Server für einen einzelnen DeepL-Übersetzungs-Endpoint in TypeScript. Auf das Nötigste reduziert — keine Tests, keine Retries, keine Pagination, kein Rate Limiting:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";import { CallToolRequestSchema, ListToolsRequestSchema,} from "@modelcontextprotocol/sdk/types.js";
const API_KEY = process.env.DEEPL_API_KEY;if (!API_KEY) throw new Error("DEEPL_API_KEY required");
const server = new Server( { name: "deepl-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "translate", description: "Translate text into a target language. " + "Supports up to 50 texts per request.", inputSchema: { type: "object", properties: { text: { type: "array", items: { type: "string" }, description: "Array of texts to translate", }, target_lang: { type: "string", description: "Target language code (EN-US, DE, FR ...)", }, source_lang: { type: "string", description: "Source language code. Omit for auto-detect", }, formality: { type: "string", enum: [ "default", "more", "less", "prefer_more", "prefer_less", ], }, }, required: ["text", "target_lang"], }, }, ],}));
server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== "translate") { throw new Error(`Unknown tool: ${request.params.name}`); }
const { text, target_lang, source_lang, formality } = request.params.arguments;
const body = { text, target_lang }; if (source_lang) body.source_lang = source_lang; if (formality) body.formality = formality;
const res = await fetch("https://api.deepl.com/v2/translate", { method: "POST", headers: { Authorization: `DeepL-Auth-Key ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(body), });
if (!res.ok) { const err = await res.text(); return { content: [{ type: "text", text: `DeepL error ${res.status}: ${err}` }], isError: true, }; }
const data = await res.json(); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], };});
const transport = new StdioServerTransport();await server.connect(transport);Das sind 90 Zeilen für einen einzigen Endpoint — bereits auf das Minimum reduziert. Keine Retries. Kein Rate-Limit-Handling. Keine Pagination. Kein strukturiertes Error-Mapping. Und der API-Key liegt in einer Umgebungsvariable, wodurch Credentials oft ohne zentrale Governance über Client- und Server-Konfigurationen verstreut sind.
Ein produktionsreifer Wrapper mit mehreren Endpoints, ordentlichem Error-Handling, Retry-Logik und Rate Limiting wächst leicht auf über 200 Zeilen — plus package.json, Build-Schritt und ein Prozess, der laufen muss.
Jetzt multipliziere das mit jeder API, die angebunden werden soll.
Dieselbe Integration in DADL
Abschnitt betitelt „Dieselbe Integration in DADL“Hier ist dasselbe DeepL-Übersetzungs-Tool in DADL beschrieben:
backend: name: deepl type: rest base_url: https://api.deepl.com/v2 description: "DeepL translation API"
auth: # ← credential injection handled by ToolMesh type: bearer credential: deepl_auth_key # references a server-side secret, never exposed to the model prefix: "DeepL-Auth-Key "
defaults: errors: # ← retry and error handling for all tools retry_on: [429, 502, 503, 529] retry_strategy: max_retries: 3 backoff: exponential initial_delay: 1s
tools: translate: method: POST path: /translate access: write # ← access classification for authorization description: "Translate text into a target language" params: # ← parameter mapping: type, location, validation text: type: array in: body required: true description: "Array of texts to translate" target_lang: type: string in: body required: true description: "Target language code (EN-US, DE, FR)" source_lang: type: string in: body description: "Source language. Omit for auto-detect" formality: type: string in: body description: "default, more, less, prefer_more, prefer_less"40 Zeilen YAML. Kein Code. Kein Build-Schritt. Keine eigene Server-Runtime, die gebaut und betrieben werden muss.
Doch kürzer ist nicht der Punkt. Der Punkt ist, was zur Laufzeit passiert.
Der Control Layer, den man nicht selbst baut
Abschnitt betitelt „Der Control Layer, den man nicht selbst baut“Die meisten handgeschriebenen Wrapper konzentrieren sich auf eine Sache: eine API aufrufbar machen. Sie bekommen den Request raus und die Response zurück. Das ist notwendig, aber für den Produktionsbetrieb nicht ausreichend.
Die schwierigeren Fragen sind: Wer darf dieses Tool aufrufen? Wo liegen die Credentials? Was passiert mit sensiblen Daten in der Response? Gibt es einen Audit Trail?
Bei einem eigenen Wrapper werden diese Aspekte entweder nachträglich drangeschraubt oder stillschweigend ignoriert. Mit DADL und ToolMesh sind sie der Default:
| Concern | Custom MCP wrapper | DADL + ToolMesh |
|---|---|---|
| Credentials | In der Client-Konfiguration, sichtbar für das Modell | Serverseitig zur Laufzeit injiziert, nie offengelegt |
| Autorisierung | Typischerweise keine — voller Zugriff für alle | Pro Tool, pro Benutzer Zugriffskontrolle |
| Audit Logging | Nicht eingebaut | Jeder Aufruf protokolliert und abfragbar |
| Output Filtering | Nicht eingebaut | Policies können sensible Daten redigieren, bevor sie das Modell erreichen |
| Retries | Backoff-Logik selbst implementieren | Deklariert in retry_strategy, von der Runtime gehandhabt |
| Pagination | Cursor-/Offset-Logik selbst bauen | Konfiguriert via pagination.strategy |
| Error-Handling | Responses manuell parsen | Strukturiert via errors.message_path |
| Deployment | Bauen, paketieren, Prozess betreiben | Eine .dadl-Datei in ToolMesh ablegen |
DADL beschreibt, was diese API ist. ToolMesh kümmert sich darum, wie Aufrufe an sie ausgeführt und kontrolliert werden. Diese Trennung ist die architektonische Verschiebung, auf die es ankommt — nicht nur die Zeilenzahl.
Du schreibst es nicht — dein LLM tut es
Abschnitt betitelt „Du schreibst es nicht — dein LLM tut es“DADL wurde von Anfang an AI-native entworfen. Das Format ist kompakt, deklarativ und nah an der Struktur bestehender API-Spezifikationen.
Das heißt: Man kann seinem LLM einen OpenAPI-Spec, eine Swagger-Definition oder sogar rohe API-Dokumentation geben und es bitten, daraus eine DADL-Datei zu erzeugen. In den meisten Fällen ist das Ergebnis im ersten Durchlauf brauchbar. Reviewen, Edge Cases anpassen, deployen.
Im Vergleich dazu: ein LLM dazu bringen, einen kompletten MCP-Server zu generieren. Das Modell muss funktionierenden Code produzieren — Imports, Typdefinitionen, Error-Handling, Transport-Setup, Build-Konfiguration. Jede Zeile ist ein potenzieller Bug. Der Output muss getestet, debugged und manuell validiert werden, bevor er auch nur in die Nähe von Production kommt.
Mit DADL produziert das LLM eine Datenstruktur. Stimmt ein Feld nicht, ändert man eine Zeile YAML. Fehlt ein Parameter, fügt man drei Zeilen hinzu. Wenn etwas bricht, ist es häufiger ein reviewbares Spec-Problem als eine undurchsichtige Runtime-Exception irgendwo in generiertem Integrationscode.
Das ist der eigentliche Hebel. DADL ist nicht nur einfacher für Menschen zu schreiben. Es ist dramatisch einfacher für KI, korrekt zu erzeugen.
Wie das skaliert
Abschnitt betitelt „Wie das skaliert“Das DeepL-Beispiel oben deckt einen einzigen Endpoint ab. Echte APIs haben Dutzende.
Die vollständige DeepL-DADL-Definition deckt 13 Tools ab — Übersetzung, Dokumenten-Upload, Dokumenten-Status, Glossare, Textverbesserung, Sprachlisten, Usage-Tracking — in unter 500 Zeilen YAML. Die GitHub-Definition deckt 202 Tools ab: Repositories, Issues, Pull Requests, Commits, Code-Suche und mehr. Das als handgeschriebenen MCP-Server zu bauen ist kein Wochenend-Projekt. Das ist ein Produkt.
Aktuell enthält die DADL Registry 24 Backend-Definitionen mit 3.115 Tools über APIs wie GitHub, Cloudflare, Hetzner Cloud, Linode, GitLab und andere. Jede davon ist eine einzelne reviewbare YAML-Datei.
Mit wachsender Anzahl an Tools kommt eine weitere Skalierungsfrage: Context-Window-Overhead. ToolMesh begegnet dem mit Code Mode, bei dem das Modell über zwei Meta-Tools arbeitet — list_tools und execute_code — anstatt Hunderte von Tool-Definitionen direkt im Kontext mitzuschleppen. Damit bleibt die Tool-Discovery effizient, egal wie viele Backends angebunden sind.
Was DADL nicht tut
Abschnitt betitelt „Was DADL nicht tut“DADL ist ein deklaratives Format zur Beschreibung von REST-APIs. Es ist keine Workflow-Engine, keine General-Purpose-Programmiersprache und kein Ersatz für jede Art von MCP-Server.
Wenn eine Integration eigene Business-Logik, komplexe mehrstufige Orchestrierung oder Nicht-REST-Protokolle braucht, ist ein eigener Server weiterhin die richtige Wahl. ToolMesh kann auch damit umgehen — es verbindet sowohl DADL-beschriebene Backends als auch bestehende MCP-Server.
Aber für die große Klasse von Integrationen, die im Kern „eine REST-API mit den richtigen Auth-Daten und Parametern aufrufen” sind — und das sind die meisten — ist ein eigener Wrapper ein schlechter Default. Er dupliziert Infrastruktur-Aspekte, verteilt Kontroll-Logik über Codebases und erzeugt Wartungsaufwand, der keinen einzigartigen Mehrwert bringt.
Die Verschiebung
Abschnitt betitelt „Die Verschiebung“Das MCP-Ökosystem hat das Protokoll-Problem gelöst. Clients und Hosts sprechen dieselbe Sprache.
Aber Protokoll-Standardisierung hat Backend-Integration nicht günstig gemacht. Jede neue API bedeutet immer noch einen neuen Server, eine neue Codebase, eine neue Runtime, eine neue Wartungslast. Genau deshalb hören die meisten Teams nach einer Handvoll Integrationen auf, und der lange Schwanz nützlicher APIs bleibt nicht angebunden.
DADL ändert die Arbeitseinheit. Statt „einen Server bauen” wird die Aufgabe „die API beschreiben.” Statt eines Software-Projekts pro Integration bekommt man eine reviewbare YAML-Datei pro Backend — ausgeführt über eine Runtime, die Sicherheit, Credentials und Governance zentral handhabt.
Das ist nicht nur weniger Code. Es ist weniger Varianz, weniger Risiko und ein fundamental besserer Default, um KI-Agenten an reale Systeme anzubinden.
Stöbere in der DADL Registry, wirf einen Blick in die ToolMesh-Dokumentation oder den Quellcode auf GitHub.