[BUG] URL-mode elicitation broken: client capability dropped from {form,url} to {} (~2.1.108); server elicitation/create mode:"url" rejected with -32602
Preflight Checklist
- [x] I have searched existing issues — this regression is also tracked in #48164. This is a consolidated, root-caused report (minimal repro + likely cause + reference implementation); happy for it to be linked/merged there.
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code no longer supports MCP URL-mode elicitation (elicitation/create with mode: "url", per the 2025-11-25 spec). This is a regression in the advertised client capability:
- v2.1.87 advertised
"elicitation": { "form": {}, "url": {} }— but silently answered url-mode requests with{"action":"cancel"}(the URL was never shown to the user). - ~v2.1.108 onward narrowed the capability to
"elicitation": {}, which per the spec means form-mode only. URL-mode requests now hard-fail with-32602 "Client does not support URL-mode elicitation requests".
Net effect: url-mode elicitation has never worked end-to-end, and the capability is now dropped entirely. This blocks every server-initiated out-of-band flow — OAuth/3LO, credential entry, and human-in-the-loop confirmation.
What Should Happen?
Per the 2025-11-25 spec, Claude Code should:
- Advertise
"elicitation": { "form": {}, "url": {} }atinitialize. - On a
mode: "url"elicitation/create, show the user the full URL with consent controls, open it out-of-band (browser), and returnaccept/decline/cancelaccordingly. - Support the
URLElicitationRequiredError(-32042) retry path: run the required url-elicitation(s), then retry the originaltools/call.
Steps to Reproduce
- Save this minimal stdio MCP server as
url_elicit_server.py:
#!/usr/bin/env python3
"""Minimal stdio MCP server that sends a URL-mode elicitation after initialize."""
import json, sys
def send(msg):
sys.stdout.write(json.dumps(msg) + "\n"); sys.stdout.flush()
for line in sys.stdin:
line = line.strip()
if not line:
continue
msg = json.loads(line)
method, mid = msg.get("method"), msg.get("id")
if method == "initialize":
send({"jsonrpc":"2.0","id":mid,"result":{
"protocolVersion":"2025-11-25",
"capabilities":{"tools":{}},
"serverInfo":{"name":"url-elicit-test","version":"1.0.0"}}})
elif method == "notifications/initialized":
send({"jsonrpc":"2.0","id":1,"method":"elicitation/create","params":{
"mode":"url",
"elicitationId":"550e8400-e29b-41d4-a716-446655440000",
"url":"https://example.com/authorize",
"message":"Please authorize to continue."}})
elif method == "tools/list":
send({"jsonrpc":"2.0","id":mid,"result":{"tools":[]}})
elif "result" in msg or "error" in msg:
sys.stderr.write("CLIENT RESPONSE: " + json.dumps(msg) + "\n"); sys.stderr.flush()
- Register it in
~/.claude.json(use an absolute path):
{ "mcpServers": { "url-elicit-test": { "type": "stdio", "command": "python3", "args": ["/ABS/PATH/url_elicit_server.py"] } } }
- Run
claude --debug. - Observe in the debug output: (a) the client's
initializecapabilities show"elicitation": {}(nourl), and (b) the client's response to the server'smode:"url"elicitation/createis-32602 "Client does not support URL-mode elicitation requests". The URL is never shown to the user.
Error Messages/Logs
# Current build — capability advertised at initialize:
{"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"roots":{},"elicitation":{}}, ... }}
# Client response to the server's mode:"url" elicitation/create:
{"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"MCP error -32602: Client does not support URL-mode elicitation requests"}}
# For comparison, v2.1.87 advertised url-mode but silently cancelled (URL never shown):
{"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"roots":{},"elicitation":{"form":{},"url":{}}},"clientInfo":{"name":"claude-code","version":"2.1.87"}}}
# -> elicitation response: {"result":{"action":"cancel"},"jsonrpc":"2.0","id":1}
Claude Model
Not applicable — transport/capability-layer behavior, independent of the model.
Is this a regression?
Yes — url mode was advertised in 2.1.87 and dropped at ~2.1.108.
Last Working Version
2.1.87 (last version to advertise url; note even there the url flow returned cancel without showing the URL).
Claude Code Version
2.1.108 (where the capability was dropped to {}, per the wire captures in #48164); reported still unresolved on later versions, while the docs continue to advertise the feature.
Platform
Anthropic API (per #48164 — behavior is protocol-level, not platform-specific).
Operating System
macOS (per #48164 — transport-layer; not OS-specific).
Terminal/Shell
N/A — protocol-level (stdio MCP server), independent of the terminal.
Additional Information
Likely root cause (and why a fix is now safe). The {form,url} → {} narrowing lines up with older MCP servers crashing on the new capability keys: the Java MCP SDK ≤ 0.17.1 modeled ClientCapabilities.Elicitation as an empty record and threw UnrecognizedPropertyException: Unrecognized field "form" during initialize (see #35389 and open-metadata/OpenMetadata#26454). That was fixed server-side in Java SDK ≥ 0.18.0, so narrowing the client capability to {} is no longer necessary and can be reverted to { "form": {}, "url": {} }.
Reference implementation. VS Code's Copilot MCP client ships url-mode end-to-end and is a close blueprint:
- capability decl →
src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.ts(elicitation: { form: {}, url: {} }) - url handling →
src/vs/workbench/contrib/mcp/browser/mcpElicitationService.ts(_elicitUrl→ opener service) -32042retry →src/vs/workbench/contrib/mcp/common/mcpServer.ts
Why it matters. URL-mode is the spec-native way to do human-in-the-loop confirmation and out-of-band auth without secrets passing through the client or model context. For MCP gateways/proxies it's required to deliver require-confirmation as a single blocking, resumable step (via -32042) and to drive upstream OAuth/3LO for proxied servers. Recent commenters on #48164 are independently asking for the same.
Docs contradiction. code.claude.com/docs/en/mcp states Claude Code supports url-mode ("opens a browser URL for authentication or approval"), but the client rejects it. Please either implement it or correct the docs.
Related: #48164 (same regression), #35353 (VS Code extension variant), #35389 (Java SDK crash = the trigger).
/cc @localden
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