Skip to content

Commit b89f82c

Browse files
authored
Merge branch 'main' into patch-1
2 parents 9da045a + 91db0d9 commit b89f82c

File tree

33 files changed

+1728
-1649
lines changed

33 files changed

+1728
-1649
lines changed

aws-kb-retrieval-server/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:22.12-alpine as builder
1+
FROM node:22.12-alpine AS builder
22

33
COPY src/aws-kb-retrieval-server /app
44
COPY tsconfig.json /tsconfig.json

brave-search/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:22.12-alpine as builder
1+
FROM node:22.12-alpine AS builder
22

33
# Must be entire project because `prepare` script is run during `npm install` and requires all files.
44
COPY src/brave-search /app

everart/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:22.12-alpine as builder
1+
FROM node:22.12-alpine AS builder
22

33
COPY src/everart /app
44
COPY tsconfig.json /tsconfig.json

everything/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:22.12-alpine as builder
1+
FROM node:22.12-alpine AS builder
22

33
COPY src/everything /app
44
COPY tsconfig.json /tsconfig.json

everything/everything.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ export const createServer = () => {
411411
maxTokens,
412412
);
413413
return {
414-
content: [{ type: "text", text: `LLM sampling result: ${result}` }],
414+
content: [{ type: "text", text: `LLM sampling result: ${result.content.text}` }],
415415
};
416416
}
417417

fetch/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ classifiers = [
1717
]
1818
dependencies = [
1919
"markdownify>=0.13.1",
20-
"mcp>=1.0.0",
20+
"mcp>=1.1.3",
2121
"protego>=0.3.1",
2222
"pydantic>=2.0.0",
2323
"readabilipy>=0.2.0",

fetch/src/mcp_server_fetch/server.py

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from mcp.server import Server
88
from mcp.server.stdio import stdio_server
99
from mcp.types import (
10+
ErrorData,
1011
GetPromptResult,
1112
Prompt,
1213
PromptArgument,
@@ -79,15 +80,15 @@ async def check_may_autonomously_fetch_url(url: str, user_agent: str) -> None:
7980
headers={"User-Agent": user_agent},
8081
)
8182
except HTTPError:
82-
raise McpError(
83-
INTERNAL_ERROR,
84-
f"Failed to fetch robots.txt {robot_txt_url} due to a connection issue",
85-
)
83+
raise McpError(ErrorData(
84+
code=INTERNAL_ERROR,
85+
message=f"Failed to fetch robots.txt {robot_txt_url} due to a connection issue",
86+
))
8687
if response.status_code in (401, 403):
87-
raise McpError(
88-
INTERNAL_ERROR,
89-
f"When fetching robots.txt ({robot_txt_url}), received status {response.status_code} so assuming that autonomous fetching is not allowed, the user can try manually fetching by using the fetch prompt",
90-
)
88+
raise McpError(ErrorData(
89+
code=INTERNAL_ERROR,
90+
message=f"When fetching robots.txt ({robot_txt_url}), received status {response.status_code} so assuming that autonomous fetching is not allowed, the user can try manually fetching by using the fetch prompt",
91+
))
9192
elif 400 <= response.status_code < 500:
9293
return
9394
robot_txt = response.text
@@ -96,15 +97,15 @@ async def check_may_autonomously_fetch_url(url: str, user_agent: str) -> None:
9697
)
9798
robot_parser = Protego.parse(processed_robot_txt)
9899
if not robot_parser.can_fetch(str(url), user_agent):
99-
raise McpError(
100-
INTERNAL_ERROR,
101-
f"The sites robots.txt ({robot_txt_url}), specifies that autonomous fetching of this page is not allowed, "
100+
raise McpError(ErrorData(
101+
code=INTERNAL_ERROR,
102+
message=f"The sites robots.txt ({robot_txt_url}), specifies that autonomous fetching of this page is not allowed, "
102103
f"<useragent>{user_agent}</useragent>\n"
103104
f"<url>{url}</url>"
104105
f"<robots>\n{robot_txt}\n</robots>\n"
105106
f"The assistant must let the user know that it failed to view the page. The assistant may provide further guidance based on the above information.\n"
106107
f"The assistant can tell the user that they can try manually fetching the page by using the fetch prompt within their UI.",
107-
)
108+
))
108109

109110

110111
async def fetch_url(
@@ -124,12 +125,12 @@ async def fetch_url(
124125
timeout=30,
125126
)
126127
except HTTPError as e:
127-
raise McpError(INTERNAL_ERROR, f"Failed to fetch {url}: {e!r}")
128+
raise McpError(ErrorData(code=INTERNAL_ERROR, message=f"Failed to fetch {url}: {e!r}"))
128129
if response.status_code >= 400:
129-
raise McpError(
130-
INTERNAL_ERROR,
131-
f"Failed to fetch {url} - status code {response.status_code}",
132-
)
130+
raise McpError(ErrorData(
131+
code=INTERNAL_ERROR,
132+
message=f"Failed to fetch {url} - status code {response.status_code}",
133+
))
133134

134135
page_raw = response.text
135136

@@ -221,27 +222,39 @@ async def call_tool(name, arguments: dict) -> list[TextContent]:
221222
try:
222223
args = Fetch(**arguments)
223224
except ValueError as e:
224-
raise McpError(INVALID_PARAMS, str(e))
225+
raise McpError(ErrorData(code=INVALID_PARAMS, message=str(e)))
225226

226227
url = str(args.url)
227228
if not url:
228-
raise McpError(INVALID_PARAMS, "URL is required")
229+
raise McpError(ErrorData(code=INVALID_PARAMS, message="URL is required"))
229230

230231
if not ignore_robots_txt:
231232
await check_may_autonomously_fetch_url(url, user_agent_autonomous)
232233

233234
content, prefix = await fetch_url(
234235
url, user_agent_autonomous, force_raw=args.raw
235236
)
236-
if len(content) > args.max_length:
237-
content = content[args.start_index : args.start_index + args.max_length]
238-
content += f"\n\n<error>Content truncated. Call the fetch tool with a start_index of {args.start_index + args.max_length} to get more content.</error>"
237+
original_length = len(content)
238+
if args.start_index >= original_length:
239+
content = "<error>No more content available.</error>"
240+
else:
241+
truncated_content = content[args.start_index : args.start_index + args.max_length]
242+
if not truncated_content:
243+
content = "<error>No more content available.</error>"
244+
else:
245+
content = truncated_content
246+
actual_content_length = len(truncated_content)
247+
remaining_content = original_length - (args.start_index + actual_content_length)
248+
# Only add the prompt to continue fetching if there is still remaining content
249+
if actual_content_length == args.max_length and remaining_content > 0:
250+
next_start = args.start_index + actual_content_length
251+
content += f"\n\n<error>Content truncated. Call the fetch tool with a start_index of {next_start} to get more content.</error>"
239252
return [TextContent(type="text", text=f"{prefix}Contents of {url}:\n{content}")]
240253

241254
@server.get_prompt()
242255
async def get_prompt(name: str, arguments: dict | None) -> GetPromptResult:
243256
if not arguments or "url" not in arguments:
244-
raise McpError(INVALID_PARAMS, "URL is required")
257+
raise McpError(ErrorData(code=INVALID_PARAMS, message="URL is required"))
245258

246259
url = arguments["url"]
247260

0 commit comments

Comments
 (0)