@@ -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
111111async 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 ,
@@ -179,13 +179,16 @@ class Fetch(BaseModel):
179179
180180
181181async 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 (
0 commit comments