|
28 | 28 |
|
29 | 29 | logger = logging.getLogger(__name__) |
30 | 30 |
|
| 31 | + |
| 32 | +def _get_proxy_url() -> Optional[str]: |
| 33 | + """Build proxy URL from PROXY_USERNAME and PROXY_PASSWORD env vars.""" |
| 34 | + username = os.environ.get("PROXY_USERNAME") |
| 35 | + password = os.environ.get("PROXY_PASSWORD") |
| 36 | + if username and password: |
| 37 | + return f"http://{username}:{password}@p.webshare.io:80/" |
| 38 | + return None |
| 39 | + |
| 40 | + |
31 | 41 | # DuckDuckGo does not require authentication, but we follow the auth extraction |
32 | 42 | # pattern for consistency with other MCP servers. |
33 | 43 |
|
@@ -109,7 +119,8 @@ async def search( |
109 | 119 |
|
110 | 120 | await ctx.info(f"Searching DuckDuckGo for: {query}") |
111 | 121 |
|
112 | | - async with httpx.AsyncClient() as client: |
| 122 | + proxy = _get_proxy_url() |
| 123 | + async with httpx.AsyncClient(proxy=proxy) as client: |
113 | 124 | response = await client.post( |
114 | 125 | self.BASE_URL, data=data, headers=self.HEADERS, timeout=30.0 |
115 | 126 | ) |
@@ -174,7 +185,8 @@ async def fetch_and_parse(self, url: str, ctx: Context) -> str: |
174 | 185 | try: |
175 | 186 | await ctx.info(f"Fetching content from: {url}") |
176 | 187 |
|
177 | | - async with httpx.AsyncClient() as client: |
| 188 | + proxy = _get_proxy_url() |
| 189 | + async with httpx.AsyncClient(proxy=proxy) as client: |
178 | 190 | response = await client.get( |
179 | 191 | url, |
180 | 192 | headers={ |
|
0 commit comments