MCP Proxy

Un servidor proxy para solicitudes MCP, compatible con transportes SSE y stdio.

Documentación

mcp-proxy

GitHub License PyPI - Python Version PyPI - Downloads codecov

Acerca de

El mcp-proxy es una herramienta que permite cambiar entre transportes de servidor. Hay dos modos compatibles:

  1. stdio a SSE/StreamableHTTP
  2. SSE a stdio

1. stdio a SSE/StreamableHTTP

Ejecuta un servidor proxy desde stdio que se conecta a un servidor SSE remoto.

Este modo permite que clientes como Claude Desktop se comuniquen con un servidor remoto a través de SSE aunque no sea compatible de forma nativa.

graph LR
    A["Claude Desktop"] <--> |stdio| B["mcp-proxy"]
    B <--> |SSE| C["External MCP Server"]

    style A fill:#ffe6f9,stroke:#333,color:black,stroke-width:2px
    style B fill:#e6e6ff,stroke:#333,color:black,stroke-width:2px
    style C fill:#e6ffe6,stroke:#333,color:black,stroke-width:2px

1.1 Configuración

Este modo requiere proporcionar la URL del endpoint SSE del servidor MCP como primer argumento del programa. Si el servidor utiliza el transporte Streamable HTTP, asegúrate de imponerlo en el lado de mcp-proxy pasando --transport=streamablehttp.

Argumentos

NombreRequeridoDescripciónEjemplo
command_or_urlEl endpoint SSE del servidor MCP al que conectarsehttp://example.io/sse
--headersNoCabeceras a usar para la conexión SSE del servidor MCPAuthorization 'Bearer my-secret-access-token'
--transportNoDecide qué protocolo de transporte usar al conectarse a un servidor MCP. Puede ser 'sse' o 'streamablehttp'streamablehttp
--client-idNoID de cliente OAuth2 para autenticaciónyour_client_id
--client-secretNoSecreto de cliente OAuth2 para autenticaciónyour_client_secret
--token-urlNoURL del endpoint de token OAuth2 para autenticaciónhttps://auth.example.com/oauth/token

Variables de entorno

NombreRequeridoDescripciónEjemplo
API_ACCESS_TOKENNoPuede usarse en lugar de --headers Authorization 'Bearer <API_ACCESS_TOKEN>'YOUR_TOKEN

1.2 Ejemplo de uso

mcp-proxy debe ser iniciado por el cliente MCP, por lo que la configuración debe realizarse en consecuencia.

Para Claude Desktop, la entrada de configuración puede verse así:

{
  "mcpServers": {
    "mcp-proxy": {
      "command": "mcp-proxy",
      "args": [
        "http://example.io/sse"
      ],
      "env": {
        "API_ACCESS_TOKEN": "access-token"
      }
    }
  }
}

2. SSE a stdio

Ejecuta un servidor proxy que expone un servidor SSE que se conecta a un servidor stdio local.

Esto permite conexiones remotas al servidor stdio local. El mcp-proxy abre un puerto para escuchar solicitudes SSE, y lanza un servidor stdio local que maneja las solicitudes MCP.

graph LR
    A["LLM Client"] <-->|SSE| B["mcp-proxy"]
    B <-->|stdio| C["Local MCP Server"]

    style A fill:#ffe6f9,stroke:#333,color:black,stroke-width:2px
    style B fill:#e6e6ff,stroke:#333,color:black,stroke-width:2px
    style C fill:#e6ffe6,stroke:#333,color:black,stroke-width:2px

2.1 Configuración

Este modo requiere que se establezca el argumento --sse-port. El argumento --sse-host puede establecerse para especificar la dirección IP del host en la que el servidor SSE escuchará. Se pueden pasar variables de entorno adicionales al servidor stdio local usando el argumento --env. Los argumentos de línea de comandos para el servidor stdio local deben pasarse después del separador --.

Argumentos

