Skip to content

Commit 49e6546

Browse files
authored
Merge branch 'main' into main
2 parents da67686 + e181222 commit 49e6546

File tree

16 files changed

+888
-154
lines changed

16 files changed

+888
-154
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Large diffs are not rendered by default.

package-lock.json

Lines changed: 650 additions & 96 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/fetch/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ ModelContextProtocol/1.0 (User-Specified; +https://github.com/modelcontextprotoc
107107

108108
This can be customized by adding the argument `--user-agent=YourUserAgent` to the `args` list in the configuration.
109109

110+
### Customization - Proxy
111+
112+
The server can be configured to use a proxy by using the `--proxy-url` argument.
113+
110114
## Debugging
111115

112116
You can use the MCP inspector to debug the server. For uvx installations:

src/fetch/pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-server-fetch"
3-
version = "0.6.2"
3+
version = "0.6.3"
44
description = "A Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs"
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -16,6 +16,7 @@ classifiers = [
1616
"Programming Language :: Python :: 3.10",
1717
]
1818
dependencies = [
19+
"httpx<0.28",
1920
"markdownify>=0.13.1",
2021
"mcp>=1.1.3",
2122
"protego>=0.3.1",

src/fetch/src/mcp_server_fetch/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ def main():
1515
action="store_true",
1616
help="Ignore robots.txt restrictions",
1717
)
18+
parser.add_argument("--proxy-url", type=str, help="Proxy URL to use for requests")
1819

1920
args = parser.parse_args()
20-
asyncio.run(serve(args.user_agent, args.ignore_robots_txt))
21+
asyncio.run(serve(args.user_agent, args.ignore_robots_txt, args.proxy_url))
2122

2223

2324
if __name__ == "__main__":

src/fetch/src/mcp_server_fetch/server.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def get_robots_txt_url(url: str) -> str:
6363
return robots_url
6464

6565

66-
async def check_may_autonomously_fetch_url(url: str, user_agent: str) -> None:
66+
async def check_may_autonomously_fetch_url(url: str, user_agent: str, proxy_url: str | None = None) -> None:
6767
"""
6868
Check if the URL can be fetched by the user agent according to the robots.txt file.
6969
Raises a McpError if not.
@@ -72,7 +72,7 @@ async def check_may_autonomously_fetch_url(url: str, user_agent: str) -> None:
7272

7373
robot_txt_url = get_robots_txt_url(url)
7474

75-
async with AsyncClient() as client:
75+
async with AsyncClient(proxies=proxy_url) as client:
7676
try:
7777
response = await client.get(
7878
robot_txt_url,
@@ -109,14 +109,14 @@ async def check_may_autonomously_fetch_url(url: str, user_agent: str) -> None:
109109

110110

111111
async def fetch_url(
112-
url: str, user_agent: str, force_raw: bool = False
112+
url: str, user_agent: str, force_raw: bool = False, proxy_url: str | None = None
113113
) -> Tuple[str, str]:
114114
"""
115115
Fetch the URL and return the content in a form ready for the LLM, as well as a prefix string with status information.
116116
"""
117117
from httpx import AsyncClient, HTTPError
118118

119-
async with AsyncClient() as client:
119+
async with AsyncClient(proxies=proxy_url) as client:
120120
try:
121121
response = await client.get(
122122
url,
@@ -173,19 +173,22 @@ class Fetch(BaseModel):
173173
bool,
174174
Field(
175175
default=False,
176-
description="Get the actual HTML content if the requested page, without simplification.",
176+
description="Get the actual HTML content of the requested page, without simplification.",
177177
),
178178
]
179179

180180

181181
async def serve(
182-
custom_user_agent: str | None = None, ignore_robots_txt: bool = False
182+
custom_user_agent: str | None = None,
183+
ignore_robots_txt: bool = False,
184+
proxy_url: str | None = None,
183185
) -> None:
184186
"""Run the fetch MCP server.
185187
186188
Args:
187189
custom_user_agent: Optional custom User-Agent string to use for requests
188190
ignore_robots_txt: Whether to ignore robots.txt restrictions
191+
proxy_url: Optional proxy URL to use for requests
189192
"""
190193
server = Server("mcp-fetch")
191194
user_agent_autonomous = custom_user_agent or DEFAULT_USER_AGENT_AUTONOMOUS
@@ -229,10 +232,10 @@ async def call_tool(name, arguments: dict) -> list[TextContent]:
229232
raise McpError(ErrorData(code=INVALID_PARAMS, message="URL is required"))
230233

231234
if not ignore_robots_txt:
232-
await check_may_autonomously_fetch_url(url, user_agent_autonomous)
235+
await check_may_autonomously_fetch_url(url, user_agent_autonomous, proxy_url)
233236

234237
content, prefix = await fetch_url(
235-
url, user_agent_autonomous, force_raw=args.raw
238+
url, user_agent_autonomous, force_raw=args.raw, proxy_url=proxy_url
236239
)
237240
original_length = len(content)
238241
if args.start_index >= original_length:
@@ -259,7 +262,7 @@ async def get_prompt(name: str, arguments: dict | None) -> GetPromptResult:
259262
url = arguments["url"]
260263

261264
try:
262-
content, prefix = await fetch_url(url, user_agent_manual)
265+
content, prefix = await fetch_url(url, user_agent_manual, proxy_url=proxy_url)
263266
# TODO: after SDK bug is addressed, don't catch the exception
264267
except McpError as e:
265268
return GetPromptResult(

src/filesystem/README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,16 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio
4141
- Features:
4242
- Line-based and multi-line content matching
4343
- Whitespace normalization with indentation preservation
44-
- Fuzzy matching with confidence scoring
4544
- Multiple simultaneous edits with correct positioning
4645
- Indentation style detection and preservation
4746
- Git-style diff output with context
4847
- Preview changes with dry run mode
49-
- Failed match debugging with confidence scores
5048
- Inputs:
5149
- `path` (string): File to edit
5250
- `edits` (array): List of edit operations
5351
- `oldText` (string): Text to search for (can be substring)
5452
- `newText` (string): Text to replace with
5553
- `dryRun` (boolean): Preview changes without applying (default: false)
56-
- `options` (object): Optional formatting settings
57-
- `preserveIndentation` (boolean): Keep existing indentation (default: true)
58-
- `normalizeWhitespace` (boolean): Normalize spaces while preserving structure (default: true)
59-
- `partialMatch` (boolean): Enable fuzzy matching (default: true)
6054
- Returns detailed diff and match information for dry runs, otherwise applies changes
6155
- Best Practice: Always use dryRun first to preview changes before applying them
6256

src/filesystem/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const allowedDirectories = args.map(dir =>
4242
// Validate that all directories exist and are accessible
4343
await Promise.all(args.map(async (dir) => {
4444
try {
45-
const stats = await fs.stat(dir);
45+
const stats = await fs.stat(expandHome(dir));
4646
if (!stats.isDirectory()) {
4747
console.error(`Error: ${dir} is not a directory`);
4848
process.exit(1);

src/git/uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/github/common/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export const GitHubLabelSchema = z.object({
157157
name: z.string(),
158158
color: z.string(),
159159
default: z.boolean(),
160-
description: z.string().optional(),
160+
description: z.string().nullable().optional(),
161161
});
162162

163163
export const GitHubMilestoneSchema = z.object({

0 commit comments

Comments
 (0)