¡Hola developer 👋🏻! Si llevas un tiempo trabajando con MCP Servers, seguro que te has encontrado con este escenario: el servidor funciona bien, el caso de uso es potente… pero en cuanto intentas usarlo en equipo, desde varios agentes, en una compañía o en remoto, todo empieza a complicarse. Y no, el problema no es solo stdio.
En este artículo te voy a enseñar un patrón muy práctico y realista: usar un MCP Server para crear un proxy que permita ejecutar MCP Servers como un servicio HTTP, centralizando además las credenciales (PATs, API Keys, tokens).
Un enfoque especialmente útil para entornos corporativos, Agentic DevOps y agentes compartidos.
🤔 El problema real con muchos MCP Servers
Cuando pasamos de pruebas locales a escenarios reales, suelen aparecer dos grandes frenos.
1️⃣ MCP Servers basados en stdio
Muchos MCP Servers funcionan únicamente vía stdio, lo que implica que:
- ❌ Solo pueden ejecutarse localmente
- ❌ No pueden exponerse directamente como servicios
- ❌ Cada cliente debe lanzar su propio proceso
Esto ya es una limitación importante cuando quieres algo compartido o centralizado. Si tu problema principal no es este, te recomiendo que eches un vistazo a Azure API Management, el cual, como servicio, también permite hacer de proxy de MCP Servers que soporten SSE o Streamable HTTP.
2️⃣ MCP Servers que requieren credenciales (PAT, API Keys, tokens…)
Además, una gran parte de los MCP Servers:
- ❌ Requieren Personal Access Tokens (PAT) u otros secretos
- ❌ Obligan a configurar credenciales en cada cliente
- ❌ Dificultan el uso compartido entre agentes o personas
- ❌ Incrementan el riesgo de fugas de credenciales
Y aquí viene el matiz importante:
👉 Incluso aunque el MCP Server NO use stdio, el simple hecho de requerir credenciales ya complica muchísimo su adopción en equipos y entornos corporativos, especialmente si esas credenciales son diferentes a las corporativas.
Si quieres saber más sobre MCP Servers puedes echarle un vistazo a mi playlist de mi canal de YouTube:
El verdadero problema
El problema real no es solo técnico. Muchos MCP Servers no están pensados para ejecutarse como servicios compartidos, ni desde el punto de vista de ejecución ni de seguridad.
✅ La idea: MCP Server como proxy de otro MCP Server
La solución pasa por desacoplar completamente al cliente MCP del MCP Server real. Ejecutar el MCP Server real en una máquina o contenedor centralizado, y exponerlo vía HTTP, centralizando también las credenciales.
Con este enfoque conseguimos:
- ✅ Ejecutar MCP Servers stdio o no-stdio en un entorno controlado
- ✅ Evitar distribuir PATs, API Keys o tokens a los clientes
- ✅ Acceder desde cualquier cliente MCP vía HTTP
- ✅ Compartir el acceso entre múltiples usuarios o agentes
- ✅ Aplicar políticas de seguridad y autenticación en un único punto
- ✅ Desplegarlo como servicio remoto (VM, contenedor, Kubernetes…)
FastMCP encaja perfectamente como capa de proxy y control, porque además viene integrado como parte del SDK a día de hoy.
🎯 Caso práctico: Azure DevOps MCP Server
En el repositorio uso como ejemplo el Azure DevOps MCP Server, porque concentra los dos problemas más habituales:
- Usa stdio → no puede exponerse directamente como servicio
- Requiere un Personal Access Token (PAT) o autenticarse usando Azure CLI.
🏗️ Arquitectura del proxy MCP
El flujo es el siguiente:
- El cliente MCP (Copilot, Claude, VS Code…) habla HTTP
- FastMCP actúa como proxy
- El MCP Server original sigue funcionando como siempre
- Las credenciales viven solo en el servidor, no en los clientes
Esto simplifica muchísimo la arquitectura y mejora la seguridad.
📋 Requisitos
Para ejecutar este ejemplo necesitas:
- Python 3.10+
- Node.js 20+ (en el caso del ejemplo de Azure DevOps)
- Las credenciales necesarias del MCP Server que vayas a hacer de proxy
🚀 Instalación paso a paso
1️⃣ Clonar el repositorio
git clone https://github.com/0GiS0/mcp-server-as-a-proxy.git
cd mcp-server-as-a-proxy
2️⃣ Instalar dependencias
pip install -e .
3️⃣ Configurar variables de entorno
cp .env.example .env
Ejemplo para Azure DevOps:
AZURE_DEVOPS_ORG=tu-organizacion
ADO_MCP_AUTH_TOKEN=tu-personal-access-token
4️⃣ Ejecutar el proxy
python proxy_server.py
El proxy quedará disponible en http://localhost:8080/mcp
🍿 El resultado
⚠️ Importante
Este ejemplo es una PoC para demostrar que técnicamente es posible hacer de proxy de otro MCP Server pero no se ha tenido en cuenta (o si, pero en pensamiento 🥲) la escalabilidad de este escenario. Es decir: en este ejemplo se está lanzado el MCP Server definitivo como un proceso único, lo cual implica que cada petición espera al mismo backend, por lo que sin balanceo de carga no hay distribución de las requests y por lo tanto habría un cuello de botella. Existen varias formas de escalar como ya sabes:
- Escalar horizontalmente (multiples instancias de esta implemetación)
- Usar Gunicorn con workers
- Pool de procesos en backend
- Kubernetes/container con réplicas
Por otro lado, es importante saber que en general todos los servicios tienen limites en cuanto al número de peticiones que se pueden hacer, normalmente, al minuto usando el mismo PAT por lo que es probable que si estás usando «el mismo para todo» porque no hay alternativa, puedas necesitar múltiples PATs con rotación.
Esta implementación no es la ideal pero en muchos casos a día de hoy es la única medianamente viable.
🔧 Adaptar el proxy a otro MCP Server
Aquí está la clave de todo el patrón.
Usamos StdioTransport (o el transport que necesites) para lanzar el MCP Server real y lo envolvemos con FastMCP.as_proxy:
from fastmcp import FastMCP
from fastmcp.server.proxy import ProxyClient
from fastmcp.client.transports import StdioTransport
transport = StdioTransport(
command="npx", # o python, node, etc.
args=["-y", "@tu-mcp/server"],
env={
"API_KEY": "tu-api-key",
"OTHER_SECRET": "..."
}
)
proxy = FastMCP.as_proxy(
ProxyClient(transport),
name="MiMCPProxy"
)
if __name__ == "__main__":
proxy.run(transport="http", host="0.0.0.0", port=8080)
👉 El MCP Server no necesita modificarse.
👉 Las credenciales se quedan en el servidor.
👉 Los clientes solo hablan HTTP.
🔌 Configuración del cliente MCP
VS Code (mcp.json)
{
"servers": {
"mi-proxy": {
"type": "http",
"url": "http://localhost:8080/mcp"
}
}
}
Claude Desktop
{
"mcpServers": {
"mi-proxy": {
"url": "http://localhost:8080/mcp",
"transport": "http"
}
}
}
⚠️ Seguridad: no lo ignores
Este ejemplo no incluye autenticación propia por simplicidad 👉 No lo expongas tal cual en producción.
🔐 Autenticación con Microsoft Entra ID
FastMCP incluye soporte nativo para autenticación con Azure / Entra ID:
from fastmcp.server.auth.providers.azure import AzureProvider
auth_provider = AzureProvider(
client_id="tu-app-client-id",
client_secret="tu-client-secret",
tenant_id="tu-tenant-id",
base_url="http://localhost:8080",
required_scopes=["mcp-access"],
)
proxy = FastMCP.as_proxy(
ProxyClient(transport),
name="MiProxy",
auth=auth_provider
)
Ideal para entornos corporativos con control de acceso real.
🧠 Conclusión
Este patrón no va solo de stdio.
Va de algo mucho más importante:
- Centralizar ejecución
- Centralizar credenciales (PATs, API Keys, tokens)
- Evitar configuración local en cada cliente
- Hacer MCP usable de verdad en entornos reales
Con este enfoque puedes:
- Exponer MCP Servers como servicios
- Compartirlos entre agentes
- Proteger secretos
- Integrarlos en infraestructuras corporativas
¡Nos vemos 👋🏻!
