remote-mcp-server-authless

sujianjob/remote-mcp-server-authless

3.2

If you are the rightful owner of remote-mcp-server-authless 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 guide provides instructions for deploying a remote MCP server with JWT authentication on Cloudflare Workers, offering a secure and maintainable solution for managing model context protocols.

Tools
3
Resources
0
Prompts
0

Building a Remote MCP Server on Cloudflare (With JWT Authentication)

This example allows you to deploy a remote MCP server with JWT Bearer Token authentication on Cloudflare Workers. The server uses a simplified authentication mechanism for better maintainability.

Get started:

Deploy to Workers

This will deploy your MCP server to a URL like: remote-mcp-server-authless.<your-account>.workers.dev/sse

Alternatively, you can use the command line below to get the remote MCP Server created on your local machine:

npm create cloudflare@latest -- my-mcp-server --template=cloudflare/ai/demos/remote-mcp-authless

๐Ÿ” JWT Authentication Configuration

This MCP server uses a simplified JWT Bearer Token authentication mechanism for better security and maintainability.

Environment Variables

VariableDescriptionExample
JWT_SECRETSecret key for JWT token validationyour-super-secure-jwt-secret

Setting up Authentication

Configure JWT secret for token validation:

# Set JWT secret
wrangler secret put JWT_SECRET
# Enter: your-super-secure-jwt-secret

Authentication Method

Include the JWT token in the Authorization header:

curl -H "Authorization: Bearer your-jwt-token" https://your-worker.workers.dev/sse

Generating JWT Tokens

Use the included utility to generate JWT tokens:

# Generate a JWT token
npm run generate-jwt

Or programmatically:

import { generateJWT } from './src/auth-utils.js';

const payload = {
  userId: 'user123',
  username: 'john_doe',
  roles: ['user']
};

const token = await generateJWT(payload, 'your-jwt-secret', 3600); // 1 hour expiry
console.log('Generated JWT:', token);

Customizing your MCP Server

To add your own tools to the MCP server, define each tool inside the init() method of src/index.ts using this.server.tool(...).

Connect to Cloudflare AI Playground

You can connect to your MCP server from the Cloudflare AI Playground, which is a remote MCP client:

  1. Go to https://playground.ai.cloudflare.com/
  2. Enter your deployed MCP server URL (remote-mcp-server-authless.<your-account>.workers.dev/sse)
  3. Important: Add authentication header: Authorization: Bearer your-jwt-token
  4. You can now use your MCP tools directly from the playground!

Health Check Endpoint

The server includes a health check endpoint that doesn't require authentication:

curl https://mcp.123648.xyz/health

Response:

{
  "status": "ok",
  "timestamp": "2024-01-01T00:00:00.000Z",
  "service": "MCP Server with JWT Auth"
}

Connect Claude Desktop to your MCP server

You can also connect to your remote MCP server from local MCP clients, by using the mcp-remote proxy.

To connect to your MCP server from Claude Desktop, follow Anthropic's Quickstart and within Claude Desktop go to Settings > Developer > Edit Config.

Without Authentication (Development)

{
  "mcpServers": {
    "calculator": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8787/sse"
      ]
    }
  }
}

With JWT Authentication (Production)

{
  "mcpServers": {
    "calculator": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://remote-mcp-server-authless.your-account.workers.dev/sse"
      ],
      "env": {
        "MCP_REMOTE_HEADERS": "{\"Authorization\": \"Bearer your-jwt-token\"}"
      }
    }
  }
}

Restart Claude and you should see the tools become available.

๐Ÿ”ง Development and Testing

Local Development

  1. Clone the repository
  2. Install dependencies: npm install
  3. Set up environment variables in .dev.vars file:
    JWT_SECRET=your-local-jwt-secret
    
  4. Start development server: npm run dev

Testing Authentication

Test the health endpoint (no auth required):

curl http://localhost:8787/health

Test with JWT token:

curl -H "Authorization: Bearer your-jwt-token" http://localhost:8787/sse

Test with invalid JWT token (should return 401):

curl -H "Authorization: Bearer invalid-token" http://localhost:8787/sse

Security Best Practices

  1. Use Strong JWT Secrets: Generate cryptographically secure JWT secrets with sufficient length (64+ characters)
  2. Rotate Secrets Regularly: Implement a secret rotation strategy for production environments
  3. Use HTTPS: Always use HTTPS in production to protect authentication tokens in transit
  4. Monitor Access: Review logs regularly for suspicious authentication attempts
  5. Environment Separation: Use different secrets for development, staging, and production environments
  6. Token Expiry: Set appropriate expiration times for JWT tokens

Troubleshooting

Authentication Failed Errors:

  • Verify your JWT token is correct and not expired
  • Check that the Authorization header is properly formatted (Authorization: Bearer <token>)
  • Ensure the JWT_SECRET environment variable is correctly set
  • Check the server logs for detailed error messages

Token Issues:

  • Generate a new JWT token using npm run generate-jwt
  • Verify the token payload contains the required fields
  • Check token expiration time

๐Ÿš€ Interactive Feedback System (v2.0)

