[BUG] MCP OAuth: resource parameter is double-encoded when the server URL has a query string (Supabase returns 422)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
What happens
Adding a remote HTTP MCP server whose URL contains a query string makes the OAuth
authorize request fail. The resource parameter is encoded wrongly: the ? is
encoded twice and the & between query parameters is not encoded at all.
Supabase's authorization server responds with:
422 {"message": "resource: Resource must be a valid MCP endpoint"}
The same server URL authenticates fine with VS Code's built-in MCP client.
Config (.mcp.json)
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=<ref>&features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching"
}
}
}
Steps to reproduce
- Add the config above (any Supabase project ref).
- Run /mcp, select the server, choose Authenticate.
- The browser opens the authorize URL and Supabase returns 422.
Authorize URL Claude Code generates (session values redacted)
https://api.supabase.com/v1/oauth/authorize?response_type=code&client_id=<redacted>&...
&resource=https://mcp.supabase.com/mcp%253Fproject_ref=<ref>&features=docs%252Caccount%252C...
%253Fis?double-encoded, so the server decodes it to
https://mcp.supabase.com/mcp%3Fproject_ref=..., which is not a valid endpoint.
&features=...is not encoded, so it is split off as a separate top-level
parameter of the authorize URL instead of staying inside resource.
Expected
resource is the server URL encoded exactly once, e.g.
resource=https%3A%2F%2Fmcp.supabase.com%2Fmcp%3Fproject_ref%3D<ref>%26features%3D...
(or the canonical resource from the server's protected-resource metadata).
Also observed
After failed attempts, re-authenticating the same server name returned
{"message": "Unrecognized client_id"}, which suggests a stale dynamic client
registration is reused. Renaming the server works around that part.
Environment
- Claude Code VS Code extension, version: <fill in>
- macOS 26 (Darwin 25.6.0)
- MCP server: https://mcp.supabase.com/mcp (hosted Supabase MCP)
Workaround
Use a Supabase personal access token in headers.Authorization instead of OAuth.
What Should Happen?
Claude should not deform the URL, the URL works fine with VS codes native mcp.
Error Messages/Logs
Steps to Reproduce
What happens
Adding a remote HTTP MCP server whose URL contains a query string makes the OAuth
authorize request fail. The resource parameter is encoded wrongly: the ? is
encoded twice and the & between query parameters is not encoded at all.
Supabase's authorization server responds with:
422 {"message": "resource: Resource must be a valid MCP endpoint"}
The same server URL authenticates fine with VS Code's built-in MCP client.
Config (.mcp.json)
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=<ref>&features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching"
}
}
}
Steps to reproduce
- Add the config above (any Supabase project ref).
- Run /mcp, select the server, choose Authenticate.
- The browser opens the authorize URL and Supabase returns 422.
Authorize URL Claude Code generates (session values redacted)
https://api.supabase.com/v1/oauth/authorize?response_type=code&client_id=<redacted>&...
&resource=https://mcp.supabase.com/mcp%253Fproject_ref=<ref>&features=docs%252Caccount%252C...
%253Fis?double-encoded, so the server decodes it to
https://mcp.supabase.com/mcp%3Fproject_ref=..., which is not a valid endpoint.
&features=...is not encoded, so it is split off as a separate top-level
parameter of the authorize URL instead of staying inside resource.
Expected
resource is the server URL encoded exactly once, e.g.
resource=https%3A%2F%2Fmcp.supabase.com%2Fmcp%3Fproject_ref%3D<ref>%26features%3D...
(or the canonical resource from the server's protected-resource metadata).
Also observed
After failed attempts, re-authenticating the same server name returned
{"message": "Unrecognized client_id"}, which suggests a stale dynamic client
registration is reused. Renaming the server works around that part.
Environment
- Claude Code VS Code extension, version: <fill in>
- macOS 26 (Darwin 25.6.0)
- MCP server: https://mcp.supabase.com/mcp (hosted Supabase MCP)
Workaround
Use a Supabase personal access token in headers.Authorization instead of OAuth.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.296
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