Zum Inhalt springen

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.

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.

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.

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:

ConcernCustom MCP wrapperDADL + ToolMesh
CredentialsIn der Client-Konfiguration, sichtbar für das ModellServerseitig zur Laufzeit injiziert, nie offengelegt
AutorisierungTypischerweise keine — voller Zugriff für allePro Tool, pro Benutzer Zugriffskontrolle
Audit LoggingNicht eingebautJeder Aufruf protokolliert und abfragbar
Output FilteringNicht eingebautPolicies können sensible Daten redigieren, bevor sie das Modell erreichen
RetriesBackoff-Logik selbst implementierenDeklariert in retry_strategy, von der Runtime gehandhabt
PaginationCursor-/Offset-Logik selbst bauenKonfiguriert via pagination.strategy
Error-HandlingResponses manuell parsenStrukturiert via errors.message_path
DeploymentBauen, paketieren, Prozess betreibenEine .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.

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.

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.

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.

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.