logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

mcp-protocol-bridge

A utility designed to interface between conventional standard input/output (stdio) mechanisms and the Model Context Protocol (MCP) transport layers utilizing Server-Sent Events (SSE) or Streamable HTTP protocols, enabling bidirectional data flow and inter-process communication.

Author

mcp-protocol-bridge logo

sparfenyuk

MIT License

Quick Info

GitHub GitHub Stars 1820
NPM Weekly Downloads 0
Tools 1
Last Updated 2026-02-19

Tags

streamablehttpproxyhttpmcp proxysse streamablehttpstreamablehttp protocols

mcp-protocol-bridge

GitHub License PyPI - Python Version PyPI - Downloads codecov

Overview

The mcp-protocol-bridge utility serves as a versatile intermediary for adapting MCP communication transports. It supports two principal operational paradigms:

  1. Translating standard I/O streams to remote SSE/StreamableHTTP connections.
  2. Exposing a local stdio MCP server through an externally accessible SSE listener.

1. Stdio to Remote Endpoint Translation

Initiates a proxy process that relays data from the local standard input/output channel to a designated remote MCP Server endpoint configured for SSE or Streamable HTTP.

This capability is crucial for enabling clients, such as Claude Desktop, to interface with external servers using SSE when native support is absent.

graph LR
    A["Client (e.g., Claude Desktop)"] <--> |stdio IPC| B["mcp-protocol-bridge"]
    B <--> |SSE/StreamableHTTP| C["Remote MCP Backend"]

    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 Configuration Parameters

This mode mandates specifying the target MCP Server's SSE endpoint URL as the primary positional argument. If the backend utilizes the Streamable HTTP protocol, this must be explicitly signaled via the --transport=streamablehttp flag.

Arguments

Name Mandatory Description Example
target_endpoint Yes The Uniform Resource Locator (URL) for the MCP server's SSE communication sink. http://example.io/sse
--headers No Custom HTTP headers injected into the connection request destined for the MCP server. Authorization 'Bearer my-secret-access-token'
--transport No Protocol selection for the outbound connection: 'sse' or 'streamablehttp'. Defaults to SSE. streamablehttp

Environment Variables

Name Mandatory Description Example
API_ACCESS_TOKEN No Alternative mechanism to supply the Authorization header: Authorization 'Bearer <API_ACCESS_TOKEN>' YOUR_TOKEN

1.2 Usage Demonstration

Configuration must be set up within the MCP Client application to invoke mcp-protocol-bridge.

For instance, within Claude Desktop's configuration schema:

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

2. Local Endpoint Exposure via SSE

Launches a proxy instance that advertises itself as an SSE server, funneling incoming requests to a locally executed stdio-based MCP server process.

This architecture permits external consumers to interact with a locally running service via HTTP/SSE.

graph LR
    A["Remote LLM Client"] <-->|SSE Request| B["mcp-protocol-bridge"]
    B <-->|stdio Stream| C["Local MCP Server Process"]

    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 Configuration Parameters

Operation in this mode mandates the specification of the port the SSE listener binds to, using the --port argument (or the deprecated --sse-port). The binding interface can be controlled via --host (or --sse-host). Supplementary environment variables for the spawned stdio server are passed using repeated --env flags. Arguments intended for the underlying stdio server must follow the -- delimiter.

Arguments

Name Mandatory Description Example
stdio_command Yes The executable command to initiate the subservient MCP stdio service. uvx mcp-server-fetch
--port No, ephemeral port selected The TCP port number for the external SSE listener. 8080
--host No, bound to 127.0.0.1 The network interface address on which the SSE listener binds. 0.0.0.0
--env No Augments the environment variables available to the spawned child process. Repeatable. FOO BAR
--cwd No Sets the operational directory context for the child process execution. /tmp
--pass-environment No Propagates all host environment variables to the child process. Negated by --no-pass-environment. --no-pass-environment
--allow-origin No Defines CORS policies for incoming SSE connections. Repeatable. Default: no external access. --allow-origin "*"
--stateless No Activates stateless processing for Streamable HTTP interactions. Defaults to False. --no-stateless
--named-server NAME COMMAND_STRING No Registers an auxiliary stdio handler accessible at /servers/NAME/. --named-server fetch 'uvx mcp-server-fetch'
--named-server-config FILE_PATH No Path to a JSON manifest exclusively defining named stdio handlers. --named-server-config /path/to/servers.json
--sse-port (Obsolete) No, ephemeral port selected Alias for --port. 8080
--sse-host (Obsolete) No, bound to 127.0.0.1 Alias for --host. 0.0.0.0

2.2 Usage Demonstration

Launching the bridge to serve a local mcp-server-fetch on TCP port 8080:

# Basic execution (uses default host 127.0.0.1)
mcp-protocol-bridge uvx mcp-server-fetch

# Specify host and port explicitly
mcp-protocol-bridge --host=0.0.0.0 --port=8080 uvx mcp-server-fetch

# Passing arguments to the backend server using the separator
mcp-protocol-bridge --port=8080 -- uvx mcp-server-fetch --client-id=BridgeClient

