JIT Namespace Loader for AI Agent Tools - an MCP server that proxies other MCP servers and CLI tools with lazy loading
Project description
🔀 mcp-switch
JIT Namespace Loader for AI Agent Tools
Instead of loading 50 tool schemas into context, agents see 3 meta-tools. Load only what you need, when you need it.
The Problem
Every MCP server you add dumps all its tool schemas into the agent's context window at startup:
| Server | Tools |
|---|---|
| PostgreSQL | 5 tools |
| GitHub | 12 tools |
| Slack | 8 tools |
| Docker | 6 tools |
| Kubernetes | 15 tools |
| Total | 46 tool schemas |
46 tool definitions compete for the LLM's attention on every single request - even when the agent is just writing CSS. Attention dilution from irrelevant tools measurably degrades reasoning quality.
Before vs After
- Agent context: [46 tool schemas loaded]
- User: "Fix the CSS padding on the navbar"
- Agent: *wades through postgres, k8s, slack tools to find the right one*
+ Agent context: [3 tool schemas loaded]
+ User: "Fix the CSS padding on the navbar"
+ Agent: *focuses on the task, no irrelevant tools*
+
+ User: "Now check the database for user records"
+ Agent: *calls load_namespace("postgres")*
+ Agent: [3 meta-tools + 5 postgres tools] *queries directly*
How It Works
flowchart TB
Agent["🤖 AI Agent<br/><i>Claude Code / Cursor / Codex / Hermes / OpenClaw</i>"]
subgraph Router["mcp-switch"]
Meta["3 Meta-Tools<br/>list_namespaces · load_namespace · unload_namespace"]
Registry["Registry"]
Meta --> Registry
end
Agent -- "MCP (stdio)" --> Meta
subgraph Backends["Backends (lazy-started on demand)"]
MCP1["🔌 MCP Backend<br/>postgres"]
MCP2["🔌 MCP Backend<br/>github"]
CLI1["⚡ CLI Backend<br/>git, docker, system"]
end
Registry -. "load_namespace('postgres')" .-> MCP1
Registry -. "load_namespace('github')" .-> MCP2
Registry -. "load_namespace('git')" .-> CLI1
MCP1 -- "stdio" --> S1["mcp-server-postgres"]
MCP2 -- "stdio" --> S2["mcp-server-github"]
3 meta-tools give the agent on-demand access to any namespace:
list_namespaces()
-> ["postgres", "github", "docker", "slack", "git"]
load_namespace("postgres")
-> Starts backend, adds tools: postgres__query, postgres__list_tables, ...
-> Sends tools/list_changed notification to client
unload_namespace("postgres")
-> Removes tools, optionally stops backend, frees context
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: Import Your Existing MCP Config
If you already have MCP servers configured in Claude Desktop, Cursor, or VS Code, mcp-switch can import them automatically:
# 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
This creates ~/.config/mcp-switch/config.yaml from your existing setup. No rewriting configs by hand.
Don't have existing MCP servers? Skip to Step 2 and create a config manually - see Configuration.
Step 2: Connect to Your Agent
Pick your agent and add one config block. That's the entire setup.
Claude Code
Option A: One-liner
claude mcp add router -- uvx mcp-switch serve --config ~/.config/mcp-switch/config.yaml
Option B: Project config (.mcp.json)
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Cursor
Add to Cursor Settings > MCP Servers, or create .cursor/mcp.json:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
OpenAI Codex
Add to your Codex MCP config:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Pro tip: Move your existing
mcpServersentries intomcp-switch.yamlas namespaces, then replace them all with the singlerouterentry above. You go from N server configs to 1.
Windsurf
Add to your Windsurf MCP config:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Cline
Add to Cline MCP settings:
{
"mcpServers": {
"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"]
OpenClaw
Add to your OpenClaw MCP config:
{
"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"]
}
}
}
Amazon Q CLI
Add to ~/.aws/amazonq/mcp.json:
{
"mcpServers": {
"router": {
"command": "uvx",
"args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
}
}
}
Any Other 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.
Configuration
Quick Start: Import Existing
uvx mcp-switch init
Auto-detects Claude Desktop, Cursor, VS Code, and Windsurf configs and converts them.
Manual Config
Create ~/.config/mcp-switch/config.yaml:
namespaces:
# Proxy to real MCP servers (lazy startup)
postgres:
type: mcp
command: "uvx mcp-server-postgres"
args: ["--connection-string", "postgresql://localhost/mydb"]
description:***@modelcontextprotocol/server-github"]
description: "Manage GitHub repos, issues, PRs"
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"
# 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"
git_diff:
command: "git diff"
description: "Show unstaged changes"
docker:
type: cli
description: "Docker container management"
tools:
docker_ps:
command: "docker ps --format 'table {{.Names}}\t{{.Status}}'"
description: "List running containers"
docker_logs:
command: "docker logs {container}"
description: "Show container logs"
parameters:
container:
type: string
description: "Container name or ID"
required: true
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
Validate Your Config
uvx mcp-switch validate
uvx mcp-switch list
Namespace Types
mcp - Proxy to MCP Servers
Connects to a real MCP server via stdio. The backend starts lazily when the namespace is first loaded and stops when unloaded.
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}"
cli - Wrap Shell Commands
Turns shell commands into MCP tools. No server process needed. Parameters use {name} template substitution.
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
Example: Agent in Action
User: "Fix the CSS padding on the navbar"
Agent: *3 meta-tools in context, focuses on the task*
User: "Now check the database for user records"
Agent: I'll load the database tools.
-> list_namespaces()
-> ["postgres", "github", "docker", "git"]
-> load_namespace("postgres")
-> 5 tools added: postgres__query, postgres__list_tables, ...
-> postgres__query({"sql": "SELECT * FROM users LIMIT 10"})
-> *returns results*
Agent: Done with the database, freeing context.
-> unload_namespace("postgres")
-> 5 tools removed
License
MIT - 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.1.0.tar.gz.
File metadata
- Download URL: mcp_switch-0.1.0.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fb5f4d3aa7eb9ceccc3e0a609e9fc9fea8b9c3d0d1433af8503044599b10b61
|
|
| MD5 |
2db722a72ed2990a1441d38070cd09c9
|
|
| BLAKE2b-256 |
92d5e3e2131e00d09ae6df2c1e7c4aad900dd7f1bd6d424868604f216765251e
|
File details
Details for the file mcp_switch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_switch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f57aacf500ae0fb7cd81c7b1f188cb4bfb81ceade69ea91837f6e290f850b34c
|
|
| MD5 |
5338e1ee222492a193c32de28a369d92
|
|
| BLAKE2b-256 |
8d5a068fd2ca56a97b5e3e6f5ca4dac431bf863e87969b1101042456c2e7260e
|