Labsco
pezzos logo

Remote MCP Proxy

ā˜… 2

from pezzos

A Docker-based proxy to access local MCP servers through Claude's web UI using the Remote MCP protocol.

šŸ”„šŸ”„šŸ”„āœ“ VerifiedAccount requiredAdvanced setup

Remote MCP Proxy

Seamlessly use your favorite MCP servers anywhere. This project packages a small Go proxy that lets you connect local or experimental MCP servers to Claude.ai and the mobile app. Even if a server isn't officially "remote" yet, this proxy exposes it over Claude's new Remote MCP protocol so you can start integrating immediately.

Why This Exists

Existing MCP servers often run only on your desktop, making them impossible to use with Claude's web UI or phone app. The Remote MCP protocol solves this, but not every server supports it yet. This proxy fills that gap so you can experiment right away.

How It Works

Run the proxy in Docker and it will:

  • Launches and monitors your local MCP servers automatically
  • Converts traffic between HTTP/SSE and standard MCP JSON-RPC
  • Hosts several MCP servers at once under different URL paths
  • Reuses the familiar claude_desktop_config.json format
  • Shuts down cleanly and cleans up any spawned processes
  • Exposes a /health endpoint so you can check status at a glance

🌐 Dynamic URL Structure

Auto-Generated Format: Each MCP server is automatically available at:

https://{server-name}.mcp.{DOMAIN}/sse

Examples (from your config.json):

  • https://memory.mcp.your-domain.com/sse
  • https://sequential-thinking.mcp.your-domain.com/sse
  • https://notion.mcp.your-domain.com/sse

Where {DOMAIN} is set in your .env file and {server-name} matches the key in your config.json file.

šŸ”§ Make Commands Reference

CommandDescription
make helpShow all available commands
make install-depsInstall gomplate dependency
make generateGenerate docker-compose.yml from config.json
make buildBuild Docker images
make upGenerate config and start services
make downStop and remove services
make restartRestart services with new config
make logsShow service logs
make cleanRemove generated files

Why Dynamic Subdomain Generation?

Claude.ai expects Remote MCP endpoints at root level (/sse), not path-based routing. This automated subdomain approach:

  • āœ… Matches Remote MCP standard format
  • āœ… Auto-scales with config.json changes
  • āœ… Provides clean separation between servers
  • āœ… Eliminates manual Traefik configuration
  • āœ… Enables instant deployment of new servers

Docker Compose with Traefik

Wildcard Subdomain Configuration

The service is configured to work with Traefik reverse proxy for automatic HTTPS and wildcard subdomain routing:

version: '3.8'
services:
  remote-mcp-proxy:
    build: .
    container_name: remote-mcp-proxy
    restart: unless-stopped
    volumes:
      - ./config.json:/app/config.json:ro
    environment:
      - GO_ENV=production
    networks:
      - proxy
    labels:
      # Wildcard subdomain routing for dynamic MCP servers
      - traefik.enable=true
      - traefik.http.routers.mcp-wildcard.rule=Host(`*.mcp.${DOMAIN}`)
      - traefik.http.routers.mcp-wildcard.entrypoints=websecure
      - traefik.http.routers.mcp-wildcard.tls=true
      - traefik.http.routers.mcp-wildcard.tls.certresolver=letsencrypt
      - traefik.http.services.mcp-wildcard.loadbalancer.server.port=8080
      
      # Utility endpoints on main domain
      - traefik.http.routers.mcp-main.rule=Host(`mcp.${DOMAIN}`)
      - traefik.http.routers.mcp-main.entrypoints=websecure
      - traefik.http.routers.mcp-main.tls=true
      - traefik.http.routers.mcp-main.tls.certresolver=letsencrypt
      - traefik.http.services.mcp-main.loadbalancer.server.port=8080

networks:
  proxy:
    external: true

