MCP Chain
Un marco de middleware componible para construir cadenas de servidores MCP sofisticadas, inspirado en Ruby Rack.
Documentación
MCP Chain
Un framework de middleware componible para construir cadenas de servidores MCP, inspirado en Ruby Rack. MCP Chain te permite crear proxies transparentes que se sitúan entre clientes y servidores MCP, transformando solicitudes y respuestas mediante funciones de Python.
MCP Chain resuelve el problema de añadir preocupaciones transversales (autenticación, registro de actividad, transformación de solicitudes) a servidores MCP existentes sin modificarlos. Utiliza un patrón de proxy transparente donde cada capa de middleware aparece como un servidor MCP estándar para los clientes, mientras reenvía solicitudes a servidores posteriores. El middleware también puede orquestar múltiples llamadas MCP en segundo plano usando IA, transformando APIs granulares en MCPs inteligentes que realizan tareas complejas de múltiples pasos.
Inicio rápido
Instala y ejecuta con uvx - no se requiere configuración:
# cli_server.py
from mcp_chain import mcp_chain, CLIMCPServer
cli_server = CLIMCPServer(
name="dev-tools",
commands=["git", "ls", "grep"],
descriptions={
"git": "Git version control operations",
"ls": "List directory contents",
"grep": "Search text patterns"
}
)
# Auto-detected by CLI
chain = mcp_chain().then(cli_server)
uvx mcp-chain cli_server.py
Añade a tu mcp.json:
{
"mcpServers": {
"dev-tools": {
"command": "uvx",
"args": ["mcp-chain", "cli_server.py"]
}
}
}
Ejemplos
Middleware de Autenticación
Añade autenticación a cualquier servidor MCP:
from mcp_chain import mcp_chain, ExternalMCPServer, serve
def require_auth(next_server, request_dict):
if not request_dict.get("auth_token"):
return {"error": "Authentication required", "code": 401}
return next_server.handle_request(request_dict)
chain = (mcp_chain()
.then(None, require_auth)
.then(ExternalMCPServer("postgres", "postgres-mcp")))
serve(chain, name="Authenticated Postgres")
Transformación de Solicitudes/Respuestas
Transforma metadatos y solicitudes:
from mcp_chain import mcp_chain, CLIMCPServer
def add_company_context(next_server, metadata_dict):
metadata = next_server.get_metadata()
for tool in metadata.get("tools", []):
tool["description"] = f"ACME Corp: {tool.get('description', '')}"
return metadata
def add_headers(next_server, request_dict):
request_dict["headers"] = {"X-Company": "ACME"}
response = next_server.handle_request(request_dict)
response["processed_by"] = "acme-proxy"
return response
cli_server = CLIMCPServer(name="tools", commands=["git", "docker"])
chain = (mcp_chain()
.then(add_company_context, add_headers)
.then(cli_server))
Cadena de Múltiples Middlewares
Apila autenticación, registro de actividad y transformación:
import logging
from mcp_chain import mcp_chain, ExternalMCPServer, serve
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("mcp-chain")
def auth_middleware(next_server, request_dict):
if not request_dict.get("auth_token"):
return {"error": "Authentication required", "code": 401}
return next_server.handle_request(request_dict)
def logging_middleware(next_server, request_dict):
logger.info(f"Request: {request_dict.get('method')}")
response = next_server.handle_request(request_dict)
logger.info(f"Response: {response.get('result', 'error')}")
return response
def context_middleware(next_server, metadata_dict):
metadata = next_server.get_metadata()
for tool in metadata.get("tools", []):
tool["description"] = f"Enterprise: {tool.get('description', '')}"
return metadata
chain = (mcp_chain()
.then(context_middleware, auth_middleware)
.then(None, logging_middleware)
.then(ExternalMCPServer("postgres", "postgres-mcp")))
serve(chain, name="Enterprise Postgres")
Uso Programático
Usa la función serve() directamente:
from mcp_chain import mcp_chain, CLIMCPServer, serve
def rate_limit_middleware(next_server, request_dict):
# Add rate limiting logic
return next_server.handle_request(request_dict)
cli_server = CLIMCPServer(name="secure-tools", commands=["git"])
chain = mcp_chain().then(None, rate_limit_middleware).then(cli_server)
serve(chain, name="Rate Limited Tools", port=8000)
Arquitectura
MCP Chain utiliza un patrón de middleware funcional donde cada capa transforma solicitudes/respuestas y reenvía a la siguiente capa:
graph TD
A["MCP Client"] --> B["FastMCP"]
B --> C["mcp_chain()"]
C --> D1["middleware_1"]
D1 --> D2["middleware_2"]
D2 --> E["downstream_server"]
E -- "response" --> D2
D2 -- "response" --> D1
D1 -- "response" --> C
C -- "response" --> B
B -- "response" --> A
Cada capa de middleware:
- Recibe solicitudes de la capa anterior (o del cliente)
- Transforma la solicitud/metadatos usando diccionarios de Python
- Reenvía a la siguiente capa (o al servidor posterior)
- Recibe la respuesta de vuelta
- Transforma la respuesta según sea necesario
- Devuelve a la capa anterior (o al cliente)
Principios Fundamentales:
- Proxy Transparente: Cada middleware aparece como un servidor MCP estándar para los clientes
- Procesamiento Basado en Diccionarios: El procesamiento interno usa diccionarios de Python, no cadenas JSON
- Componible: El middleware puede encadenarse ya que cada capa es un servidor MCP
- Cero Sobrecarga: Sin serialización/deserialización en la cadena de middleware
Construido sobre el SDK oficial de FastMCP para total cumplimiento del protocolo MCP.
API
Funciones Principales
from mcp_chain import mcp_chain, serve, CLIMCPServer, ExternalMCPServer
# Create a chain
chain = mcp_chain()
# Add middleware layers
chain = chain.then(metadata_transformer, request_transformer)
chain = chain.then(downstream_server)
# Start server
serve(chain, name="My Server", port=8000)
Construcción de Cadenas
# Metadata transformer (transforms server capabilities)
def metadata_transformer(next_server, metadata_dict):
metadata = next_server.get_metadata()
# Transform metadata dict and return
return metadata
# Request transformer (transforms requests/responses)
def request_transformer(next_server, request_dict):
# Transform request dict
response = next_server.handle_request(request_dict)
# Transform response dict and return
return response
# Add to chain
chain = mcp_chain().then(metadata_transformer, request_transformer)
Servidores Integrados
# CLI server - exposes command-line tools as MCP tools
cli_server = CLIMCPServer(
name="my-tools",
commands=["git", "docker", "npm"],
descriptions={
"git": "Git operations",
"docker": "Container management",
"npm": "Package management"
}
)
# External server proxy
external_server = ExternalMCPServer("server-name", "command-to-run")
Auto-Detección
El CLI detecta automáticamente variables de cadena en tus archivos de Python:
# Any of these variable names work:
chain = mcp_chain().then(...)
my_chain = mcp_chain().then(...)
server_chain = mcp_chain().then(...)
proxy = mcp_chain().then(...)
Ejecuta con: uvx mcp-chain filename.py
Desarrollo
Este proyecto fue desarrollado principalmente con asistentes de IA y está diseñado para flujos de trabajo de desarrollo asistidos por IA. La estructura del código está pensada para ser fácilmente comprendida y modificada por herramientas de IA. La carpeta ai/ contiene documentos de contexto y notas de diseño específicamente para asistentes de IA que trabajen en este repositorio.
Instalación
# Development install
git clone https://github.com/ronie-uliana/mcp-chain
cd mcp-chain
uv sync
Pruebas
# Fast unit tests
uv run pytest tests/ -m "not integration" -v
# Integration tests (with timeout protection)
timeout 30 uv run pytest tests/ -m integration -v
# All tests
timeout 45 uv run pytest tests/ -v
# Local CI pipeline
./scripts/test-ci.sh
Publicación
uv build && uv publish
Las versiones se publican automáticamente en PyPI mediante GitHub Actions en cada nueva versión.
Opciones de Instalación
# Recommended: Run with uvx (no installation)
uvx mcp-chain my_chain.py
# Install from PyPI
pip install mcp-chain
# Run installed version
python -m mcp_chain my_chain.py
# or
mcp-chain my_chain.py