codeant-ai-for-open-source[bot] commented on code in PR #40469:
URL: https://github.com/apache/superset/pull/40469#discussion_r3311458075
##########
superset/mcp_service/jwt_verifier.py:
##########
@@ -61,21 +63,227 @@
"_jwt_failure_reason", default=None
)
+_HTML_STYLES = """
+ *, *::before, *::after { box-sizing: border-box; }
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
+ background: #f5f5f5;
+ color: #1a1a1a;
+ margin: 0;
+ padding: 40px 16px;
+ line-height: 1.6;
+ }
+ .card {
+ max-width: 640px;
+ margin: 0 auto;
+ background: #ffffff;
+ border-radius: 8px;
+ box-shadow: 0 1px 4px rgba(0,0,0,.12);
+ padding: 40px 40px 32px;
+ }
+ h1 { font-size: 1.4rem; margin: 0 0 8px; }
+ .badge {
+ display: inline-block;
+ background: #e8f4fd;
+ color: #0070c0;
+ font-size: .75rem;
+ font-weight: 600;
+ padding: 2px 8px;
+ border-radius: 4px;
+ margin-bottom: 20px;
+ letter-spacing: .04em;
+ text-transform: uppercase;
+ }
+ p { margin: 0 0 20px; color: #444; }
+ h2 { font-size: 1rem; margin: 24px 0 8px; color: #1a1a1a; }
+ pre {
+ background: #f0f0f0;
+ border-radius: 6px;
+ padding: 16px;
+ font-size: .85rem;
+ overflow-x: auto;
+ margin: 0 0 24px;
+ }
+ code {
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo,
monospace;
+ }
+ .note {
+ font-size: .85rem;
+ color: #666;
+ border-left: 3px solid #ddd;
+ padding-left: 12px;
+ margin-top: 24px;
+ }"""
+
+_DEFAULT_CLIENTS = [
+ "Claude Desktop",
+ "Claude Code (CLI)",
+ "Cursor",
+]
+
+_DEFAULT_HELLO_PAGE_CONFIG: dict[str, Any] = {
+ # Page heading and browser tab title
+ "title": "Superset MCP Server",
+ # Key name used in the mcpServers config snippet (e.g. "superset",
"my-company")
+ "server_key": "superset",
+ # Include "transport": "streamable-http" in the config snippet.
+ # Recommended: Claude Desktop defaults to SSE so the transport must be
explicit.
+ "show_transport": True,
+ # Supported MCP clients listed on the page
+ "clients": _DEFAULT_CLIENTS,
+}
+
+
+def _build_config_snippet(
+ auth_enabled: bool, server_key: str, show_transport: bool
+) -> str:
+ inner_parts = [' "url": "<this-url>"']
+ if show_transport:
+ inner_parts.append(' "transport": "streamable-http"')
+ if auth_enabled:
+ inner_parts.append(
+ ' "headers": {\n'
+ ' "Authorization": "Bearer <your-api-key>"\n'
+ " }"
+ )
+ inner = ",\n".join(inner_parts)
+ return f'{{\n "mcpServers": {{\n "{server_key}": {{\n{inner}\n }}\n
}}\n}}'
Review Comment:
**Suggestion:** The generated JSON config snippet inserts `server_key`
directly into a JSON string literal; if the configured key contains quotes or
backslashes, the snippet becomes invalid JSON and setup instructions will fail
for users. Serialize or escape `server_key` as a JSON string before
interpolation. [logic error]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ⚠️ Generated MCP client snippet may be invalid JSON.
- ⚠️ Users copying config see confusing parse-time failures.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Configure the MCP hello page via Flask config so that
`flask_app.config["MCP_HELLO_PAGE"]` contains a `server_key` value with
characters that
must be escaped in JSON, for example: `MCP_HELLO_PAGE = {"server_key":
"my\"superset"}`;
this config is later read by `_build_starlette_middleware()` at
`superset/mcp_service/server.py:79`.
2. Start the MCP HTTP server via `run_server()` in
`superset/mcp_service/server.py:90-151`, which invokes
`_build_starlette_middleware(flask_app)` at `server.py:167-169`; that
constructs
`BrowserHelloMiddleware` whose `__init__()` (`jwt_verifier.py:251-260`) calls
`_build_browser_hello_html(auth_enabled, page_config)`
(`jwt_verifier.py:153-215`).
3. `_build_browser_hello_html()` calls `_build_config_snippet(auth_enabled,
server_key,
show_transport)` at `jwt_verifier.py:163`, passing the configured
`server_key` string
containing an embedded quote.
4. `_build_config_snippet()` builds the JSON snippet string using `return
f'{{\n
"mcpServers": {{\n "{server_key}": {{\n{inner}\n }}\n }}\n}}'` at
`jwt_verifier.py:150`
without escaping `server_key`; when the browser loads the hello page and the
operator
copies the `<code>` block into an MCP client config, the resulting JSON
contains a key
like `"my"superset": { ... }`, which is syntactically invalid and will cause
JSON parsing
failures in the client.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=52a14186df96452792c8f38f9d7f5230&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
| [Fix in VSCode
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=52a14186df96452792c8f38f9d7f5230&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset/mcp_service/jwt_verifier.py
**Line:** 150:150
**Comment:**
*Logic Error: The generated JSON config snippet inserts `server_key`
directly into a JSON string literal; if the configured key contains quotes or
backslashes, the snippet becomes invalid JSON and setup instructions will fail
for users. Serialize or escape `server_key` as a JSON string before
interpolation.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=820b5b880dc735e53012efcf3ee2b72f85c6e10e4e4275b21ea30566a61e95ac&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=820b5b880dc735e53012efcf3ee2b72f85c6e10e4e4275b21ea30566a61e95ac&reaction=dislike'>👎</a>
##########
superset/mcp_service/jwt_verifier.py:
##########
@@ -61,21 +63,227 @@
"_jwt_failure_reason", default=None
)
+_HTML_STYLES = """
+ *, *::before, *::after { box-sizing: border-box; }
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
+ background: #f5f5f5;
+ color: #1a1a1a;
+ margin: 0;
+ padding: 40px 16px;
+ line-height: 1.6;
+ }
+ .card {
+ max-width: 640px;
+ margin: 0 auto;
+ background: #ffffff;
+ border-radius: 8px;
+ box-shadow: 0 1px 4px rgba(0,0,0,.12);
+ padding: 40px 40px 32px;
+ }
+ h1 { font-size: 1.4rem; margin: 0 0 8px; }
+ .badge {
+ display: inline-block;
+ background: #e8f4fd;
+ color: #0070c0;
+ font-size: .75rem;
+ font-weight: 600;
+ padding: 2px 8px;
+ border-radius: 4px;
+ margin-bottom: 20px;
+ letter-spacing: .04em;
+ text-transform: uppercase;
+ }
+ p { margin: 0 0 20px; color: #444; }
+ h2 { font-size: 1rem; margin: 24px 0 8px; color: #1a1a1a; }
+ pre {
+ background: #f0f0f0;
+ border-radius: 6px;
+ padding: 16px;
+ font-size: .85rem;
+ overflow-x: auto;
+ margin: 0 0 24px;
+ }
+ code {
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo,
monospace;
+ }
+ .note {
+ font-size: .85rem;
+ color: #666;
+ border-left: 3px solid #ddd;
+ padding-left: 12px;
+ margin-top: 24px;
+ }"""
+
+_DEFAULT_CLIENTS = [
+ "Claude Desktop",
+ "Claude Code (CLI)",
+ "Cursor",
+]
+
+_DEFAULT_HELLO_PAGE_CONFIG: dict[str, Any] = {
+ # Page heading and browser tab title
+ "title": "Superset MCP Server",
+ # Key name used in the mcpServers config snippet (e.g. "superset",
"my-company")
+ "server_key": "superset",
+ # Include "transport": "streamable-http" in the config snippet.
+ # Recommended: Claude Desktop defaults to SSE so the transport must be
explicit.
+ "show_transport": True,
+ # Supported MCP clients listed on the page
+ "clients": _DEFAULT_CLIENTS,
+}
+
+
+def _build_config_snippet(
+ auth_enabled: bool, server_key: str, show_transport: bool
+) -> str:
+ inner_parts = [' "url": "<this-url>"']
+ if show_transport:
+ inner_parts.append(' "transport": "streamable-http"')
+ if auth_enabled:
+ inner_parts.append(
+ ' "headers": {\n'
+ ' "Authorization": "Bearer <your-api-key>"\n'
+ " }"
+ )
+ inner = ",\n".join(inner_parts)
+ return f'{{\n "mcpServers": {{\n "{server_key}": {{\n{inner}\n }}\n
}}\n}}'
+
+
+def _build_browser_hello_html(
+ auth_enabled: bool,
+ page_config: dict[str, Any] | None = None,
+) -> str:
+ cfg = {**_DEFAULT_HELLO_PAGE_CONFIG, **(page_config or {})}
+ title: str = cfg["title"]
+ server_key: str = cfg["server_key"]
+ show_transport: bool = cfg["show_transport"]
+ clients: list[str] = cfg["clients"]
+
+ config_block = _build_config_snippet(auth_enabled, server_key,
show_transport)
+
+ if auth_enabled:
+ connect_desc = (
+ "Add the following to your MCP client configuration, "
+ "replacing the URL and API key with your actual values:"
+ )
+ note = (
+ "Replace <code><this-url></code> with the full URL of this
page and "
+ "<code><your-api-key></code> with a valid API key or JWT
token."
+ )
+ else:
+ connect_desc = (
+ "Add the following to your MCP client configuration, "
+ "replacing the URL with your actual server URL:"
+ )
+ note = "Replace <code><this-url></code> with the full URL of
this page."
+
+ client_items = "\n".join(f" <li>{c}</li>" for c in clients)
+
+ return f"""<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{title}</title>
+ <style>{_HTML_STYLES}
+ </style>
+</head>
+<body>
+ <div class="card">
+ <div class="badge">MCP API Endpoint</div>
+ <h1>{title}</h1>
+ <p>
Review Comment:
**Suggestion:** Config-driven page values are interpolated directly into
HTML without escaping, so a crafted `MCP_HELLO_PAGE["title"]` value can inject
markup/script into the response. Escape dynamic HTML content before rendering
to prevent XSS and broken markup. [security]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ❌ Admin-defined hello page config can inject arbitrary HTML.
- ⚠️ XSS possible if config built from untrusted inputs.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Configure the Flask app used by the MCP service so that
`flask_app.config["MCP_HELLO_PAGE"]` includes an untrusted HTML string for
`title`, for
example in deployment config: `MCP_HELLO_PAGE = {"title": "<img src=x
onerror=alert(1)>",
"server_key": "superset"}`; this config is later read in
`_build_starlette_middleware()`
at `superset/mcp_service/server.py:79`.
2. Start the MCP HTTP server via `run_server()` in
`superset/mcp_service/server.py:90-151`
(e.g. `superset mcp run --port 5008`), which obtains a Flask app from
`get_flask_app()`
(`superset/mcp_service/flask_singleton.py:99-106`) and then calls
`_build_starlette_middleware(flask_app)` at `server.py:167-169`.
3. `_build_starlette_middleware()` reads `page_config =
flask_app.config.get("MCP_HELLO_PAGE", None)` at `server.py:79` and
constructs
`BrowserHelloMiddleware` with this `page_config`;
`BrowserHelloMiddleware.__init__()`
(`jwt_verifier.py:251-260`) calls `_build_browser_hello_html(auth_enabled,
page_config)`
at `jwt_verifier.py:153-215`.
4. `_build_browser_hello_html()` merges defaults and config into `cfg` and
interpolates
`cfg["title"]` directly into the HTML template at `jwt_verifier.py:188-196`
— specifically
`<title>{title}</title>` and `<h1>{title}</h1>` — without escaping; when a
browser
requests `GET /mcp` with a browser-style `Accept: text/html` header
(triggering
`BrowserHelloMiddleware.dispatch()` at `jwt_verifier.py:262-267`), the
response contains
`<img src=x onerror=alert(1)>` in the title and heading, and the `onerror`
JavaScript
executes in the MCP server's origin context.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=ee4aa5f1b432408d954357875a0047aa&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
| [Fix in VSCode
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=ee4aa5f1b432408d954357875a0047aa&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset/mcp_service/jwt_verifier.py
**Line:** 189:196
**Comment:**
*Security: Config-driven page values are interpolated directly into
HTML without escaping, so a crafted `MCP_HELLO_PAGE["title"]` value can inject
markup/script into the response. Escape dynamic HTML content before rendering
to prevent XSS and broken markup.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=3d6bd2405ffe33fa2273f662c3dfdb75480d63d5e121f9fc04af63895716be7f&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=3d6bd2405ffe33fa2273f662c3dfdb75480d63d5e121f9fc04af63895716be7f&reaction=dislike'>👎</a>
##########
superset/mcp_service/jwt_verifier.py:
##########
@@ -61,21 +63,227 @@
"_jwt_failure_reason", default=None
)
+_HTML_STYLES = """
+ *, *::before, *::after { box-sizing: border-box; }
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
+ background: #f5f5f5;
+ color: #1a1a1a;
+ margin: 0;
+ padding: 40px 16px;
+ line-height: 1.6;
+ }
+ .card {
+ max-width: 640px;
+ margin: 0 auto;
+ background: #ffffff;
+ border-radius: 8px;
+ box-shadow: 0 1px 4px rgba(0,0,0,.12);
+ padding: 40px 40px 32px;
+ }
+ h1 { font-size: 1.4rem; margin: 0 0 8px; }
+ .badge {
+ display: inline-block;
+ background: #e8f4fd;
+ color: #0070c0;
+ font-size: .75rem;
+ font-weight: 600;
+ padding: 2px 8px;
+ border-radius: 4px;
+ margin-bottom: 20px;
+ letter-spacing: .04em;
+ text-transform: uppercase;
+ }
+ p { margin: 0 0 20px; color: #444; }
+ h2 { font-size: 1rem; margin: 24px 0 8px; color: #1a1a1a; }
+ pre {
+ background: #f0f0f0;
+ border-radius: 6px;
+ padding: 16px;
+ font-size: .85rem;
+ overflow-x: auto;
+ margin: 0 0 24px;
+ }
+ code {
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo,
monospace;
+ }
+ .note {
+ font-size: .85rem;
+ color: #666;
+ border-left: 3px solid #ddd;
+ padding-left: 12px;
+ margin-top: 24px;
+ }"""
+
+_DEFAULT_CLIENTS = [
+ "Claude Desktop",
+ "Claude Code (CLI)",
+ "Cursor",
+]
+
+_DEFAULT_HELLO_PAGE_CONFIG: dict[str, Any] = {
+ # Page heading and browser tab title
+ "title": "Superset MCP Server",
+ # Key name used in the mcpServers config snippet (e.g. "superset",
"my-company")
+ "server_key": "superset",
+ # Include "transport": "streamable-http" in the config snippet.
+ # Recommended: Claude Desktop defaults to SSE so the transport must be
explicit.
+ "show_transport": True,
+ # Supported MCP clients listed on the page
+ "clients": _DEFAULT_CLIENTS,
+}
+
+
+def _build_config_snippet(
+ auth_enabled: bool, server_key: str, show_transport: bool
+) -> str:
+ inner_parts = [' "url": "<this-url>"']
+ if show_transport:
+ inner_parts.append(' "transport": "streamable-http"')
+ if auth_enabled:
+ inner_parts.append(
+ ' "headers": {\n'
+ ' "Authorization": "Bearer <your-api-key>"\n'
+ " }"
+ )
+ inner = ",\n".join(inner_parts)
+ return f'{{\n "mcpServers": {{\n "{server_key}": {{\n{inner}\n }}\n
}}\n}}'
+
+
+def _build_browser_hello_html(
+ auth_enabled: bool,
+ page_config: dict[str, Any] | None = None,
+) -> str:
+ cfg = {**_DEFAULT_HELLO_PAGE_CONFIG, **(page_config or {})}
+ title: str = cfg["title"]
+ server_key: str = cfg["server_key"]
+ show_transport: bool = cfg["show_transport"]
+ clients: list[str] = cfg["clients"]
+
+ config_block = _build_config_snippet(auth_enabled, server_key,
show_transport)
+
+ if auth_enabled:
+ connect_desc = (
+ "Add the following to your MCP client configuration, "
+ "replacing the URL and API key with your actual values:"
+ )
+ note = (
+ "Replace <code><this-url></code> with the full URL of this
page and "
+ "<code><your-api-key></code> with a valid API key or JWT
token."
+ )
+ else:
+ connect_desc = (
+ "Add the following to your MCP client configuration, "
+ "replacing the URL with your actual server URL:"
+ )
+ note = "Replace <code><this-url></code> with the full URL of
this page."
+
+ client_items = "\n".join(f" <li>{c}</li>" for c in clients)
+
+ return f"""<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{title}</title>
+ <style>{_HTML_STYLES}
+ </style>
+</head>
+<body>
+ <div class="card">
+ <div class="badge">MCP API Endpoint</div>
+ <h1>{title}</h1>
+ <p>
+ This is the <strong>Model Context Protocol (MCP)</strong> endpoint for
+ Apache Superset. It is an API designed for AI coding assistants —
+ not a web page to browse directly.
+ </p>
+ <h2>How to connect</h2>
+ <p>{connect_desc}</p>
+ <pre><code>{config_block}</code></pre>
+ <h2>Supported clients</h2>
+ <p>This endpoint works with any MCP-compatible client, including:</p>
+ <ul style="color:#444;margin:0 0 20px;padding-left:20px;">
+{client_items}
+ <li>Any client that supports the <code>streamable-http</code>
transport</li>
+ </ul>
+ <div class="note">
+ {note}
+ </div>
+ </div>
+</body>
+</html>"""
+
+
+# Pre-built for _auth_error_handler (auth-required context, default config)
+_MCP_BROWSER_HELLO_HTML = _build_browser_hello_html(auth_enabled=True)
+
+
+def _prefers_browser_html(conn: HTTPConnection) -> bool:
+ """Return True when the request looks like a browser navigation.
+
+ Checks both the HTTP method (GET/HEAD only) and the Accept header
+ (text/html present, application/json and text/event-stream absent).
+ Case-insensitive to handle unusual but valid header values.
+ """
+ if conn.scope.get("method") not in ("GET", "HEAD"):
+ return False
+ accept = conn.headers.get("accept", "").lower()
+ return (
+ "text/html" in accept
+ and "application/json" not in accept
+ and "text/event-stream" not in accept
+ )
+
+
+class BrowserHelloMiddleware(BaseHTTPMiddleware):
+ """Starlette middleware that returns a browser-friendly hello page.
+
+ Intercepts GET/HEAD requests with a browser Accept header before they
+ reach FastMCP's router (which returns 405 for GET). Works regardless
+ of whether MCP_AUTH_ENABLED is True or False.
+
+ When auth_enabled=True the page includes Bearer token setup instructions.
+ When auth_enabled=False the page omits the Authorization header from the
+ config snippet since no credentials are required.
+ """
+
+ def __init__(
+ self,
+ app: Any,
+ auth_enabled: bool = False,
+ page_config: dict[str, Any] | None = None,
+ ) -> None:
+ super().__init__(app)
+ self._html = _build_browser_hello_html(
+ auth_enabled=auth_enabled, page_config=page_config
+ )
+
+ async def dispatch(
+ self, request: Request, call_next: Callable[..., Any]
+ ) -> Response:
+ if request.method in ("GET", "HEAD") and
_prefers_browser_html(request):
+ return HTMLResponse(content=self._html, status_code=200)
Review Comment:
**Suggestion:** The hello middleware currently returns the HTML page for any
`GET`/`HEAD` request that advertises `text/html`, without checking the request
path. That makes unrelated or unknown routes return `200` with the MCP page
instead of their real response (for example, expected `404`/`405`), which can
mask routing errors and break endpoint behavior. Restrict this branch to the
MCP endpoint path only. [incorrect condition logic]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ❌ Unknown MCP HTTP paths return 200 hello instead 404.
- ⚠️ Masks routing errors when debugging MCP reverse proxies.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Start the MCP HTTP server via `run_server()` in
`superset/mcp_service/server.py:90-151`, e.g. using the documented CLI
`superset mcp run
--port 5008`, which constructs an HTTP app and passes
`middleware=starlette_middleware` at
`server.py:179-185`.
2. `_build_starlette_middleware()` in `superset/mcp_service/server.py:72-87`
wraps the
FastMCP ASGI app with `BrowserHelloMiddleware` (from
`superset/mcp_service/jwt_verifier.py:239-267`) as Starlette middleware, so
it sees all
incoming HTTP requests regardless of path.
3. From a browser (or with curl mimicking a browser header), send a GET
request to an
undefined path on the MCP server, for example: `GET /nonexistent HTTP/1.1`
with header
`Accept: text/html,*/*` against `http://localhost:5008` (the host/port used
in
`run_server()`).
4. `BrowserHelloMiddleware.dispatch()` at `jwt_verifier.py:262-267` evaluates
`request.method in ("GET", "HEAD")` and calls
`_prefers_browser_html(request)` at
`jwt_verifier.py:222-236`, which returns True because `Accept` contains
`text/html` and
not `application/json`/`text/event-stream`; it then immediately returns
`HTMLResponse(content=self._html, status_code=200)` for `/nonexistent`, so
the underlying
FastMCP router never runs and the client sees a 200 MCP hello page instead
of the expected
404/405 for an unknown route.
```
</details>
[Fix in
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=3e7b9d1633904e3bbc8385f5548a70f7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
| [Fix in VSCode
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=3e7b9d1633904e3bbc8385f5548a70f7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset/mcp_service/jwt_verifier.py
**Line:** 265:266
**Comment:**
*Incorrect Condition Logic: The hello middleware currently returns the
HTML page for any `GET`/`HEAD` request that advertises `text/html`, without
checking the request path. That makes unrelated or unknown routes return `200`
with the MCP page instead of their real response (for example, expected
`404`/`405`), which can mask routing errors and break endpoint behavior.
Restrict this branch to the MCP endpoint path only.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=bc86581180a79fb66ae16ad83f19a3245d92776e8e680f819645352787053e59&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40469&comment_hash=bc86581180a79fb66ae16ad83f19a3245d92776e8e680f819645352787053e59&reaction=dislike'>👎</a>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]