Server Contracts: Fähigkeiten stabil veröffentlichen
Ein neues Pflichtfeld validiert sauber, eine nutzerspezifische Toolliste wird öffentlich gecacht und eine Änderungsnotification gilt als Migrationsplan. Formal spricht alles MCP — fachlich brechen dennoch mehrere Hosts gleichzeitig.
Lehrtext · 10 Abschnitte · zuletzt geprüft: 2026-09-04
Vom Backend zur veröffentlichten Fähigkeit
Dieses Modul setzt voraus, dass du die MCP-Rollen und Primitives kennst. Jetzt geht es um den Vertrag innerhalb eines Servers: Was darf ein Host entdecken, wie versteht er die Bedeutung einer Eingabe, und was bleibt trotz eines stabilen Namens veränderbar? Ein MCP-Vertrag ist eine absichtlich kleine, veröffentlichte Sicht auf eine Fähigkeit — nicht ein Spiegelbild der internen Datenbank, Queue oder REST-API.
- Interne Implementierung
- Kann Tabellen, Jobnamen, Auth-Provider und Fehlerdetails ändern
- Veröffentlichter MCP-Vertrag
- Beschreibt stabile Operationen, Argumente, Ressourcen und Capability-Signale
- Host-Policy
- Entscheidet separat, was aus dem Angebot sichtbar oder ausführbar wird
Der Vertrag hat zwei Schichten. Die Drahtform legt Namen, JSON-Schema, URI, Argumente und Ergebnisfelder fest. Die fachliche Semantik sagt, welche Entität gemeint ist, welche Wirkung ein Aufruf hat und welche Fehler der Konsument erwarten darf. Ein Schema kann unverändert bleiben und trotzdem brechen, wenn status: complete plötzlich einen anderen Geschäftsprozess bezeichnet. Umgekehrt kann eine additive Schemaerweiterung kompatibel sein, wenn alte Eingaben dieselbe Bedeutung behalten. Beide Schichten gehören ins Release-Review.
Der Vertrag beginnt mit Discovery
Tools, Resources und Prompts werden über ihre jeweiligen Listen sichtbar. Der Host kann dabei paginieren und Ergebnisse cachen. Diese Liste ist deshalb nicht bloß UI-Metadaten: Name, Beschreibung, Eingabeform und weitere veröffentlichte Felder bilden die Capability, auf die ein Host seine Auswahl, Anzeigen und Integrationslogik stützt.
server/discover lesen→Vollständige paginierte Liste entdecken→Cachehinweise und Host-Policy anwenden→Fähigkeit anbieten oder aufrufenIm modernen Core ist server/discover für Server verpflichtend und für Clients optional. Es liefert unterstützte Revisionen und grobe Capabilities; die konkreten Tools, Resources und Prompts kommen weiterhin aus ihren Listenmethoden. Listen sind paginiert und sollen deterministisch sortiert sein. Ihre Resultate tragen ttlMs und cacheScope. Ein TTL ist ein Frischehinweis, keine Garantie, dass der Bestand bis dahin unverändert bleibt. Bei cacheScope: public darf eine Antwort zwischen Autorisierungskontexten geteilt werden; diese Angabe wäre für nutzerspezifische Toollisten gefährlich.
Eine nutzerspezifische Toolliste cachen
Szenario
Administratorin A sieht acht Tools, Operator B nur drei. Beide verwenden denselben Host.
Anforderungen
- Der Server filtert
tools/listanhand der Autorisierung jedes Requests - Die Resultate tragen
cacheScope: private - Der Cachekey trennt Autorisierungskontexte
- Eine Listenänderung macht betroffene Einträge stale
Schritte
- Alle Seiten deterministisch lesen
- Empfangszeit und
ttlMsspeichern - Toolliste nur im passenden Kontext wiederverwenden
- Bei Fehler oder Notification gezielt neu lesen
Merksatz: Caching optimiert einen Vertrag; es darf dessen Sichtbarkeitsgrenze nicht erweitern.
Ein veröffentlichtes Schema ist ein Kompatibilitätsversprechen
Ein Tool veröffentlicht mit inputSchema eine JSON-Schema-Beschreibung seiner Argumente. Hosts und Modelle können diese Beschreibung für Auswahl und Konstruktion verwenden. Dadurch wird die Form der Eingabe Teil des öffentlichen Vertrags: Ein neues Pflichtfeld, ein engerer Wertebereich oder dieselbe Feldbezeichnung mit neuer Bedeutung kann vorhandene Aufrufer brechen — auch wenn der Tool-Name gleich bleibt.
- Kompatibel erweitern
- Optionales, klar dokumentiertes Feld hinzufügen und die bisherige Bedeutung erhalten
- Breaking Change
- Pflichtfeld hinzufügen, Typ oder erlaubte Werte einschränken oder Feldsemantik ändern
- Migration
- Alten Vertrag erhalten oder eine getrennte, eindeutig benannte Capability für die neue Bedeutung veröffentlichen
Ohne explizites $schema gilt JSON Schema 2020-12; Implementierungen müssen mindestens diesen Dialekt unterstützen. inputSchema eines Tools bleibt ein Objekt, outputSchema darf im modernen Protokoll jedes JSON-Schema beschreiben und structuredContent entsprechend auch Array, String, Zahl, Boolean oder Null sein. Externe $ref-Ziele dürfen nicht automatisch aus dem Netz geladen werden. Ein opt-in Resolver braucht Allowlist, Netzgrenzen, Timeout und Größenlimit. Auch lokale Komposition mit oneOf oder allOf braucht Tiefen- und Zeitbudgets, sonst wird Vertragsvalidierung selbst zur Ressourcenangriffsfläche.
Kompatibilität muss in beide Richtungen konkret benannt werden. Ein älterer Client sendet unbekannte neue optionale Felder nicht; der Server braucht dafür ein Verhalten mit derselben bisherigen Bedeutung. Ein neuer Client kann zusätzliche Felder senden; ein älterer Server kennt sie möglicherweise nicht. additionalProperties: false macht solche Erweiterungen bewusst streng und kann eine parallele Capability nötig machen. Ein permissiveres Schema erleichtert Erweiterung, akzeptiert aber Tippfehler leichter. Es gibt keinen universellen Gewinner: Der Vertrag muss festlegen, ob unbekannte Felder abgelehnt, ignoriert oder über eine eigene Erweiterungsfläche getragen werden.
Resources brauchen adressierbare Bedeutung
Eine Resource wird durch eine URI referenziert. Eine Resource Template beschreibt eine wiederverwendbare URI-Form mit Argumenten. Die URI ist damit ein Vertragsschlüssel: Sie sollte die fachliche Identität transportieren, nicht eine flüchtige interne Dateistruktur, einen zufälligen Cache-Pfad oder ein implizites URL-Routing des aktuellen Frameworks.
- Stabil
inventory://tenant/acme/services/paymentssteht für eine fachliche Resource- Fragil
file:///tmp/export-8472.jsonleakt eine temporäre Umsetzung- Template
- Eine dokumentierte URI-Form macht variable Teile sichtbar und vervollständigbar
Ein Resource-Vertrag umfasst mehr als die URI: name, optionaler Titel, Beschreibung, mimeType, Größe und Annotations helfen dem Host bei Auswahl und Darstellung. resources/read kann mehrere Inhalte zurückgeben, deren jeweilige URI zur angeforderten Resource passt. Ein Template macht Variablen mit RFC-6570-Syntax sichtbar, ersetzt aber keine Autorisierung. Eine syntaktisch passende URI darf nicht genügen, um einen fremden Tenant oder privaten Pfad zu lesen. Stabilität und Zugriffskontrolle sind getrennte Zusagen.
Prompts sind ausgewählte Workflow-Verträge
Ein Prompt bietet einen vom Nutzer wählbaren Einstieg in einen Workflow. Er kann Argumente definieren; für Prompt- und Resource-Template-Argumente kann ein Server optional Vervollständigungen anbieten. Das ist ein interaktiver Vertrag: Argumentnamen und ihre Bedeutung müssen stabil genug sein, dass ein Host eine verständliche Auswahloberfläche und sichere Vorbelegung erzeugen kann.
- Prompt
- Nutzer wählt einen benannten Workflow und füllt dessen Argumente
- Completion
- Server schlägt kontextuelle Werte vor, wenn die Capability ausgehandelt wurde
- Tool
- Modell kann eine Operation vorschlagen; das ist keine Prompt-Alternative nur wegen ähnlicher Parameter
Prompt-Argumente sind benannte Stringwerte, kein beliebig tiefes Tool-Schema. Das begrenzt die Komplexität einer nutzergesteuerten Vorlage und ist ein Signal gegen versteckte Maschinen-APIs im Prompt. Der Server liefert bei prompts/get Nachrichten mit Rollen und Inhalt; der Host entscheidet, wie er sie zeigt und in eine Modellinteraktion übernimmt. Namen, Argumente und gelieferte Rollen sind deshalb ein Nutzervertrag. Wer einen Argumentnamen umdeutet oder eine assistierende Nachricht plötzlich als Nutzeranweisung liefert, ändert Semantik auch ohne Schemafehler.
Capabilities sind veröffentlichte Zusagen des Servers
Im modernen MCP bringt jeder Client-Request seine Client-Capabilities mit. Server-Capabilities sind über server/discover auffindbar. Für einen Server ist das mehr als Dekoration: Wer tools.listChanged oder resources.subscribe deklariert, signalisiert optionale Interaktionen, die der Client gezielt verwenden kann. Eine implementierte, aber nicht deklarierte Funktion ist kein verlässlicher Teil des veröffentlichten Vertrags; eine deklarierte Funktion muss der Server tatsächlich bedienen.
server/discover veröffentlichen→Client öffnet nur unterstützte Interaktion→Server hält Verhalten und Deklaration konsistentCapabilities sind keine Berechtigungen. tools: {} sagt, dass der Server die Toolmethoden spricht; es sagt nicht, dass jeder authentifizierte Aufrufer jedes Tool sehen oder ausführen darf. Die konkrete Liste darf mit der Autorisierung des Requests variieren, solange sie nicht von einer Verbindung oder früheren Aufrufen abhängt. Ebenso darf ein Server keine Client-Fähigkeit voraussetzen, die im aktuellen Request fehlt. Dann muss er den definierten Fehler MissingRequiredClientCapabilityError liefern, statt still auf Connection-State zurückzugreifen.
Ein Konsument prüft Capabilities an der Stelle, an der er die optionale Interaktion plant. Für Listenänderungen reichen tools und ein grundsätzlich erreichbarer Server nicht: listChanged: true muss veröffentlicht sein, und der Client öffnet einen subscriptions/listen-Stream mit dem passenden Filter. Der Server bestätigt zuerst, welche Teilmenge er tatsächlich bedient. Diese Bestätigung verhindert, dass der Client aus seiner Anfrage eine Zusage ableitet. Preis: Jede optionale Kombination erweitert die Testmatrix aus Server-Capability, Client-Capability, Autorisierung, Subscription und Fallback.
Annotations helfen bei Darstellung, nicht bei Freigabe
Tools, Resources und Prompts können Beschreibungen und Annotations tragen. Bei Tools enthalten Annotations unter anderem Hinweise wie readOnlyHint, destructiveHint, idempotentHint oder openWorldHint. Laut Spezifikation sind diese Hinweise untrusted und unverbindlich. Sie unterstützen Ranking, Darstellung und Risikohinweise, dürfen aber keine Autorisierungs-, Approval- oder Sandbox-Policy ersetzen.
- Annotation
- Hinweis für Host oder UI, etwa zur erwarteten Wirkung
- Serverdurchsetzung
- Tatsächliche Validierung und Berechtigung vor Ausführung
- Host-Policy
- Unabhängige Freigabe, Allowlist, Nutzerbestätigung und Kontextgrenze
Dasselbe gilt für clientInfo und serverInfo: Beide sind selbst gemeldete Implementierungsdaten für Anzeige, Logging und Diagnose. Die Spezifikation untersagt, daraus sicherheitsrelevantes Verhalten abzuleiten. Ein Servername ist außerdem nicht global eindeutig und eignet sich nicht zur Auflösung kollidierender Toolnamen. Der Host braucht eine eigene stabile Serveridentität aus Konfiguration, Installation oder autorisierter Herkunft. Beschreibende Metadaten können diese Identität ergänzen, aber nicht erzeugen.
Auch Toolnamen sind nur innerhalb eines Servers eindeutig. Aggregiert ein Host zwei Server mit jeweils search, braucht er eine eigene Disambiguierungsstrategie, etwa einen stabilen konfigurierten Namespace. Den selbst gemeldeten serverInfo.name als Sicherheitsnamespace zu verwenden wäre falsch: Zwei Server dürfen denselben Namen melden. Die Anzeige darf freundlich bleiben, während interne IDs Herkunft und Installation eindeutig halten. Nachteil: Präfixe und interne Identitäten erschweren Migrationen; ohne sie kann ein Modell oder Nutzer jedoch nicht zuverlässig erkennen, welche Vertrauensdomäne eine gleichnamige Fähigkeit ausführt.
Releases brauchen einen Semantik- und Migrationsplan
MCP standardisiert Tool-Beschreibung und Discovery, aber keine allgemeine SemVer-, Deprecation- oder Migrationspolitik für deine fachliche API. Ein Release, das ein Pflichtargument ergänzt, einen Rückgabewert anders interpretiert oder eine Wirkung erweitert, ist deshalb eine Produkt- und Kompatibilitätsentscheidung des Serverteams. notifications/tools/list_changed kann interessierte Clients über eine veränderte Liste informieren, löst aber keine Migration aus.
- Additiv: Neue optionale Fähigkeit mit klarer Bedeutung veröffentlichen und bestehende Aufrufe erhalten.
- Breaking: Alten Vertrag weiter bedienen oder eine getrennte Capability für die neue Semantik anbieten.
- Deprecation: Übergangszeit, Kommunikation und Entfernung bewusst im eigenen Release-Prozess festlegen.
In Revision 2026-07-28 erhält ein Client Änderungsnotifications nur über einen von ihm geöffneten subscriptions/listen-Stream und nur für angeforderte, vom Server unterstützte Typen. Eine Notification ist ein Invalidierungssignal: Der Client liest den Vertrag neu, statt die Änderung aus der Nachricht zu erraten. Caching bleibt komplementär. Ein frischer Cache wird bei relevanter Notification sofort stale; ohne Stream endet seine angenommene Frische spätestens nach ttlMs. Bei paginierten Listen ist jede Seite separat cachebar, aber es gibt keine seitenübergreifende Snapshot-Garantie.
Eine Listenänderung und eine semantische Migration sind verschiedene Ereignisse. Das Signal sagt nur, dass der Konsument neu listen sollte. Es übermittelt keinen Diff und beweist nicht, dass alte Aufrufe noch funktionieren. Bei einem inkompatiblen Pflichtfeld braucht das Serverteam daher weiterhin eine Übergangsstrategie: alte Form akzeptieren, sicheren Default dokumentieren oder eine getrennte neue Capability veröffentlichen. Erst wenn unterstützte Clients migriert und beobachtet sind, kann der alte Vertrag entfallen. Preis: Paralleler Betrieb erhöht Code- und Testlast; ein sofortiger Bruch verlagert diese Last unkontrolliert auf alle Hosts.
Ein Vertrags-Review vor dem Release
Prüfe einen Serververtrag in vier Fragen: Bleibt die veröffentlichte Bedeutung unabhängig von der Backend-Implementierung? Kann ein Host vollständige Fähigkeiten entdecken und nur nach Negotiation nutzen? Werden Schema, URI und Prompt-Argumente auf beiden Seiten gleich verstanden? Und erhält jede Änderung einen expliziten Policy- und Kompatibilitätsschritt?
- Mache Namen, URIs, Argumente und Seiteneffekte für den Konsumenten verständlich.
- Halte interne IDs, Dateipfade und unkontrollierte Backend-Fehler aus dem öffentlichen Vertrag heraus.
- Kopple Vertrauensentscheidungen nie an Beschreibungen oder Annotations des Servers.
Vertragsreview für search_docs
Szenario
Ein Release ergänzt Mandantenfilter, strukturierte Treffer und eine dynamische Toolliste.
Anforderungen
- Alte Aufrufe ohne Filter behalten ihre dokumentierte Bedeutung
outputSchemabeschreibt die neuen strukturierten Treffer- Nutzerspezifische Listen bleiben
cacheScope: private - Änderungen invalidieren nur Clients mit passender Subscription
Schritte
- Drahtschema gegen JSON Schema
2020-12prüfen - fachliche Semantik alt gegen neu vergleichen
- Cache- und Notification-Vertrag festlegen
- Migration mit alten und neuen Hosts testen
Merksatz: Schema, Semantik, Sichtbarkeit und Frische sind vier getrennte Vertragsachsen.
Gleich entscheidest du acht Vertragsgrenzen
Die Checks folgen derselben Linie: erst eine stabile Capability statt eines Backend-Leaks, dann Discovery und Schema, anschließend Resources und Prompts, danach präzise deklarierte Server-Capabilities, unverbindliche Annotations und bewusst migrierte Releases. Entscheidend ist jeweils nicht, was ein Server technisch senden kann, sondern welche Aussage ein Host belastbar als Vertrag verwenden darf.
Du entscheidest gleich über Discovery, Capability-Deklaration, additive Schemaänderungen, stabile Resource-URIs, Prompt-Argumente, untrusted Annotations, Cache-Invalidierung und eine kontrollierte Semantikmigration. Prüfe jeweils zuerst, welche Zusage ein Konsument vernünftigerweise ableitet. Danach trennst du Form, Bedeutung, Autorisierung und Aktualität. Wer diese Ebenen vermischt, bekommt Verträge, die formal validieren und im Betrieb dennoch falsche Aktionen oder Daten erzeugen.
Nutze für jede Antwort denselben Review-Satz: Wer darf was in welcher Form unter welcher Bedeutung wie lange als aktuell ansehen? inputSchema und outputSchema beantworten die Form. Beschreibung, URI und dokumentierte Seiteneffekte tragen Bedeutung. Autorisierung und Host-Policy bestimmen Sichtbarkeit und Ausführung. ttlMs, cacheScope und Subscriptions steuern Aktualität. Keine einzelne dieser Achsen ersetzt die anderen. Ein belastbarer Serververtrag benennt sie getrennt und macht ihre jeweiligen Nachteile sichtbar. Schreibe die erwartete Reaktion auf unbekannte Felder, abgelaufene Cacheeinträge, entfernte Capabilities und nicht unterstützte Revisionen ausdrücklich in Contract-Tests. Das verhindert, dass nur der glückliche Pfad dokumentiert ist. Ein Host muss einen veralteten Vertrag verwerfen können, ohne eine ungeprüfte Ersatzfähigkeit zu erfinden; ein Server muss einen ungültigen Request ablehnen können, ohne seine interne Implementierung offenzulegen. Diese Fehlerpfade sind Teil der veröffentlichten Bedeutung und nicht bloß Betriebsdetails.
Jetzt anwenden
Diesen Stoff gibt es als Modul mit bewerteten Entscheidungs-Checks — dieselbe Einführung, danach die Übungen.
Zum Modul →Quellen & Aktualität10 Primärquellen · zuletzt geprüft:
- 01modelcontextprotocol.io/specification/2026-07-28/basic/index
- 02modelcontextprotocol.io/specification/2026-07-28/basic/versioning
- 03modelcontextprotocol.io/specification/2026-07-28/server/discover
- 04modelcontextprotocol.io/specification/2026-07-28/server/tools
- 05modelcontextprotocol.io/specification/2026-07-28/server/resources
- 06modelcontextprotocol.io/specification/2026-07-28/server/prompts
- 07modelcontextprotocol.io/specification/2026-07-…er/utilities/caching
- 08modelcontextprotocol.io/specification/2026-07-…lities/subscriptions
- 09json-schema.org/draft/2020-12/json-schema-validation
- 10modelcontextprotocol.io/specification/2026-07-…utilities/completion