MCP Server Proxy Configuration
The Model Context Protocol (MCP) enables AI assistants like Claude to interact with external tools and data sources through standardized server interfaces. MCP servers that provide web access -- fetching pages, scraping data, calling APIs -- need proxy infrastructure to ensure reliable access to external websites.
Why MCP Servers Need Proxies
MCP servers that access the web face unique challenges:
- **Server-side execution**: MCP servers run on the host machine or cloud infrastructure with IPs that may be blocked by target websites.
- **AI-driven requests**: The AI assistant decides which URLs to fetch, potentially targeting heavily protected sites without warning.
- **Sustained access**: MCP tools may be called repeatedly for similar URLs as the AI explores a topic, accumulating requests from a single IP.
- **Diverse targets**: A single conversation might trigger web fetches from documentation, search engines, APIs, and content sites.
Proxy Configuration for MCP Servers
#### TypeScript MCP Server with Proxy
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { HttpsProxyAgent } from 'https-proxy-agent';const proxyAgent = new HttpsProxyAgent( 'http://user:pass@gate.hexproxies.com:8080' );
// MCP tool that fetches web content through proxy server.setRequestHandler('tools/call', async (request) => { if (request.params.name === 'fetch_webpage') { const url = request.params.arguments?.url as string;
const response = await fetch(url, { agent: proxyAgent, headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...', }, timeout: 30000, });
const html = await response.text(); return { content: [{ type: 'text', text: html }], }; } }); ```
#### Python MCP Server with Proxy
from mcp.server import ServerPROXY_URL = "http://user:pass@gate.hexproxies.com:8080"
app = Server("web-fetcher")
@app.tool() async def fetch_webpage(url: str) -> str: """Fetch a webpage through residential proxy.""" async with httpx.AsyncClient( proxy=PROXY_URL, timeout=30.0, headers={"User-Agent": "Mozilla/5.0 ..."} ) as client: response = await client.get(url) return response.text ```
Geo-Targeted MCP Tools
Create MCP tools that accept geographic context for location-specific web access:
@app.tool()
async def fetch_webpage_from_location(url: str, country: str = "us") -> str:
"""Fetch a webpage as seen from a specific country."""async with httpx.AsyncClient( proxy=proxy_url, timeout=30.0, ) as client: response = await client.get(url) return response.text ```
This enables the AI assistant to see web content from any geographic perspective, useful for tasks involving regional pricing, localized content, or geo-restricted access.
Browser-Based MCP Tools
For MCP tools that need to render JavaScript-heavy pages:
async function fetchRenderedPage(url: string, country: string = 'us') { const browser = await chromium.launch({ proxy: { server: 'http://gate.hexproxies.com:8080', username: `user-country-${country}`, password: 'your-password', }, });
const page = await browser.newPage(); await page.goto(url, { waitUntil: 'networkidle' }); const content = await page.content(); await browser.close(); return content; } ```
Production MCP Server Patterns
#### Session Management
Maintain proxy sessions per conversation to ensure consistent geographic identity:
import randomclass ProxySessionManager: def __init__(self): self.sessions = {}
def get_proxy_for_conversation(self, conversation_id, country="us"): if conversation_id not in self.sessions: session_id = ''.join(random.choices(string.ascii_lowercase, k=8)) self.sessions[conversation_id] = session_id session = self.sessions[conversation_id] return f"http://user-country-{country}-session-{session}:pass@gate.hexproxies.com:8080" ```
#### Rate Limiting
Implement per-URL rate limiting in your MCP server to be a good proxy consumer:
from collections import defaultdictclass RateLimiter: def __init__(self, min_interval=2.0): self.last_request = defaultdict(float) self.min_interval = min_interval
async def wait_if_needed(self, domain): elapsed = time.time() - self.last_request[domain] if elapsed < self.min_interval: await asyncio.sleep(self.min_interval - elapsed) self.last_request[domain] = time.time() ```
#### Error Handling
Return clear error messages to the AI assistant when proxy or access issues occur:
@app.tool()
async def fetch_webpage(url: str) -> str:
try:
async with httpx.AsyncClient(proxy=PROXY_URL, timeout=30.0) as client:
response = await client.get(url)
if response.status_code == 403:
return "Access blocked by the website. Try a different URL or approach."
response.raise_for_status()
return response.text
except httpx.TimeoutException:
return "Request timed out. The website may be slow or blocking this request."
except Exception as e:
return f"Failed to fetch page: {str(e)}"Cost Management
MCP tool calls are driven by AI conversation context. A single conversation might trigger 5-20 web fetches. At 100-500 KB per fetch, typical proxy bandwidth per conversation is 0.5-10 MB. Monthly costs depend on conversation volume but are typically modest for most MCP deployments.