Metadata-Version: 2.4
Name: mcp-switch
Version: 0.4.0
Summary: Context-saving MCP switchboard for AI agents - lazy-load tools, resources, and prompts only when needed
Project-URL: Homepage, https://github.com/Zer0Wav3s/mcp-switch
Project-URL: Repository, https://github.com/Zer0Wav3s/mcp-switch
Project-URL: Issues, https://github.com/Zer0Wav3s/mcp-switch/issues
Author: ZeroWaves
License-Expression: MIT
License-File: LICENSE
Keywords: agent,ai,claude-code,codex,cursor,hermes,lazy-loading,mcp,model-context-protocol,namespace,proxy,tools
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Requires-Dist: click>=8.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# 🔀 mcp-switch

**Give your AI agent only the MCP capabilities it needs, right when it needs them.**

[![PyPI](https://img.shields.io/pypi/v/mcp-switch?style=for-the-badge&logo=pypi&logoColor=white&color=3775A9)](https://pypi.org/project/mcp-switch/)
[![License](https://img.shields.io/badge/License-MIT-22C55E?style=for-the-badge)](LICENSE)

</div>

---

## 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.

```mermaid
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](https://docs.astral.sh/uv/getting-started/installation/) first: `curl -LsSf https://astral.sh/uv/install.sh | sh`

### Step 1: Create Your Config

**Option A: Interactive setup wizard**

```bash
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**

```bash
# 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`:

```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

```bash
# 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.

<details>
<summary><strong>Claude Code</strong></summary>

```bash
claude mcp add router -- uvx mcp-switch serve --config ~/.config/mcp-switch/config.yaml
```

Or add to `.mcp.json`:

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

</details>

<details>
<summary><strong>Cursor</strong></summary>

Add to `.cursor/mcp.json`:

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

</details>

<details>
<summary><strong>VS Code Copilot</strong></summary>

Add to `.vscode/mcp.json`:

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

</details>

<details>
<summary><strong>Hermes</strong></summary>

Add to `~/.hermes/config.yaml`:

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

Or generate it: `uvx mcp-switch export hermes`

</details>

<details>
<summary><strong>Claude Desktop / Windsurf / Codex / Cline / Amazon Q / Any MCP Client</strong></summary>

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.

</details>

---

## Namespace Types

### `mcp` - Local MCP Servers (stdio)

Starts a real MCP server as a subprocess. Lazy-started on first load, stopped on unload.

```yaml
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.

```yaml
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.

```yaml
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:

```yaml
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:

```yaml
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

```yaml
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:

```bash
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)

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`

### Environment Variables

Use `${VAR_NAME}` syntax in config values. mcp-switch expands them at load time:

```yaml
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 doctor` to 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 doctor` catches empty env expansions

**Agent ignores or misuses mcp-switch tools**
- Make namespace `description` fields clear and specific
- Keep namespace names short and descriptive

---

## License

MIT - 2026 ZeroWaves - see [LICENSE](LICENSE).

<!-- mcp-name: io.github.Zer0Wav3s/mcp-switch -->
