Skip to content

Commit 35b5f99

Browse files
committed
feat: support proxying multiple MCP stdio servers to SSE
1 parent 774b4aa commit 35b5f99

File tree

6 files changed

+698
-160
lines changed

6 files changed

+698
-160
lines changed

README.md

Lines changed: 116 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@
77
[![smithery badge](https://smithery.ai/badge/mcp-proxy)](https://smithery.ai/server/mcp-proxy)
88

99
- [mcp-proxy](#mcp-proxy)
10-
- [About](#about)
11-
- [1. stdio to SSE/StreamableHttp](#1-stdio-to-sse)
12-
- [1.1 Configuration](#11-configuration)
13-
- [1.2 Example usage](#12-example-usage)
14-
- [2. SSE to stdio](#2-sse-to-stdio)
15-
- [2.1 Configuration](#21-configuration)
16-
- [2.2 Example usage](#22-example-usage)
17-
- [Installation](#installation)
18-
- [Installing via Smithery](#installing-via-smithery)
19-
- [Installing via PyPI](#installing-via-pypi)
20-
- [Installing via Github repository (latest)](#installing-via-github-repository-latest)
21-
- [Installing as container](#installing-as-container)
22-
- [Troubleshooting](#troubleshooting)
23-
- [Extending the container image](#extending-the-container-image)
24-
- [Docker Compose Setup](#docker-compose-setup)
25-
- [Command line arguments](#command-line-arguments)
26-
- [Testing](#testing)
10+
- [About](#about)
11+
- [1. stdio to SSE/StreamableHTTP](#1-stdio-to-ssestreamablehttp)
12+
- [1.1 Configuration](#11-configuration)
13+
- [1.2 Example usage](#12-example-usage)
14+
- [2. SSE to stdio](#2-sse-to-stdio)
15+
- [2.1 Configuration](#21-configuration)
16+
- [2.2 Example usage](#22-example-usage)
17+
- [Installation](#installation)
18+
- [Installing via Smithery](#installing-via-smithery)
19+
- [Installing via PyPI](#installing-via-pypi)
20+
- [Installing via Github repository (latest)](#installing-via-github-repository-latest)
21+
- [Installing as container](#installing-as-container)
22+
- [Troubleshooting](#troubleshooting)
23+
- [Extending the container image](#extending-the-container-image)
24+
- [Docker Compose Setup](#docker-compose-setup)
25+
- [Command line arguments](#command-line-arguments)
26+
- [Example config file](#example-config-file)
27+
- [Testing](#testing)
2728

2829
## About
2930

@@ -124,6 +125,8 @@ Arguments
124125
| `--pass-environment` | No | Pass through all environment variables when spawning the server | --no-pass-environment |
125126
| `--allow-origin` | No | Allowed origins for the SSE server. Can be used multiple times. Default is no CORS allowed. | --allow-cors "\*" |
126127
| `--stateless` | No | Enable stateless mode for streamable http transports. Default is False | --no-stateless |
128+
| `--named-server NAME COMMAND_STRING` | No | Defines a named stdio server. `NAME` is used in the URL path `/servers/NAME/`. `COMMAND_STRING` is the command to start the server (e.g., 'uvx mcp-server-fetch'). Can be used multiple times. This argument is ignored if `--named-server-config` is used. | --named-server myfetch 'uvx mcp-server-fetch' |
129+
| `--named-server-config FILE_PATH` | No | Path to a JSON file defining named stdio servers. If provided, this is the exclusive source for named servers, and `--named-server` CLI arguments are ignored. See format below. | --named-server-config /path/to/servers.json |
127130
| `--sse-port` (deprecated) | No, random available | The SSE server port to listen on | 8080 |
128131
| `--sse-host` (deprecated) | No, `127.0.0.1` by default | The host IP address that the SSE server will listen on | 0.0.0.0 |
129132

@@ -147,10 +150,52 @@ mcp-proxy --host=0.0.0.0 --port=8080 uvx mcp-server-fetch
147150
# Note that the `--` separator is used to separate the `mcp-proxy` arguments from the `mcp-server-fetch` arguments
148151
# (deprecated) mcp-proxy --sse-port=8080 -- uvx mcp-server-fetch --user-agent=YourUserAgent
149152
mcp-proxy --port=8080 -- uvx mcp-server-fetch --user-agent=YourUserAgent
153+
154+
# Start multiple named MCP servers behind the proxy
155+
mcp-proxy --port=8080 --named-server fetch 'uvx mcp-server-fetch' --named-server fetch2 'uvx mcp-server-fetch'
156+
157+
# Start multiple named MCP servers using a configuration file
158+
mcp-proxy --port=8080 --named-server-config ./servers.json
159+
```
160+
161+
If a default server is specified (the `command_or_url` argument without `--named-server` or `--named-server-config`), it will be accessible at the root paths (e.g., `http://127.0.0.1:8080/sse`).
162+
Named servers (whether defined by `--named-server` or `--named-server-config`) will be accessible under `/servers/<server-name>/` (e.g., `http://127.0.0.1:8080/servers/fetch1/sse`).
163+
The `/status` endpoint provides global status.
164+
165+
**JSON Configuration File Format for `--named-server-config`:**
166+
167+
The JSON file should follow this structure:
168+
169+
```json
170+
{
171+
"mcpServers": {
172+
"fetch": {
173+
"disabled": false,
174+
"timeout": 60,
175+
"command": "uvx",
176+
"args": [
177+
"mcp-server-fetch"
178+
],
179+
"transportType": "stdio"
180+
},
181+
"github": {
182+
"timeout": 60,
183+
"command": "npx",
184+
"args": [
185+
"-y",
186+
"@modelcontextprotocol/server-github"
187+
],
188+
"transportType": "stdio"
189+
}
190+
}
191+
}
150192
```
151193

152-
This will start an MCP server that can be connected to at `http://127.0.0.1:8080/sse` via SSE, or
153-
`http://127.0.0.1:8080/mcp/` via StreamableHttp
194+
- `mcpServers`: A dictionary where each key is the server name (used in the URL path, e.g., `/servers/fetch/`) and the value is an object defining the server.
195+
- `command`: (Required) The command to execute for the stdio server.
196+
- `args`: (Optional) A list of arguments for the command. Defaults to an empty list.
197+
- `disabled`: (Optional) If `true`, this server definition will be skipped. Defaults to `false`.
198+
- `timeout` and `transportType`: These fields are present in standard MCP client configurations but are currently **ignored** by `mcp-proxy` when loading named servers. The transport type is implicitly "stdio".
154199

155200
## Installation
156201

@@ -256,15 +301,21 @@ services:
256301
## Command line arguments
257302

258303
```bash
259-
usage: mcp-proxy [-h] [-H KEY VALUE] [-e KEY VALUE] [--cwd CWD] [--pass-environment | --no-pass-environment] [--debug | --no-debug] [--port PORT]
260-
[--host HOST] [--stateless | --no-stateless] [--sse-port SSE_PORT] [--sse-host SSE_HOST]
261-
[--allow-origin ALLOW_ORIGIN [ALLOW_ORIGIN ...]]
304+
usage: mcp-proxy [-h] [-H KEY VALUE] [-e KEY VALUE] [--cwd CWD] [--pass-environment | --no-pass-environment] [--debug | --no-debug]
305+
[--named-server NAME COMMAND_STRING] [--named-server-config FILE_PATH] [--port PORT] [--host HOST]
306+
[--stateless | --no-stateless] [--sse-port SSE_PORT] [--sse-host SSE_HOST] [--allow-origin ALLOW_ORIGIN [ALLOW_ORIGIN ...]]
262307
[command_or_url] [args ...]
263308
264-
Start the MCP proxy in one of two possible modes: as an SSE or stdio client.
309+
Start the MCP proxy.
310+
It can run as an SSE client (connecting to a remote SSE server and exposing stdio).
311+
Or, it can run as an SSE server (connecting to local stdio command(s) and exposing them over SSE).
312+
When running as an SSE server, it can proxy a single default stdio command or multiple named stdio commands (defined via CLI or a config file).
265313
266314
positional arguments:
267-
command_or_url Command or URL to connect to. When a URL, will run an SSE client, otherwise will run the given command and connect as a stdio client. See corresponding options for more details.
315+
command_or_url Command or URL.
316+
If URL (http/https): Runs in SSE client mode.
317+
If command string: Runs in SSE server mode, this is the default stdio server.
318+
If --named-server or --named-server-config is used, this can be omitted if no default server is desired.
268319
269320
options:
270321
-h, --help show this help message and exit
@@ -274,12 +325,16 @@ SSE client options:
274325
Headers to pass to the SSE server. Can be used multiple times.
275326
276327
stdio client options:
277-
args Any extra arguments to the command to spawn the server
278-
-e, --env KEY VALUE Environment variables used when spawning the server. Can be used multiple times.
279-
--cwd CWD The working directory to use when spawning the process.
328+
args Any extra arguments to the command to spawn the default server. Ignored if only named servers are defined.
329+
-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.
330+
--cwd CWD The working directory to use when spawning the default server process. Named servers inherit the proxy's CWD.
280331
--pass-environment, --no-pass-environment
281-
Pass through all environment variables when spawning the server.
332+
Pass through all environment variables when spawning all server processes.
282333
--debug, --no-debug Enable debug mode with detailed logging output.
334+
--named-server NAME COMMAND_STRING
335+
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. Can be specified multiple times. Ignored if --named-server-config is used.
336+
--named-server-config FILE_PATH
337+
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.
283338
284339
SSE server options:
285340
--port PORT Port to expose an SSE server on. Default is a random port
@@ -294,9 +349,39 @@ SSE server options:
294349
Examples:
295350
mcp-proxy http://localhost:8080/sse
296351
mcp-proxy --headers Authorization 'Bearer YOUR_TOKEN' http://localhost:8080/sse
297-
mcp-proxy --port 8080 -- your-command --arg1 value1 --arg2 value2
298-
mcp-proxy your-command --port 8080 -e KEY VALUE -e ANOTHER_KEY ANOTHER_VALUE
299-
mcp-proxy your-command --port 8080 --allow-origin='*'
352+
mcp-proxy --port 8080 -- my-default-command --arg1 value1
353+
mcp-proxy --port 8080 --named-server fetch1 'uvx mcp-server-fetch' --named-server tool2 'my-custom-tool --verbose'
354+
mcp-proxy --port 8080 --named-server-config /path/to/servers.json
355+
mcp-proxy --port 8080 --named-server-config /path/to/servers.json -- my-default-command --arg1
356+
mcp-proxy --port 8080 -e KEY VALUE -e ANOTHER_KEY ANOTHER_VALUE -- my-default-command
357+
mcp-proxy --port 8080 --allow-origin='*' -- my-default-command
358+
```
359+
360+
### Example config file
361+
362+
```json
363+
{
364+
"mcpServers": {
365+
"fetch": {
366+
"disabled": false,
367+
"timeout": 60,
368+
"command": "uvx",
369+
"args": [
370+
"mcp-server-fetch"
371+
],
372+
"transportType": "stdio"
373+
},
374+
"github": {
375+
"timeout": 60,
376+
"command": "npx",
377+
"args": [
378+
"-y",
379+
"@modelcontextprotocol/server-github"
380+
],
381+
"transportType": "stdio"
382+
}
383+
}
384+
}
300385
```
301386

302387
## Testing

config_example.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"mcpServers": {
3+
"fetch": {
4+
"disabled": false,
5+
"timeout": 60,
6+
"command": "uvx",
7+
"args": [
8+
"mcp-server-fetch"
9+
],
10+
"transportType": "stdio"
11+
},
12+
"github": {
13+
"disabled": false,
14+
"timeout": 60,
15+
"command": "npx",
16+
"args": [
17+
"-y",
18+
"@modelcontextprotocol/server-github"
19+
],
20+
"transportType": "stdio"
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)