VS Code extension's MCP OAuth flow sends malformed resource parameter (double-encoded, params leak into outer URL)
Summary
When authenticating an HTTP-transport MCP server (Supabase MCP, https://mcp.supabase.com/mcp?project_ref=...&features=...) from the VS Code extension's "MCP servers" panel, the generated OAuth authorize URL has a malformed resource parameter. The authorization server rejects it with {"message":"resource: Resource must be a valid MCP endpoint"}.
The same MCP server authenticates successfully when run from the terminal CLI (claude mcp list / /mcp), using the same Claude Code version. This points to a separate/divergent OAuth URL-construction code path in the VS Code extension vs. the CLI.
Environment
- Claude Code CLI version: 2.1.183
- Claude Code VS Code extension version: anthropic.claude-code@2.1.183 (latest available via marketplace at time of report)
- OS: Windows 11
- MCP server config (
.mcp.json):
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=<redacted>&features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching%2Cstorage"
}
}
}
Steps to reproduce
- Add an HTTP MCP server whose URL itself contains a query string (e.g. Supabase's remote MCP endpoint, which requires
project_refand optionallyfeaturesas query params). - Open the "MCP servers" panel in the VS Code extension, select the server, click Authenticate.
- Inspect the generated
authorizeURL.
Actual result
The resource parameter is malformed — the embedded ? is double-encoded (%253F instead of %3F), and the rest of the embedded query string (project_ref, features) is not encoded at all, so it leaks out as sibling top-level query parameters on the outer authorize URL instead of staying part of the resource value:
...&resource=https://mcp.supabase.com/mcp%253Fproject_ref=<redacted>&features=docs%252Caccount%252Cdatabase%252Cdebugging%252Cdevelopment%252Cfunctions%252Cbranching%252Cstorage
Supabase's OAuth server rejects this with:
{"message":"resource: Resource must be a valid MCP endpoint"}
This was reproduced consistently across multiple authentication attempts from the VS Code panel (different client_id/code_challenge each time, same malformed structure).
Expected result
The resource parameter should be the full MCP server URL, properly URL-encoded as a single value, matching the behavior already correct in the terminal/CLI flow:
...&resource=https%3A%2F%2Fmcp.supabase.com%2Fmcp%3Fproject_ref%3D<redacted>%26features%3Ddocs%252Caccount%252Cdatabase%252Cdebugging%252Cdevelopment%252Cfunctions%252Cbranching%252Cstorage
(Note: commas in features are double-encoded as %252C here because they're already percent-encoded as %2C in the source URL — that part is correct. Only the embedded ?, &, and = need single-encoding to %3F, %26, %3D; they are currently either double-encoded or not encoded at all, inconsistently.)
Workaround
Two workarounds were confirmed:
- Authenticate via the terminal (
claude mcp listor/mcpfrom an interactive CLI session) instead of the VS Code panel — the CLI builds theresourceparameter correctly. However, the resulting token does not appear to be shared with the VS Code panel's own connection state — the panel still shows "Needs Auth" even after a successful terminal auth for the same server URL. - Manually correcting the malformed
resourceparameter in the browser's address bar before submitting the authorize request (re-encoding the embedded MCP URL as a single properly-escaped value, keepingclient_id/code_challenge/state/redirect_uriunchanged) also completes authentication successfully, confirming the bug is purely in how the panel constructs theresourcevalue client-side, not a server-side rejection issue.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