Base de connaissances

Pourquoi votre serveur MCP a besoin d'une couche proxy

Les serveurs MCP qui récupèrent des données web en direct sont bloqués comme n'importe quel scraper. Pourquoi cela se produit, et comment router leurs requêtes via des proxies résidentiels.

Chris Collins

Chris Collins

20 juin 2026 · 12 min de lecture

Le Model Context Protocol a résolu la mauvaise moitié du problème en premier, et ce n’est pas une critique, c’est simplement l’ordre dans lequel les choses se sont passées. MCP nous a donné un moyen propre et standardisé de connecter un modèle de langage à des outils et des données. Ce qu’il ne fait délibérément pas, c’est résoudre ce qui se passe quand l’un de ces outils atteint le web ouvert et que le web ouvert répond avec un 403.

Si vous avez construit ou exploité un serveur MCP qui récupère des URLs, scrape des pages, interroge des résultats de recherche ou extrait des données en direct pour un modèle, vous avez probablement déjà rencontré ce mur. Le serveur fonctionne parfaitement sur votre ordinateur portable. Vous le déployez sur un serveur cloud, vous y pointez votre agent, et soudainement la moitié des requêtes reviennent sous forme de pages CAPTCHA, de messages “accès refusé”, ou de redirections géographiques vers le site du mauvais pays. Rien dans votre code MCP n’a changé. L’IP, si.

Cet article porte sur ce manque : pourquoi les serveurs MCP qui récupèrent des pages web se font bloquer, pourquoi ce n’est pas un problème que MCP doit résoudre, et comment une couche de proxy résidentiel le comble avec quelques lignes de code.

Un rappel rapide sur l’endroit où l’accès web se produit

MCP présente une séparation claire des rôles. Un hôte (Claude Desktop, un IDE, un runtime d’agent) exécute un client MCP, qui communique avec un ou plusieurs serveurs MCP. Chaque serveur expose des outils, des ressources et des prompts. Lorsque le modèle décide d’utiliser un outil, l’appel circule de l’hôte vers le client puis vers le serveur, le serveur effectue le travail réel, et le résultat revient dans l’autre sens.

L’élément important pour cette discussion : le serveur est l’endroit où se produisent les effets de bord dans le monde réel. Lorsque vous construisez un outil fetch, un outil search ou un outil scrape_page, la requête HTTP sortante provient du processus du serveur MCP, où que ce processus soit en cours d’exécution. Le modèle ne fait pas la requête. L’hôte non plus. C’est le serveur qui le fait.

Ainsi, l’IP que le site web cible voit est celle du serveur MCP. Et c’est tout le problème.

Pourquoi les serveurs MCP qui récupèrent des pages web se font bloquer

Trois facteurs s’accumulent, et ils s’accumulent spécifiquement contre les serveurs MCP d’une façon qui ne s’applique pas à un humain avec un navigateur.

Votre serveur MCP est presque certainement sur une IP de datacenter. Si vous l’avez déployé sur AWS, GCP, Fly, Render, un VPS ou n’importe quel hébergeur cloud, son IP sortante appartient à un ASN de fournisseur d’hébergement. Les systèmes anti-bot (Cloudflare, Akamai, DataDome) traitent les ASN de datacenter comme coupables jusqu’à preuve du contraire. Une requête provenant d’une IP AWS vers un site protégé est signalée avant même que le serveur n’envoie un en-tête. C’est la principale raison pour laquelle “ça marchait en local” se transforme en “c’est bloqué en prod” : votre connexion domestique est résidentielle, votre serveur cloud ne l’est pas.

Le trafic des agents est en rafales et concentré. Un agent ne navigue pas comme une personne. Il envoie une séquence de requêtes dans une fenêtre de temps réduite, souvent vers le même domaine, puis se tait. Depuis une seule IP, ce schéma est immédiatement identifié comme de l’automatisation. Nous avons écrit séparément sur la forme du trafic des agents IA, mais en résumé : les limites de débit et la détection comportementale qu’un humain ne déclenche jamais, un agent les déclenche constamment, parce que tout le trafic provient d’une seule adresse.

Vous n’avez aucun contrôle géographique. Votre serveur MCP s’exécute dans une seule région. Si le modèle doit voir une page produit comme un acheteur allemand, un résultat de recherche comme un utilisateur à Tokyo, ou un prix comme un client américain, un serveur mono-région ne peut physiquement pas le faire. Le site géolocalise l’IP du serveur et sert le contenu du mauvais pays, silencieusement. Le modèle raisonne alors sur des données qu’il croit correctes et qui ne le sont pas.

Aucun de ces problèmes n’est un bug dans votre serveur MCP. Ce sont des propriétés de l’endroit où il s’exécute et de sa forme. MCP fait exactement son travail, transporter l’appel d’outil. Il n’a jamais été conçu pour masquer l’IP.

