MCP聚合网关

MCP Gateway 是一款生产级联邦网关服务,将多个 MCP(模型上下文协议)服务器聚合到一个带命名空间和认证的统一端点,内置 75 个开箱即用工具,适用于需要为 Claude Desktop 等客户端提供统一、安全、可扩展 MCP 访问的开发与部署场景。

  • by mohandshamada
  • TypeScript
  • 混合部署
  • 4 星标
  • 更新于
在 GitHub 查看 mohandshamada/MCP-GATEWAY

使用说明

MCP Gateway

A production-ready Federated Gateway Service for the Model Context Protocol (MCP) that aggregates multiple MCP servers into a single, namespaced, authenticated endpoint with 75 pre-installed tools ready to use out of the box.


Highlights

  • 75 Tools Pre-installed - 5 MCP servers ready to use immediately
  • Zero Configuration Startup - Just npm install && npm start
  • Caddy Integration - Automatic SSL with Let's Encrypt, reverse proxy
  • OAuth Support - Client ID/Secret authentication for Claude app integration
  • Claude Desktop Ready - Auto-generated configuration for Claude app
  • Ubuntu Server Optimized - Full root access with secure 755 permissions for MCP tools
  • Production Hardened - Circuit breaker, retry logic, health monitoring, graceful degradation
  • Enterprise Features - Request correlation, persistent configuration, comprehensive logging

Pre-installed MCP Servers

Server Tools Description
Filesystem 14 Read/write files, directories, search, file info
Memory 9 Knowledge graph with entities, relations, observations
Sequential Thinking 1 Step-by-step problem solving with branching
Desktop Commander 25 Terminal commands, file editing, process management
Chrome DevTools 29 Browser debugging, performance analysis, network inspection
O'Reilly Learning 5 Access O'Reilly Learning Platform content
AI Unified Memory 8 Shared memory server for Claude, Kimi, Hermes, OpenClaw
Total 91 Ready to use immediately

Quick Start

Complete Installation (Recommended)

The interactive install script handles everything - dependencies, domain setup, OAuth, and SSL:

# Clone and run complete installation
git clone https://github.com/mohandshamada/MCP-Gateway.git
cd MCP-Gateway
sudo ./scripts/install.sh

The install script will:

  • Install Node.js 22+ and system dependencies
  • Install Google Chrome (for Chrome DevTools MCP)
  • Install and configure Caddy with automatic SSL
  • Ask for your domain name
  • Set up OAuth server with your credentials
  • Configure and start all services
  • Print your SSE link and OAuth credentials

Alternative: Step-by-Step Installation

# Clone and run setup
git clone https://github.com/mohandshamada/MCP-Gateway.git
cd MCP-Gateway
sudo ./scripts/setup-ubuntu.sh

This setup script will:

  • Install Node.js 22+ and system dependencies
  • Install all MCP server packages
  • Install Google Chrome (for Chrome DevTools MCP)
  • Create directories with secure 755 permissions
  • Build the gateway
  • Create and enable systemd service

Production Setup with Caddy (SSL + Domain)

For production deployment with HTTPS and domain:

# Set your domain and email
export DOMAIN="mcp.example.com"
export EMAIL="admin@example.com"

# Run setup scripts in order
sudo ./scripts/setup-ubuntu.sh      # System dependencies
sudo ./scripts/setup-caddy.sh       # Caddy reverse proxy
sudo ./scripts/setup-gateway.sh     # MCP Gateway service

The setup scripts will:

  • Install and configure Caddy web server
  • Set up automatic SSL via Let's Encrypt
  • Create systemd services for both Caddy and MCP Gateway
  • Configure proper log directories and permissions

See DEPLOYMENT.md for detailed deployment instructions.

Manual Installation

# Clone repository
git clone https://github.com/mohandshamada/MCP-Gateway.git
cd MCP-Gateway/mcp-gateway

# Install dependencies (includes all MCP servers)
npm install

# Setup MCP directories
npm run setup:mcp

# Build
npm run build

# Start
npm start

Verify Installation

Use the built-in validation script for a comprehensive check:

./scripts/validate-installation.sh

Or use the quick health check:

./scripts/health-check.sh

Verify manually:

# Check health (all 5 servers should be healthy)
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/admin/health

# Expected: {"status":"healthy","servers":{"total":5,"healthy":5,"unhealthy":0}}

# List all 71 tools
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/admin/tools | jq '.data.total'

# Expected: 71

Documentation

For detailed guides, see:


Connect Claude as Remote MCP Server (SSE)