ๆœฌ MCP ๆœๅŠกๅ™จ็Žฐๅทฒๅ‡็บงไธบๅฎŒๆ•ด็š„ไบคไบ’ๅผๅ้ฆˆๆ”ถ้›†็ณป็ปŸ๏ผŒๆไพ›ไปฅไธ‹ๆ–ฐๅŠŸ่ƒฝ๏ผš

โœจ ๆ–ฐๅขžๅŠŸ่ƒฝ

๐Ÿ“‹ ๅฎŒๆ•ด็š„ๅ้ฆˆ API
  • ๅˆ›ๅปบไผš่ฏ: POST /api/feedback/create - ๅˆ›ๅปบๆ–ฐ็š„ๅ้ฆˆไผš่ฏ
  • ่Žทๅ–็Šถๆ€: GET /api/feedback/{sessionId}/status - ๆŸฅ่ฏขไผš่ฏ็Šถๆ€
  • ๆไบคๅ้ฆˆ: POST /api/feedback/{sessionId}/submit - ๆไบค็”จๆˆทๅ้ฆˆ
  • ่Žทๅ–็ป“ๆžœ: GET /api/feedback/{sessionId}/result - ่Žทๅ–ๅ้ฆˆ็ป“ๆžœ
๐ŸŽจ ๅ“ๅบ”ๅผ Web ็•Œ้ข
  • ๅ้ฆˆ้กต้ข: GET /feedback/{sessionId} - ็”จๆˆทๅ‹ๅฅฝ็š„ๅ้ฆˆ็•Œ้ข
  • ไธป้ข˜ๆ”ฏๆŒ: ๆ”ฏๆŒๆ˜Žๆš—ไธป้ข˜ๅˆ‡ๆข (?theme=dark|light)
  • ๅคš่ฏญ่จ€: ๆ”ฏๆŒไธญ่‹ฑๆ–‡ๅˆ‡ๆข (?lang=zh|en)
  • ๅ“ๅบ”ๅผ่ฎพ่ฎก: ้€‚้…ๆกŒ้ขๅ’Œ็งปๅŠจ่ฎพๅค‡
โšก WebSocket ๅฎžๆ—ถ้€šไฟก
  • ๅฎžๆ—ถ็Šถๆ€ๆ›ดๆ–ฐ: ไผš่ฏ็Šถๆ€ๅ˜ๅŒ–ๆ—ถ่‡ชๅŠจๆŽจ้€
  • ๅคš็ซฏๅŒๆญฅ: ๆ”ฏๆŒๅคšไธชๅฎขๆˆท็ซฏๅŒๆ—ถ็›‘ๅฌ
  • App ้›†ๆˆ: ๆ”ฏๆŒ็งปๅŠจๅบ”็”จๅ’Œ Web ๅบ”็”จ่ฟžๆŽฅ
๐Ÿ› ๏ธ ๅขžๅผบ็š„ MCP ๅทฅๅ…ท
  • interactive_feedback: ๅˆ›ๅปบๅ้ฆˆไผš่ฏ
  • get_feedback_result: ่Žทๅ–ๅ้ฆˆ็ป“ๆžœ
  • check_feedback_status: ๆฃ€ๆŸฅไผš่ฏ็Šถๆ€

๐Ÿ“– ไฝฟ็”จ็คบไพ‹

1. ้€š่ฟ‡ MCP ๅทฅๅ…ทๅˆ›ๅปบๅ้ฆˆไผš่ฏ
// ๅœจ Claude Desktop ๆˆ–ๅ…ถไป– MCP ๅฎขๆˆท็ซฏไธญไฝฟ็”จ
{
  "tool": "interactive_feedback",
  "arguments": {
    "message": "่ฏทๅฏนๆˆ‘ไปฌ็š„ๆœๅŠก่ฟ›่กŒ่ฏ„ไปท",
    "predefinedOptions": ["้žๅธธๆปกๆ„", "ๆปกๆ„", "ไธ€่ˆฌ", "ไธๆปกๆ„"],
    "timeout": 600,
    "metadata": {
      "source": "customer-service",
      "category": "satisfaction-survey"
    }
  }
}
2. ้€š่ฟ‡ API ๅˆ›ๅปบๅ้ฆˆไผš่ฏ
curl -X POST https://your-worker.workers.dev/api/feedback/create \
  -H "Authorization: Bearer your-jwt-token" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "่ฏท้€‰ๆ‹ฉๆ‚จๅ–œๆฌข็š„ๅŠŸ่ƒฝ",
    "predefinedOptions": ["ๅŠŸ่ƒฝA", "ๅŠŸ่ƒฝB", "ๅŠŸ่ƒฝC"],
    "timeout": 300
  }'
3. ็”จๆˆท่ฎฟ้—ฎๅ้ฆˆ็•Œ้ข

็”จๆˆท่ฎฟ้—ฎ่ฟ”ๅ›ž็š„ feedbackUrl๏ผŒไพ‹ๅฆ‚๏ผš

