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

  1. Validate arguments against Fetch.model_json_schema() before invoking the tool.
  2. Ensure url is an absolute, well-formed URL (scheme + host).
  3. 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

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


AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12). Data as JSON: /api/errors/98ce1d327c2d9572. Report an issue: GitHub.