MCP Gateway exposes an SSE (Server-Sent Events) endpoint that allows Claude to connect as a remote MCP server. This gives Claude access to all 71 tools from anywhere.

SSE Endpoint URL

https://your-domain.com/sse

Or for local development:

http://localhost:3000/sse

Step-by-Step: Add to Claude as Remote MCP Server

  1. Get your gateway URL and token

    After running setup, your endpoint will be:

    SSE Endpoint: https://your-domain.com/sse
    API Token: sk-xxxxxxxxxxxxx (from setup or config)
    
  2. Open Claude Desktop Settings

    • Open Claude Desktop application
    • Go to Settings (gear icon)
    • Navigate to Developer > Edit Config
  3. Add the MCP Gateway as Remote Server

    Add this to your claude_desktop_config.json:

    {
      "mcpServers": {
        "mcp-gateway": {
          "url": "https://your-domain.com/sse",
          "transport": "sse",
          "headers": {
            "Authorization": "Bearer YOUR_API_TOKEN"
          }
        }
      }
    }
    
  4. Restart Claude Desktop

    Close and reopen Claude Desktop to load the new MCP server.

  5. Verify Connection

    In Claude, you should now see 71 tools available from the MCP Gateway.

Get Your Configuration Automatically

The gateway provides an API endpoint to generate your Claude configuration:

# Get full configuration with your token embedded
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://your-domain.com/admin/client-config/claude

