Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/fetch/src/mcp_server_fetch/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
INTERNAL_ERROR,
)
from protego import Protego
from pydantic import BaseModel, Field, AnyUrl
from pydantic import AnyUrl, BaseModel, Field, WithJsonSchema

DEFAULT_USER_AGENT_AUTONOMOUS = "ModelContextProtocol/1.0 (Autonomous; +https://github.com/modelcontextprotocol/servers)"
DEFAULT_USER_AGENT_MANUAL = "ModelContextProtocol/1.0 (User-Specified; +https://github.com/modelcontextprotocol/servers)"
Expand Down Expand Up @@ -151,14 +151,18 @@ async def fetch_url(
class Fetch(BaseModel):
"""Parameters for fetching a URL."""

url: Annotated[AnyUrl, Field(description="URL to fetch")]
url: Annotated[
AnyUrl,
Field(description="URL to fetch"),
WithJsonSchema({"type": "string", "description": "URL to fetch"}),
]
max_length: Annotated[
int,
Field(
default=5000,
description="Maximum number of characters to return.",
gt=0,
lt=1000000,
ge=1,
le=999999,
),
]
start_index: Annotated[
Expand Down
33 changes: 33 additions & 0 deletions src/fetch/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from mcp.shared.exceptions import McpError

from mcp_server_fetch.server import (
Fetch,
extract_content_from_html,
get_robots_txt_url,
check_may_autonomously_fetch_url,
Expand All @@ -13,6 +14,38 @@
)


class TestFetchToolSchema:
"""Tests for the Fetch model JSON schema compatibility."""

def test_schema_uses_inclusive_bounds(self):
"""Ensure the schema uses minimum/maximum instead of exclusiveMinimum/exclusiveMaximum.
Some LLM providers (e.g. Google Gemini) only support OpenAPI 3.0
schema keywords and reject exclusiveMinimum/exclusiveMaximum.
"""
schema = Fetch.model_json_schema()
max_length_schema = schema["properties"]["max_length"]

assert "exclusiveMinimum" not in max_length_schema
assert "exclusiveMaximum" not in max_length_schema
assert max_length_schema["minimum"] == 1
assert max_length_schema["maximum"] == 999999

def test_url_schema_omits_unsupported_keywords(self):
"""Ensure the url field schema avoids format/minLength keywords.
Some LLM providers (e.g. Google Gemini) only support a limited set
of keywords for string types and reject unsupported ones like
format: "uri" or minLength.
"""
schema = Fetch.model_json_schema()
url_schema = schema["properties"]["url"]

assert "format" not in url_schema
assert "minLength" not in url_schema
assert url_schema["type"] == "string"


class TestGetRobotsTxtUrl:
"""Tests for get_robots_txt_url function."""

Expand Down
Loading