mcp-stdio-mux
One shared process per MCP server across every AI agent session, app and profile on your machine.
Open four Claude Code sessions and each one starts its own copy of every stdio
MCP server you configured. Add Codex, Cursor, or a second profile and the copies
multiply. mcp-stdio-mux puts one shared backend behind all of them; each
session reaches it through a 1.2 MB relay instead of a server of its own.
Install
uvx mcp-stdio-mux setup
Setup finds Claude Code (every profile), Claude Desktop, Codex (every profile),
Gemini CLI, Cursor, Windsurf and OpenCode, shows what it will change, and asks
once. It installs itself as a uv tool so your configs point at a path that
stays. Restart your agent sessions afterwards.
Without uv: pipx install mcp-stdio-mux && mcp-stdio-mux setup.
Setup also gives Claude Code and Codex an agent skill, so you can ask an agent to "share my MCP servers" or "share the server I just added".
Measured
Four sessions of one server, every process the sessions caused (relays, daemon,
backend and its children), macOS 27.2 on Apple silicon with 16 GB, three runs on
10 November 2026. The unit is phys_footprint, the "Memory" column of Activity
Monitor.
| Server | Without a mux | With mcp-stdio-mux | Saved |
|---|---|---|---|
| serena (Python) | 679–757 MB | 202–203 MB | 70–73% |
| tilth (Node) | 57 MB | 36 MB | 37% |
Each session's own process drops from 12–94 MB to 1.2 MB. The saving grows with the number of sessions and with how heavy the server is. Reproduce it with any server:
python scripts/benchmark.py --sessions 4 -- tilth --mcp
python scripts/benchmark.py --sessions 4 \
--prefix "mcp-stdio-mux run --domain bench --server tilth" -- tilth --mcp
What setup changes, and what it never touches
- Each local (stdio) server's command in your user-level config files becomes
mcp-stdio-mux run --domain <profile> --server <name> -- <original command>. The original command stays readable after--. - Every file is backed up to
~/.local/state/mcp-stdio-mux/backups/first, written atomically through symlinks with its permissions kept, then read back. - Remote (HTTP or SSE) servers, project
.mcp.jsonfiles, and servers you marknativeare never touched. A file that nothing changes keeps its exact bytes. mcp-stdio-mux undorestores each file's exact bytes when the app has not written to it since setup, and removes only the wrapper when it has.- Running setup a second time changes nothing that is already shared.
Who shares with whom
Two sessions share one backend only when all of these match:
| Part | Where it comes from |
|---|---|
| Domain | The profile name: ~/.claude-work and ~/.codex-work are both work; default profiles are default. |
| Command | The exact backend command and arguments. |
| Credentials | A SHA-256 of the environment variables the config declares. Values are never logged. |
| Workspace | The git root, for servers bound to the directory they start in. |
Differently named profiles never share unless you map them to one domain.
Each backend also gets a scope:
| Scope | When | Backend |
|---|---|---|
global |
Default. | One per signature, started in your home directory. |
workspace |
An argument flag names cwd, project, workspace or root, an argument is ., or the config sets cwd. |
One per signature and git root. |
session |
The first tools/list reply has a tool named like browser, tab, page, navigate, click, screenshot, session, login or logout. |
One per session. |
Until a server is classified, a second session waits (up to 20 seconds), so no session attaches to a stateful server before the mux knows it is one.
Configuration
Optional. ~/.config/mcp-stdio-mux/config.toml:
[profiles]
work = "default" # let the work profile share with the default one
[servers]
my-browser = "session" # by server name or executable name
heavy-indexer = "native" # leave it alone; takes effect on the next setup
Scopes are global, workspace, session and native.
Commands
| Command | What it does |
|---|---|
mcp-stdio-mux status |
Which servers each config shares, and every running backend with its sessions and memory. |
mcp-stdio-mux setup [--dry-run] [--yes] |
Share every stdio server in every detected config. |
mcp-stdio-mux undo [--yes] |
Put every config back and remove the skill. |
mcp-stdio-mux run ... |
What your apps call. You do not run this yourself. |
How it works
- The app starts
mcp-stdio-mux run, a short-lived shim. - The shim finds or starts the daemon for its launch signature (one lock per
signature), passes its stdin and stdout to the daemon over the Unix socket
(
SCM_RIGHTS), and replaces itself with/bin/catnamedmcp-stdio-mux: <server>. That relay is the 1.2 MB the app keeps. - The daemon runs the backend in its own process group. It gives each session's
JSON-RPC ids and progress tokens a private namespace, answers later
initializecalls from the first result, and sends server requests (roots, sampling, elicitation) to a session that supports them. - A session ends when the app closes its stdin, kills the relay, or exits. When
the last session is gone, the daemon waits five minutes, then stops the
backend's whole process group, so
npxchildren do not outlive it.
Sockets live in a directory only you can read ($XDG_RUNTIME_DIR/mcp-stdio-mux
or /tmp/mcp-stdio-mux-<uid>), and a Unix socket cannot be reached from another
machine.
Limits
- macOS and Linux. Windows is not supported.
- A shared backend inherits environment variables the config does not declare from the session that started it. Declare anything that differs.
- A server that keeps per-client state but whose tool names do not show it must
be marked
session. - When a backend crashes, its in-flight requests fail and are not replayed; the next session start launches a new backend.
- An app that dies without being reaped by its parent keeps its session until its relay is killed.
Development
Runtime code is Python 3.11+ standard library only.
PYTHONPATH=src python -m unittest discover -s tests -t .
ruff format --check src tests scripts && ruff check src tests scripts
License
MIT
Metadata
Release files for mcp-stdio-mux 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mcp_stdio_mux-0.1.1.tar.gz | 45.1 kB | With provenance | Details for mcp_stdio_mux-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mcp_stdio_mux-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for mcp_stdio_mux-0.1.1-py3-none-any.whl |
Total release size: 79.9 kB
Release files / mcp_stdio_mux-0.1.1.tar.gz
| Download URL | mcp_stdio_mux-0.1.1.tar.gz |
|---|---|
| Size | 45.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
55537d924d8d0982eba737e7b986d8faf5fd06f93612213d9095e81e242f39fd
|
|
BLAKE2b-256 checksum How to use checksums |
fc9b106d3ed8e59119811ad3076876ae6628208ba034328036c179cc2f947abb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logRelease files / mcp_stdio_mux-0.1.1-py3-none-any.whl
| Download URL | mcp_stdio_mux-0.1.1-py3-none-any.whl |
|---|---|
| Size | 34.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6cc0bbdb876c29a8628dd7b12ba2863e337580ebea8be97e8968547f42c6fc09
|
|
BLAKE2b-256 checksum How to use checksums |
ded8911d6f43a4adf5f5b92b92f1e5c286954f9bf77c9b23fc1ceca5c672a1b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logSecurity for mcp-stdio-mux 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for mcp_stdio_mux-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.