# Output (ready to use):
{
  "mcpServers": {
    "mcp-gateway": {
      "url": "https://your-domain.com/sse",
      "transport": "sse",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

Test SSE Connection

Before adding to Claude, verify the SSE endpoint works:

# Test SSE connection (should stream events)
curl -N \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: text/event-stream" \
  https://your-domain.com/sse

# Check available tools
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://your-domain.com/admin/tools | jq '.data.total'
# Expected: 71

Configuration File Locations

Platform Config File Path
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json
Linux ~/.config/Claude/claude_desktop_config.json

Example: Complete Configuration

{
  "mcpServers": {
    "mcp-gateway": {
      "url": "https://mcp.example.com/sse",
      "transport": "sse",
      "headers": {
        "Authorization": "Bearer sk-a1b2c3d4e5f6g7h8i9j0..."
      }
    }
  }
}

Troubleshooting Connection

Issue Solution
"Connection refused" Check gateway is running: curl https://your-domain.com/admin/health
"401 Unauthorized" Verify your API token is correct
"SSL certificate error" Ensure Caddy has valid SSL cert, or use HTTP for local dev
"No tools available" Check server health: curl .../admin/servers
"Timeout" SSE needs long-lived connections; check firewall/proxy settings

Claude Desktop Integration

Quick Setup

  1. Run the Caddy setup script to configure your domain:

    sudo ./scripts/setup-caddy.sh
    
  2. Get your client configuration:

    curl -H "Authorization: Bearer YOUR_TOKEN" https://your-domain.com/admin/client-config/claude
    
  3. Add to your Claude Desktop config (claude_desktop_config.json):

    {
      "mcpServers": {
        "mcp-gateway": {
          "url": "https://your-domain.com/sse",
          "transport": "sse",
          "headers": {
            "Authorization": "Bearer YOUR_TOKEN"
          }
        }
      }
    }
    
  4. Restart Claude Desktop

Auto-Generated Configuration

After setup, client configurations are saved to client-configs/:

client-configs/
├── claude-desktop-config.json   # Claude Desktop configuration
├── sse-client-config.json       # Generic SSE client configuration
├── oauth-client-config.json     # OAuth configuration (if enabled)
└── test-connection.sh           # Connection test script

Get Configuration via API

# Full configuration with instructions
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/client-config

# Download Claude Desktop config file directly
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/client-config/claude

Caddy Reverse Proxy Setup

Quick Setup (Recommended)

Use the simplified setup script:

# Set environment variables
export DOMAIN="mcp.example.com"
export EMAIL="admin@example.com"

# Run setup
sudo ./scripts/setup-caddy.sh

The script will:

  • Create caddy system user if needed
  • Install Caddy if not present
  • Set up log directory with proper permissions
  • Set up ACME storage directories for SSL certificates
  • Install and configure Caddyfile from template
  • Validate configuration and start service

Caddyfile Template

The setup uses scripts/Caddyfile.template which includes:

  • Automatic SSL via Let's Encrypt
  • Security headers (X-Frame-Options, XSS protection, etc.)
  • SSE endpoint with streaming support (no timeout)
  • JSON logging with rotation

Advanced Setup

For more comprehensive setups with OAuth and client configuration generation:

sudo ./scripts/caddy-integration.sh

This script provides:

  • Interactive configuration - Prompts for domain, OAuth settings
  • Configuration detection - Reads MCP Gateway settings automatically
  • Client config generation - Creates ready-to-use Claude Desktop configs
  • Testing suite - Runs integration tests after setup

Available Commands

# Interactive setup (default)
sudo ./scripts/caddy-integration.sh

# Check current status
sudo ./scripts/caddy-integration.sh --check

# Run integration tests
sudo ./scripts/caddy-integration.sh --test

# Fix common issues automatically
sudo ./scripts/caddy-integration.sh --fix

# Non-interactive setup (for automation)
sudo MCP_DOMAIN=mcp.example.com ./scripts/caddy-integration.sh --non-interactive

Manual Caddy Configuration

Create /etc/caddy/Caddyfile:

{
    email admin@example.com
}

your-domain.com {
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Referrer-Policy strict-origin-when-cross-origin
        -Server
    }

    # SSE endpoint needs special handling for long-lived connections
    handle /sse* {
        reverse_proxy 127.0.0.1:3000 {
            transport http {
                read_timeout 0
                write_timeout 0
            }
            flush_interval -1
        }
    }

    # All other endpoints
    handle {
        reverse_proxy 127.0.0.1:3000
    }

    log {
        output file /var/log/caddy/mcp-gateway.log {
            roll_size 100mb
            roll_keep 5
        }
        format json
    }
}

Start Caddy:

sudo systemctl enable caddy
sudo systemctl start caddy

OAuth Configuration

MCP Gateway includes a built-in OAuth 2.0 authorization server and also supports connecting to external OAuth providers:

Feature Description
Built-in OAuth Server Issue tokens directly from the gateway - no external provider needed
Gateway OAuth Authenticate clients connecting to the gateway
Server OAuth Authenticate gateway to remote MCP servers

Built-in OAuth Server (Recommended)

The gateway includes a complete OAuth 2.0 authorization server. This is the easiest way to get OAuth working.

Enable the Built-in OAuth Server

Edit config/gateway.json:

{
  "oauthServer": {
    "enabled": true,
    "tokenExpiresIn": 3600,
    "refreshTokenExpiresIn": 86400,
    "clients": [
      {
        "clientId": "mcp-client",
        "clientSecret": "your-secure-secret-here",
        "name": "MCP Gateway Client",
        "scopes": ["mcp:read", "mcp:write", "mcp:admin"],
        "grantTypes": ["client_credentials", "password", "refresh_token"]
      }
    ]
  }
}

Get an OAuth Token

# Using client credentials grant
curl -X POST http://localhost:3000/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=mcp-client" \
  -d "client_secret=your-secure-secret-here"

# Response:
{
  "access_token": "abc123def456...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "mcp:read mcp:write mcp:admin"
}

Ready-to-Use SSE URL with OAuth Token

After getting a token, use it to connect:

# Get token and save it
TOKEN=$(curl -s -X POST http://localhost:3000/oauth/token \
  -d "grant_type=client_credentials" \
  -d "client_id=mcp-client" \
  -d "client_secret=your-secure-secret-here" | jq -r '.access_token')

# Use token to access SSE endpoint
curl -N -H "Authorization: Bearer $TOKEN" http://localhost:3000/sse

# Or with domain
curl -N -H "Authorization: Bearer $TOKEN" https://mcp.example.com/sse

Claude Desktop Configuration with OAuth

{
  "mcpServers": {
    "mcp-gateway": {
      "url": "https://mcp.example.com/sse",
      "transport": "sse",
      "headers": {
        "Authorization": "Bearer YOUR_OAUTH_TOKEN"
      }
    }
  }
}

Built-in OAuth Server Endpoints

Endpoint Method Auth Required Description
POST /oauth/token POST No Get access token
POST /oauth/revoke POST No Revoke a token
POST /oauth/validate POST No Validate a token
GET /.well-known/openid-configuration GET No OAuth discovery
GET /oauth/info GET Yes Server info and stats
POST /oauth/clients POST Yes Register new client
DELETE /oauth/clients/:id DELETE Yes Remove client

Supported Grant Types

Grant Type Use Case Example
client_credentials Server-to-server, API access grant_type=client_credentials
password User login (with username/password) grant_type=password&username=user&password=pass
refresh_token Refresh expired tokens grant_type=refresh_token&refresh_token=xxx

Register a New OAuth Client via API

curl -X POST http://localhost:3000/oauth/clients \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "my-app",
    "clientSecret": "my-app-secret",
    "name": "My Application",
    "scopes": ["mcp:read", "mcp:write"],
    "grantTypes": ["client_credentials"]
  }'

Check OAuth Server Status

curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/oauth/info

# Response:
{
  "enabled": true,
  "stats": {
    "clients": 1,
    "activeTokens": 5,
    "refreshTokens": 2
  },
  "clients": [
    {
      "clientId": "mcp-client",
      "name": "MCP Gateway Client",
      "scopes": ["mcp:read", "mcp:write", "mcp:admin"],
      "grantTypes": ["client_credentials", "password", "refresh_token"]
    }
  ]
}

OAuth Configuration Options

Option Type Default Description
enabled boolean false Enable the built-in OAuth server
issuer string auto OAuth issuer URL (auto-detected from request)
tokenExpiresIn number 3600 Access token lifetime in seconds
refreshTokenExpiresIn number 86400 Refresh token lifetime in seconds
clients array [] Pre-registered OAuth clients

OAuth Client Configuration

Option Type Required Description
clientId string Yes Unique client identifier
clientSecret string Yes Client secret for authentication
name string Yes Human-readable client name
scopes string[] No Allowed scopes (default: all)
grantTypes string[] No Allowed grant types (default: client_credentials)

Quick Start: Test OAuth Server

A standalone test OAuth server is also included for development:

# Start the test OAuth server on port 9000
node scripts/oauth-server.cjs 9000

# Test credentials:
# Client ID: mcp-gateway-client
# Client Secret: mcp-gateway-secret

Get a token:

curl -X POST http://localhost:9000/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=mcp-gateway-client" \
  -d "client_secret=mcp-gateway-secret"

# Response:
# {
#   "access_token": "abc123...",
#   "token_type": "Bearer",
#   "expires_in": 3600,
#   "scope": "mcp:read mcp:write mcp:admin"
# }

Test OAuth server endpoints:

Endpoint Method Description
/oauth/token POST Token endpoint (client_credentials, password, refresh_token)
/.well-known/openid-configuration GET OAuth discovery endpoint
/health GET Health check

Generate Authentication Token

Use the token generator script to create new static tokens:

# Generate token with your domain (adds to config, prints ready URLs)
./scripts/generate-token.sh mcp.example.com

# Output includes:
# - Generated token
# - Ready-to-use SSE URLs with token
# - Claude Desktop config snippet
# - curl test command

Enable Gateway OAuth (External Provider)

For using an external OAuth provider, edit config/gateway.json:

{
  "auth": {
    "enabled": true,
    "tokens": ["your-api-token"],
    "oauth": {
      "enabled": true,
      "clientId": "your-client-id",
      "clientSecret": "your-client-secret",
      "issuer": "https://auth.example.com",
      "authorizationUrl": "https://auth.example.com/authorize",
      "tokenUrl": "https://auth.example.com/token",
      "scopes": ["mcp:read", "mcp:write"]
    }
  }
}

Connect to OAuth-Protected Remote MCP Servers

Configure a remote SSE server that requires OAuth:

{
  "servers": [
    {
      "id": "remote-oauth-server",
      "transport": "sse",
      "url": "https://api.example.com/mcp/sse",
      "oauth": {
        "clientId": "${API_CLIENT_ID}",
        "clientSecret": "${API_CLIENT_SECRET}",
        "tokenUrl": "https://auth.example.com/oauth/token",
        "grantType": "client_credentials",
        "scopes": ["mcp:read", "mcp:write"],
        "audience": "https://api.example.com",
        "refreshBeforeExpiry": 60
      },
      "enabled": true
    }
  ]
}

Set environment variables:

export API_CLIENT_ID="your-client-id"
export API_CLIENT_SECRET="your-client-secret"

Supported OAuth Grant Types

Grant Type Use Case Required Config
client_credentials Server-to-server clientId, clientSecret, tokenUrl
password User credentials + username, password
refresh_token Token refresh Automatic when refresh_token provided

Production OAuth Providers

Auth0 (Recommended for ease of setup)

  1. Create an account at auth0.com
  2. Create an API and Application
  3. Configure:
{
  "oauth": {
    "clientId": "YOUR_AUTH0_CLIENT_ID",
    "clientSecret": "YOUR_AUTH0_CLIENT_SECRET",
    "tokenUrl": "https://YOUR_DOMAIN.auth0.com/oauth/token",
    "audience": "https://your-api.example.com",
    "grantType": "client_credentials"
  }
}

Keycloak (Self-hosted, free)

# Install with Docker
docker run -p 8080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:latest start-dev

# Access: http://localhost:8080
# Create realm, client, and configure:
{
  "oauth": {
    "clientId": "mcp-gateway",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "tokenUrl": "http://localhost:8080/realms/myrealm/protocol/openid-connect/token",
    "grantType": "client_credentials"
  }
}

AWS Cognito

{
  "oauth": {
    "clientId": "YOUR_COGNITO_CLIENT_ID",
    "clientSecret": "YOUR_COGNITO_CLIENT_SECRET",
    "tokenUrl": "https://YOUR_POOL.auth.REGION.amazoncognito.com/oauth2/token",
    "grantType": "client_credentials"
  }
}

OAuth Configuration Options

Option Type Required Description
clientId string Yes OAuth client ID (supports ${ENV_VAR} syntax)
clientSecret string Yes OAuth client secret (supports ${ENV_VAR} syntax)
tokenUrl string Yes Token endpoint URL
grantType string No client_credentials (default), password, refresh_token
scopes string[] No OAuth scopes to request
audience string No API audience (Auth0, etc.)
username string No Username (password grant only)
password string No Password (password grant only)
refreshBeforeExpiry number No Seconds before expiry to refresh (default: 60)

Example OAuth Configuration File

See config/gateway.oauth-example.json for a complete example with:

  • Gateway-level OAuth for client authentication
  • Remote server OAuth configuration
  • Environment variable references

Domain Configuration

{
  "domain": {
    "domain": "mcp.example.com",
    "publicUrl": "https://mcp.example.com",
    "ssl": {
      "enabled": true,
      "email": "admin@example.com"
    },
    "proxy": {
      "enabled": true,
      "type": "caddy"
    }
  }
}

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                              MCP Gateway                                     │
│                                                                              │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐ │
│  │     Auth     │──▶│    Router    │──▶│   Registry   │──▶│   Adapters   │ │
│  │  Middleware  │   │  (Namespace) │   │ (Health/Pool)│   │ (Stdio/SSE)  │ │
│  └──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘ │
│         │                                                         │          │
│         │              ┌──────────────────────────────────────────┤          │
│         │              │                                          │          │
│         ▼              ▼                                          ▼          │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │                        Production Features                               ││
│  │  • Circuit Breaker    • Retry w/ Backoff    • Request Correlation       ││
│  │  • Rate Limiting      • Health Checks       • Graceful Degradation      ││
│  │  • Config Persistence • Permission Mgmt    • Hot Reload                 ││
│  │  • OAuth Support      • Caddy Integration  • Claude App Ready           ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘
                            │
          ┌─────────────────┼─────────────────┐
          │                 │                 │
          ▼                 ▼                 ▼
   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐
   │   Caddy     │   │  Let's      │   │   Claude    │
   │   Proxy     │   │  Encrypt    │   │   Desktop   │
   │   (SSL)     │   │   (SSL)     │   │   (Client)  │
   └─────────────┘   └─────────────┘   └─────────────┘

API Reference

MCP Protocol Endpoints

Endpoint Method Description
/sse GET Server-Sent Events connection for MCP protocol
/message POST JSON-RPC message endpoint (requires X-Session-ID)
/rpc POST Direct JSON-RPC endpoint (stateless)

Admin Endpoints

Endpoint Method Description
/admin/health GET Health check with server status
/admin/status GET Detailed gateway status
/admin/servers GET List all registered servers
/admin/servers POST Register a new server (persisted to config)
/admin/servers/:id GET Get server details with circuit breaker status
/admin/servers/:id DELETE Unregister a server
/admin/servers/:id/restart POST Restart a server
/admin/tools GET List all 71 namespaced tools
/admin/metrics GET Gateway metrics and statistics

Client Configuration Endpoints

Endpoint Method Description
/admin/client-config GET Get full client configuration with instructions
/admin/client-config/claude GET Download Claude Desktop config file

Permission Management Endpoints

Endpoint Method Description
/admin/permissions GET Get current permission status (root/sudo)
/admin/permissions/set POST Set file/directory permissions
/admin/permissions/mkdir POST Create directory with secure 755 permissions
/admin/permissions/exec POST Execute command with elevated privileges

Authentication

All endpoints require Bearer token authentication:

curl -H "Authorization: Bearer YOUR_TOKEN" https://your-domain.com/admin/health

Configuration

Full Configuration Example (config/gateway.json)

{
  "gateway": {
    "host": "0.0.0.0",
    "port": 3000,
    "name": "MCP Gateway",
    "version": "1.0.0"
  },
  "domain": {
    "domain": "mcp.example.com",
    "publicUrl": "https://mcp.example.com",
    "ssl": {
      "enabled": true,
      "email": "admin@example.com"
    },
    "proxy": {
      "enabled": true,
      "type": "caddy"
    }
  },
  "auth": {
    "enabled": true,
    "tokens": ["sk-your-secure-token-here"],
    "oauth": {
      "enabled": false,
      "clientId": null,
      "clientSecret": null
    }
  },
  "servers": [
    {
      "id": "filesystem",
      "transport": "stdio",
      "command": "node",
      "args": ["node_modules/@modelcontextprotocol/server-filesystem/dist/index.js", "/home", "/tmp"],
      "enabled": true,
      "timeout": 60000,
      "maxRetries": 3
    }
  ],
  "settings": {
    "requestTimeout": 120000,
    "enableHealthChecks": true,
    "healthCheckInterval": 30000,
    "enableRateLimiting": true,
    "rateLimit": {
      "windowMs": 60000,
      "maxRequests": 200
    }
  }
}

Server Configuration Options

Option Type Default Description
id string required Unique server ID (used as namespace prefix)
transport string required "stdio" or "sse"
command string - Command to spawn (stdio only)
args string[] [] Command arguments
url string - SSE endpoint URL (sse only)
env object {} Environment variables
enabled boolean true Whether server is enabled
lazyLoad boolean false Start on-demand
timeout number 60000 Request timeout (ms)
maxRetries number 3 Max restart attempts

Environment Variables

# Configuration file path
CONFIG_PATH=/path/to/gateway.json

# Authentication tokens (comma-separated)
MCP_GATEWAY_TOKENS=token1,token2,token3

# Single token
MCP_GATEWAY_TOKEN=your-token

# Node environment
NODE_ENV=production

# Domain (for non-interactive setup)
MCP_DOMAIN=mcp.example.com
MCP_SSL_EMAIL=admin@example.com

# OAuth (for non-interactive setup)
MCP_OAUTH_ENABLED=true
MCP_OAUTH_CLIENT_ID=your-client-id
MCP_OAUTH_CLIENT_SECRET=your-client-secret
MCP_OAUTH_ISSUER=https://auth.example.com

Tool Namespacing

All tools are automatically namespaced to prevent collisions:

Server Original Tool Namespaced Tool
filesystem read_file filesystem__read_file
memory create_entities memory__create_entities
desktop-commander execute_command desktop-commander__execute_command
chrome-devtools navigate_page chrome-devtools__navigate_page

Example: Call a Namespaced Tool

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "filesystem__read_file",
    "arguments": {
      "path": "/home/user/document.txt"
    }
  }
}