# Registering and running multiple dedicated backend services
mcp-protocol-bridge --port=8080 --named-server fetch 'uvx mcp-server-fetch' --named-server processor 'my-processor-tool'

# Utilizing a comprehensive JSON configuration file for backend definitions
mcp-protocol-bridge --port=8080 --named-server-config ./service_definitions.json

Named Service Definitions

  • NAME: The identifier used in the service path structure (e.g., accessing the service via http://host:port/servers/NAME/sse).
  • COMMAND_STRING: The complete invocation string for the stdio handler (e.g., 'uvx mcp-server-fetch --option'). Multiple --named-server arguments are processed sequentially. This mechanism is overridden entirely if --named-server-config is present.
  • FILE_PATH: If provided, this JSON file dictates the sole definitions for named handlers; CLI arguments for named servers are ignored.

If a default handler is specified (via the positional argument stdio_command without any named server configuration), it is accessible at the root paths (e.g., http://127.0.0.1:8080/sse).

Named services are reached via the path prefix /servers/<server-name>/ (e.g., http://127.0.0.1:8080/servers/fetch/sse). A global /status endpoint reports on all operational handlers.

JSON Configuration File Schema for --named-server-config:

The file must conform to this structure:

{
  "mcpServers": {
    "fetch_service": {
      "disabled": false,
      "timeout": 60,
      "command": "uvx",
      "args": [
        "mcp-server-fetch"
      ],
      "transportType": "stdio"
    },
    "github_adapter": {
      "timeout": 60,
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-github"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      },
      "transportType": "stdio"
    }
  }
}
  • mcpServers: A map where keys are the server identifiers (used in URL paths) and values define service parameters.
  • command: (Mandatory) The program executable path.
  • args: (Optional) A list of arguments passed to the command. Defaults to an empty list.
  • disabled: (Optional) Boolean; if false, the server definition is skipped. Defaults to true (paradoxically, it defaults to disabled in the structure but enabled via CLI defaults, contextually assume true means 'skip loading this definition').
  • timeout and transportType: Included for structural fidelity with general MCP client configs but are ignored by mcp-protocol-bridge when loading named configurations; transport is always assumed to be 'stdio' linkage.

Acquisition Methods

Installation via PyPI Artifacts

The officially released, stable version resides on the Python Package Index (PyPI).

# Preferred installation method using 'uv'
uv tool install mcp-protocol-bridge

# Alternative installation using 'pipx'
pipx install mcp-protocol-bridge

After installation, invoke using the mcp-protocol-bridge executable name. Refer to the operational modes above for configuration.

Installation from Repository Head

The most recent development version can be sourced directly from the Git repository:

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

[!NOTE] To refresh an existing installation, execute uv tool upgrade --reinstall.

[!NOTE] To completely remove the installed tool, use uv tool uninstall mcp-protocol-bridge.

Containerized Deployment

Since version 0.3.2, a container image is published, enabling deployment via container runtimes:

docker run --rm -t ghcr.io/sparfenyuk/mcp-protocol-bridge:latest-alpine --help

Debugging Common Issues

  • Symptom: Client (e.g., Claude Desktop) reports ENOENT error during server bootstrap.

Remedy: The system cannot locate the executable. Determine the absolute path using shell commands (where mcp-protocol-bridge on Unix-like systems or where.exe mcp-protocol-bridge on Windows). Then, configure the client to use this full path within its server definition: json "fetch_service": { "command": "/absolute/path/to/bin/mcp-protocol-bridge", "args": [ "http://localhost:8932/sse" ] }

Container Image Customization

It is possible to derive a custom container image based on the official release to incorporate supplementary utilities. For instance, if the uv package manager is needed within the container context:

# File: mcp-bridge.Dockerfile

FROM ghcr.io/sparfenyuk/mcp-protocol-bridge:latest-alpine

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

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

ENTRYPOINT ["catatonit", "--", "mcp-protocol-bridge"]

Docker Compose Orchestration

This custom image can then be integrated into a Docker Compose definition:

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

[!NOTE] Ensure --pass-environment is included if the underlying stdio server relies on host environment variables to locate its runtime dependencies, preventing errors like "No interpreter found in managed installations or search path".

Command Line Interface Options

usage: mcp-protocol-bridge [-h] [--version] [-H KEY VALUE] [--transport {sse,streamablehttp}]
                 [-e KEY VALUE] [--cwd CWD]
                 [--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 ...]]
                 [stdio_command] [args ...]

Orchestrates communication between stdio and remote/local MCP transport protocols.

positional arguments:
  stdio_command         The command to launch for the default stdio server if no named servers are active, or the target URL for remote connections. If a URL, runs client mode. Otherwise, this is the default server command.

options:
  -h, --help            Display this comprehensive help summary and terminate.
  --version             Output version information and exit.

Remote Client Configuration:
  -H, --headers KEY VALUE
                        Custom HTTP request headers sent to the remote SSE sink. Repeatable.
  --transport {sse,streamablehttp}
                        Selects the remote protocol type. Default is SSE.

Local Server (stdio) Process Control:
  -e, --env KEY VALUE   Environment variables injected into the spawned default stdio process. Repeatable.
  --cwd CWD             The starting directory context for the default server process.
  --pass-environment, --no-pass-environment
                        Toggle propagation of host environment variables to spawned processes.
  --log-level LEVEL     Set verbosity: DEBUG, INFO (default), WARNING, ERROR.
  --debug, --no-debug   Enables verbose diagnostic logging (equivalent to --log-level DEBUG).
  --named-server NAME COMMAND_STRING
                        Registers a specific stdio backend service accessible via /servers/NAME/.
  --named-server-config FILE_PATH
                        Specifies an exclusive JSON file source for defining all named backend services.

Local SSE Listener Configuration:
  --port PORT           TCP port number for the external SSE listener. Default is dynamically assigned.
  --host HOST           Network interface address for binding the SSE listener. Default is 127.0.0.1.
  --stateless, --no-stateless
                        Enables stateless operation for Streamable HTTP connections. Default False.
  --sse-port SSE_PORT   (Deprecated alias for --port)
  --sse-host SSE_HOST   (Deprecated alias for --host)
  --allow-origin ALLOW_ORIGIN [ALLOW_ORIGIN ...]
                        Whitelist acceptable client origins for CORS. Default: Strict.

Example Invocations:
  mcp-protocol-bridge http://remote.com/events
  mcp-protocol-bridge --port 9000 --allow-origin='*' -- my-stdio-backend --config /etc/config.yaml
  mcp-protocol-bridge --port 8080 --named-server-config ./services.json

Example Configuration File Structure

(This mirrors the JSON structure detailed earlier, confirming the configuration source format.)

Verification Procedures

Test the integrated functionality by routing a known good MCP command through the bridge. The mcp-server-fetch utility serves as an excellent benchmark target.

# 1. Activate the bridge to listen on 8080, spawning mcp-server-fetch locally
mcp-protocol-bridge --port=8080 uvx mcp-server-fetch & # Run in background

# 2. Use a second instance of the bridge in client mode to connect to the spawned SSE service
mcp-protocol-bridge http://127.0.0.1:8080/sse

# 3. Terminate the client instance (second server)
# (Send Ctrl+C)

# 4. Return the primary bridge instance to foreground
fg

# 5. Terminate the primary bridge instance
# (Send Ctrl+C)

WIKIPEDIA: The XMLHttpRequest (XHR) object is a fundamental Application Programming Interface within web browsers, facilitating asynchronous transmission of Hypertext Transfer Protocol (HTTP) requests to a server. Its introduction enabled web applications to update content dynamically without necessitating a full page reload, a core principle underlying Asynchronous JavaScript and XML (Ajax). Before XHR, server interaction relied primarily on traditional form submissions or hyperlink navigation, both resulting in page replacement.

== Chronology == The underlying concept for asynchronous request handling originated with Microsoft developers creating Outlook in 2000. This concept was first materialized in Internet Explorer version 5 (1999), although it employed proprietary COM object instantiation syntax, specifically ActiveXObject("Msxml2.XMLHTTP") and ActiveXObject("Microsoft.XMLHTTP"). By the release of Internet Explorer 7 (2006), the standardized XMLHttpRequest identifier achieved universal adoption across all major browser engines, including Mozilla's Gecko (2002), Apple's Safari 1.2 (2004), and Opera 8.0 (2005).

=== Standardization Efforts === The World Wide Web Consortium (W3C) published the initial Working Draft specification for the XMLHttpRequest object on April 5, 2006. This was succeeded by the Level 2 specification in February 2008, which introduced capabilities for progress monitoring, enabling cross-origin data exchange, and managing binary data streams. Development focus later shifted, and the Level 2 features were integrated back into the primary specification document by late 2011. Responsibility for maintaining the living document, leveraging Web IDL definitions, transitioned to the WHATWG consortium in late 2012.

== Implementation Procedure == Executing a request via XMLHttpRequest generally involves a sequential programming workflow:

  1. Instantiation: Create an instance of the XMLHttpRequest object using its constructor.
  2. Configuration: Invoke the open() method to define the request method (GET, POST, etc.), specify the target Uniform Resource Identifier (URI), and choose between synchronous or asynchronous processing.
  3. Asynchronous Listener: For asynchronous operations, register an event handler function that will be executed upon state transitions.
  4. Transmission: Initiate the actual data transfer by calling the send() method, optionally passing payload data.
  5. Response Handling: Monitor the object's readyState property within the listener. Upon reaching state 4 (DONE), the server response is typically available in responseText or equivalent properties.

Beyond these fundamental steps, XHR offers extensive controls: custom HTTP headers can be prepended; data uploads can occur within the send() payload; responses can be automatically parsed from JSON into usable JavaScript structures; and streaming data can be processed incrementally instead of waiting for completion. Furthermore, operations can be manually terminated or assigned strict timeouts.

== Cross-Domain Access Restrictions ==

See Also

`