https://your-worker.workers.dev/feedback/123e4567-e89b-12d3-a456-426614174000?theme=dark&lang=zh
4. ่Žทๅ–ๅ้ฆˆ็ป“ๆžœ
curl -H "Authorization: Bearer your-jwt-token" \
  https://your-worker.workers.dev/api/feedback/123e4567-e89b-12d3-a456-426614174000/result
5. WebSocket ๅฎžๆ—ถ็›‘ๅฌ
const ws = new WebSocket('wss://your-worker.workers.dev/ws/123e4567-e89b-12d3-a456-426614174000?apiKey=your-api-key&clientType=web');

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log('ๆ”ถๅˆฐๆถˆๆฏ:', message);

  switch (message.type) {
    case 'connection_established':
      console.log('่ฟžๆŽฅๅทฒๅปบ็ซ‹');
      break;
    case 'session_status_changed':
      console.log('็Šถๆ€ๅ˜ๅŒ–:', message.data);
      break;
    case 'feedback_submitted':
      console.log('ๅ้ฆˆๅทฒๆไบค:', message.data);
      break;
  }
};

๐Ÿงช ๆต‹่ฏ•

่ฟ่กŒๅฎŒๆ•ด็š„ๆต‹่ฏ•ๅฅ—ไปถ๏ผš

# ๅฎ‰่ฃ…ๆต‹่ฏ•ไพ่ต–
npm install

# ่ฟ่กŒๆต‹่ฏ•
node test/interactive-feedback-tests.js

ๆต‹่ฏ•ๅŒ…ๆ‹ฌ๏ผš

  • โœ… ๅฅๅบทๆฃ€ๆŸฅ
  • โœ… ๅˆ›ๅปบๅ้ฆˆไผš่ฏ
  • โœ… ่Žทๅ–ไผš่ฏ็Šถๆ€
  • โœ… ๆไบคๅ้ฆˆ
  • โœ… ่Žทๅ–ๅ้ฆˆ็ป“ๆžœ
  • โœ… ๅ้ฆˆ็•Œ้ข่ฎฟ้—ฎ
  • โœ… WebSocket ่ฟžๆŽฅ

๐Ÿ”ง ้…็ฝฎ้€‰้กน

็Žฏๅขƒๅ˜้‡
ๅ˜้‡ๆ่ฟฐ้ป˜่ฎคๅ€ผ
JWT_SECRETJWT ไปค็‰Œๅฏ†้’ฅๅฟ…้œ€
OAUTH_KVKV ๅญ˜ๅ‚จ็ป‘ๅฎšๅฟ…้œ€
ไผš่ฏ้…็ฝฎ
  • ้ป˜่ฎค่ถ…ๆ—ถ: 300 ็ง’ (5 ๅˆ†้’Ÿ)
  • ๆœ€ๅคง่ถ…ๆ—ถ: 3600 ็ง’ (1 ๅฐๆ—ถ)
  • ๆœ€ๅคงๆถˆๆฏ้•ฟๅบฆ: 1000 ๅญ—็ฌฆ
  • ๆœ€ๅคง้€‰้กนๆ•ฐ้‡: 10 ไธช
  • ๆœ€ๅคง้€‰้กน้•ฟๅบฆ: 100 ๅญ—็ฌฆ

๐Ÿ—๏ธ ๆžถๆž„่ฏดๆ˜Ž

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   MCP Client    โ”‚    โ”‚   Web Browser   โ”‚    โ”‚  Mobile App     โ”‚
โ”‚  (Claude etc.)  โ”‚    โ”‚                 โ”‚    โ”‚                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚                      โ”‚                      โ”‚
          โ”‚ JWT Auth             โ”‚ No Auth              โ”‚ WebSocket
          โ”‚                      โ”‚                      โ”‚
          โ–ผ                      โ–ผ                      โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                 Cloudflare Worker                               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ MCP Handler โ”‚  โ”‚ API Handler โ”‚  โ”‚   WebSocket Handler     โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                           โ”‚                                     โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚              Feedback Service                            โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚   KV Storage    โ”‚
                    โ”‚   (Sessions)    โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“š API ๆ–‡ๆกฃ

่ฏฆ็ป†็š„ API ๆ–‡ๆกฃ่ฏทๅ‚่€ƒ docs/api-design.md ๆ–‡ไปถใ€‚

๐Ÿ”„ ็‰ˆๆœฌๅކๅฒ

  • v2.0.0: ๅฎŒๆ•ด็š„ไบคไบ’ๅผๅ้ฆˆ็ณป็ปŸ

    • ๆ–ฐๅขž RESTful API
    • ๅ“ๅบ”ๅผ Web ็•Œ้ข
    • WebSocket ๅฎžๆ—ถ้€šไฟก
    • ๅขžๅผบ็š„ MCP ๅทฅๅ…ท
    • ๅฎŒๆ•ด็š„ๆต‹่ฏ•ๅฅ—ไปถ
  • v1.0.0: ๅŸบ็ก€ MCP ๆœๅŠกๅ™จ

    • JWT ่ฎค่ฏ
    • ๅŸบ็ก€ๅ้ฆˆๅทฅๅ…ท
    • KV ๅญ˜ๅ‚จ