Production Features

Circuit Breaker Pattern

Protects against cascading failures:

States: CLOSED → OPEN → HALF_OPEN → CLOSED

- Failure threshold: 5 consecutive failures
- Recovery timeout: 30 seconds
- Success threshold: 2 successes to close

Check circuit breaker status:

curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/servers/filesystem | jq '.data.circuitBreaker'

Retry Logic with Exponential Backoff

Retry 1: 1000ms + jitter
Retry 2: 2000ms + jitter
Retry 3: 4000ms + jitter
Max delay: 30000ms

Request Correlation

Every request gets a unique ID for tracing:

# Request
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/health

# Response includes x-request-id header
# Logs include requestId for correlation

Persistent Configuration

Server changes via API are automatically saved to disk:

# Register server (automatically saved to gateway.json)
curl -X POST https://your-domain.com/admin/servers \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id": "new-server", "transport": "stdio", "command": "node", "args": ["server.js"]}'

# Server will persist across restarts

Health Monitoring

Use the built-in health check script:

# Run health check (reads token from config automatically)
./scripts/health-check.sh

# With custom domain
./scripts/health-check.sh mcp.example.com

The health check script:

  • Reads auth token from config/gateway.json automatically
  • Tests localhost direct connection
  • Tests HTTPS via Caddy (when domain is configured)
  • Shows status of all registered MCP servers
  • Returns exit code 0 on success, 1 on failure (CI/monitoring friendly)

