Skip to content

A lightweight MCP server which connects to other MCP servers, handles OAUTH, and intelligently exposes the correct tools to the client.

License

Notifications You must be signed in to change notification settings

BlueprintLabIO/mcp-switch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MCP Switch (OAuth Supported!)

A lightweight MCP router that connects AI tools (Claude Desktop, Cursor, VS Code) to other MCP servers. It handles OAuth locally and forwards requests to downstream MCPs. It does NOT implement API-specific MCP tool wrappers itself.

Scope clarification: This project’s responsibility is routing and auth. If you need API-specific tools (e.g., Gmail, Calendar, GitHub issues), run those as separate MCP servers and point mcp-switch at them. Avoid adding direct API wrappers here to prevent duplication and scope creep.

πŸš€ Quick Start

# 1. Clone and install
git clone https://github.com/BlueprintDesignLab/mcp-switch
cd mcp-switch
npm install

# 2. Authenticate with providers (opens browser)
npm run auth:google
npm run auth:github
npm run auth:slack

# 3. Start the gateway
npm start
# Server running on http://localhost:8042

# 4. Configure your AI client (see below)

That's it! No OAuth app creation, no credential downloads, no complex configuration.

πŸ“‹ What This Does

  • Single Gateway: Route requests from clients to one or more downstream MCP servers
  • OAuth Automation: Handles token refresh, PKCE flows, provider quirks (for MCPs that require OAuth)
  • Local & Private: All tokens stored encrypted on your machine
  • Multi-Client: Multiple AI clients share the same server instance
  • Out of scope: Implementing API-specific MCP tools; build or reuse dedicated MCP servers for that purpose
Claude Desktop ──┐
                 β”œβ”€β”€ HTTP ──▢ MCP Switch (this repo) ──▢ Downstream MCP servers
VS Code      ─────                 (localhost:8042)       (e.g., Gmail MCP, GitHub MCP)
                 β”‚
Cursor       β”€β”€β”€β”€β”˜

πŸ“¦ Dependencies

Core Dependencies

{
  "@modelcontextprotocol/sdk": "^1.0.0",
  "express": "^4.18.0",
  "googleapis": "^131.0.0",
  "@octokit/rest": "^20.0.0",
  "@slack/web-api": "^7.0.0",
  "@notionhq/client": "^2.2.0",
  "open": "^10.0.0"
}

Pre-registered OAuth Apps

  • Google: Calendar, Gmail, Drive APIs (read-only by default)
  • GitHub: Repositories, Issues, Profile (public data + authorized private)
  • Slack: Channels, Messages, Files (workspace you authorize)
  • Notion: Databases, Pages (pages you share with the integration)

System Requirements

  • Node.js 18+ (for ES modules and native fetch)
  • macOS/Linux/Windows (cross-platform)
  • Port 8042 available (configurable)

πŸ”§ Installation

1. Provider Authentication (if a downstream MCP needs OAuth)

Use the included auth scripts only to obtain local tokens required to reach downstream MCP servers that rely on OAuth. Do not add direct API functionality here.

Google

npm run auth:google
# Opens browser β†’ Sign in β†’ Allow permissions β†’ Done!

GitHub

npm run auth:github  
# Opens browser β†’ Sign in β†’ Allow permissions β†’ Done!

If a provider’s functionality is desired, run or install its dedicated MCP server and configure mcp-switch to route to it.

2. Client Configuration

Claude Desktop

// ~/.config/claude-desktop/config.json
{
  "mcpServers": {
    "oauth-gateway": {
      "url": "http://localhost:8042"
    }
  }
}

VS Code / Cursor

// settings.json
{
  "mcp.servers": {
    "oauth-gateway": {
      "url": "http://localhost:8042"
    }
  }
}

πŸ” Security Architecture

Threat Model

  • Asset: OAuth access/refresh tokens for your connected services
  • Boundary: Your local machine (trusted environment)
  • Risks: Token theft via malware, accidental exposure, token replay