NombreRequeridoDescripciónEjemplo
command_or_urlEl comando para lanzar el servidor MCP stdiouvx mcp-server-fetch
--portNo, aleatorio disponibleEl puerto del servidor MCP en el que escuchar8080
--hostNo, 127.0.0.1 por defectoLa dirección IP del host en la que el servidor MCP escuchará0.0.0.0
--envNoVariables de entorno adicionales para pasar al servidor MCP stdio. Se puede usar varias veces.FOO BAR
--cwdNoEl directorio de trabajo para pasar al proceso del servidor MCP stdio./tmp
--pass-environmentNoPasar todas las variables de entorno al lanzar el servidor--no-pass-environment
--allow-originNoOrígenes permitidos para el servidor SSE. Se puede usar varias veces. Por defecto no se permite CORS.--allow-origin "*"
--expose-headerNoCabeceras añadidas a Access-Control-Expose-Headers. Se puede usar varias veces. Por defecto a mcp-session-id.--expose-header Custom-Header
--statelessNoHabilitar el modo sin estado para transportes streamable http. Por defecto es False--no-stateless
--named-server NAME COMMAND_STRINGNoDefine un servidor stdio con nombre.--named-server fetch 'uvx mcp-server-fetch'
--named-server-config FILE_PATHNoRuta a un archivo JSON que define servidores stdio con nombre.--named-server-config /path/to/servers.json
--sse-port (obsoleto)No, aleatorio disponibleEl puerto del servidor SSE en el que escuchar8080
--sse-host (obsoleto)No, 127.0.0.1 por defectoLa dirección IP del host en la que el servidor SSE escuchará0.0.0.0

2.2 Ejemplo de uso

Para iniciar el servidor mcp-proxy que escucha en el puerto 8080 y se conecta al servidor MCP local:

# Start the MCP server behind the proxy
mcp-proxy uvx mcp-server-fetch

# Start the MCP server behind the proxy with a custom port
# (deprecated) mcp-proxy --sse-port=8080 uvx mcp-server-fetch
mcp-proxy --port=8080 uvx mcp-server-fetch

# Start the MCP server behind the proxy with a custom host and port
# (deprecated) mcp-proxy --sse-host=0.0.0.0 --sse-port=8080 uvx mcp-server-fetch
mcp-proxy --host=0.0.0.0 --port=8080 uvx mcp-server-fetch

# Start the MCP server behind the proxy with a custom user agent
# Note that the `--` separator is used to separate the `mcp-proxy` arguments from the `mcp-server-fetch` arguments
# (deprecated) mcp-proxy --sse-port=8080 -- uvx mcp-server-fetch --user-agent=YourUserAgent
mcp-proxy --port=8080 -- uvx mcp-server-fetch --user-agent=YourUserAgent

# Start multiple named MCP servers behind the proxy
mcp-proxy --port=8080 --named-server fetch 'uvx mcp-server-fetch' --named-server fetch2 'uvx mcp-server-fetch'

# Start multiple named MCP servers using a configuration file
mcp-proxy --port=8080 --named-server-config ./servers.json

# Start the MCP server with CORS enabled and custom exposed headers
mcp-proxy --port=8080 --allow-origin='*' --expose-header Custom-Header uvx mcp-server-fetch

Servidores con nombre

  • NAME se usa en la ruta URL /servers/NAME/.
  • COMMAND_STRING es el comando para iniciar el servidor (por ejemplo, 'uvx mcp-server-fetch').
    • Se puede usar varias veces.
    • Este argumento se ignora si se usa --named-server-config.
  • FILE_PATH - Si se proporciona, esta es la fuente exclusiva para servidores con nombre, y los argumentos CLI --named-server se ignoran.