Or check manually:

# Quick health check
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/health

# Detailed metrics
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/metrics

Ubuntu Server Deployment

Setup Scripts

Run the setup scripts in order for a complete deployment:

# 1. System dependencies (Node.js, Chrome, etc.)
sudo ./scripts/setup-ubuntu.sh

# 2. Caddy reverse proxy (SSL, domain configuration)
export DOMAIN="mcp.example.com"
export EMAIL="admin@example.com"
sudo ./scripts/setup-caddy.sh

# 3. MCP Gateway service (systemd, config validation)
sudo ./scripts/setup-gateway.sh

Systemd Services

Both services are managed via systemd:

# MCP Gateway
sudo systemctl start mcp-gateway
sudo systemctl stop mcp-gateway
sudo systemctl restart mcp-gateway
sudo systemctl status mcp-gateway
sudo journalctl -u mcp-gateway -f

# Caddy
sudo systemctl start caddy
sudo systemctl stop caddy
sudo systemctl restart caddy
sudo systemctl status caddy
sudo journalctl -u caddy -f

Verify Deployment

# Run health check
./scripts/health-check.sh

# Or manually
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/health

File Permissions

The gateway runs with full permissions for MCP tool access:

# Check permission status
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/permissions

# Create directory with secure permissions (755)
curl -X POST https://your-domain.com/admin/permissions/mkdir \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "/opt/data/uploads"}'

