# Hört auf, REST-API-Wrapper für MCP nachzubauen

> Selbst ein abgespeckter MCP-Wrapper sind 90 Zeilen TypeScript. Produktions-Wrapper wachsen auf über 200 Zeilen. Dieselbe Integration in DADL braucht 40 Zeilen YAML — und der eigentliche Gewinn ist nicht die Zeilenzahl.

Canonical: https://www.toolmesh.io/de/blog/dadl-the-end-of-mcp-server-boilerplate/

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

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:

```typescript

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

Hier ist dasselbe DeepL-Übersetzungs-Tool in DADL beschrieben:

```yaml
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

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

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

Das DeepL-Beispiel oben deckt einen einzigen Endpoint ab. Echte APIs haben Dutzende.

Die vollständige [DeepL-DADL-Definition](https://dadl.ai) deckt 13 Tools ab — Übersetzung, Dokumenten-Upload, Dokumenten-Status, Glossare, Textverbesserung, Sprachlisten, Usage-Tracking — in unter 500 Zeilen YAML. Die [GitHub-Definition](https://dadl.ai) 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](https://dadl.ai) {{registry.apis}} Backend-Definitionen mit {{registry.tools}} 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

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

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](https://dadl.ai), wirf einen Blick in die [ToolMesh-Dokumentation](/de/getting-started/) oder den Quellcode auf [GitHub](https://github.com/DunkelCloud/ToolMesh).
