modelcontextprotocol / modelcontextprotocol/python-sdk
Revocation requires client_secret to be present
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 24.3k
- フォーク
- 4k
- 平均マージ
- 1日 1時間
- マージ済み PR(30日)
- 31
説明
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
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
src/mcp/server/auth/handlers/revoke.py の RevocationRequest から始め、関連するバリデーションの動作を確認してください。パブリッククライアントの失効リクエストでは client_secret を省略できることを確認し、その後、token と client_id のみを含む提供された Pydantic の例を使って、バリデーションが成功することを検証してください。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- authentication
- issue の種類
- バグ
- 難易度
- 1/5
- 見積もり時間
- 1時間未満
- 活発さ
- 活発
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 91/100