Security Controls

1. Token Encryption (AES-256-GCM)

// tokens.json is encrypted at rest
{
  "google": {
    "encrypted": "a1b2c3d4...",
    "iv": "random_iv",
    "authTag": "auth_tag"
  }
}

2. PKCE for All OAuth Flows

// RFC 7636 - prevents authorization code interception
const codeChallenge = crypto
  .createHash('sha256')
  .update(randomCodeVerifier)
  .digest('base64url');

3. Minimal Scopes

// Request only necessary permissions
const googleScopes = [
  'https://www.googleapis.com/auth/calendar.readonly',
  'https://www.googleapis.com/auth/drive.readonly'
  // NO write permissions by default
];

4. Token Auto-Refresh

// Refresh tokens before expiry
if (token.expires_at - Date.now() < 5 * 60 * 1000) {
  await refreshToken();
}

Security Best Practices

File Permissions

chmod 600 tokens.json        # Owner read/write only
chmod 700 config/            # Owner access only

Environment Variables

# Never commit secrets to git
echo "tokens.json" >> .gitignore
echo ".env" >> .gitignore

🚨 Common Issues

Server Issues

# Port 8042 already in use
# Fix: Use different port
PORT=8043 npm start

# Server won't start
# Check: Node.js version
node --version  # Should be 18+

OAuth Errors

# "Browser didn't open"
# Fix: Manual browser navigation
npm run auth:google --manual

# "Token expired"  
# Fix: Re-authenticate with provider
npm run auth:google

MCP Connection Issues

# Claude can't connect
# Check: Server is running
curl http://localhost:8042/health

# Should return: {"status": "ok"}

πŸ” How It Works

Architecture

MCP Client ──HTTP/SSE──▢ MCP Switch (router) ──HTTP/SSE──▢ Downstream MCP servers
(Claude/Cursor/VS Code)      (Express)                 (e.g., Gmail MCP, GitHub MCP)

Request Flow

  1. MCP Client calls tool via HTTP POST to /message
  2. Gateway validates request and checks tokens
  3. OAuth Logic refreshes expired tokens automatically
  4. Provider API called with valid Bearer token
  5. Response streamed back via Server-Sent Events

Token Flow

  1. Initial Auth: User runs npm run auth:google β†’ browser OAuth flow
  2. Token Storage: Access/refresh tokens encrypted locally
  3. Auto-Refresh: Tokens refreshed automatically before expiry
  4. Shared Instance: All MCP clients use same server and tokens

πŸ“š Development

Project Structure

src/
β”œβ”€β”€ server.js           # Express server + MCP SSE transport
β”œβ”€β”€ providers/
β”‚   β”œβ”€β”€ google.js       # Google OAuth + API integration
β”‚   β”œβ”€β”€ github.js       # GitHub OAuth + API integration  
β”‚   └── base.js         # Shared provider interface
β”œβ”€β”€ oauth/
β”‚   β”œβ”€β”€ manager.js      # OAuth flow orchestration
β”‚   β”œβ”€β”€ storage.js      # Encrypted token storage
β”‚   └── pkce.js         # PKCE implementation
└── tools/
    └── registry.js     # MCP tool registration

Development Commands

npm start               # Start server (production)
npm run dev             # Start with hot reload
npm run test            # Run test suite

Adding New Destinations

  • Add routing targets for downstream MCP servers; do not add direct API wrappers.
  • Expose configuration to map tool namespaces to external MCP endpoints.
  • Keep OAuth handling limited to what’s required to reach those MCPs.

πŸ“œ License

MIT License - see LICENSE for details.

🀝 Contributing

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/new-provider
  3. Add tests: npm run test
  4. Submit pull request

⚠️ Disclaimer

This is a development tool for personal use. Review the code before using with sensitive data. Each OAuth provider has its own terms of service that you must follow.

About

A lightweight MCP server which connects to other MCP servers, handles OAUTH, and intelligently exposes the correct tools to the client.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published