[SILO-1181] feat: support configurable subpath prefix for MCP server#106
[SILO-1181] feat: support configurable subpath prefix for MCP server#106Prashant-Surya wants to merge 2 commits into
Conversation
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds ChangesHTTP Path Prefix Configuration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
plane_mcp/__main__.py (2)
136-136:⚠️ Potential issue | 🟡 MinorStartup log message no longer matches mounted paths.
The message still says
/mcpand/header/mcp, but mounts are now under/http/mcpand/http/api-key/mcp(plus optional prefix). Update this to avoid operational confusion.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plane_mcp/__main__.py` at line 136, Update the startup log in __main__.py so the logger.info message reflects the actual mounted routes; replace the outdated "/mcp" and "/header/mcp" text in the logger.info call with the current paths "/http/mcp" and "/http/api-key/mcp" (and include any configured optional prefix if your app prepends one) so the log accurately shows where the HTTP endpoints are mounted.
91-115:⚠️ Potential issue | 🟠 MajorNormalize
MCP_PATH_PREFIXbefore composing routes.Raw concatenation can produce malformed paths (for example
/→//http,mcp→mcp/http). Normalize once, then reuse.Proposed fix
- prefix = os.getenv("MCP_PATH_PREFIX") or "" + raw_prefix = (os.getenv("MCP_PATH_PREFIX") or "").strip() + if raw_prefix in {"", "/"}: + prefix = "" + else: + prefix = raw_prefix if raw_prefix.startswith("/") else f"/{raw_prefix}" + prefix = prefix.rstrip("/") oauth_mcp = get_oauth_mcp(prefix + "/http") oauth_app = oauth_mcp.http_app(stateless_http=True) header_app = get_header_mcp().http_app(stateless_http=True) sse_mcp = get_oauth_mcp(prefix) sse_app = sse_mcp.http_app(transport="sse")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plane_mcp/__main__.py` around lines 91 - 115, Normalize the MCP_PATH_PREFIX string once instead of raw concatenation: compute prefix_raw = os.getenv("MCP_PATH_PREFIX") or "" then normalize to prefix = ("/" + prefix_raw.strip("/")) if prefix_raw.strip("/") else "" so the value either is "" or begins with a single leading slash and has no trailing slash; then update calls that currently do prefix + "/http" and prefix + "/http/api-key" (the get_oauth_mcp calls and the Mount arguments) to use f"{prefix}/http" and f"{prefix}/http/api-key" (or construct the path with the normalized prefix), and keep Mount(prefix or "/", app=sse_app) as-is so routes do not get double slashes; change the prefix assignment near where prefix is defined and leave get_oauth_mcp, get_header_mcp, oauth_mcp, sse_mcp, oauth_well_known, sse_well_known, and the Starlette routes/Mount entries otherwise unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@plane_mcp/__main__.py`:
- Line 136: Update the startup log in __main__.py so the logger.info message
reflects the actual mounted routes; replace the outdated "/mcp" and
"/header/mcp" text in the logger.info call with the current paths "/http/mcp"
and "/http/api-key/mcp" (and include any configured optional prefix if your app
prepends one) so the log accurately shows where the HTTP endpoints are mounted.
- Around line 91-115: Normalize the MCP_PATH_PREFIX string once instead of raw
concatenation: compute prefix_raw = os.getenv("MCP_PATH_PREFIX") or "" then
normalize to prefix = ("/" + prefix_raw.strip("/")) if prefix_raw.strip("/")
else "" so the value either is "" or begins with a single leading slash and has
no trailing slash; then update calls that currently do prefix + "/http" and
prefix + "/http/api-key" (the get_oauth_mcp calls and the Mount arguments) to
use f"{prefix}/http" and f"{prefix}/http/api-key" (or construct the path with
the normalized prefix), and keep Mount(prefix or "/", app=sse_app) as-is so
routes do not get double slashes; change the prefix assignment near where prefix
is defined and leave get_oauth_mcp, get_header_mcp, oauth_mcp, sse_mcp,
oauth_well_known, sse_well_known, and the Starlette routes/Mount entries
otherwise unchanged.
Allows deploying the HTTP server under an ingress subpath (e.g. /mcp) by mounting the OAuth, header-auth, and SSE transports under the prefix and passing the prefix into each OAuth provider's base_url so advertised metadata URLs (issuer, authorize, token, register, resource) resolve to the externally-visible path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b5ad536 to
54ece08
Compare
Summary
MCP_PATH_PREFIXenv var so the HTTP server can be deployed behind an ingress that serves it under a subpath (e.g./mcp)./http/mcp), header-auth streamable-http (/http/api-key/mcp), and SSE (/sse) — are now mounted under the prefix.base_urlis built with the prefix so advertised metadata (issuer, authorize, token, register, and protected-resource URLs) resolves to the externally-visible path.mcp_pathfor well-known routes stays at/mcpand/sse(relative tobase_url) to avoid double-prefixing the advertised resource URL.MCP_PATH_PREFIXis unset, routing and metadata are identical to before — no behavior change for existing deployments.Tracks: SILO-1181.
Test plan
MCP_PATH_PREFIX=/mcp,PLANE_OAUTH_PROVIDER_BASE_URL=http://localhost:8211(no prefix in env var).GET /.well-known/oauth-authorization-server/mcp/httpreturns issuerhttp://localhost:8211/mcp/httpand registration endpointhttp://localhost:8211/mcp/http/register.GET /.well-known/oauth-authorization-server/mcp(SSE) returns issuerhttp://localhost:8211/mcp.GET /.well-known/oauth-protected-resource/mcp/http/mcpadvertises resourcehttp://localhost:8211/mcp/http/mcp.POST /mcp/http/mcpreturns 401 (OAuth challenge) — not 404.POST /mcp/http/api-key/mcpwith validx-workspace-slug+authorizationheaders initializes successfully.GET /mcp/ssereturns 401 (not 404).test_client.py::test_oauth_mcpagainsthttp://localhost:8211/mcp/http/mcpcompletes successfully.MCP_PATH_PREFIXset, existing URLs (/http/mcp,/http/api-key/mcp,/sse) continue to work unchanged.🤖 Generated with Claude Code
Summary by CodeRabbit