Skip to content
Conduit

mcp server

MCP-GATEWAY

mohandshamada/MCP-GATEWAYcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 22, 2026

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.

Node.js TypeScript MCP License


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

ServerToolsDescription
Filesystem14Read/write files, directories, search, file info
Memory9Knowledge graph with entities, relations, observations
Sequential Thinking1Step-by-step problem solving with branching
Desktop Commander25Terminal commands, file editing, process management
Chrome DevTools29Browser debugging, performance analysis, network inspection
O'Reilly Learning5Access O'Reilly Learning Platform content
AI Unified Memory8Shared memory server for Claude, Kimi, Hermes, OpenClaw
Total91Ready 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

PlatformConfig 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

IssueSolution
"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:

FeatureDescription
Built-in OAuth ServerIssue tokens directly from the gateway - no external provider needed
Gateway OAuthAuthenticate clients connecting to the gateway
Server OAuthAuthenticate 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

EndpointMethodAuth RequiredDescription
POST /oauth/tokenPOSTNoGet access token
POST /oauth/revokePOSTNoRevoke a token
POST /oauth/validatePOSTNoValidate a token
GET /.well-known/openid-configurationGETNoOAuth discovery
GET /oauth/infoGETYesServer info and stats
POST /oauth/clientsPOSTYesRegister new client
DELETE /oauth/clients/:idDELETEYesRemove client

Supported Grant Types

Grant TypeUse CaseExample
client_credentialsServer-to-server, API accessgrant_type=client_credentials
passwordUser login (with username/password)grant_type=password&username=user&password=pass
refresh_tokenRefresh expired tokensgrant_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

OptionTypeDefaultDescription
enabledbooleanfalseEnable the built-in OAuth server
issuerstringautoOAuth issuer URL (auto-detected from request)
tokenExpiresInnumber3600Access token lifetime in seconds
refreshTokenExpiresInnumber86400Refresh token lifetime in seconds
clientsarray[]Pre-registered OAuth clients

OAuth Client Configuration

OptionTypeRequiredDescription
clientIdstringYesUnique client identifier
clientSecretstringYesClient secret for authentication
namestringYesHuman-readable client name
scopesstring[]NoAllowed scopes (default: all)
grantTypesstring[]NoAllowed 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:

EndpointMethodDescription
/oauth/tokenPOSTToken endpoint (client_credentials, password, refresh_token)
/.well-known/openid-configurationGETOAuth discovery endpoint
/healthGETHealth 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 TypeUse CaseRequired Config
client_credentialsServer-to-serverclientId, clientSecret, tokenUrl
passwordUser credentials+ username, password
refresh_tokenToken refreshAutomatic 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

OptionTypeRequiredDescription
clientIdstringYesOAuth client ID (supports ${ENV_VAR} syntax)
clientSecretstringYesOAuth client secret (supports ${ENV_VAR} syntax)
tokenUrlstringYesToken endpoint URL
grantTypestringNoclient_credentials (default), password, refresh_token
scopesstring[]NoOAuth scopes to request
audiencestringNoAPI audience (Auth0, etc.)
usernamestringNoUsername (password grant only)
passwordstringNoPassword (password grant only)
refreshBeforeExpirynumberNoSeconds 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

EndpointMethodDescription
/sseGETServer-Sent Events connection for MCP protocol
/messagePOSTJSON-RPC message endpoint (requires X-Session-ID)
/rpcPOSTDirect JSON-RPC endpoint (stateless)

Admin Endpoints

EndpointMethodDescription
/admin/healthGETHealth check with server status
/admin/statusGETDetailed gateway status
/admin/serversGETList all registered servers
/admin/serversPOSTRegister a new server (persisted to config)
/admin/servers/:idGETGet server details with circuit breaker status
/admin/servers/:idDELETEUnregister a server
/admin/servers/:id/restartPOSTRestart a server
/admin/toolsGETList all 71 namespaced tools
/admin/metricsGETGateway metrics and statistics

Client Configuration Endpoints

EndpointMethodDescription
/admin/client-configGETGet full client configuration with instructions
/admin/client-config/claudeGETDownload Claude Desktop config file

Permission Management Endpoints

EndpointMethodDescription
/admin/permissionsGETGet current permission status (root/sudo)
/admin/permissions/setPOSTSet file/directory permissions
/admin/permissions/mkdirPOSTCreate directory with secure 755 permissions
/admin/permissions/execPOSTExecute 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

OptionTypeDefaultDescription
idstringrequiredUnique server ID (used as namespace prefix)
transportstringrequired"stdio" or "sse"
commandstring-Command to spawn (stdio only)
argsstring[][]Command arguments
urlstring-SSE endpoint URL (sse only)
envobject{}Environment variables
enabledbooleantrueWhether server is enabled
lazyLoadbooleanfalseStart on-demand
timeoutnumber60000Request timeout (ms)
maxRetriesnumber3Max 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:

ServerOriginal ToolNamespaced Tool
filesystemread_filefilesystem__read_file
memorycreate_entitiesmemory__create_entities
desktop-commanderexecute_commanddesktop-commander__execute_command
chrome-devtoolsnavigate_pagechrome-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)

ToolDescription
read_file, read_text_fileRead file contents
read_media_fileRead images/audio as base64
read_multiple_filesBatch file reading
write_fileCreate/overwrite files
edit_fileLine-based file editing
create_directoryCreate directories
list_directoryList directory contents
directory_treeRecursive tree view
move_fileMove/rename files
search_filesGlob pattern search
get_file_infoFile metadata
list_allowed_directoriesShow accessible paths

Memory Server (9 tools)

ToolDescription
create_entitiesCreate knowledge graph entities
create_relationsCreate entity relationships
add_observationsAdd facts to entities
delete_entitiesRemove entities
delete_observationsRemove observations
delete_relationsRemove relationships
read_graphRead entire knowledge graph
search_nodesSearch entities
open_nodesOpen specific entities

Sequential Thinking (1 tool)

ToolDescription
sequentialthinkingStep-by-step problem solving with revision and branching

Desktop Commander (25 tools)

ToolDescription
execute_commandRun shell commands
read_file, write_fileFile operations
edit_blockSurgical text replacement
start_search, stop_searchBackground file search
list_directoryDirectory listing
create_directoryCreate directories
move_fileMove/rename files
get_config, set_config_valueConfiguration management
start_process, interact_with_processProcess management
And more...

Chrome DevTools (26 tools)

ToolDescription
navigate_pageNavigate to URL
take_screenshotTake screenshots
click_elementClick elements
type_textType text into inputs
scroll_pageScroll the page
get_console_messagesGet browser console logs
get_network_requestsInspect network requests
run_performance_tracePerformance profiling
evaluate_javascriptExecute 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

↑↓ navigate openesc close