Pourquoi ce n’est pas le rôle de MCP de résoudre ce problème

Il vaut la peine d’être explicite, car les gens attendent parfois que le protocole développe une fonctionnalité qui ne viendra pas. MCP est un protocole pour la communication modèle-outil. Il standardise la façon dont un outil est décrit, appelé, et dont les résultats reviennent. Le transport entre le client et le serveur (stdio, ou Streamable HTTP) concerne la plomberie de l’agent, pas la façon dont le serveur atteint internet.

La façon dont votre outil fetch communique avec le monde extérieur est un détail d’implémentation de votre serveur, exactement comme la bibliothèque HTTP que vous utilisez ou la façon dont vous analysez la réponse. Le protocole ne devrait pas le dicter, et ne le fait pas. Ce qui signifie que la couche d’accès web vous appartient. La bonne nouvelle, c’est que c’est une couche petite et bien comprise : router les requêtes sortantes du serveur via des IP résidentielles.

La solution : un proxy résidentiel derrière l’outil fetch

Le schéma est simple. Au lieu que l’outil de votre serveur MCP effectue une requête directe depuis son IP de datacenter, il effectue la requête via une passerelle de proxy résidentiel. Le site cible voit une vraie IP de consommateur dans le bon pays, avec le profil de confiance d’une vraie connexion domestique, et la requête passe.

Voici un serveur MCP Python minimal avec un outil fetch_url qui route via la passerelle Shifter. L’échafaudage MCP est du FastMCP standard ; la partie qui compte est le câblage proxies sur le client HTTP.

import os
import httpx
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("web-fetch")
# One gateway endpoint, targeting encoded in the username.
# Keep credentials in env, never in the tool definition.
USER = os.environ["SHIFTER_USER"] # e.g. "customer-<id>"
PASS = os.environ["SHIFTER_PASS"]
GATEWAY = "p.shifter.io:443"
def proxy_url(country: str = "us") -> str:
return f"http://{USER}-country-{country}:{PASS}@{GATEWAY}"
@mcp.tool()
async def fetch_url(url: str, country: str = "us") -> str:
"""Fetch a URL through a residential IP in the given country."""
proxies = proxy_url(country)
async with httpx.AsyncClient(proxy=proxies, timeout=30) as client:
r = await client.get(url, follow_redirects=True)
r.raise_for_status()
return r.text
if __name__ == "__main__":
mcp.run()

C’est tout le changement nécessaire. Le modèle appelle fetch_url("https://example.com/product", country="de"), la requête part via une IP résidentielle en Allemagne, et le site sert la page allemande à ce qui ressemble à un acheteur allemand. Changez country et le modèle voit la même page à travers les yeux d’un autre marché, sans redéploiement et sans second serveur.

Le ciblage géographique est la partie dont les agents ont le plus besoin

Le problème de blocage est celui que les gens remarquent en premier, mais le problème géographique est celui qui corrompt silencieusement les résultats. Un serveur MCP ancré dans une seule région, c’est un LLM qui regarde le monde par un seul judas.

Parce que la passerelle Shifter encode le ciblage dans le nom d’utilisateur, votre outil fetch peut prendre un argument country (ou état, ville, voire ASN) et laisser le modèle choisir par appel. Cela transforme un serveur mono-région en serveur mondial. Un agent de recherche comparant les prix entre marchés, un agent d’assurance qualité de localisation vérifiant comment un site s’affiche dans cinq pays, un agent de surveillance SERP récupérant les résultats Google comme un utilisateur local, tous ont exactement besoin de cela et ne peuvent pas l’obtenir d’un outil fetch hébergé sur un cloud classique.

Pour les flux en plusieurs étapes où l’agent a besoin de la même IP sur plusieurs appels (une connexion, puis une séquence de pages authentifiées), ajoutez une session persistante en incluant un identifiant de session et un TTL dans le nom d’utilisateur. La même IP est maintenue pendant toute la durée du TTL :

def sticky_proxy_url(country: str, session: str, ttl: int = 600) -> str:
return f"http://{USER}-country-{country}-sid-{session}-ttl-{ttl}:{PASS}@{GATEWAY}"

Un outil browse_session peut ainsi maintenir une identité stable tout au long des étapes d’une tâche, au lieu de changer d’IP en cours de flux et de déclencher toutes les vérifications de session du site.

Ce qu’il faut garder à l’esprit

Une couche proxy n’est pas un interrupteur magique “jamais bloqué”, et la traiter comme telle est la façon dont les gens gaspillent de la bande passante. Quelques notes pratiques :

Mettez en cache de manière agressive. Les agents récupèrent constamment les mêmes URLs. Un petit cache devant votre outil fetch réduit considérablement la bande passante proxy (et votre coût), et est aussi plus rapide pour le modèle. Ne proxifiez pas une requête dont vous avez déjà la réponse.

