Files
gh-jezweb-claude-skills-ski…/references/common-issues.md
2025-11-30 08:24:23 +08:00

6.8 KiB

Common Issues and Troubleshooting

Detailed troubleshooting for the 15 most common Cloudflare MCP server errors.


1. McpAgent Class Not Exported

Error: TypeError: Cannot read properties of undefined (reading 'serve')

Diagnosis: Check if your McpAgent class is exported

Solution:

// ✅ CORRECT
export class MyMCP extends McpAgent { ... }

// ❌ WRONG
class MyMCP extends McpAgent { ... }  // Missing export!

2. Transport Mismatch

Error: Connection failed: Unexpected response format

Diagnosis: Client and server transport don't match

Debug:

# Check what your server supports
curl https://my-mcp.workers.dev/sse
curl https://my-mcp.workers.dev/mcp

Solution: Serve both transports (see SKILL.md Transport section)


3. OAuth Redirect URI Mismatch

Error: OAuth error: redirect_uri does not match

Diagnosis: Check client configuration vs deployed URL

Common causes:

  • Developed with localhost, deployed to workers.dev
  • HTTP vs HTTPS
  • Missing /oauth/callback path
  • Typo in domain

Solution:

// Update after deployment
{
  "mcpServers": {
    "my-mcp": {
      "url": "https://my-mcp.YOUR_ACCOUNT.workers.dev/sse",
      "auth": {
        "authorizationUrl": "https://my-mcp.YOUR_ACCOUNT.workers.dev/authorize",
        "tokenUrl": "https://my-mcp.YOUR_ACCOUNT.workers.dev/token"
      }
    }
  }
}

4. WebSocket Hibernation State Loss

Error: State not found after WebSocket reconnect

Diagnosis: Using in-memory state instead of storage

Wrong:

class MyMCP extends McpAgent {
  userId: string;  // ❌ Lost on hibernation!

  async init() {
    this.userId = "123";
  }
}

Correct:

class MyMCP extends McpAgent {
  async init() {
    await this.state.storage.put("userId", "123");  // ✅ Persisted
  }
}

5. Durable Objects Binding Missing

Error: Cannot read properties of undefined (reading 'idFromName')

Diagnosis: Check wrangler.jsonc

Solution:

{
  "durable_objects": {
    "bindings": [
      {
        "name": "MY_MCP",
        "class_name": "MyMCP",
        "script_name": "my-mcp-server"
      }
    ]
  }
}

6. Migration Not Defined

Error: Durable Object class MyMCP has no migration defined

Diagnosis: First DO deployment needs migration

Solution:

{
  "migrations": [
    {
      "tag": "v1",
      "new_classes": ["MyMCP"]
    }
  ]
}

After first deployment, migrations are locked. Subsequent changes require new migration tags (v2, v3, etc.).


7. CORS Errors

Error: Access blocked by CORS policy

Diagnosis: Remote MCP server needs CORS headers

Solution: Use OAuthProvider (handles CORS automatically) or add headers:

return new Response(body, {
  headers: {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
  }
});

8. Client Configuration Format Error

Error: Claude Desktop doesn't see MCP server

Diagnosis: Check JSON format

Wrong:

{
  "mcpServers": [  // ❌ Array instead of object!
    {
      "name": "my-mcp",
      "url": "..."
    }
  ]
}

Correct:

{
  "mcpServers": {  // ✅ Object with named servers
    "my-mcp": {
      "url": "..."
    }
  }
}

Location:

  • Mac: ~/.config/claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json
  • Linux: ~/.config/claude/claude_desktop_config.json

9. serializeAttachment() Not Used

Error: WebSocket metadata lost on hibernation

Solution:

// Store metadata on WebSocket
webSocket.serializeAttachment({
  userId: "123",
  sessionId: "abc",
  connectedAt: Date.now()
});

// Retrieve on wake
const metadata = webSocket.deserializeAttachment();
console.log(metadata.userId);  // "123"

Security risk: Users don't know what they're authorizing

Wrong:

allowConsentScreen: false  // ❌ Never in production!

Correct:

allowConsentScreen: true  // ✅ Always in production

11. JWT Signing Key Missing

Error: JWT_SIGNING_KEY environment variable not set

Solution:

# Generate secure key
openssl rand -base64 32

# Add to secrets
npx wrangler secret put JWT_SIGNING_KEY

# Or add to wrangler.jsonc (less secure)
"vars": {
  "JWT_SIGNING_KEY": "generated-key-here"
}

12. Environment Variables Not Configured

Error: env.MY_VAR is undefined

Diagnosis: Variables only in .dev.vars, not in wrangler.jsonc

Wrong:

# .dev.vars only (works locally, fails in production)
MY_VAR=value

Correct:

// wrangler.jsonc
{
  "vars": {
    "MY_VAR": "production-value"
  }
}

For secrets:

npx wrangler secret put MY_SECRET

13. Tool Schema Validation Error

Error: ZodError: Invalid input type

Diagnosis: Client sends different type than schema expects

Solution: Use Zod transforms or coerce

// Client sends string "123", but you need number
{
  count: z.string().transform(val => parseInt(val, 10))
}

// Or use coerce
{
  count: z.coerce.number()
}

14. Multiple Transport Endpoints Conflicting

Error: /sse returns 404 after adding /mcp

Diagnosis: Path matching issue

Wrong:

if (pathname === "/sse") {  // ❌ Misses /sse/message
  return MyMCP.serveSSE("/sse").fetch(request, env, ctx);
}

Correct:

if (pathname === "/sse" || pathname.startsWith("/sse/")) {  // ✅
  return MyMCP.serveSSE("/sse").fetch(request, env, ctx);
}

15. Local Testing Limitations

Error: OAuth flow fails in npm run dev

Diagnosis: Miniflare doesn't support all DO features

Solutions:

Option 1: Use remote dev

npx wrangler dev --remote

Option 2: Test OAuth on deployed Worker

npx wrangler deploy
# Test at https://my-mcp.workers.dev

Option 3: Mock OAuth for local testing

if (env.ENVIRONMENT === "development") {
  // Skip OAuth, use mock user
  return {
    userId: "test-user",
    email: "test@example.com"
  };
}

General Debugging Tips

Check Logs

npx wrangler tail

Test with MCP Inspector

npx @modelcontextprotocol/inspector@latest

Verify Bindings

npx wrangler kv:namespace list
npx wrangler d1 list

Check Deployment

npx wrangler deployments list

View Worker Code

npx wrangler whoami
# Visit dashboard: https://dash.cloudflare.com/

Still stuck? Check: