diff --git a/src/fastmcp/server/auth/oauth_proxy.py b/src/fastmcp/server/auth/oauth_proxy.py index 717b6aa01..c525da1af 100644 --- a/src/fastmcp/server/auth/oauth_proxy.py +++ b/src/fastmcp/server/auth/oauth_proxy.py @@ -68,9 +68,10 @@ from fastmcp.utilities.logging import get_logger from fastmcp.utilities.ui import ( BUTTON_STYLES, DETAIL_BOX_STYLES, + DETAILS_STYLES, INFO_BOX_STYLES, + REDIRECT_SECTION_STYLES, TOOLTIP_STYLES, - create_detail_box, create_logo, create_page, create_secure_html_response, @@ -233,16 +234,13 @@ def create_consent_html( txn_id: str, csrf_token: str, client_name: str | None = None, - title: str = "Authorization Consent", + title: str = "Application Access Request", server_name: str | None = None, server_icon_url: str | None = None, server_website_url: str | None = None, + client_website_url: str | None = None, ) -> str: """Create a styled HTML consent page for OAuth authorization requests.""" - # Format scopes for display - scopes_display = ", ".join(scopes) if scopes else "None" - - # Build warning box with client name if available import html as html_module client_display = html_module.escape(client_name or client_id) @@ -251,29 +249,58 @@ def create_consent_html( # Make server name a hyperlink if website URL is available if server_website_url: website_url_escaped = html_module.escape(server_website_url) - server_display = f'{server_name_escaped}' + server_display = f'{server_name_escaped}' else: server_display = server_name_escaped - warning_box = f""" -
-

{client_display} is requesting access to {server_display}.

-

Review the details below before approving.

+ # Build intro box with call-to-action + intro_box = f""" +
+

The application {client_display} wants to access the MCP server {server_display}. Please ensure you recognize the callback address below.

""" - # Build detail box with client information - detail_rows = [] - if client_name: - detail_rows.append(("Client Name", client_name)) - detail_rows.extend( + # Build redirect URI section (yellow box, centered) + redirect_uri_escaped = html_module.escape(redirect_uri) + redirect_section = f""" +
+ Credentials will be sent to: +
{redirect_uri_escaped}
+
+ """ + + # Build advanced details with collapsible section + detail_rows = [ + ("Application Name", html_module.escape(client_name or client_id)), + ("Application Website", html_module.escape(client_website_url or "N/A")), + ("Application ID", client_id), + ("Redirect URI", redirect_uri_escaped), + ( + "Requested Scopes", + ", ".join(html_module.escape(s) for s in scopes) if scopes else "None", + ), + ] + + detail_rows_html = "\n".join( [ - ("Client ID", client_id), - ("Redirect URI", redirect_uri), - ("Requested Scopes", scopes_display), + f""" +
+
{label}:
+
{value}
+
+ """ + for label, value in detail_rows ] ) - detail_box = create_detail_box(detail_rows) + + advanced_details = f""" +
+ Advanced Details +
+ {detail_rows_html} +
+
+ """ # Build form with buttons form = f""" @@ -281,13 +308,13 @@ def create_consent_html(
- +
""" - # Build help link with tooltip + # Build help link with tooltip (identical to current implementation) help_link = """