modelcontextprotocol / modelcontextprotocol/python-sdk
Revocation requires client_secret to be present
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 24.3k
- Fork
- 4k
- Merge medio
- 1g 1h
- PR unite (30g)
- 31
Descrizione
Initial Checks
- I confirm that I'm using the newest release of my line (the latest 2.x, or the latest 1.x if I'm still on v1)
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Release line
2.x (current stable)
Description
What happened?
When Claude Code (or any other public client) triggers revocation - revoke handler requires client_secret to be present, as seen here:
Per OAuth 2.0 specifications (RFC 6749 Section 2.3 and RFC 7009 Section 5), public clients do not have a client_secret and identify themselves using only client_id.
This leads to issue when public clients do not sent client secret at all.
In Pydantic v2, defining a field as str | None without a default value still marks the field as required (i.e., nullable value, but the key must exist in the request body).
Steps to reproduce
- Authenticate using a public OAuth client (e.g., Claude Code CLI).
- Trigger token revocation (e.g., re-authenticating or logging out).
- The authorization server returns a
400 Bad Requestwith:
{"error":"invalid_request","error_description":"client_secret: Field required"}
Expected behavior
client_secret should be optional so public clients can revoke tokens without sending a client_secret key.
Fix
Adding default value for client_secret:
client_secret: str | None = None
Workaround
As workaround I'm overriding Request type:
from mcp.server.auth.handlers import revoke
class FixedRevocationRequest(revoke.RevocationRequest):
client_secret: str | None = None
revoke.RevocationRequest = FixedRevocationRequest
Example Code
from mcp.server.auth.handlers.revoke import RevocationRequest
from pydantic import ValidationError
# Simulate a public client request: client_secret parameter omitted entirely
form_no_secret = {"token": "abc", "client_id": "local-scurri-mcp"}
try:
req = RevocationRequest.model_validate(form_no_secret)
print("no-secret: OK ->", req)
except ValidationError as e:
print("no-secret: FAILS ->", e.errors()[0]["msg"])
Python & MCP Python SDK
MCP version: 2.2.0
Python version: 3.13.9
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia in src/mcp/server/auth/handlers/revoke.py, in RevocationRequest, e rivedi il comportamento di validazione collegato. Conferma che una richiesta di revoca da parte di un client pubblico può omettere client_secret, quindi usa l'esempio Pydantic fornito con solo token e client_id per verificare che la validazione abbia esito positivo.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- authentication
- Tipo di issue
- Bug
- Difficoltà
- 1/5
- Tempo stimato
- Meno di un'ora
- Stato di attività
- Attiva
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 91/100