# Set permissions
curl -X POST https://your-domain.com/admin/permissions/set \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "/opt/data", "mode": 511, "recursive": true}'

Directory Structure

MCP-GATEWAY/
├── config/
│   ├── gateway.json          # Main configuration
│   └── gateway.example.json  # Example configuration
├── client-configs/           # Generated client configurations
│   ├── claude-desktop-config.json
│   ├── sse-client-config.json
│   └── test-connection.sh
├── dist/                     # Compiled JavaScript
├── docs/                     # Documentation
├── logs/                     # Application logs
├── mcp-data/                 # MCP tool data (755 permissions)
│   ├── data/
│   ├── cache/
│   ├── downloads/
│   ├── screenshots/
│   ├── uploads/
│   └── workspace/
├── node_modules/             # Includes all MCP servers
├── scripts/
│   ├── setup-ubuntu.sh       # System dependencies setup
│   ├── setup-caddy.sh        # Caddy reverse proxy setup
│   ├── setup-gateway.sh      # MCP Gateway service setup
│   ├── health-check.sh       # Health check script (reads token from config)
│   ├── generate-token.sh     # Generate auth tokens with ready-to-use URLs
│   ├── oauth-server.cjs      # Test OAuth authorization server
│   ├── Caddyfile.template    # Caddy configuration template
│   └── caddy-integration.sh  # Advanced Caddy integration with OAuth
├── src/                      # TypeScript source
├── tests/                    # Test files
├── DEPLOYMENT.md             # Quick deployment guide
└── README.md                 # This file

