OAuth für den MCP-Server: Claude und ChatGPT verbinden sich ohne Token

OAuth

Vor ein paar Wochen habe ich darüber geschrieben, warum KI-Agenten persönliche Tokens brauchen. Das Setup am Ende dieses Beitrags funktioniert in Claude Code gut: Token erstellen, einen Befehl ausführen, und dein Agent kann Fehlerberichte lesen.

Dann wollten Leute BugDump zu Claude im Web hinzufügen, und es ging nicht.

In einem benutzerdefinierten Connector von Claude gibt es keinen Platz, um ein Token einzufügen. In ChatGPT auch nicht. VS Code nimmt einen Header, wenn du seine Konfigurationsdatei bearbeitest, aber der Ablauf „Add Server“ fragt nicht danach. Die MCP-Clients, die die meisten Leute nutzen, erwarten eine URL, und wenn der Server mit 401 antwortet, erwarten sie eine Anmeldung.

Also habe ich meinen MCP-Server um eine Anmeldung erweitert. Der Code war der kleine Teil. So sieht es für die Person aus, die sich verbindet, und das sind die vier Entscheidungen, die die meiste Zeit gekostet haben.

Wie sich ein MCP-Client anmeldet

Du kopierst https://api.bugdump.com/api/mcp und fügst es in Claude als benutzerdefinierten Connector hinzu, oder du klickst auf der MCP-Seite deines Projekts auf Zu Claude hinzufügen, das erledigt das Kopieren für dich. Claude öffnet eine BugDump-Seite in deinem Browser. Du meldest dich an, wählst, ob die App Dinge ändern oder nur lesen darf, und klickst auf Erlauben.

Zustimmungsseite von BugDump mit der Frage „Claude erlauben, dein BugDump-Konto zu nutzen?“, ausgewählt ist „Lesen und schreiben“, die andere Option ist „Nur lesen“, dazu die Buttons „Erlauben“ und „Abbrechen“

Dahinter steckt der Ablauf, den die MCP-Spezifikation beschreibt. Die erste Anfrage kommt als 401 zurück, mit einem WWW-Authenticate-Header, der auf ein kleines JSON-Dokument zeigt. Dieses Dokument nennt den Server, der die Anmeldung übernimmt. Claude holt die Metadaten dieses Servers, schickt dich zur Anmeldeseite und tauscht das Ergebnis gegen ein Token. Nichts davon ist spezifisch für Claude. Ein Client, der sich an die Spezifikation hält, braucht nur die URL, um die Anmeldeseite zu finden.

Eine Verbindung für alle deine Projekte

Persönliche Tokens sind in BugDump an ein einziges Projekt gebunden. Das ist ein sauberes Modell. Ein Token für Acme Store sieht Acme Admin nicht, und niemand muss sich fragen, in welchem Projekt der Agent gerade arbeitet.

Ich wollte es auch für die Anmeldung beibehalten, eine Verbindung pro Projekt, vielleicht mit einer URL pro Projekt. Dann habe ich versucht, eine zweite hinzuzufügen. Claude fügt dieselbe Connector-URL nicht zweimal hinzu, und eine eigene URL für jedes Projekt bedeutet für jedes einen eigenen Connector, den man einrichten und im Blick behalten muss. Wer drei Projekte hat, hätte am Ende drei Connectors, und die meisten würden nach dem ersten aufhören.

Deshalb gehört eine Verbindung per Anmeldung dir, nicht einem Projekt. Sie erreicht jedes Projekt, in dem du Mitglied bist, und jedes andere Tool bekommt ein zusätzliches Argument, project: den Slug des Projekts, den man weglassen kann, wenn man nur zu einem Projekt gehört. Ein neues Tool, list_projects, sagt dem Assistenten, was er erreichen kann, einschließlich des Keys jedes Projekts, damit er weiß, dass AS-1 zu Acme Store gehört.

Am besten gefällt mir, was passiert, wenn der Assistent vergisst zu sagen, welches Projekt er meint. Ich wähle keins für ihn aus. Wenn du zu mehr als einem Projekt gehörst, kommt der Aufruf damit zurück:

JSON
{
  "error": "MCP_PROJECT_REQUIRED",
  "message": "This account belongs to several projects. Pass `project` with the slug of the one the user means.",
  "projects": [
    { "slug": "acme-admin", "key": "AA", "name": "Acme Admin", "role": "OWNER" },
    { "slug": "acme-store", "key": "AS", "name": "Acme Store", "role": "OWNER" }
  ]
}

Das kommt als eigenes Ergebnis des Tools zurück, nicht als Protokollfehler, also liest das Modell es und versucht es mit dem richtigen Slug noch einmal. Oft sollte es dazu nicht kommen: Die Anweisungen des Servers sagen dem Assistenten, vor allem anderen list_projects aufzurufen.

Die Mitgliedschaft wird bei jedem Aufruf geprüft. Wenn jemand ein Projekt verlässt, verliert der Assistent dieser Person beim nächsten Request den Zugriff darauf, und es gibt nichts aufzuräumen.

Nur bekannte Clients: Client ID Metadata Documents