Si se especifica un servidor predeterminado (el argumento command_or_url sin --named-server o --named-server-config), será accesible en las rutas raíz (por ejemplo, http://127.0.0.1:8080/sse).

Los servidores con nombre (ya sea definidos por --named-server o --named-server-config) serán accesibles bajo /servers/<server-name>/ (por ejemplo, http://127.0.0.1:8080/servers/fetch1/sse). El endpoint /status proporciona el estado global.

Formato de archivo de configuración JSON para --named-server-config:

El archivo JSON debe seguir esta estructura:

{
  "mcpServers": {
    "fetch": {
      "disabled": false,
      "timeout": 60,
      "command": "uvx",
      "args": [
        "mcp-server-fetch"
      ],
      "transportType": "stdio"
    },
    "github": {
      "timeout": 60,
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-github"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      },
      "transportType": "stdio"
    }
  }
}
  • mcpServers: Un diccionario donde cada clave es el nombre del servidor (usado en la ruta URL, por ejemplo, /servers/fetch/) y el valor es un objeto que define el servidor.
  • command: (Requerido) El comando a ejecutar para el servidor stdio.
  • args: (Opcional) Una lista de argumentos para el comando. Por defecto es una lista vacía.
  • enabled: (Opcional) Si false, esta definición de servidor se omitirá. Por defecto es true.
  • timeout y transportType: Estos campos están presentes en las configuraciones estándar de clientes MCP, pero actualmente son ignorados por mcp-proxy al cargar servidores con nombre. El tipo de transporte es implícitamente "stdio".

Instalación

Instalación mediante PyPI

La versión estable del paquete está disponible en el repositorio de PyPI. Puedes instalarlo usando el siguiente comando:

# Option 1: With uv (recommended)
uv tool install mcp-proxy

# Option 2: With pipx (alternative)
pipx install mcp-proxy

Una vez instalado, puedes ejecutar el servidor usando el comando mcp-proxy. Consulta las opciones de configuración para cada modo anterior.

Instalación mediante el repositorio de GitHub (última versión)

La última versión del paquete se puede instalar desde el repositorio git usando el siguiente comando:

uv tool install git+https://github.com/sparfenyuk/mcp-proxy

[!NOTE] Si ya has instalado el servidor, puedes actualizarlo usando el comando uv tool upgrade --reinstall.

[!NOTE] Si quieres eliminar el servidor, usa el comando uv tool uninstall mcp-proxy.

Instalación como contenedor

A partir de la versión 0.3.2, es posible extraer y ejecutar la imagen de contenedor correspondiente. Las imágenes de lanzamiento se publican en GHCR y Docker Hub como manifiestos multi-plataforma para linux/amd64 y linux/arm64; Docker selecciona automáticamente la imagen adecuada para la arquitectura del host.

docker run --rm -t ghcr.io/sparfenyuk/mcp-proxy:v0.12.0 --help
docker run --rm -t sparfenyuk/mcp-proxy:v0.12.0 --help

Solución de problemas

  • Problema: Claude Desktop no puede iniciar el servidor: código ENOENT en los registros

    Solución: Intenta usar la ruta completa al binario. Para ello, abre una terminal y ejecuta el comando which mcp-proxy (macOS, Linux) o where.exe mcp-proxy (Windows). Luego, usa la ruta de salida como valor para el atributo 'command':

      "fetch": {
        "command": "/full/path/to/bin/mcp-proxy",
        "args": [
          "http://localhost:8932/sse"
        ]
      }
    

Extender la imagen del contenedor

Puedes extender la imagen del contenedor mcp-proxy para incluir ejecutables adicionales. Por ejemplo, uv no está incluido por defecto, pero puedes crear una imagen personalizada con él:

# file: mcp-proxy.Dockerfile

FROM ghcr.io/sparfenyuk/mcp-proxy:latest

# Install the 'uv' package
RUN python3 -m ensurepip && pip install --no-cache-dir uv

ENV PATH="/usr/local/bin:$PATH" \
    UV_PYTHON_PREFERENCE=only-system

ENTRYPOINT ["catatonit", "--", "mcp-proxy"]

Configuración de Docker Compose

Con el Dockerfile personalizado, puedes definir un servicio en tu archivo de Docker Compose:

services:
  mcp-proxy-custom:
    build:
      context: .
      dockerfile: mcp-proxy.Dockerfile
    network_mode: host
    restart: unless-stopped
    ports:
      - 8096:8096
    command: "--pass-environment --port=8096 --sse-host 0.0.0.0 uvx mcp-server-fetch"

[!NOTE] No olvides establecer el argumento --pass-environment, de lo contrario terminarás con el error "No interpreter found in managed installations or search path"

Argumentos de línea de comandos

usage: mcp-proxy [-h] [--version] [-H KEY VALUE]
                 [--transport {sse,streamablehttp}] [--verify-ssl [VALUE]]
                 [--no-verify-ssl] [-e KEY VALUE] [--cwd CWD]
                 [--client-id CLIENT_ID] [--client-secret CLIENT_SECRET] [--token-url TOKEN_URL]
                 [--pass-environment | --no-pass-environment]
                 [--log-level LEVEL] [--debug | --no-debug]
                 [--named-server NAME COMMAND_STRING]
                 [--named-server-config FILE_PATH] [--port PORT] [--host HOST]
                 [--stateless | --no-stateless] [--sse-port SSE_PORT]
                 [--sse-host SSE_HOST]
                 [--allow-origin ALLOW_ORIGIN [ALLOW_ORIGIN ...]]
                 [--expose-header HEADER]
                 [command_or_url] [args ...]

Start the MCP proxy in one of two possible modes: as a client or a server.

positional arguments:
  command_or_url        Command or URL to connect to. When a URL, will run an SSE/StreamableHTTP client. Otherwise, if --named-server is not used, this will be the command for the default stdio client. If --named-server is used, this argument is ignored for stdio mode unless no default server is desired. See corresponding options for more details.

options:
  -h, --help            show this help message and exit
  --version             Show the version and exit

SSE/StreamableHTTP client options:
  -H, --headers KEY VALUE
                        Headers to pass to the SSE server. Can be used multiple times.
  --transport {sse,streamablehttp}
                        The transport to use for the client. Default is SSE.
  --verify-ssl [VALUE]  Control SSL verification when acting as a client. Use without a value to force verification, pass 'false' to disable, or provide a path to a PEM bundle.
  --no-verify-ssl       Disable SSL verification (alias for --verify-ssl false).
  --client-id CLIENT_ID
                        OAuth2 client ID for authentication
  --client-secret CLIENT_SECRET
                        OAuth2 client secret for authentication
  --token-url TOKEN_URL
                        OAuth2 token URL for authentication

stdio client options:
  args                  Any extra arguments to the command to spawn the default server. Ignored if only named servers are defined.
  -e, --env KEY VALUE   Environment variables used when spawning the default server. Can be used multiple times. For named servers, environment is inherited or passed via --pass-environment.
  --cwd CWD             The working directory to use when spawning the default server process. Named servers inherit the proxy's CWD.
  --pass-environment, --no-pass-environment
                        Pass through all environment variables when spawning all server processes.
  --log-level LEVEL     Set the log level. Default is INFO.
  --debug, --no-debug   Enable debug mode with detailed logging output. Equivalent to --log-level DEBUG. If both --debug and --log-level are provided, --debug takes precedence.
  --named-server NAME COMMAND_STRING
                        Define a named stdio server. NAME is for the URL path /servers/NAME/. COMMAND_STRING is a single string with the command and its arguments (e.g., 'uvx mcp-server-fetch --timeout 10'). These servers inherit the proxy's CWD and environment from --pass-environment.
  --named-server-config FILE_PATH
                        Path to a JSON configuration file for named stdio servers. If provided, this will be the exclusive source for named server definitions, and any --named-server CLI arguments will be ignored.

SSE server options:
  --port PORT           Port to expose an SSE server on. Default is a random port
  --host HOST           Host to expose an SSE server on. Default is 127.0.0.1
  --stateless, --no-stateless
                        Enable stateless mode for streamable http transports. Default is False
  --sse-port SSE_PORT   (deprecated) Same as --port
  --sse-host SSE_HOST   (deprecated) Same as --host
  --allow-origin ALLOW_ORIGIN [ALLOW_ORIGIN ...]
                        Allowed origins for the SSE server. Can be used multiple times. Default is no CORS allowed.
  --expose-header HEADER
                        Headers to expose via Access-Control-Expose-Headers. Defaults to 'Mcp-Session-Id'. Can be used multiple times.

Examples:
  mcp-proxy http://localhost:8080/sse
  mcp-proxy --no-verify-ssl https://server.local/sse
  mcp-proxy --transport streamablehttp http://localhost:8080/mcp
  mcp-proxy --headers Authorization 'Bearer YOUR_TOKEN' http://localhost:8080/sse
  mcp-proxy --client-id CLIENT_ID --client-secret CLIENT_SECRET --token-url https://auth.example.com/token http://localhost:8080/sse
  mcp-proxy --port 8080 -- your-command --arg1 value1 --arg2 value2
  mcp-proxy --named-server fetch 'uvx mcp-server-fetch' --port 8080
  mcp-proxy your-command --port 8080 -e KEY VALUE -e ANOTHER_KEY ANOTHER_VALUE
  mcp-proxy your-command --port 8080 --allow-origin='*'
  mcp-proxy your-command --port 8080 --allow-origin='*' --expose-header Custom-Header

Ejemplo de archivo de configuración

{
  "mcpServers": {
    "fetch": {
      "enabled": true,
      "timeout": 60,
      "command": "uvx",
      "args": [
        "mcp-server-fetch"
      ],
      "transportType": "stdio"
    },
    "github": {
      "timeout": 60,
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-github"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      },
      "transportType": "stdio"
    }
  }
}

Pruebas

Comprueba el servidor mcp-proxy ejecutándolo con el servidor mcp-server-fetch. Puedes usar la herramienta de inspección para probar el servidor de destino.

# Run the stdio server called mcp-server-fetch behind the proxy over SSE
mcp-proxy --port=8080 uvx mcp-server-fetch &

# Connect to the SSE proxy server spawned above using another instance of mcp-proxy given the URL of the SSE server
mcp-proxy http://127.0.0.1:8080/sse

# Send CTRL+C to stop the second server

# Bring the first server to the foreground
fg

# Send CTRL+C to stop the first server