Development

# Install dependencies
npm install

# Development mode with hot reload
npm run dev

# Type checking
npm run typecheck

# Linting
npm run lint
npm run lint:fix

# Run tests
npm test
npm run test:watch
npm run test:coverage

# Build for production
npm run build

Available Tools by Server

Filesystem Server (14 tools)

Tool Description
read_file, read_text_file Read file contents
read_media_file Read images/audio as base64
read_multiple_files Batch file reading
write_file Create/overwrite files
edit_file Line-based file editing
create_directory Create directories
list_directory List directory contents
directory_tree Recursive tree view
move_file Move/rename files
search_files Glob pattern search
get_file_info File metadata
list_allowed_directories Show accessible paths

Memory Server (9 tools)

Tool Description
create_entities Create knowledge graph entities
create_relations Create entity relationships
add_observations Add facts to entities
delete_entities Remove entities
delete_observations Remove observations
delete_relations Remove relationships
read_graph Read entire knowledge graph
search_nodes Search entities
open_nodes Open specific entities

Sequential Thinking (1 tool)

Tool Description
sequentialthinking Step-by-step problem solving with revision and branching

Desktop Commander (25 tools)

Tool Description
execute_command Run shell commands
read_file, write_file File operations
edit_block Surgical text replacement
start_search, stop_search Background file search
list_directory Directory listing
create_directory Create directories
move_file Move/rename files
get_config, set_config_value Configuration management
start_process, interact_with_process Process management
And more...

Chrome DevTools (26 tools)

Tool Description
navigate_page Navigate to URL
take_screenshot Take screenshots
click_element Click elements
type_text Type text into inputs
scroll_page Scroll the page
get_console_messages Get browser console logs
get_network_requests Inspect network requests
run_performance_trace Performance profiling
evaluate_javascript Execute JavaScript
And more...

