Quand vous n'avez qu'un serveur MCP, le brancher dans un client suffit. Dès que vous en avez plusieurs, chacun avec sa propre authentification, son transport et son cycle de vie, câbler chaque serveur dans chaque agent devient ingérable. C'est le problème que résout une passerelle MCP.
ContextForge (le projet mcp-context-forge d'IBM, sous licence Apache 2.0) est une passerelle et un registre MCP. Il se place devant vos serveurs MCP, vos APIs REST et vos agents A2A, et expose un endpoint unifié avec découverte centralisée, authentification, rate-limiting et observabilité. Ce n'est pas un générateur de serveur comme reShapr ; c'est la couche de gouvernance au-dessus de vos serveurs.
Ce guide déroule un lab reproductible : déployer la passerelle, fédérer un serveur MCP existant, composer un serveur virtuel unifié, puis appeler un outil au travers, le tout piloté par l'API REST.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déployer ContextForge en local avec Docker.
- Fédérer un serveur MCP existant derrière la passerelle.
- Composer un serveur virtuel exposé en endpoint MCP unifié.
- Appeler un outil fédéré par l'API et gérer la gouvernance (JWT, SSRF).
Prérequis
Section intitulée « Prérequis »- Docker et Docker Compose.
- Les bases du Model Context Protocol : serveur, outils, transports.
- Un client HTTP (
curl) etjqpour lire les réponses JSON.
ContextForge en bref
Section intitulée « ContextForge en bref »Trois notions structurent la passerelle. Les comprendre évite de confondre un serveur fédéré et un serveur virtuel.
- Gateway (fédération) : un serveur MCP distant que la passerelle enregistre et introspecte. À l'enregistrement, ContextForge découvre automatiquement ses outils, prompts et ressources.
- Tool : un outil exposé à travers la passerelle. Il vient soit d'un serveur MCP fédéré, soit d'une API REST que vous déclarez directement.
- Virtual server : un regroupement d'outils choisis, publié comme un seul endpoint MCP que vos agents consomment. C'est la brique qui compose une vue cohérente à partir de plusieurs sources.
Autour de ça, ContextForge ajoute la gouvernance : authentification JWT et RBAC, rate-limiting, protection SSRF, registres de prompts et de ressources, et observabilité OpenTelemetry.
Déployer la passerelle
Section intitulée « Déployer la passerelle »Le compose.yaml lance la passerelle sur le port 4444, avec une base SQLite et un compte administrateur. La clé JWT_SECRET_KEY doit faire au moins 32 octets.
services: gateway: image: ghcr.io/ibm/mcp-context-forge:latest container_name: cf-gateway ports: ["4444:4444"] environment: - HOST=0.0.0.0 - MCPGATEWAY_UI_ENABLED=true - MCPGATEWAY_ADMIN_API_ENABLED=true - AUTH_REQUIRED=true - JWT_SECRET_KEY=my-test-key-but-now-longer-than-32-bytes - PLATFORM_ADMIN_EMAIL=admin@example.com - PLATFORM_ADMIN_PASSWORD=changeme - DATABASE_URL=sqlite:////data/mcp.db - SECURE_COOKIES=false volumes: - ./data:/data networks: [cfnet]
networks: cfnet:mkdir -p data && chmod 777 datadocker compose up -dToute l'API est protégée. On génère un jeton JWT avec l'utilitaire fourni, en réutilisant exactement le même secret que JWT_SECRET_KEY :
TOKEN=$(docker exec cf-gateway python3 -m mcpgateway.utils.create_jwt_token \ --username admin@example.com --exp 10080 \ --secret my-test-key-but-now-longer-than-32-bytes)Un appel de vérification confirme la version et l'état du runtime :
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:4444/version | jq '.app, .platform.python'# { "name": "ContextForge", "version": "1.0.4", "mcp_protocol_version": "2025-11-25" }# "3.12.13"
curl -s http://localhost:4444/health | jq '.status, .mcp_runtime.effective_mode'# "healthy"# "off" <- le sidecar Rust est bien désactivé par défautLe champ effective_mode: "off" confirme le point du départ : le plan de contrôle est en Python, le sidecar Rust n'intervient pas.
Fédérer un serveur MCP
Section intitulée « Fédérer un serveur MCP »Pour la démo, on fédère un petit serveur MCP d'horloge (fast-time-server) lancé en SSE sur le même réseau Docker. L'enregistrement se fait par un POST /gateways :
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"name":"fast_time","url":"http://fasttime:8080/sse","transport":"SSE"}' \ http://localhost:4444/gatewaysUne fois le réglage appliqué et la passerelle redémarrée, l'enregistrement réussit et ContextForge introspecte le serveur : ses outils apparaissent automatiquement dans le registre.
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:4444/tools \ | jq '.[] | {name, id}'# { "name": "fast-time-get-system-time", "id": "addedc953912436cb67c5fac1edfd8f3" }# { "name": "fast-time-convert-time", "id": "c713864ab5bc4ee2834a8b3c7ffc5098" }Composer un serveur virtuel unifié
Section intitulée « Composer un serveur virtuel unifié »Un POST /servers regroupe les outils choisis derrière un endpoint MCP unique. On référence les identifiants d'outils obtenus ci-dessus :
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"server":{"name":"horloge","associated_tools":["addedc953912436cb67c5fac1edfd8f3","c713864ab5bc4ee2834a8b3c7ffc5098"]}}' \ http://localhost:4444/servers | jq '{id, name, associatedTools}'# { "id": "058e85525e3844e39f02cd78f37b5b83", "name": "horloge",# "associatedTools": ["fast-time-get-system-time","fast-time-convert-time"] }Le serveur virtuel expose alors un endpoint MCP que n'importe quel client (Claude Desktop, un agent LangGraph, l'inspecteur MCP) peut consommer avec le même jeton :
http://localhost:4444/servers/058e85525e3844e39f02cd78f37b5b83/mcpC'est tout l'intérêt : vos agents ne connaissent qu'une URL et un jeton, la passerelle s'occupe du reste.
Appeler un outil au travers de la passerelle
Section intitulée « Appeler un outil au travers de la passerelle »L'appel se fait en JSON-RPC 2.0 sur /rpc, méthode tools/call :
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"fast-time-get-system-time","arguments":{}}}' \ http://localhost:4444/rpc | jq '.result.content[0].text'# "2026-07-03T12:23:13Z"La réponse vient bien du serveur fast-time fédéré, mais elle a transité par la passerelle : authentifiée, journalisée, et soumise aux politiques. Le client, lui, n'a parlé qu'à ContextForge.
Exposer une API REST comme outil MCP
Section intitulée « Exposer une API REST comme outil MCP »ContextForge ne fédère pas que des serveurs MCP : il transforme aussi une API REST en outil MCP, via un POST /tools. Vous décrivez l'endpoint et son schéma d'entrée, la passerelle l'expose comme n'importe quel autre outil :
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"tool":{"name":"weather","url":"https://api.exemple.com/weather","integration_type":"REST","request_type":"GET","input_schema":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}' \ http://localhost:4444/toolsC'est le recouvrement avec reShapr : pour envelopper une API isolée, les deux savent le faire. La différence est que ContextForge le fait au sein d'une plateforme qui fédère et gouverne l'ensemble.
Le sidecar Rust, sans surprise pour ce guide
Section intitulée « Le sidecar Rust, sans surprise pour ce guide »Le projet migre progressivement le chemin de données vers un runtime Rust (sessions, event-store, exécution directe des outils), pour la performance. Deux points à retenir :
- Le plan de contrôle reste en Python : validation JWT, RBAC, hooks de plugins et l'API d'administration utilisée ici.
- Le sidecar s'active par paliers via
RUST_MCP_MODE(off,shadow,edge,full), désactivé par défaut. Vous l'avez vu dans/healthaveceffective_mode: "off".
Autrement dit, l'API et les concepts de ce guide ne bougent pas avec cette évolution : le Rust accélère le transport, il ne remplace pas la surface que vous pilotez.
Sécurité et gouvernance
Section intitulée « Sécurité et gouvernance »- Authentification : JWT par défaut sur l'API (l'auth Basic API est désactivée), plus RBAC. Protégez
JWT_SECRET_KEYcomme un secret de production. - Protection SSRF : activée par défaut, elle empêche la passerelle d'atteindre des adresses internes non autorisées. Ouvrez uniquement ce dont vous avez besoin via
SSRF_ALLOWED_NETWORKS. - Rate-limiting et retries au niveau des adaptateurs, pour ne pas laisser un agent emballé saturer un serveur en aval.
- Observabilité : traces OpenTelemetry exportables vers Jaeger, Zipkin ou Phoenix, indispensables quand plusieurs agents appellent plusieurs serveurs.
ContextForge ou reShapr
Section intitulée « ContextForge ou reShapr »Ils ne jouent pas au même étage, et se combinent bien.
- reShapr répond à « j'ai une API REST/GraphQL/gRPC à exposer en MCP, vite et sans coder ». Outil léger, mono-source.
- ContextForge répond à « j'ai plusieurs serveurs MCP à unifier, sécuriser et observer derrière un point d'entrée ». Plateforme de gouvernance.
Vous pouvez générer des serveurs avec reShapr, puis les fédérer dans ContextForge.
Dépannage
Section intitulée « Dépannage »blocked by SSRF protection: la cible est une adresse privée. Autorisez la plage viaSSRF_ALLOWED_NETWORKS(recommandé) ouSSRF_ALLOW_PRIVATE_NETWORKS=trueen lab.401/403sur l'API : le jeton a été généré avec un secret différent deJWT_SECRET_KEY, ou il a expiré (--expen minutes). Régénérez-le avec le bon secret.- Image introuvable sur un tag précis : tous les tags semver ne sont pas publiés sur
ghcr.io. Lelatestcorrespondait ici à la 1.0.4. Épinglez ensuite un tag reproductible plutôt quelatest. - La passerelle en conteneur ne joint pas un serveur sur l'hôte : mettez-les sur le même réseau Docker (nom de service) ou utilisez
host.docker.internal.
À retenir
Section intitulée « À retenir »- ContextForge est une passerelle et un registre MCP : un endpoint unifié devant vos serveurs MCP, APIs REST et agents.
- On fédère un serveur (
/gateways), la passerelle découvre ses outils, on les regroupe en serveur virtuel (/servers), et on appelle via/rpc. - La gouvernance est native : JWT/RBAC, protection SSRF par défaut, rate-limiting, observabilité OpenTelemetry.
- Le plan de contrôle reste Python ; le sidecar Rust est un accélérateur optionnel (
RUST_MCP_MODE=offpar défaut). - Face à reShapr, ContextForge est la couche plateforme, pas le générateur mono-API.