Im klassischen OAuth wird eine App beim Server registriert, bevor sie irgendjemanden um Zugriff bitten kann, entweder von Hand oder über Dynamic Client Registration. Der neuere Ansatz, den die MCP-Spezifikation empfiehlt, Client ID Metadata Documents, lässt eine App sich stattdessen mit einer URL ausweisen, die sie selbst kontrolliert. Bei Claude ist das eine JSON-Datei auf claude.ai, die unter anderem die Adressen auflistet, an denen Claude das Anmeldeergebnis empfangen darf.

Das ist ein gutes Design. Für sich allein heißt es aber, dass alle, die eine JSON-Datei hosten können, unter einem beliebigen Namen auf deiner Zustimmungsseite auftauchen können.

Deshalb akzeptiert BugDump vier Apps: Claude, Claude Code und VS Code über die exakte URL ihres Dokuments und ChatGPT über ein festes Muster auf chatgpt.com, weil es pro Verbindung ein eigenes Dokument veröffentlicht. Die Zustimmungsseite zeigt den Namen der App und den Host, auf dem ihr Dokument liegt („Angefragt von claude.ai“), und den kann die App nicht fälschen. Dynamic Client Registration ist abgeschaltet. Cursor nutzt sie, also bleibt Cursor bei einem persönlichen Token, genau wie Scripts und CI-Jobs. Dafür sind Tokens ohnehin gut.

Token, Zustimmung und Konto bei jedem Request prüfen

Ein Access-Token gilt eine Stunde. Danach tauscht die App im Hintergrund ein Refresh-Token gegen ein neues, und so bleibt eine Verbindung wochenlang bestehen, ohne dass du dich neu anmelden musst. Nur fragt der Refresh-Schritt nicht nach, ob du die App noch verbunden haben willst oder ob dein Konto noch aktiv ist.

Also fragt mein MCP-Endpunkt nach, jedes Mal. Bei jedem Request prüft er, dass das Access-Token existiert und nicht abgelaufen ist, dass deine Zustimmung für diese App noch besteht und dass dein Konto aktiv und kein Gastkonto ist. Wenn du eine App trennst, werden ihre Zustimmung und alle ihre Tokens auf einmal gelöscht, und schon ihr nächster Aufruf scheitert mit einem 401, der sie zurück zur Anmeldeseite schickt. Änderst du dein Passwort oder setzt es zurück, werden alle Apps auf einmal getrennt, und genau das willst du, wenn du es änderst, weil etwas durchgesickert ist.

„Verbundene Apps“ in den Sicherheitseinstellungen des BugDump-Kontos: VS Code mit „Nur lesen“, Claude Code und Claude mit „Lesen und schreiben“, jeweils mit dem Button „Trennen“

Die Tokens selbst sind Zufallsstrings, die als Hashes gespeichert werden, genau wie persönliche Tokens. Es gibt keine Signaturschlüssel, die rotiert werden müssen, und ein Token zu widerrufen heißt, eine Zeile zu löschen.

Der Assistent handelt weiterhin in deinem Namen

Alles andere ist absichtlich gleich geblieben. Eine per Anmeldung verbundene App tritt als du auf und sieht, was du sehen kannst. Jede Änderung, die sie macht, erscheint in der Historie und den Kommentaren der Aufgabe unter deinem Namen, mit dem Label via MCP, und das Audit-Log hält fest, welche App sie gemacht hat. Wählst du „Nur lesen“, werden die Schreib-Tools gar nicht erst registriert: Das Modell sieht move_task nie, also kann es auch nicht versuchen, es aufzurufen.

BugDump-Aufgabe „Checkout button does nothing on Safari“ mit einem Kommentar, den Claude unter dem Namen von Alex Rivera geschrieben hat, markiert mit via MCP

Das ist Claude an einem Checkout-Bug in Safari. Claude hat die Aufgabe gelesen, eine Notiz hinterlassen, wo zuerst zu suchen ist, sie nach „In Arbeit“ verschoben und zugewiesen. Wer die Aufgabe später liest, sieht sofort, welcher Teil vom Assistenten kam.

Was noch hakt

  • ChatGPT braucht den Entwicklermodus, um einen eigenen MCP-Server hinzuzufügen, und der Entwicklermodus braucht ein bezahltes ChatGPT-Abo.

  • Zugriff ändern heißt neu verbinden. Um einer App mit Lesezugriff Schreibrechte zu geben, trennst du sie und verbindest sie neu. Mir ist lieber, du triffst diese Entscheidung bewusst statt nebenbei über einen Schalter, den du dann vergisst, aber es ist ein zusätzlicher Schritt.

  • Das Label nennt die App noch nicht. Ein Kommentar sagt „via MCP“, nicht „via Claude“. Jeder Kommentar und jeder Eintrag in der Historie speichert bereits, welche App ihn erstellt hat, die Aufgabenseite zeigt es nur noch nicht an.

BugDump mit Claude, ChatGPT oder VS Code verbinden

Öffne die Seite MCP-Server eines beliebigen Projekts und klick auf Zu Claude hinzufügen, oder kopiere die URL in ChatGPT oder VS Code. Die Schritte für jede App stehen in Claude, ChatGPT oder VS Code mit BugDump verbinden. Wenn du Cursor nutzt oder ein Script anbindest, funktionieren persönliche Tokens genau wie vorher: siehe BugDump mit Claude Code nutzen (MCP).

Mehr zum Thema