Key Configuration Points:

  1. Wildcard Rule: Host(\*.mcp.${DOMAIN}`)captures all subdomains likememory.mcp.domain.com`
  2. Dynamic SSL: Traefik automatically generates SSL certificates for new subdomains
  3. Main Domain: mcp.${DOMAIN} for utility endpoints (/health, /listmcp)
  4. DNS Requirement: Wildcard DNS record *.mcp.domain.com must be configured

Development

Prerequisites

  • Go 1.21 or later
  • Docker
  • Your MCP servers' dependencies (Node.js, Python, etc.)

Local Development

# Clone the repository
git clone <repository-url>
cd remote-mcp-proxy

# Install Go dependencies
go mod tidy

# Build locally
go build -o remote-mcp-proxy .

# Run locally (requires config.json at /app/config.json)
./remote-mcp-proxy

# Or build and run with Docker
docker build -t remote-mcp-proxy .
docker run -v $(pwd)/config.json:/app/config.json -p 8080:8080 remote-mcp-proxy

Development Commands

  • Build: go build -o remote-mcp-proxy .
  • Run: ./remote-mcp-proxy
  • Test: go test ./...
  • Lint: go fmt ./... and go vet ./...
  • Dependencies: go mod tidy

Testing

The Remote MCP Proxy includes comprehensive tests to ensure reliability and correctness.

Quick Test

# Run all tests
./test/run-tests.sh

Manual Testing

# Unit tests only
go test -v ./protocol ./mcp ./proxy

# Integration tests
go test -v .

# Tests with coverage
go test -cover ./...

# Short tests (skip integration)
go test -short ./...

# Benchmarks
go test -bench=. -benchmem ./...

Test Configurations

Several test configurations are provided in the test/ directory:

  • test/minimal-config.json: Basic echo server for testing
  • test/development-config.json: Common MCP servers for development
  • test/production-config.json: Production server examples
  • test/config.json: Full test suite configuration

Testing with Different Configurations

# Test with minimal config
CONFIG_PATH=./test/minimal-config.json ./remote-mcp-proxy

# Test with development servers (requires npm packages)
CONFIG_PATH=./test/development-config.json ./remote-mcp-proxy

# Test specific functionality
curl http://localhost:8080/health
curl -X GET http://localhost:8080/simple-echo/sse \
  -H "Accept: text/event-stream"

Test Coverage

The test suite covers:

  • Protocol Translation: JSON-RPC ↔ Remote MCP message conversion
  • Connection Management: Session handling, timeouts, cleanup
  • Error Handling: Invalid requests, server failures, network issues
  • Concurrency: Multiple simultaneous connections
  • Authentication: Token validation and CORS
  • Health Checks: Server status monitoring
  • Integration: End-to-end workflow testing

CI/CD Testing

For automated testing in CI environments:

# Install dependencies
go mod download

# Run tests with XML output (for CI)
go test -v ./... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html

# Static analysis
go vet ./...
go fmt ./...

Adding New MCP Servers

  1. Add the server configuration to config.json
  2. Restart the proxy container
  3. The new server will be available at /{server-name}/sse

Architecture

The proxy is built in Go and consists of:

  • HTTP Proxy Server: Handles incoming Remote MCP requests using Gorilla Mux router
  • MCP Process Manager: Spawns and manages local MCP server processes with health monitoring
  • Protocol Translator: Converts between HTTP/SSE and MCP JSON-RPC protocols
  • Configuration Loader: Reads and validates MCP server configs (claude_desktop_config.json format)
  • SSE Handler: Implements Server-Sent Events for real-time Remote MCP communication

Technology Stack

  • Go 1.21: Core language for performance and concurrency
  • Gorilla Mux: HTTP routing and path-based server selection
  • Standard Library: Process management (os/exec), HTTP/SSE, JSON handling
  • Alpine Linux: Minimal Docker base image for production deployment

Remote MCP Protocol Implementation

The proxy implements the Remote MCP protocol specification to enable Claude.ai integration:

Protocol Flow

  1. OAuth 2.0 Authentication: Claude.ai authenticates using Bearer tokens via OAuth 2.0 Dynamic Client Registration
  2. Initialize Handshake: Synchronous POST request to /{server}/sse with initialize message
  3. Session Management: Sessions are tracked using Mcp-Session-Id header and marked as initialized immediately after successful handshake
  4. Tool Discovery: Follow-up requests use the same session to discover and call tools
  5. SSE Communication: Server-Sent Events for real-time message delivery (future requests)

Critical Implementation Details

Synchronous Initialize: Unlike local MCP servers, Claude.ai expects a synchronous JSON response to the initialize POST request, not an asynchronous SSE response.

Session Initialization: Sessions MUST be marked as initialized immediately after a successful MCP server response. Waiting for a separate "initialized" notification will cause tool discovery to fail.

Stdio Concurrency: MCP server stdout access is serialized using dedicated readMu mutex to prevent deadlocks when multiple Claude.ai requests access the same server simultaneously.

Timeout Handling: 30-second timeout for initialize responses to accommodate slow npm-based MCP servers. Shorter timeouts cause "context deadline exceeded" errors.

Tool Name Normalization: Tool names are automatically converted from hyphenated format (API-get-user) to snake_case (api_get_user) for Claude.ai compatibility, with bidirectional transformation for tool calls.

šŸ“Š Monitoring, Health Checks & Resource Management

The proxy includes comprehensive monitoring and stability features designed to prevent server hangs and ensure reliable operation.

šŸ” Health Monitoring & Auto-Recovery

Proactive Health Checks: The proxy continuously monitors all MCP servers with periodic ping checks every 30 seconds.

# Check overall health
curl https://mcp.your-domain.com/health
# Response: {"status":"healthy"}

# Get detailed health status for all MCP servers
curl https://mcp.your-domain.com/health/servers
# Response: {
#   "timestamp": "2025-06-26T10:30:00Z",
#   "servers": {
#     "memory": {
#       "name": "memory",
#       "status": "healthy",
#       "lastCheck": "2025-06-26T10:29:45Z",
#       "responseTimeMs": 120,
#       "consecutiveFails": 0,
#       "restartCount": 0
#     }
#   },
#   "summary": {
#     "total": 4,
#     "healthy": 3,
#     "unhealthy": 1,
#     "unknown": 0
#   }
# }

Automatic Recovery: When servers become unresponsive:

  • āœ… Early Detection: 3 consecutive failed health checks trigger recovery
  • āœ… Smart Restart: Automatic server restart with graceful cleanup
  • āœ… Restart Limits: Maximum 3 restarts per 5-minute window to prevent loops
  • āœ… Status Tracking: Comprehensive health history and error tracking

šŸ“ˆ Resource Monitoring & Alerting

Real-time Resource Tracking: Monitor memory and CPU usage of all MCP processes.

# Get current resource usage for all MCP processes
curl https://mcp.your-domain.com/health/resources
# Response: {
#   "timestamp": "2025-06-26T10:30:00Z",
#   "processes": [
#     {
#       "pid": 123,
#       "name": "memory-server",
#       "memoryMB": 145.2,
#       "cpuPercent": 2.1,
#       "virtualMB": 512.0,
#       "residentMB": 145.2
#     }
#   ],
#   "summary": {
#     "processCount": 4,
#     "totalMemoryMB": 580.5,
#     "totalCPU": 8.3,
#     "averageMemoryMB": 145.1,
#     "averageCPU": 2.1
#   }
# }

Alert Thresholds:

  • 🚨 Memory Alert: >500MB per process
  • 🚨 CPU Alert: >80% CPU usage per process
  • šŸ“Š Logging: Resource summaries logged every minute

šŸ›”ļø Resource Management & Container Limits

Container Resource Limits: Prevent resource exhaustion that can cause server hangs.

# Docker Compose Resource Configuration
deploy:
  resources:
    limits:
      memory: 2G        # Maximum memory allocation
      cpus: '2.0'       # Maximum CPU allocation
    reservations:
      memory: 512M      # Guaranteed memory
      cpus: '0.5'       # Guaranteed CPU

Benefits:

  • āœ… Prevents OOM: Memory limits prevent out-of-memory conditions
  • āœ… CPU Protection: CPU limits prevent CPU starvation
  • āœ… Predictable Performance: Resource reservations ensure baseline performance
  • āœ… Container Stability: Improved overall system stability

šŸ“‹ Server Management & Debugging

Server Status Monitoring:

# List all configured MCP servers and their status
curl https://mcp.your-domain.com/listmcp
# Response: {
#   "count": 4,
#   "servers": [
#     {
#       "name": "memory",
#       "running": true,
#       "pid": 123,
#       "command": "npx",
#       "args": ["-y", "@modelcontextprotocol/server-memory"]
#     }
#   ]
# }

# List available tools for a specific MCP server
curl https://mcp.your-domain.com/listtools/memory
# Response: {
#   "server": "memory",
#   "response": {
#     "jsonrpc": "2.0",
#     "result": {
#       "tools": [
#         {
#           "name": "create_entities",
#           "description": "Create multiple new entities in the knowledge graph"
#         }
#       ]
#     }
#   }
# }

# Manual connection cleanup (if needed)
curl -X POST https://mcp.your-domain.com/cleanup

šŸ”§ Enhanced Logging & Debugging

Structured Logging: All logs include session correlation for better debugging.

Log Locations (with volume mount /logs):

  • šŸ“„ System Logs: /logs/system.log - Proxy operations and health monitoring
  • šŸ“„ MCP Server Logs: /logs/mcp-{server-name}.log - Individual server logs
  • šŸ“„ Log Retention: Configurable cleanup (default: 24h system, 12h MCP)

Log Levels (configured via environment variables):

# .env configuration
LOG_LEVEL_SYSTEM=INFO      # System logging level
LOG_LEVEL_MCP=DEBUG        # MCP server logging level
LOG_RETENTION_SYSTEM=24h   # System log retention
LOG_RETENTION_MCP=12h      # MCP log retention

Enhanced Request Tracing: Every request includes Method, ID, and SessionID for complete traceability:

2025/06/26 10:30:15 [INFO] Method: initialize, ID: 0, SessionID: abc123-def456
2025/06/26 10:30:16 [INFO] Successfully received response from server memory

šŸš€ Production Monitoring Setup

External Monitoring Integration: Use the health APIs with your monitoring stack.

Prometheus/Grafana Example:

# prometheus.yml
scrape_configs:
  - job_name: 'mcp-proxy'
    static_configs:
      - targets: ['mcp.your-domain.com']
    metrics_path: '/health/resources'
    scheme: https

Uptime Monitoring:

# Health check endpoint for uptime monitors
https://mcp.your-domain.com/health

# Expected response: {"status":"healthy"}

Alert Rules Examples:

  • Server health: Check /health/servers for unhealthy status
  • Resource usage: Monitor /health/resources for threshold violations
  • Process count: Alert if fewer processes than expected servers

šŸ› ļø Troubleshooting with New Features

Memory Server Hanging Issues (Addressed in latest version):

  1. Check Health Status: curl https://mcp.your-domain.com/health/servers
  2. Review Resource Usage: curl https://mcp.your-domain.com/health/resources
  3. Monitor Auto-Recovery: Health checker will automatically restart hung servers
  4. Check Logs: Review /logs/mcp-memory.log for detailed error analysis

Resource Exhaustion Prevention:

  • Container limits prevent runaway processes
  • Resource monitoring provides early warning
  • Automatic cleanup of old log files prevents disk issues

These monitoring features provide comprehensive visibility into MCP server health and performance, with automatic recovery capabilities to ensure reliable operation in production environments.