mcp-server

0xb007ab1e/mcp-server

3.2

If you are the rightful owner of mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

This project implements a Model Context Protocol (MCP) server using Cloudflare Workers with strict versioned API endpoint conventions.

MCP Cloudflare Worker - Strict Versioned API

This project implements a Model Context Protocol (MCP) server using Cloudflare Workers with strict versioned API endpoint conventions.

API Versioning Convention

Canonical Production Route: /mcp/v1/*

All production API endpoints are served under the /mcp/v1/* namespace. Future versions will be served from /mcp/v2/*, /mcp/v3/*, etc.

Supported V1 Endpoints

  • GET /mcp/v1/ - API information and endpoint listing
  • POST /mcp/v1/jsonrpc - JSON-RPC 2.0 endpoint for MCP methods
  • GET /mcp/v1/capabilities - Server capabilities and supported methods
  • GET /mcp/v1/health - Health check endpoint
  • GET /mcp/v1/version - Version information

Semantic Versioned JSON-RPC Methods

All JSON-RPC methods expose semantic versioning in the format "1.x.y":

{
  "method": "tools/list",
  "version": "1.0.0",
  "description": "List available tools"
}

Directory Structure

src/
ā”œā”€ā”€ index.js              # Main Worker entry point with routing
└── v1/                   # V1 API implementation
    ā”œā”€ā”€ index.js          # V1 route handler
    ā”œā”€ā”€ server.js         # MCP server implementation
    └── methods.js        # Semantic versioned method definitions

Strict Routing Enforcement

The system strictly enforces that only /mcp/v1/* routes respond successfully. Any other route patterns return a 404 error:

  • āŒ /mcp/v2/* → 404
  • āŒ /api/v1/* → 404
  • āŒ /v1/* → 404
  • āŒ /mcp/latest/* → 404
  • āŒ /mcp/V1/* → 404 (case sensitive)

Integration Tests

The project includes comprehensive integration tests that MUST FAIL if any non-v1 route responds successfully:

npm run test:integration

Tests validate:

  • āœ… All V1 endpoints respond correctly
  • āœ… All non-V1 routes return 404
  • āœ… Semantic versioning is properly implemented
  • āœ… Version consistency across endpoints

Development

Setup

# Install dependencies
npm install

# Run tests
npm test
npm run test:integration

# Start development server
npm run dev

# Deploy to Cloudflare
npm run deploy

Environment Configuration

Copy .env.example to .env.local and configure your environment variables:

cp .env.example .env.local

Adding Future Versions

To add v2 API support:

  1. Create src/v2/ directory
  2. Implement v2 handlers
  3. Update main router in src/index.js
  4. Add route pattern: /mcp/v2/*
  5. Update integration tests

API Response Format

Success Response (V1)

{
  "version": "1.0.0",
  "capabilities": {
    "tools": true,
    "resources": true,
    "prompts": true,
    "logging": true
  },
  "supportedMethods": [
    {
      "method": "initialize",
      "version": "1.0.0", 
      "description": "Initialize MCP session"
    }
  ]
}

Error Response (Non-V1)

{
  "error": {
    "code": -32000,
    "message": "Endpoint not found",
    "data": {
      "message": "Only /mcp/v1/* endpoints are supported",
      "supportedVersions": ["v1"],
      "requestedPath": "/mcp/v2/capabilities"
    }
  }
}

MCP Protocol Compliance

This implementation follows the Model Context Protocol specification:

  • JSON-RPC 2.0 transport
  • Standard MCP method names
  • Proper error handling
  • CORS support for web clients

Security Features

  • CORS headers configured
  • Input validation on JSON-RPC requests
  • Error messages don't leak sensitive information
  • Rate limiting ready (via Wrangler configuration)

Secrets Management

Secrets are managed through Cloudflare's Workers secret system using the Wrangler CLI. This approach ensures that sensitive data like API keys, tokens, and passwords are stored securely and never exposed in your code or environment files.

Setting Secrets

Use the provided script to set all secrets at once:

./scripts/secret-set.sh

This script will prompt you for each required secret value and set them using wrangler secret put.

Alternatively, set secrets individually:

wrangler secret put API_KEY
wrangler secret put SECRET_KEY
wrangler secret put DATABASE_URL

Rotating Secrets Without Downtime

To rotate secrets without causing downtime, follow this zero-downtime rotation strategy:

  1. Prepare the new secret value but don't deploy it yet
  2. Update the secret in Cloudflare using Wrangler:
    wrangler secret put API_KEY
    # Enter the new secret value when prompted
    
  3. Deploy immediately to activate the new secret:
    wrangler deploy
    
  4. Verify the deployment by testing a few API calls
  5. Revoke the old secret from the external service (if applicable)

Secret Rotation Best Practices

  • Rotate secrets regularly (every 90 days recommended)
  • Use different secrets for different environments (production, staging, development)
  • Never commit secrets to version control - they should only exist in Cloudflare's secure storage
  • Monitor for failed authentication after rotation to catch any missed updates
  • Keep a rollback plan - know how to quickly revert to the previous secret if needed

Environment-Specific Secrets

For multiple environments, use Wrangler's environment flag:

# Set secret for production
wrangler secret put API_KEY --env production

# Set secret for staging  
wrangler secret put API_KEY --env staging

Accessing Secrets in Worker Code

Secrets are available in the Worker environment:

export default {
  async fetch(request, env, ctx) {
    const apiKey = env.API_KEY;
    const secretKey = env.SECRET_KEY;
    
    // Use secrets in your Worker logic
    // Never log or expose secret values
  }
};

Security Considerations

  • Never log secret values in your Worker code
  • Use environment variables instead of hardcoded secrets
  • Implement proper error handling that doesn't leak secret information
  • Regularly audit secret usage and remove unused secrets

DNS Management

The project includes automated DNS management tools to configure and sync DNS records with Cloudflare for your custom domain.

DNS Records Configuration

The DNS sync tool automatically manages these records:

  • Root domain (example.com) - A record pointing to your server IP
  • API subdomain (api.example.com) - CNAME record for API endpoints
  • MCP subdomain (mcp.example.com) - CNAME record for MCP server
  • Dev API subdomain (dev-api.example.com) - CNAME record for development

All records are configured with orange-cloud proxy enabled for security and performance benefits.

Environment Variables for DNS

Set these environment variables for DNS management:

export CF_API_TOKEN="your_cloudflare_api_token_with_dns_permissions"
export CF_ZONE_ID="your_cloudflare_zone_id"
export DOMAIN="your_domain.com"
export SERVER_IP="your_server_ip"  # Optional, auto-detected if not set

DNS Sync Commands

Sync DNS records with Cloudflare:

# Sync DNS records (applies changes)
make dns-sync

# Preview changes without applying them
make dns-sync-dry

# Check current DNS resolution
make dns-check

DNS Propagation Status

The DNS sync tool automatically:

  • āœ… Verifies A/CNAME records for all subdomains
  • āœ… Ensures orange-cloud proxy is enabled
  • āœ… Prints pending propagation status
  • āœ… Shows current vs expected DNS resolution

Troubleshooting DNS

If DNS records aren't propagating:

  1. Check Cloudflare dashboard - Verify records are created correctly
  2. Wait for propagation - DNS changes can take 24-48 hours globally
  3. Use DNS checking tools - Try dig or online DNS checkers
  4. Purge Cloudflare cache - Use Cloudflare API to purge cache
# Check DNS resolution for all configured domains
DOMAIN=your-domain.com make dns-check

# Run dry-run to see what changes would be made
DRY_RUN=true make dns-sync

Custom Domain Setup Guide

  1. Get Cloudflare credentials:

    • Create API token with Zone:Read, DNS:Edit permissions
    • Find your Zone ID in Cloudflare dashboard
  2. Configure environment:

    export CF_API_TOKEN="your_token_here"
    export CF_ZONE_ID="your_zone_id_here"
    export DOMAIN="yourdomain.com"
    
  3. Sync DNS records:

    make dns-sync
    
  4. Update Wrangler configuration: Update wrangler.toml with your domain:

    [env.production]
    routes = [
      { pattern = "*/mcp/v1/*", zone_name = "yourdomain.com" }
    ]
    
  5. Deploy with custom domain:

    wrangler deploy --env production
    

Deployment

Deploy to Cloudflare Workers:

wrangler deploy

The worker will be available at your Cloudflare Workers domain with the /mcp/v1/* endpoints active.

Production Deployment with Custom Domain

  1. Set up DNS records (first time only):

    make dns-sync
    
  2. Deploy to production:

    make deploy
    
  3. Verify deployment:

    curl https://yourdomain.com/mcp/v1/health