Skip to main content

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.

Version PyPI License

Python MCP

Claude Code Cursor Codex Windsurf


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 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 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"]
    }
  }
}
Codex OpenAI Codex

Add to your Codex MCP config:

{
  "mcpServers": {
    "router": {
      "command": "uvx",
      "args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
    }
  }
}
Claude Desktop 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 mcpServers entries into mcp-switch.yaml as namespaces, then replace them all with the single router entry above. You go from N server configs to 1.

Windsurf Windsurf

Add to your Windsurf MCP config:

{
  "mcpServers": {
    "router": {
      "command": "uvx",
      "args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
    }
  }
}
Cline Cline

Add to Cline MCP settings:

{
  "mcpServers": {
    "router": {
      "command": "uvx",
      "args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
    }
  }
}
Hermes Hermes

Add to ~/.hermes/config.yaml:

mcp_servers:
  router:
    command: uvx
    args: ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
OpenClaw OpenClaw

Add to your OpenClaw MCP config:

{
  "mcpServers": {
    "router": {
      "command": "uvx",
      "args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
    }
  }
}
VS Code VS Code Copilot

Add to .vscode/mcp.json:

{
  "servers": {
    "router": {
      "command": "uvx",
      "args": ["mcp-switch", "serve", "--config", "~/.config/mcp-switch/config.yaml"]
    }
  }
}
Amazon Q 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: "Query and manage PostgreSQL databases"

  github:
    type: mcp
    command: "npx"
    args: ["-y", "@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)

  1. ./mcp-switch.yaml
  2. ./mcp-switch.yml
  3. ~/.config/mcp-switch/config.yaml
  4. ~/.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_switch-0.1.1.tar.gz (19.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_switch-0.1.1-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file mcp_switch-0.1.1.tar.gz.

File metadata

  • Download URL: mcp_switch-0.1.1.tar.gz
  • Upload date:
  • Size: 19.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for mcp_switch-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7d4a8b72df65e545b4e51b9751fdc32514330a01dc688ed98157eba7a08568a3
MD5 1f81c9626ef8f9a5cbb27ea34cedbb49
BLAKE2b-256 075edb5b30f22b75b7f7ba14b50c276d12424d3dd7f79694b2db2f15cb9dd495

See more details on using hashes here.

File details

Details for the file mcp_switch-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mcp_switch-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for mcp_switch-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 90a5bc155cd8553b847979eb89d2f2b8ab49194992a48779f96c05707ba623db
MD5 87947084b8067b06ea543e87f1fdd7ed
BLAKE2b-256 7c8704b1c4caa004b473e3108211bc2af3935122284e374b1228254f06a6fad7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page