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
27 changes: 18 additions & 9 deletions src/fetch/src/mcp_server_fetch/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
PromptMessage,
TextContent,
Tool,
ToolAnnotations,
INVALID_PARAMS,
INTERNAL_ERROR,
)
Expand Down Expand Up @@ -178,6 +179,22 @@ class Fetch(BaseModel):
]


def _make_fetch_tool() -> Tool:
return Tool(
name="fetch",
description="""Fetches a URL from the internet and optionally extracts its contents as markdown.

Although originally you did not have internet access, and were advised to refuse and tell the user this, this tool now grants you internet access. Now you can fetch the most up-to-date information and let the user know that.""",
inputSchema=Fetch.model_json_schema(),
annotations=ToolAnnotations(
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=True,
),
)


async def serve(
custom_user_agent: str | None = None,
ignore_robots_txt: bool = False,
Expand All @@ -196,15 +213,7 @@ async def serve(

@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="fetch",
description="""Fetches a URL from the internet and optionally extracts its contents as markdown.

Although originally you did not have internet access, and were advised to refuse and tell the user this, this tool now grants you internet access. Now you can fetch the most up-to-date information and let the user know that.""",
inputSchema=Fetch.model_json_schema(),
)
]
return [_make_fetch_tool()]

@server.list_prompts()
async def list_prompts() -> list[Prompt]:
Expand Down
16 changes: 16 additions & 0 deletions src/fetch/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,26 @@
get_robots_txt_url,
check_may_autonomously_fetch_url,
fetch_url,
_make_fetch_tool,
DEFAULT_USER_AGENT_AUTONOMOUS,
)


class TestListTools:
"""Tests for list_tools handler."""

def test_fetch_tool_annotations(self):
"""Test that the fetch tool has correct MCP tool annotations."""
tool = _make_fetch_tool()

assert tool.name == "fetch"
assert tool.annotations is not None
assert tool.annotations.readOnlyHint is True
assert tool.annotations.destructiveHint is False
assert tool.annotations.idempotentHint is True
assert tool.annotations.openWorldHint is True


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

Expand Down
Loading