Skip to content

Commit 7d02725

Browse files
committed
make consent optional, default true
1 parent df67c8d commit 7d02725

File tree

3 files changed

+37
-10
lines changed

3 files changed

+37
-10
lines changed

src/mcp/server/auth/handlers/consent.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from abc import ABC, abstractmethod
12
from dataclasses import dataclass
2-
from typing import Any
3+
from typing import Any, Optional
34
from urllib.parse import urlencode
45

56
from starlette.requests import Request
@@ -9,8 +10,27 @@
910
from mcp.server.auth.provider import OAuthAuthorizationServerProvider
1011

1112

13+
class AbstractConsentHandler(ABC):
14+
"""Abstract base class for handling OAuth consent operations."""
15+
16+
@abstractmethod
17+
async def handle(self, request: Request) -> Response:
18+
"""Handle consent requests - both showing the form and processing submissions."""
19+
pass
20+
21+
@abstractmethod
22+
async def _show_consent_form(self, request: Request) -> Response:
23+
"""Display the consent form to the user."""
24+
pass
25+
26+
@abstractmethod
27+
async def _process_consent(self, request: Request) -> Response:
28+
"""Process the user's consent decision."""
29+
pass
30+
31+
1232
@dataclass
13-
class ConsentHandler:
33+
class ConsentHandler(AbstractConsentHandler):
1434
provider: OAuthAuthorizationServerProvider[Any, Any, Any]
1535

1636
async def handle(self, request: Request) -> Response:
@@ -157,7 +177,7 @@ async def _show_consent_form(self, request: Request) -> HTMLResponse:
157177
"""
158178
return HTMLResponse(content=html_content)
159179

160-
async def _process_consent(self, request: Request) -> RedirectResponse:
180+
async def _process_consent(self, request: Request) -> RedirectResponse | HTMLResponse:
161181
form_data = await request.form()
162182
action = form_data.get("action")
163183

src/mcp/server/auth/routes.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,6 @@ def create_auth_routes(
115115
),
116116
methods=["POST", "OPTIONS"],
117117
),
118-
Route(
119-
CONSENT_PATH,
120-
# do not allow CORS for consent endpoint;
121-
# clients should just redirect to this
122-
endpoint=ConsentHandler(provider).handle,
123-
methods=["GET", "POST"],
124-
),
125118
]
126119

127120
if client_registration_options.enabled:
@@ -140,6 +133,18 @@ def create_auth_routes(
140133
)
141134
)
142135

136+
if client_registration_options.client_consent_required:
137+
consent_path: str = client_registration_options.client_consent_path or CONSENT_PATH
138+
routes.append(
139+
Route(
140+
consent_path,
141+
# do not allow CORS for consent endpoint;
142+
# clients should just redirect to this
143+
endpoint=ConsentHandler(provider).handle,
144+
methods=["GET", "POST"],
145+
),
146+
)
147+
143148
if revocation_options.enabled:
144149
revocation_handler = RevocationHandler(provider, client_authenticator)
145150
routes.append(

src/mcp/server/auth/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ class ClientRegistrationOptions(BaseModel):
66
client_secret_expiry_seconds: int | None = None
77
valid_scopes: list[str] | None = None
88
default_scopes: list[str] | None = None
9+
client_consent_required: bool = True
10+
client_consent_path: str | None = None
911

1012

1113
class RevocationOptions(BaseModel):

0 commit comments

Comments
 (0)