add better exception handling
This commit is contained in:
parent
04acd49299
commit
4fa58d546b
3 changed files with 37 additions and 11 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "mcp-server-fetch"
|
name = "mcp-server-fetch"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
description = "A Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs"
|
description = "A Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
import markdownify
|
import markdownify
|
||||||
import readabilipy.simple_json
|
import readabilipy.simple_json
|
||||||
|
from mcp.shared.exceptions import McpError
|
||||||
from mcp.server import Server
|
from mcp.server import Server
|
||||||
from mcp.server.stdio import stdio_server
|
from mcp.server.stdio import stdio_server
|
||||||
from mcp.types import (
|
from mcp.types import (
|
||||||
TextContent,
|
GetPromptResult,
|
||||||
Tool,
|
|
||||||
Prompt,
|
Prompt,
|
||||||
PromptArgument,
|
PromptArgument,
|
||||||
GetPromptResult,
|
|
||||||
PromptMessage,
|
PromptMessage,
|
||||||
|
TextContent,
|
||||||
|
Tool,
|
||||||
|
INVALID_PARAMS,
|
||||||
|
INTERNAL_ERROR,
|
||||||
)
|
)
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
@ -25,11 +28,16 @@ def extract_content(html: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
async def fetch_url(url: str) -> str:
|
async def fetch_url(url: str) -> str:
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient, HTTPError
|
||||||
|
|
||||||
async with AsyncClient() as client:
|
async with AsyncClient() as client:
|
||||||
response = await client.get(url)
|
try:
|
||||||
response.raise_for_status()
|
response = await client.get(url, follow_redirects=True)
|
||||||
|
except HTTPError:
|
||||||
|
raise McpError(INTERNAL_ERROR, f"Failed to fetch {url}")
|
||||||
|
if response.status_code >= 400:
|
||||||
|
raise McpError(INTERNAL_ERROR, f"Failed to fetch {url} - status code {response.status_code}")
|
||||||
|
|
||||||
page_html = response.text
|
page_html = response.text
|
||||||
|
|
||||||
return extract_content(page_html)
|
return extract_content(page_html)
|
||||||
|
|
@ -70,14 +78,32 @@ Although originally you did not have internet access, and were advised to refuse
|
||||||
|
|
||||||
@server.call_tool()
|
@server.call_tool()
|
||||||
async def call_tool(name, arguments: dict) -> list[TextContent]:
|
async def call_tool(name, arguments: dict) -> list[TextContent]:
|
||||||
url = arguments["url"]
|
url = arguments.get("url")
|
||||||
|
if not url:
|
||||||
|
raise McpError(INVALID_PARAMS, "URL is required")
|
||||||
|
|
||||||
content = await fetch_url(url)
|
content = await fetch_url(url)
|
||||||
return [TextContent(type="text", text=f"Contents of {url}:\n{content}")]
|
return [TextContent(type="text", text=f"Contents of {url}:\n{content}")]
|
||||||
|
|
||||||
@server.get_prompt()
|
@server.get_prompt()
|
||||||
async def get_prompt(name, arguments: dict) -> GetPromptResult:
|
async def get_prompt(name, arguments: dict) -> GetPromptResult:
|
||||||
url = arguments["url"]
|
url = arguments.get("url")
|
||||||
content = await fetch_url(url)
|
if not url:
|
||||||
|
raise McpError(INVALID_PARAMS, "URL is required")
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = await fetch_url(url)
|
||||||
|
# TODO: after SDK bug is addressed, don't catch the exception
|
||||||
|
except McpError as e:
|
||||||
|
return GetPromptResult(
|
||||||
|
description=f"Failed to fetch {url}",
|
||||||
|
messages=[
|
||||||
|
PromptMessage(
|
||||||
|
role="user",
|
||||||
|
content=TextContent(type="text", text=str(e)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
return GetPromptResult(
|
return GetPromptResult(
|
||||||
description=f"Contents of {url}",
|
description=f"Contents of {url}",
|
||||||
messages=[
|
messages=[
|
||||||
|
|
|
||||||
2
src/fetch/uv.lock
generated
2
src/fetch/uv.lock
generated
|
|
@ -328,7 +328,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp-server-fetch"
|
name = "mcp-server-fetch"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "markdownify" },
|
{ name = "markdownify" },
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue