Context-saving MCP switchboard for AI agents - lazy-load tools, resources, and prompts only when needed
Project description
Why?
When you connect MCP servers to your AI agent, every tool gets loaded at once - even the ones your agent doesn't need right now.
The more tools an agent sees, the slower and less accurate it gets. It's like giving someone a toolbox with 50 tools when they just need a screwdriver.
mcp-switch fixes this. Your agent starts with just 5 simple tools:
| Tool | What it does |
|---|---|
list_namespaces |
"What tool groups are available?" |
load_namespace |
"Give me the database tools" |
unload_namespace |
"I'm done, put them away" |
load_group |
"Give me all the dev tools at once" |
unload_group |
"Put all the dev tools away" |
When the agent needs database tools, it loads them. When it's done, it puts them back. Clean, fast, focused.
flowchart LR
subgraph before["Without mcp-switch"]
A1["🤖 Agent"] --> T1["46 tools loaded\n(database, GitHub, Slack,\nDocker, K8s...)"]
T1 --> R1["❌ Confused, slow,\npicks wrong tools"]
end
subgraph after["With mcp-switch"]
A2["🤖 Agent"] --> T2["5 meta-tools\n(list, load, unload,\nload_group, unload_group)"]
T2 -->|"load_namespace('postgres')"| T3["+ 5 database tools"]
T3 --> R2["✅ Focused, fast,\nright tool every time"]
T3 -->|"unload_namespace('postgres')"| T2
end
style before fill:#1a1a2e,stroke:#e74c3c,color:#fff
style after fill:#1a1a2e,stroke:#2ecc71,color:#fff
Setup
No Python install needed. Every setup below uses uvx which runs packages on-the-fly (like npx for Python).
Don't have
uvx? Install uv first:curl -LsSf https://astral.sh/uv/install.sh | sh
Step 1: Create Your Config
Option A: Interactive setup wizard
uvx mcp-switch setup
Walks you through adding namespaces, setting auth headers, configuring groups, and writes the config file for you.
Option B: Import from an existing client
# Auto-detect and import from Claude Desktop, Cursor, VS Code, or Windsurf
uvx mcp-switch init
# Or import from a specific config file
uvx mcp-switch init --from ~/.config/claude/claude_desktop_config.json
Option C: Write one manually
Create ~/.config/mcp-switch/config.yaml:
namespaces:
# Proxy to a real MCP server (stdio - starts on demand)
postgres:
type: mcp
command: "uvx mcp-server-postgres"
args: ["--connection-string", "postgresql://localhost/mydb"]
description: "Query and manage PostgreSQL databases"
idle_ttl: 300 # Auto-unload after 5 min of inactivity
# Connect to a remote/hosted MCP server (HTTP)
supabase:
type: http
url: "https://mcp.supabase.com/mcp"
headers:
Authorization: "Bearer ${SUPABASE_TOKEN}"
description: "Supabase database tools"
# Wrap CLI commands as tools (no server needed)
git:
type: cli
description: "Git version control"
tools:
git_status:
command: "git status --porcelain"
description: "Show working tree status"
git_log:
command: "git log --oneline -20"
description: "Show recent commits"
# Groups: load/unload multiple namespaces at once
groups:
dev:
- git
- postgres
Step 2: Verify It Works
# Check config is valid
uvx mcp-switch validate
# Check commands exist, env vars are set
uvx mcp-switch doctor
# Actually connect to each backend and list tools
uvx mcp-switch test
Step 3: Connect to Your Agent
Pick your agent and add one config block. That's the entire setup.
Claude Code
claude mcp add router -- uvx mcp-switch serve --config ~/.config/mcp-switch/config.yaml
Or add to .mcp.json:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Cursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
VS Code Copilot
Add to .vscode/mcp.json:
{
"servers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Hermes
Add to ~/.hermes/config.yaml:
mcp_servers:
router:
command: uvx
args: ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
Or generate it: uvx mcp-switch export hermes
Claude Desktop / Windsurf / Codex / Cline / Amazon Q / Any MCP Client
The pattern is always the same. Point your client at:
- Command:
uvx - Args:
["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
mcp-switch speaks stdio MCP, which every compliant client supports.
Namespace Types
mcp - Local MCP Servers (stdio)
Starts a real MCP server as a subprocess. Lazy-started on first load, stopped on unload.
postgres:
type: mcp
command: "uvx mcp-server-postgres"
args: ["--connection-string", "postgresql://localhost/mydb"]
description: "Query and manage PostgreSQL databases"
env:
DB_PASSWORD: "${DB_PASSWORD}"
idle_ttl: 300 # Auto-unload after 5 min
pinned: true # Never auto-evict
http - Remote MCP Servers
Connects to hosted MCP servers via HTTP. Uses StreamableHTTP with automatic SSE fallback.
supabase:
type: http
url: "https://mcp.supabase.com/mcp"
headers:
Authorization: "Bearer ${SUPABASE_TOKEN}"
description: "Supabase database tools"
idle_ttl: 600
Works with Supabase, Neon, Cloudflare Workers, or any hosted MCP server.
cli - Shell Commands as Tools
Wraps shell commands as MCP tools. No server process needed.
git:
type: cli
description: "Git version control"
tools:
git_status:
command: "git status --porcelain"
description: "Show working tree status"
git_diff:
command: "git diff {file}"
description: "Show changes for a specific file"
parameters:
file:
type: string
description: "File path to diff"
required: true
Features
Groups
Load/unload multiple namespaces in one call:
groups:
dev:
- git
- docker
- system
Agent uses load_group("dev") instead of loading each one individually.
Idle TTL Auto-Unload
Automatically unloads namespaces after a period of inactivity:
postgres:
type: mcp
command: "uvx mcp-server-postgres"
idle_ttl: 300 # 5 minutes
Timer resets on every tool call, resource read, or prompt fetch.
Pinned Namespaces & Load Caps
max_loaded_namespaces: 3 # Global cap
namespaces:
github:
type: mcp
pinned: true # Never auto-evicted when cap is reached
When the cap is hit, the least-recently-used unpinned namespace gets evicted.
Tools, Resources, and Prompts
mcp-switch proxies all three MCP capabilities. When a namespace is loaded, its tools, resources, and prompts all become available. When unloaded, they're all removed.
Export
Generate ready-to-paste config for any client:
uvx mcp-switch export claude-code
uvx mcp-switch export cursor
uvx mcp-switch export vscode
uvx mcp-switch export hermes # YAML output
uvx mcp-switch export generic
Config Reference
Config Locations (checked in order)
./mcp-switch.yaml./mcp-switch.yml~/.config/mcp-switch/config.yaml~/.mcp-switch.yaml
Or explicit: uvx mcp-switch serve --config /path/to/config.yaml
Environment Variables
Use ${VAR_NAME} syntax in config values. mcp-switch expands them at load time:
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"
headers:
Authorization: "Bearer ${SUPABASE_TOKEN}"
mcp-switch doctor will catch empty or missing env vars.
CLI Commands
| Command | What it does |
|---|---|
mcp-switch setup |
Interactive setup wizard |
mcp-switch serve |
Start the MCP server (stdio transport) |
mcp-switch init |
Import existing MCP configs |
mcp-switch validate |
Check config syntax |
mcp-switch doctor |
Check commands, env vars, health |
mcp-switch test [namespace] |
Connect to backends, list tools |
mcp-switch status |
Show config summary |
mcp-switch list |
List all namespaces |
mcp-switch export <client> |
Generate client-specific config |
Troubleshooting
"Command not found" for MCP backends
- Make sure the MCP server package is installed:
uvx mcp-server-postgres --help - Run
mcp-switch doctorto catch missing executables
HTTP backend returns 401/403
- Check your auth token is set: use
${ENV_VAR}syntax and export the variable - Run
mcp-switch test <namespace>to verify connectivity
Env var expansion shows empty values
- Use
${VAR_NAME}syntax (not$VAR_NAME) mcp-switch doctorcatches empty env expansions
Agent ignores or misuses mcp-switch tools
- Make namespace
descriptionfields clear and specific - Keep namespace names short and descriptive
License
MIT - 2026 ZeroWaves - see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_switch-0.4.0.tar.gz.
File metadata
- Download URL: mcp_switch-0.4.0.tar.gz
- Upload date:
- Size: 33.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30958d4576a51a93c0b78f7564d7782e644b14c992224b03b811b9907c14abfb
|
|
| MD5 |
a31d24696cbd37335e21ab53c4ca0cf6
|
|
| BLAKE2b-256 |
77130e7217508fc7e7c75668d4ec812c771362a037265658d123d76721dd50e4
|
Provenance
The following attestation bundles were made for mcp_switch-0.4.0.tar.gz:
Publisher:
publish.yml on Zer0Wav3s/mcp-switch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_switch-0.4.0.tar.gz -
Subject digest:
30958d4576a51a93c0b78f7564d7782e644b14c992224b03b811b9907c14abfb - Sigstore transparency entry: 1314676677
- Sigstore integration time:
-
Permalink:
Zer0Wav3s/mcp-switch@51d755691673152b1b78c10af6bc2469a2a974d3 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/Zer0Wav3s
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51d755691673152b1b78c10af6bc2469a2a974d3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file mcp_switch-0.4.0-py3-none-any.whl.
File metadata
- Download URL: mcp_switch-0.4.0-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
583d53cdf997df29aa771919b44dfedce78e9522df4116ee031960561f04f0aa
|
|
| MD5 |
fba973136cb690fecf32d2198f495ce1
|
|
| BLAKE2b-256 |
8fa71ef54511b244bb166b6184b0e376225699a54be7b95e758163a451d06ce6
|
Provenance
The following attestation bundles were made for mcp_switch-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on Zer0Wav3s/mcp-switch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_switch-0.4.0-py3-none-any.whl -
Subject digest:
583d53cdf997df29aa771919b44dfedce78e9522df4116ee031960561f04f0aa - Sigstore transparency entry: 1314676780
- Sigstore integration time:
-
Permalink:
Zer0Wav3s/mcp-switch@51d755691673152b1b78c10af6bc2469a2a974d3 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/Zer0Wav3s
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51d755691673152b1b78c10af6bc2469a2a974d3 -
Trigger Event:
release
-
Statement type: