modelcontextprotocol/servers · error · McpError
-32602
-32602
Error message
{e} What it means
In call_tool(), the tool arguments are parsed into the pydantic Fetch model; a ValueError (pydantic ValidationError) is wrapped as McpError INVALID_PARAMS (-32602). Validation rules: url must be a valid AnyUrl; max_length must be > 0 and < 1_000_000; start_index must be >= 0; raw must be a bool.
Source
Thrown at src/fetch/src/mcp_server_fetch/server.py:228
async def list_prompts() -> list[Prompt]:
return [
Prompt(
name="fetch",
description="Fetch a URL and extract its contents as markdown",
arguments=[
PromptArgument(
name="url", description="URL to fetch", required=True
)
],
)
]
@server.call_tool()
async def call_tool(name, arguments: dict) -> list[TextContent]:
try:
args = Fetch(**arguments)
except ValueError as e:
raise McpError(ErrorData(code=INVALID_PARAMS, message=str(e)))
url = str(args.url)
if not url:
raise McpError(ErrorData(code=INVALID_PARAMS, message="URL is required"))
if not ignore_robots_txt:
await check_may_autonomously_fetch_url(url, user_agent_autonomous, proxy_url)
content, prefix = await fetch_url(
url, user_agent_autonomous, force_raw=args.raw, proxy_url=proxy_url
)
original_length = len(content)
if args.start_index >= original_length:
content = "<error>No more content available.</error>"
else:
truncated_content = content[args.start_index : args.start_index + args.max_length]
if not truncated_content:
content = "<error>No more content available.</error>"View on GitHub (pinned to 76d64c822f)
Solutions
- Validate arguments against Fetch.model_json_schema() before invoking the tool.
- Ensure url is an absolute, well-formed URL (scheme + host).
- Keep max_length strictly within (0, 1_000_000) and start_index >= 0.
Example fix
# before
await call_tool('fetch', {'url': 'not a url', 'max_length': 0}) # ValidationError -> INVALID_PARAMS
# after: build through the model first
from mcp_server_fetch.server import Fetch
args = Fetch(url='https://example.com', max_length=5000, start_index=0, raw=False)
await call_tool('fetch', args.model_dump()) Defensive patterns
Strategy: validation
Validate before calling
from mcp_server_fetch.server import Fetch
from pydantic import ValidationError
try:
args = Fetch(**arguments)
except ValidationError as e:
raise ValueError(str(e)) # or return a user-facing error
# safe to call tool with args.model_dump() Try / catch
try:
args = Fetch(**arguments)
except ValueError as e:
# map to a client-facing INVALID_PARAMS-style message
raise ValueError(f'Invalid fetch arguments: {e}') Prevention
- Build arguments via the Fetch model (model_dump) rather than hand-rolling a dict.
- Validate against Fetch.model_json_schema() on the client side before invoking.
- Keep max_length in (0, 1_000_000), start_index >= 0, url absolute.
When it happens
Trigger: Omitting required url; url is not a valid absolute URL; max_length <= 0 or >= 1_000_000; start_index < 0; raw is not boolean; wrong argument types.
Common situations: Client or LLM hallucinating the schema; stale tool definition; relative instead of absolute URL.
Related errors
- -32603
- Invalid target: '{target}' - cannot start with '-'
- Invalid path: '{f}'
- Path '{f}' is outside the repository '{repo_root}'
- Invalid start_timestamp: '{start_timestamp}' - cannot start
AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12).
Data as JSON: /api/errors/98ce1d327c2d9572.
Report an issue: GitHub.