## Summary Adding `https://api.twenty.com/mcp` as an MCP server in Claude fails with `Couldn't reach the MCP server` before OAuth can start. Two independent bugs cause this: 1. **Missing path-aware well-known route.** The latest MCP spec instructs clients to probe `/.well-known/oauth-protected-resource/mcp` before `/.well-known/oauth-protected-resource`. Only the root path was registered, so the path-aware request fell through to `ServeStaticModule` and returned the SPA's `index.html` with HTTP 200. Strict clients (Claude.ai) tried to parse it as JSON and gave up. Fixed by registering both paths on the same handler. 2. **Stale protocol version.** Server advertised `2024-11-05`, which predates Streamable HTTP. We've implemented Streamable HTTP (SSE response format was added in #19528), so bumped to `2025-06-18`. Reproduction before the fix: ``` $ curl -s -o /dev/null -w "%{http_code} %{content_type}\n" https://api.twenty.com/.well-known/oauth-protected-resource/mcp 200 text/html; charset=UTF-8 ``` After the fix this returns `application/json` with the RFC 9728 metadata document. Note: this is separate from #19755 (host-aware resource URL for multi-host deployments). ## Test plan - [x] `npx jest oauth-discovery.controller` — 2/2 tests pass, including one asserting both routes are registered - [x] `npx nx lint:diff-with-main twenty-server` passes - [ ] After deploy, `curl https://api.twenty.com/.well-known/oauth-protected-resource/mcp` returns JSON (not HTML) - [ ] Adding `https://api.twenty.com/mcp` in Claude reaches the OAuth authorization screen 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>