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.
Describe the bug
The
fetchtool validatesurlthrough theFetchmodel, so a malformed URL comes back as a normalisError: trueresult. Thefetchprompt passesarguments["url"]straight tofetch_url(server.py:262-265) and catches onlyMcpError(server.py:267).fetch_urlconverts onlyhttpx.HTTPError(server.py:127), andhttpx.InvalidURLis not anHTTPError, so it escapes both handlers. Withraise_exceptions=False(server.py:288), the SDK's low-level server then answers with a JSON-RPC error whose code is0and whose message is the raw exception text.To Reproduce
mcp-server-fetch 0.6.3 (commit f46d957),
mcp1.29.0 (as inuv.lock), Python 3.14, Windows 11. Afterinitialize, 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"}}}Expected behavior
An invalid prompt argument should produce a proper parameter error (
-32602,INVALID_PARAMS) with a clear message, consistent with the tool. Code0is 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
urlthe same way the tool does before fetching:With this change, the request above returns
-32602with 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.