Passez le pays en paramètre, ne le codez pas en dur. Toute la valeur réside dans le contrôle géographique par appel. Faites de country un argument d’outil que le modèle peut définir, avec une valeur par défaut sensée, plutôt que de fixer une région dans le serveur.

Respectez la cible. Un proxy change l’IP depuis laquelle la requête provient, pas si vous devriez la faire. Respectez robots.txt là où c’est important, maintenez des taux de requêtes raisonnables, et ne martelez pas un site simplement parce que les blocages ont disparu. Notre politique d’utilisation acceptable est la référence pour ce qui est autorisé.

Gardez les identifiants hors du schéma d’outil. Le nom d’utilisateur et le mot de passe du proxy se trouvent dans des variables d’environnement sur le serveur, jamais dans la définition d’outil que le modèle voit. Le modèle doit choisir un pays, pas détenir votre mot de passe de passerelle.

Le datacenter convient pour les récupérations non protégées et neutres géographiquement. Si un outil n’interroge que vos propres APIs ou des points de terminaison publics qui ne bloquent pas et ne géolocalisent pas, il n’a pas besoin du proxy. Réservez la couche résidentielle pour les récupérations sur le web ouvert qui font face à des blocages ou nécessitent une géolocalisation. (Pour une comparaison plus complète de quand chaque type d’IP convient, voir proxies résidentiels vs datacenter.)

FAQ

MCP dispose-t-il d’un support proxy intégré ? Non, et il ne devrait pas. MCP standardise la communication modèle-outil, pas la façon dont un outil atteint internet. L’accès web sortant est un détail d’implémentation de votre serveur. Vous ajoutez un proxy au niveau du client HTTP à l’intérieur de l’outil, exactement comme indiqué ci-dessus.

Pourquoi ne pas simplement exécuter mon serveur MCP depuis une connexion résidentielle ? Vous pourriez, mais cela ne passe pas à l’échelle, ne vous donne pas de contrôle géographique par requête, et lie la fiabilité de votre agent à la disponibilité d’une connexion domestique et d’une seule IP. Une passerelle de proxy résidentiel vous donne un grand pool rotatif et un ciblage par pays par appel, sans rien héberger sur une ligne résidentielle.

Un proxy empêchera-t-il totalement le blocage de mon agent ? Il supprime la principale cause (l’IP de datacenter) et vous donne le contrôle géographique, mais le comportement compte toujours. Les schémas de requêtes en rafales, les en-têtes manquants ou incohérents, et l’ignorance des limites de débit peuvent toujours vous faire signaler. Le proxy est nécessaire, mais pas suffisant : associez-le à un comportement de requête raisonnable.

Cela fonctionne-t-il aussi avec les serveurs MCP TypeScript ? Oui. Le concept est identique : configurez votre client HTTP (fetch avec un agent, axios, undici, got) pour router via la passerelle. Le format d’URL du proxy et le ciblage par requête sont les mêmes quel que soit le langage.

Le modèle peut-il choisir le pays par requête ? Oui, c’est le schéma recommandé. Exposez country (et optionnellement état/ville) comme argument d’outil avec une valeur par défaut. Le modèle le définit en fonction de la tâche, et votre serveur l’encode dans le nom d’utilisateur du proxy à la volée.

Le routage via un proxy change-t-il la façon dont Shifter me facture ? Non. C’est la passerelle résidentielle standard au tarif habituel par Go. Un serveur MCP est simplement un autre client se connectant au même point de terminaison. La bande passante est la bande passante.

En résumé

MCP est une réponse claire à “comment un modèle appelle-t-il un outil”. Il n’a jamais été conçu pour répondre à “comment cet outil atteint-il un web ouvert hostile depuis une IP de datacenter signalée dans le mauvais pays”. Cette deuxième question est réelle, c’est à vous d’y répondre, et la réponse est une fine couche de proxy résidentiel derrière vos outils fetch.

Le câblage représente quelques lignes. Le bénéfice est un serveur MCP dont les outils web fonctionnent réellement en production, retournent les données du bon pays, et ne tombent pas en panne dès qu’un agent les pointe vers un site protégé. Si vous construisez des agents connectés au web, commencez avec la passerelle résidentielle et placez-la derrière vos outils dès le premier jour : c’est bien plus facile que de l’ajouter après que les blocages ont commencé. Pour en savoir plus sur comment donner aux agents un accès web fiable, consultez les meilleurs proxies pour les agents IA qui naviguent sur le web.

Tags : mcp ai agents model context protocol residential proxies llm tools web access

Prêt à commencer ?

Essayez les proxies résidentiels de Shifter, 205M+ IPs, 195+ pays, à partir de $1.00/GB.

Commencer