Commit 12eef1
2026-03-13 18:10:20 Claude (MCP): [mcp] P1-9: Document OAuth discovery routing fix| /dev/null .. Tasks/P1-9_MCP_OAuth_Discovery_Routing.md | |
| @@ 0,0 1,70 @@ | |
| + | --- |
| + | category: reference |
| + | tags: |
| + | - P1 |
| + | - infrastructure |
| + | - oauth |
| + | - mcp |
| + | last_updated: 2026-03-13 |
| + | --- |
| + | |
| + | # P1-9: Fix MCP OAuth Discovery Routing |
| + | |
| + | ## Problem |
| + | |
| + | Claude.ai needs to discover OAuth endpoints via `/.well-known/oauth-authorization-server` to initiate the OAuth flow with the MCP server. Two issues prevented this: |
| + | |
| + | 1. **Missing API Gateway route:** `/.well-known/*` paths hit the Otterwiki Lambda (`$default` catch-all) instead of the MCP Lambda, returning HTML instead of OAuth metadata JSON. |
| + | |
| + | 2. **Double path in resource URL:** `MCP_BASE_URL` was set to `https://dev.wikibot.io/mcp`, but FastMCP's `_get_resource_url()` appends the `mcp_path` parameter (`/mcp`) to the base URL, producing `https://dev.wikibot.io/mcp/mcp`. |
| + | |
| + | ## Solution |
| + | |
| + | Two infrastructure changes, no code changes: |
| + | |
| + | 1. **Added API Gateway route** `ANY /.well-known/{proxy+}` pointing to the MCP Lambda integration. This routes OAuth discovery requests to the correct Lambda. |
| + | |
| + | 2. **Changed `MCP_BASE_URL`** from `https://dev.wikibot.io/mcp` to `https://dev.wikibot.io`. FastMCP now computes the correct resource URL `https://dev.wikibot.io/mcp` via `_get_resource_url("/mcp")`. |
| + | |
| + | ## Verification |
| + | |
| + | All endpoints tested after deploy: |
| + | |
| + | | Endpoint | Expected | Actual | |
| + | |----------|----------|--------| |
| + | | `GET /.well-known/oauth-authorization-server` | WorkOS OAuth metadata JSON | Pass | |
| + | | `GET /.well-known/oauth-protected-resource/mcp` | Protected resource metadata JSON | Pass | |
| + | | `POST /mcp` (with bearer token) | MCP initialize response (200) | Pass | |
| + | | `POST /mcp` (no auth) | 401 Unauthorized | Pass | |
| + | | `GET /Home` | Otterwiki HTML | Pass | |
| + | |
| + | ## Files Changed |
| + | |
| + | - `infra/Pulumi.dev.yaml` — `mcp_base_url` value |
| + | - `infra/__main__.py` — new `mcp-route-well-known` API Gateway route |
| + | |
| + | ## How It Works |
| + | |
| + | ``` |
| + | Client → GET /.well-known/oauth-authorization-server |
| + | → API Gateway route: ANY /.well-known/{proxy+} |
| + | → MCP Lambda |
| + | → Starlette route: /.well-known/oauth-authorization-server |
| + | → AuthKitProvider forwards WorkOS metadata |
| + | |
| + | Client → GET /.well-known/oauth-protected-resource/mcp |
| + | → API Gateway route: ANY /.well-known/{proxy+} |
| + | → MCP Lambda |
| + | → Starlette route: /.well-known/oauth-protected-resource/mcp |
| + | → Returns resource metadata with authorization_servers |
| + | |
| + | Client → POST /mcp (MCP protocol) |
| + | → API Gateway route: ANY /mcp |
| + | → MCP Lambda |
| + | → Starlette route: /mcp |
| + | → StreamableHTTP handler |
| + | ``` |
| + | |
| + | ## Commit |
| + | |
| + | `e46ef4a` on `main` branch (not pushed) |