Repository navigation
Description
Describe the bug
The fetch tool validates url through the Fetch model, so a malformed URL comes back as a normal isError: true result. The fetch prompt passes arguments["url"] straight to fetch_url (server.py:262-265) and catches only McpError (server.py:267). fetch_url converts only httpx.HTTPError (server.py:127), and httpx.InvalidURL is not an HTTPError, so it escapes both handlers. With raise_exceptions=False (server.py:288), the SDK's low-level server then answers with a JSON-RPC error whose code is 0 and whose message is the raw exception text.
To Reproduce
mcp-server-fetch 0.6.3 (commit f46d957), mcp 1.29.0 (as in uv.lock), Python 3.14, Windows 11. After initialize, send over stdio:
{"jsonrpc": "2.0", "id": 3, "method": "prompts/get", "params": {"name": "fetch", "arguments": {"url": "http://[::1"}}}Response:
{"jsonrpc": "2.0", "id": 3, "error": {"code": 0, "message": "Invalid port: ':1'"}}The same URL through the tool is handled cleanly:
{"jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": {"name": "fetch", "arguments": {"url": "http://[::1"}}}isError: true — "1 validation error for Fetch\nurl\n Input should be a valid URL, invalid IPv6 address ..."
Expected behavior
An invalid prompt argument should produce a proper parameter error (-32602, INVALID_PARAMS) with a clear message, consistent with the tool. Code 0 is the SDK's generic fallback for unhandled exceptions, so a client can't tell a bad argument from a server fault.
Suggested fix
Validate the prompt's url the same way the tool does before fetching:
url = arguments["url"] # current code; replace with:
try:
url = str(Fetch(url=arguments["url"]).url)
except ValueError as e:
raise McpError(ErrorData(code=INVALID_PARAMS, message=str(e)))With this change, the request above returns -32602 with the validation message, and a valid URL still returns the page content (checked locally).
Additional context
Related: #3359 / #3515 (malformed input handling). I found this while testing a static checker for MCP error handling, then reproduced it by hand with a raw JSON-RPC client (no MCP client library involved). Happy to open a PR with this change if that's useful.
Activity
SuparvaCode commentedon Oct 8, 2026
Confirmed end-to-end against
main(commit 5abed86).When a prompt argument fails validation, passing it into
fetch_urlallowshttpx.InvalidURLto escape unhandled becausefetch_urlonly handleshttpx.HTTPError. Withraise_exceptions=Falseon the stdio server, the low-level server catches the unhandled exception and answers with JSON-RPC error code 0 and the raw exception text.Validating
arguments["url"]inget_promptvia the existingFetchmodel:properly rejects malformed URLs with
-32602(INVALID_PARAMS). Additionally, catchinghttpx.InvalidURLalongsidehttpx.HTTPErrorinfetch_urlensures that if an invalid URL reachesfetch_urldirectly, it is caught as anMcpErrorrather than escaping.I've pushed the fix and regression tests on
SuparvaCode/servers:fix/fetch-prompt-invalid-url-params. All 24 tests intests/test_server.pyandruff checkpass cleanly.cliffhall commentedon Oct 19, 2026
Triage: Priority Low (total 5)
buglabelStill present on v2 (checked by a local reproduction against the current code).
Board: Servers V2 (#43), Status
Incoming, awaiting maintainer review (no milestone yet). Part of the backlog triage in #4875.cliffhall commentedon Oct 29, 2026
Shipped in #5358 (merged into
v2/main), after the #5271 rollup proved the six fetch v2.3.0 PRs combine with no conflicts.fix(fetch): reject an invalid prompt URL with -32602
fix(fetch): reject an invalid prompt URL with -32602