Troubleshooting

For detailed troubleshooting, see docs/TROUBLESHOOTING.md

Quick Diagnostics

# Run comprehensive validation
./scripts/validate-installation.sh

# Quick health check
./scripts/health-check.sh

# Pre-deployment check
./scripts/pre-deploy-check.sh

SSL Certificate Issues

# Check Caddy logs
sudo journalctl -u caddy -f

# Validate Caddyfile
caddy validate --config /etc/caddy/Caddyfile

# Force certificate renewal
caddy reload --config /etc/caddy/Caddyfile

Servers show unhealthy

# Check individual server status
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/servers/filesystem

# Check circuit breaker state
jq '.data.circuitBreaker' # Look for "open" state

# Restart server
curl -X POST -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/servers/filesystem/restart

Permission denied errors

# Check if running as root
curl -H "Authorization: Bearer $TOKEN" https://your-domain.com/admin/permissions

# If not root, restart with sudo
sudo systemctl restart mcp-gateway

Chrome DevTools browser issues

# Install Chrome manually
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update && sudo apt-get install -y google-chrome-stable

# Check Chrome installation
google-chrome --version

Configuration not persisting

# Check config file permissions
ls -la config/gateway.json

# Should be writable
chmod 666 config/gateway.json

Claude Desktop not connecting

  1. Verify the gateway is running: curl https://your-domain.com/admin/health
  2. Check the SSE endpoint: curl -N https://your-domain.com/sse -H "Authorization: Bearer YOUR_TOKEN"
  3. Verify your claude_desktop_config.json has the correct URL and token
  4. Restart Claude Desktop after config changes

Running in Docker/Containers (non-systemd)

If you're running in a container or non-systemd environment:

# The setup script will detect this and create a start script
./scripts/setup-ubuntu.sh

# Then start manually using one of these methods:
./start-gateway.sh                                    # Helper script created by setup
node dist/index.js                                    # Direct execution
screen -dmS mcp-gateway bash -c 'npm start'           # Screen session
nohup node dist/index.js > logs/mcp-gateway.log 2>&1 &  # Background with nohup

Caddy can't reach the gateway

If Caddy shows "connection refused" or similar errors:

  1. Check gateway is listening on correct interface:

    # Gateway should listen on 0.0.0.0 for standalone, or 127.0.0.1 behind Caddy
    grep '"host"' config/gateway.json
    
  2. Verify log directory exists:

    # Caddy fails if log directory doesn't exist
    sudo mkdir -p /var/log/caddy
    sudo chmod 755 /var/log/caddy
    # If caddy user exists:
    sudo chown caddy:caddy /var/log/caddy
    
  3. Check Caddy can resolve the backend:

    # Caddy uses 127.0.0.1:3000 (explicit IP) instead of localhost
    # This is more reliable in containers/network namespaces
    curl http://127.0.0.1:3000/admin/health
    

Security Considerations

  • Authentication: Always use strong, unique tokens (64+ character hex recommended)
  • Timing-Safe Comparison: Token validation uses constant-time comparison to prevent timing attacks
  • Network: Behind Caddy, the gateway only listens on localhost
  • SSL: Let's Encrypt provides automatic HTTPS certificates
  • Directory Permissions: Uses secure 755 permissions (owner write, others read/execute only)
  • Command Whitelist: The /admin/permissions/exec endpoint uses a whitelist approach, only allowing safe commands
  • Rate Limiting: All endpoints including OAuth are rate-limited to prevent brute force attacks
  • CORS: Configurable allowed origins for cross-origin requests
  • Token Storage: Use environment variables for tokens in production
  • OAuth: Recommended for production Claude app integration

Generate Secure Token

openssl rand -hex 32
# Use as: sk-<generated-hex>

Non-Interactive Setup

For automation/CI:

# Set required environment variables
export DOMAIN=mcp.example.com
export EMAIL=admin@example.com

# Run setup scripts
sudo ./scripts/setup-ubuntu.sh
sudo ./scripts/setup-caddy.sh
sudo ./scripts/setup-gateway.sh

# Verify deployment
./scripts/health-check.sh

For advanced setups with OAuth:

export MCP_DOMAIN=mcp.example.com
export MCP_SSL_EMAIL=admin@example.com
export MCP_API_TOKEN=sk-$(openssl rand -hex 32)
export MCP_OAUTH_ENABLED=false

sudo -E ./scripts/caddy-integration.sh --non-interactive

License

MIT License - see LICENSE for details.

Acknowledgments