# Capability-Design: Tools und Resources mit enger Wirkung

> Tool-Schnitt, Schemas, Resource-URIs, Payloadgrößen und Legacy-Wrapper als kleine, stabile und kontrollierbare MCP-Oberfläche entwerfen.

Track: [MCP Engineering](https://physar.tech/learn/mcp-engineering)  
Kanonische Fassung: https://physar.tech/learn/mcp-engineering/capability-design  
Stand: 2026-09-04  
Interaktiver Teil: 9 Checks (nur im Browser)

## Capability-Design: Tools und Resources mit enger Wirkung

### Eine Capability ist eine kuratierte Außensicht

Ein MCP-Server ist kein automatischer Spiegel seiner REST-Endpunkte, Tabellen und Admin-Skripte. Er veröffentlicht eine absichtlich kleine Außensicht für einen probabilistischen Aufrufer. Ein Modell wählt anhand von Namen, Beschreibung und Schema; es kennt weder interne Konventionen noch die stillen Voraussetzungen eines menschlichen Operators. Deshalb muss die Capability die fachliche Absicht ausdrücken und gefährliche Freiheitsgrade entfernen.

_[Abbildung: Der MCP-Vertrag kapselt wechselnde Backends hinter einer kleinen, fachlichen Capability-Oberfläche.]_

|  |  |
| --- | --- |
| Backend-Oberfläche | Für bekannte Entwickler; oft technisch, breit und historisch gewachsen |
| MCP-Capability | Für Host und Modell; fachlich benannt, eng validiert und erklärbar |
| Policy-Grenze | Autorisiert Wirkung unabhängig von Beschreibung und Modellwahl |

> **Preis der Kapselung:** Der Server muss übersetzen und eigene Fehlersemantik pflegen. Dafür bleiben Backend-Wechsel und interne Sonderfälle aus jedem Hostvertrag heraus.

Beginne das Design mit realen Aufgaben und Missbrauchsgrenzen. Welche Nutzerfrage soll beantwortet werden, welche Wirkung ist maximal nötig, welche Identität trägt sie und welches Ergebnis braucht der nächste Schritt? Erst danach werden bestehende Endpunkte zugeordnet. Wer mit einer API-Liste startet, veröffentlicht fast zwangsläufig deren historische Schnitte. Eine kleine Capability darf intern mehrere Aufrufe bündeln, solange sie eine kohärente Fachoperation bleibt und keine neue Entscheidung versteckt. **Nachteil:** Die Übersetzung kann Backendfunktionen zunächst unzugänglich lassen; Erweiterung folgt nachgewiesenem Bedarf statt vorsorglicher Vollständigkeit.

### Tool oder Resource folgt aus der Kontrollrichtung

Ein Tool ist modellgesteuert: Das Modell kann eine parametrisierte Operation auswählen. Eine Resource ist anwendungsgesteuert: Der Host wählt adressierbaren Kontext und liest ihn. Lesen gegen ein Backend ist nicht automatisch Resource. Soll das Modell mit Suchparametern eine Abfrage initiieren, kann ein lesendes Tool richtig sein. Soll der Host ein bekanntes Runbook unter stabiler URI in den Kontext legen, ist eine Resource näher am gewünschten Kontrollmodell.

|  |  |
| --- | --- |
| `tickets/search` mit Status und Team | Tool: Modell initiiert eine parametrisierte Suche |
| `runbook://payments/timeout` | Resource: Host liest eine bekannte Kontextentität |
| `restart_service` | Tool: angeforderte Operation mit sichtbarer Wirkung |
| `cmdb://acme/services/billing` | Resource: adressierbarer Zustand für Kontext |

**Kurzcheck:** Ein Host kennt die URI eines freigegebenen Runbooks und soll dessen Inhalt gezielt in den Kontext legen. Welche Grundform passt?

- [x] Eine Resource mit stabiler URI
- [ ] Ein universelles Shell-Tool
- [ ] Ein Prompt ohne Resource-Bezug

> Richtig. Der Host kontrolliert die Auswahl eines adressierbaren Kontextobjekts.

Manche Fähigkeiten brauchen beide Formen. Eine Resource beschreibt einen Change, ein Tool genehmigt ihn. Das ist kein Duplikat: Lesen und Wirkung haben verschiedene Kontroll- und Autorisierungsgrenzen. **Nachteil:** Mehr Einträge erhöhen Discovery- und Dokumentationsaufwand. Kombiniere sie trotzdem nicht zu einer Mehrzweckfähigkeit, wenn dadurch Zustimmung oder Datenfluss unklar werden.

Auch Kosten können die Kontrollform verändern. Das Lesen einer bereits erzeugten Logresource ist erwartbar nebenwirkungsarm. Eine minutenlange Aggregation, die Compute verbraucht und einen persistenten Export anlegt, ist eine Operation, selbst wenn ihr Ergebnis nur gelesen wird. Ein sinnvolles Muster ist `create_log_export` plus Ergebnis-URI: Das Tool macht Auslösung, Parameter und Kosten sichtbar; die Resource macht das fertige Artefakt adressierbar. Der zweistufige Ablauf kostet einen zusätzlichen Call, verhindert aber, dass Hosts vermeintlich billiges Kontextlesen ungefragt vervielfachen.

### Tools werden nach Aufgaben geschnitten, nicht nach Endpunkten

Ein Modell trifft zuverlässiger, wenn ein Tool eine verständliche Aufgabe kapselt. `get_deployment_status` darf intern drei APIs abfragen und Fehler übersetzen. Drei rohe Tools für Datenbank-ID, Queue-Job und Deployment-API zwingen dagegen Host und Modell, die heutige interne Orchestrierung nachzubauen. Jede Backend-Umstellung wird dann zur externen Vertragsänderung.

**Tool-Granularität:** Der Umfang einer veröffentlichten Operation: zu fein erzwingt fragile Aufrufketten, zu grob versteckt Entscheidungen und erweitert die Wirkung.

- Benenne die fachliche Aufgabe und ihr Ergebnis.
- Halte zusammen, was atomar oder mit gemeinsamer Fehlerbehandlung ausgeführt werden muss.
- Trenne Schritte, wenn dazwischen Nutzerzustimmung oder neue Information nötig ist.
- Veröffentliche keine universelle Pass-through-Schnittstelle für beliebige Backend-Befehle.

### Deployment prüfen statt drei APIs spiegeln

Ein Server ermittelt Rolloutstatus aus Orchestrator, Monitoring und Change-System.

**Anforderungen**

- Stabile Deployment-Referenz
- dokumentiertes Statusmodell
- kontrollierte Diagnosefelder

**Schritte**

- `get_deployment_status` nimmt die fachliche Referenz
- Server ruft interne Systeme auf
- Server normalisiert Fehler und Status
- Host erhält einen stabilen Output-Vertrag

**Merksatz:** Kapselung verschiebt Komplexität an die Stelle, die Backendwissen und Autorität besitzt.

Zu grob ist die Gegenrichtung. Ein `manage_customer`, das abhängig von optionalen Feldern sucht, anlegt, sperrt oder löscht, zwingt das Modell zu impliziter Moduswahl und macht Freigaben unverständlich. Getrennte Tools können unterschiedliche Rechte, Beschreibungen und Approval-Stufen tragen. Atomare Fachoperationen dürfen trotzdem mehrere technische Schritte enthalten. Die Grenze liegt dort, wo eine neue Nutzerentscheidung, andere Berechtigung oder eigenständig behandelbare Wirkung beginnt. **Preis:** Mehr Tools vergrößern die Kandidatenmenge; der Host muss sie nach Aufgabenkontext kuratieren.

### Name, Beschreibung und Input-Schema arbeiten zusammen

Die aktuelle Spezifikation verlangt für ein Tool `name`, `description` und ein valides `inputSchema`. Der Name identifiziert, die Beschreibung erklärt Zweck und relevante Grenzen, das Schema begrenzt Form und Werte. Kein Feld kann die anderen ersetzen. `execute` mit perfektem Schema bleibt semantisch unklar; `delete_backup` mit freiem Objekt bleibt gefährlich offen.

|  |  |
| --- | --- |
| Name | Stabile, unterscheidbare Aufgabe; innerhalb des Servers eindeutig |
| Beschreibung | Wann nutzen, Wirkung, wichtige Ausschlüsse und Ergebnis |
| `inputSchema` | Zulässige Argumente, Pflichtfelder, Typen und Wertebereiche |
| `outputSchema` | Optionale prüfbare Form von `structuredContent` |

Toolnamen sollen kurz, case-sensitive und innerhalb eines Servers eindeutig sein. Aggregierende Hosts können trotzdem Namenskollisionen zwischen Servern sehen; der selbst gemeldete Servername ist dafür keine sichere globale ID. Beschreibungen gehören in einen Review, weil sie die Modellauswahl beeinflussen. Sie sind aber keine Policy. Der Server validiert jedes Argument und autorisiert die konkrete Operation auch dann, wenn das Modell exakt die dokumentierte Form liefert.

> **Trade-off:** Ein enges Schema reduziert Fehlaufrufe, erschwert aber additive Erweiterungen. Lege unbekannte Felder und optionale Defaults bewusst fest, statt zufällig von der Validatorbibliothek übernehmen zu lassen.

Beschreibungen brauchen positive und negative Abgrenzung, wenn Nachbartools ähnlich wirken. Bei `draft_customer_email` und `send_customer_email` genügt nicht zweimal eine Paraphrase des Namens. Die Beschreibung des Entwurfs sagt, dass keine Nachricht versendet wird; die Versandbeschreibung nennt die externe Wirkung und erforderliche Freigabe. Konkrete Enums, Formate und Bounds gehören ins Schema, nicht nur in Prosa. Umgekehrt gehört die fachliche Bedeutung eines Feldes nicht ausschließlich in ein Regex. Gute Auswahl entsteht aus konsistentem Namen, Beschreibung und Schema; Widersprüche machen den Vertrag für Modell und Mensch ratbar.

### Output, Fehler und Annotations bleiben untrusted

Toolresultate können `content` und `structuredContent` enthalten. Wenn `outputSchema` veröffentlicht ist, muss die strukturierte Ausgabe dazu passen; Clients sollen sie validieren. Struktur ist jedoch kein Wahrheitsbeweis. Ein kompromittiertes Backend kann schema-valide falsche Daten oder manipulative Texte liefern. Der Host behandelt Resultate daher als externe Eingabe, bevor er sie an das Modell oder ein weiteres Tool weitergibt.

Protokollfehler und Tool-Ausführungsfehler haben unterschiedliche Adressaten. Eine unbekannte Methode oder malformed Request gehört in einen JSON-RPC-Fehler. Ein fachlich ungültiges Datum oder abgelehnter Geschäftsfall kann als Toolresultat mit `isError: true` zurückkommen, damit das Modell die Argumente korrigiert. Diese Trennung gehört zum Capability-Design: Ein Modell kann nur auf Fehler reagieren, die in einer für es nutzbaren Form vorliegen.

Annotations wie `readOnlyHint`, `destructiveHint` oder `idempotentHint` helfen bei Anzeige und Risikoerklärung. Der Client muss sie als unvertrauenswürdig behandeln, solange der Server nicht vertrauenswürdig ist. Selbst dann bleiben sie Hinweise, keine Autorisierung. Ein Tool darf seine eigene Gefährlichkeit nicht verbindlich klassifizieren.

> **Doppelte Grenze:** Schema validiert Form; Policy begrenzt Wirkung. Wer beides zusammenlegt, hält formal gültige Argumente fälschlich für erlaubte Argumente.

Ein Tool ohne Parameter braucht trotzdem ein objektförmiges `inputSchema`. `type: object` akzeptiert zusätzliche Properties; mit `additionalProperties: false` wird ausdrücklich nur das leere Objekt akzeptiert. Diese kleine Differenz zeigt, warum Defaultverhalten Teil des Designs ist. Für strukturierte Ausgaben beschreibt `outputSchema` die erwartete Form; der Server muss `structuredContent` daran halten, der Client soll validieren. Für Abwärtskompatibilität empfiehlt die Spezifikation zusätzlich serialisierten Textinhalt. Das verdoppelt Darstellung, verbessert aber die Nutzbarkeit älterer oder rein textorientierter Konsumenten.

### Resource-URIs sind fachliche Identitäten

Eine Resource wird über eine URI adressiert. Diese URI sollte eine fachliche Entität stabil benennen und nicht den heutigen Speicherort leaken. `cmdb://acme/services/billing` kann denselben Service meinen, egal ob die Daten aus PostgreSQL, einem Graph Store oder einer API kommen. `file:///tmp/export-8472.json` bindet den Host dagegen an eine temporäre Datei, Cleanup-Regeln und lokale Pfade.

**Resource Template:** Eine mit RFC 6570 beschriebene URI-Form für parametrisierte Resources, etwa `cmdb://{tenant}/services/{service}`.

|  |  |
| --- | --- |
| Stabile Identität | Fachobjekt und dokumentierte Lesesemantik bleiben gleich |
| Template-Variable | Erlaubte Variabilität ist sichtbar und vervollständigbar |
| `mimeType` | Hilft bei Darstellung und Verarbeitung, ist aber nur Metadatum |
| Autorisierung | Prüft jede konkrete URI unabhängig von ihrer syntaktischen Gültigkeit |

Ein eigenes URI-Schema kostet Dokumentation und Migration. Dafür löst es Identität von Deploymentdetails. Nutze HTTPS nicht automatisch nur deshalb, weil der Backendinhalt aus dem Netz stammt. MCP-Resource-URIs sind Vertragsschlüssel; ob und wie der Server Daten lädt, bleibt seine Implementierung.

Stabil bedeutet nicht unveränderlich. Wird ein Dokument fachlich ersetzt, kann dieselbe URI die aktuelle Fassung bezeichnen, wenn genau das dokumentierte Modell ist. Muss ein Audit eine konkrete Fassung wiederfinden, braucht die Version eine eigene stabile Identität oder Metadatum mit unveränderlichem Abruf. Der Server darf diese Semantik nicht aus einem Dateipfad ableiten, den niemand außerhalb kennt. Plane außerdem Löschung und Nichtfund als Vertragsfälle: Ein unbekannter oder nicht erlaubter Bezeichner darf keine internen Pfade, Tenantnamen oder Existenzunterschiede verraten.

### Templates begrenzen Auswahl, ersetzen aber keine Policy

Resource Templates machen variable Segmente sichtbar. Sie helfen Hosts, mögliche URIs zu konstruieren und Argumente zu vervollständigen. Ein Template `inventory://{tenant}/hosts/{name}` sagt jedoch nicht, welche Tenantwerte der aktuelle Aufrufer verwenden darf. Der Server muss die aufgelöste URI gegen die Autorisierung dieses Requests prüfen.

`resources/list`, `resources/templates/list` und `resources/read` sind cachebar und liefern `ttlMs` sowie `cacheScope`. Eine öffentliche Cache-Scope ist nur korrekt, wenn der Inhalt wirklich zwischen Nutzern und Tokens geteilt werden darf. Bei mandantenspezifischen Listen oder Reads ist `private` die sichere Semantik. TTL beschreibt erwartete Frische und ist weder Berechtigungsdauer noch Unveränderlichkeitsgarantie.

Template entdecken → Parameter aus Hostkontext wählen → URI bilden → **Request autorisieren** → Resource lesen → Inhalt als untrusted verarbeiten

> **Preis:** Templates reduzieren Listenmenge, verschieben aber mehr Verantwortung in URI-Konstruktion, Validierung und aussagekräftige Fehler.

RFC 6570 beschreibt, wie Variablen expandiert werden; es definiert nicht ihre Domäne. Der MCP-Server dokumentiert daher, welche Werte sinnvoll sind, und validiert nach Expansion. Completion kann Werte vorschlagen, ist aber weder vollständige Aufzählung noch Berechtigungsnachweis. Ein Client darf einen vorgeschlagenen Tenant nicht als freigegeben behandeln. Ebenso darf der Server aus einer korrekt expandierten URI keine Identität des Nutzers ableiten. Syntaktische Konstruktion, fachliche Existenz und Autorisierung bleiben drei getrennte Prüfungen mit bewusst gleichförmigen Fehlern, wo Existenz vertraulich ist.

### Antwortgröße ist Teil der Capability

Eine Resource, die ein 80-MiB-Log liefert, kann protokollkonform und trotzdem unbrauchbar sein. Der eigentliche Konsument ist häufig ein begrenztes Kontextfenster. Ebenso schadet ein Tool, das tausende Treffer ohne Cursor oder Auswahlkriterium zurückgibt. Größe, Pagination, Filter und Zusammenfassung sind daher Capability-Entscheidungen, nicht spätere Performance-Tweaks.

- Biete stabile Filter und begrenzte Trefferzahlen statt freier Vollabzüge.
- Verweise auf Resources, wenn ein Toolresultat umfangreichen Kontext nur adressieren soll.
- Nutze `outputSchema` für maschinenlesbare Kerndaten und knappen Text für das Modell.
- Gib klare Trunkierungs- oder Pagination-Signale statt still abgeschnittener Wahrheit.

Kleine Antworten sparen Tokens und Latenz, können aber entscheidende Details verbergen. Die richtige Grenze folgt aus der Aufgabe: Statusübersicht zuerst, gezielte Detail-Resource danach. Ein willkürliches globales Zeichenlimit ist einfacher, macht aber fachlich zusammengehörige Daten unvollständig. Der Vertrag muss deshalb Auswahl und Nachladen ermöglichen.

> **Übertragbares Prinzip:** Nicht alles, was ein Backend liefern kann, gehört in einen Modellkontext. Capability-Design ist auch Budget-Design.

Der Server sollte Größenlimits nicht nur dokumentieren, sondern durchsetzen. Filter, `limit`, Cursor und gezielte Detail-URIs begrenzen Arbeit vor der Materialisierung. Stilles Abschneiden ist gefährlich, weil ein Modell Vollständigkeit annehmen kann. Gib stattdessen `nextCursor`, eine klare Trunkierungsangabe oder einen Link zum nächsten Detail zurück. Auch eingebettete Resources in Toolresultaten zählen zum Kontextbudget. **Nachteil:** Mehrstufiges Nachladen kann zusätzliche Modellrunden erzeugen; der Gewinn ist ein sichtbarer, steuerbarer Vollständigkeitsvertrag statt zufälliger Tokenüberschreitung.

### Ein Legacy-Wrapper übernimmt Verantwortung

Beim Anbinden eines Altsystems entsteht ein neuer öffentlicher Vertrag. Der Wrapper darf interne IDs, breite Servicekonten, zustandsbehaftete Transaktionen und rohe Fehlermeldungen nicht ungefiltert durchreichen. Er übersetzt eine fachliche Operation, validiert Argumente, bindet Identität, begrenzt Wirkung und normalisiert Fehler. Sonst wird aus einer historisch gewachsenen Admin-API eine modellgesteuerte Fernbedienung.

### Alte Job-API kontrolliert veröffentlichen

Die API akzeptiert freien Jobnamen, interne Server-ID und ein privilegiertes Servicekonto.

**Anforderungen**

- Erlaubte Jobtypen als Enum
- fachliche Zielreferenz
- serverseitige Tenant- und Rechteprüfung
- normalisierte Ergebnisform

**Schritte**

- Backendoperationen inventarisieren
- nur benötigte Fachaufgabe wählen
- freie Parameter durch enge Domänenwerte ersetzen
- Servicekonto hinter Policy und Audit halten
- rohe Fehler in dokumentierte Klassen übersetzen

**Merksatz:** Der Wrapper ist Sicherheits- und Semantikgrenze, nicht bloß Protokolladapter.

Diese Übersetzung kostet Entwicklungsarbeit und kann nicht jede exotische Backendfunktion sofort abdecken. Genau das ist ihr Wert. Eine enge Capability macht bewusste Lücken sichtbar; ein generisches `call_legacy_api` tarnt unbegrenzte Wirkung als Flexibilität.

Technische Konten des Wrappers brauchen dieselbe Enge wie der veröffentlichte Vertrag. Ein schmales Tool vor einem Konto mit Vollzugriff begrenzt nur den vorgesehenen Codepfad; ein Implementierungsfehler oder neues Pass-through-Feld kann die breite Berechtigung wieder freilegen. Nutze nach Möglichkeit getrennte Downstream-Rechte pro Aufgabenklasse, prüfe Objekt- und Tenantbezug serverseitig und protokolliere die fachliche Operation statt nur den technischen Endpunkt. **Nachteil:** Zusätzliche Konten und Policyregeln erhöhen Provisionierungsaufwand. Sie machen die behauptete Wirkfläche jedoch auch auf der letzten durchsetzbaren Ebene wahr.

### Neun Entscheidungen prüfen die Oberfläche

Im Check schneidest du Tools nach Aufgaben, stabilisierst Resource-URIs, verbesserst Beschreibung und Schema, wählst Templates, trennst Tool von Resource, begrenzt die sichtbare Toolmenge und Antwortgröße, kapselst ein Legacy-Backend und weist eine generische Pass-through-Fähigkeit zurück. Nutze dabei vier Fragen: Wer initiiert? Welche fachliche Bedeutung bleibt stabil? Welche Wirkung und Datenmenge sind maximal möglich? Welche Backenddetails dürfen sich ändern, ohne Hosts zu brechen?

Kontrollmodell wählen → fachliche Aufgabe benennen → **Schema und URI begrenzen** → Wirkung autorisieren → Output budgetieren → Migration testen

> **Prüfziel:** Die beste Capability ist nicht die flexibelste. Sie ist die kleinste stabile Oberfläche, die eine reale Aufgabe vollständig und kontrollierbar erfüllt.

Beurteile jede Option auch gegen ihren Preis. Ein aufgabenorientiertes Tool verschiebt Orchestrierung in den Server. Eine stabile URI erzeugt einen langfristigen Namensvertrag. Kleine Resources verlangen gezieltes Nachladen. Hostseitige Toolprofile brauchen Pflege. Enge Datenbankrechte begrenzen spontane Ad-hoc-Abfragen. Diese Kosten sind kein Argument für eine universelle Oberfläche; sie zeigen, welche Verantwortung die sichere Wahl tatsächlich übernimmt. Wenn eine Lösung nur deshalb einfach wirkt, weil sie Validierung, Auswahl oder Autorisierung an Modell und Nutzer weitergibt, ist die Komplexität nicht verschwunden, sondern an eine schwächere Grenze gewandert.

## Quellen

- Model Context Protocol Specification 2026-07-28 — Architecture — https://modelcontextprotocol.io/specification/2026-07-28/architecture
- Model Context Protocol Specification 2026-07-28 — Tools — https://modelcontextprotocol.io/specification/2026-07-28/server/tools
- Model Context Protocol Specification 2026-07-28 — Resources — https://modelcontextprotocol.io/specification/2026-07-28/server/resources
- Model Context Protocol Specification 2026-07-28 — Caching — https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching
- JSON Schema Validation Draft 2020-12 — https://json-schema.org/draft/2020-12/json-schema-validation
- RFC 6570 — URI Template — https://www.rfc-editor.org/rfc/rfc6570
- rfc-editor.org/rfc/rfc3986 — https://www.rfc-editor.org/rfc/rfc3986
- modelcontextprotocol.io/specification/2026-07-…urity_best_practices — https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices
