[BUG] MCP OAuth fails: Protected Resource domain mismatch when server uses different public URL vs internal resource URL (Asana MCP V2)
Summary
When connecting to Asana's V2 MCP server (https://mcp.asana.com/v2/mcp) with a pre-registered OAuth app (client_id + client_secret), authentication always fails with:
SDK auth failed: Protected resource
https://asana-mcp-server.asana-enterprise-account.workers.dev/v2/mcp
does not match expected https://mcp.asana.com/v2/mcp (or origin)
Environment
- Claude Code version: 2.1.140
- OS: Linux
- MCP server: Asana V2 (
https://mcp.asana.com/v2/mcp)
Steps to Reproduce
Follow the official Asana documentation exactly:
https://developers.asana.com/docs/connecting-mcp-clients-to-asanas-v2-server#claude-code
claude mcp add --transport http \
--client-id YOUR_CLIENT_ID \
--client-secret \
--callback-port 8080 \
asana https://mcp.asana.com/v2/mcp
Then attempt to authenticate via /mcp → "Authenticate".
Root Cause
https://mcp.asana.com/v2/mcp returns a WWW-Authenticate header pointing to a resource_metadata URL on a different domain:
resource_metadata="https://asana-mcp-server.asana-enterprise-account.workers.dev/.well-known/oauth-protected-resource/v2"
That metadata returns:
{
"resource": "https://asana-mcp-server.asana-enterprise-account.workers.dev/v2/mcp",
"authorization_servers": ["https://app.asana.com"]
}
Claude Code's RFC 9728 validation (added in v2.1.85) rejects the connection because the resource field (workers.dev) does not match the configured URL (mcp.asana.com).
This can be reproduced with curl:
# Step 1: Check WWW-Authenticate header
curl -si https://mcp.asana.com/v2/mcp | grep resource_metadata
# → resource_metadata="https://asana-mcp-server.asana-enterprise-account.workers.dev/..."
# Step 2: Fetch the resource metadata
curl -s "https://asana-mcp-server.asana-enterprise-account.workers.dev/.well-known/oauth-protected-resource/v2"
# → { "resource": "https://asana-mcp-server.asana-enterprise-account.workers.dev/v2/mcp" }
Asana's Official Position
Asana support confirmed this is intentional on their side — the V2 MCP server is hosted on a different domain than the public URL. They state that Claude Code needs to be updated to accept this mismatch:
"Claude Code が更新されて V2 の protected-resource メタデータを受け入れるようになるのを待つ。" ("Wait for Claude Code to be updated to accept V2's protected-resource metadata.")
Impact
- V1 SSE endpoint (
https://mcp.asana.com/sse) was shut down on 2026-05-11 - V2 is the only available endpoint
- Asana MCP is completely unusable in Claude Code as of 2026-05-11
- The official Asana documentation explicitly lists Claude Code as a supported client
Expected Behavior
When a client_id is pre-configured (i.e., the user has already registered an OAuth app), Claude Code should either:
- Relax the strict domain matching and allow connections where the
resourceURL's origin differs from the configured URL's origin, OR - Fall back to the resource URL (
https://asana-mcp-server.asana-enterprise-account.workers.dev/v2/mcp) as the effective endpoint when a mismatch is detected, OR - Add a
skipResourceCheckoption in MCP server config for cases where the server operator has confirmed the mismatch is intentional
Related Issues
- #55067 — Random port used instead of configured callbackPort (Asana MCP)
- #58091 — Asana MCP OAuth fails: redirect_uri not registered
- #52638 — HTTP MCP servers with OAuth fail (dynamic client registration) — closed as duplicate
- #27765 — MCP: Support API key authentication and improve OAuth compatibility
- anthropics/claude-plugins-official#998 — Asana MCP V2 migration blocked by OAuth incompatibility
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