Skip to main content

MCP Protocol 2025-03-26 Compliance

📋 Context & Objective

You’re building a remote MCP server to be used as a custom connector in Claude (web and desktop apps). This allows Claude users to add your server via Settings > Connectors and use your tools directly in conversations. Target Use Case: Users will:
  1. Navigate to Claude Settings > Connectors
  2. Click “Add custom connector”
  3. Enter your server’s discovery URL: https://nqfciqtsrcjorlqcglmq.supabase.co/functions/v1/mcp-router/{slug}/.well-known/mcp-server
  4. Optionally configure OAuth credentials
  5. Authenticate and enable tools
  6. Use your tools in Claude conversations

✅ Implementation Status: COMPLIANT

Discovery Endpoint ✅

  • Format: Returns PLAIN JSON (not JSON-RPC wrapped) per specification
  • URL: /.well-known/mcp-server
  • Content: Server metadata, capabilities, single /messages endpoint, authentication
  • Optimization: Discovery focuses on /messages as primary endpoint for Claude Connectors

Streamable HTTP Transport ✅

  • Primary Endpoint: /messages - Single endpoint for all JSON-RPC communication
  • Base URL Support: / - Also accepts JSON-RPC requests (mcp-remote compatibility)
  • Supported Methods: POST (JSON-RPC requests), GET (discovery/SSE streaming)
  • Protocol Compliance: Both /messages and / handle JSON-RPC identically
  • Authentication Note: Base URL (mcp-router) is publicly accessible (verify_jwt = false), but individual deployments enforce authentication based on their mcp_auth_method setting
  • Utility Endpoints: /health, /docs available but not part of MCP discovery

JSON-RPC Methods Supported ✅

  • initialize - Session initialization
  • tools/list - List available tools
  • tools/call - Execute a tool
  • resources/list - List user-defined resources
  • resources/templates/list - List resource templates
  • resources/read - Read resource content by URI
  • prompts/list - List user-defined prompts
  • prompts/get - Get prompt and render template with arguments

Pagination

Pagination fields (cursor, nextCursor) are accepted but not implemented. All list operations return nextCursor: null.

Unsupported Sub-Capabilities

  • resources/subscribe - Returns -32601 (not supported)
  • resources/listChanged - Not implemented
  • prompts/listChanged - Not implemented

Authentication ✅

  • OAuth 2.1 with PKCE support
  • JWT Bearer token support
  • Public (no-auth) mode available
  • Configurable per deployment

📊 Compliance Checklist

Discovery & Configuration ✅

  • /.well-known/mcp-server returns valid, spec-compliant PLAIN JSON
  • Discovery focuses on single /messages endpoint (MCP best practice)
  • Base URL (/) accepts JSON-RPC for mcp-remote compatibility
  • Server metadata includes all required fields with tool count
  • Endpoint URLs are complete HTTPS URLs
  • Authentication configuration is correct for deployment type
  • OAuth metadata endpoint exists (for OAuth deployments)
  • Utility endpoints in _meta for monitoring (not part of MCP discovery)

Transport Implementation ✅

  • Single /messages endpoint implements Streamable HTTP
  • POST method handles JSON-RPC messages
  • GET method supports SSE streaming
  • Legacy endpoints maintained for compatibility
  • Proper CORS headers

Protocol Compliance ✅

  • JSON-RPC 2.0 format used correctly
  • Request IDs preserved in responses
  • Error codes match specification (-32600, -32601, -32602, -32700)
  • Required methods implemented (initialize, tools/list, tools/call)

Tool Functionality ✅

  • Tools discovered via tools/list
  • Tool metadata complete (name, description, inputSchema)
  • Tools invoked via tools/call
  • Parameters validated
  • Results in MCP content format
  • OpenAPI → Tool conversion working
  • API calls execute successfully

🧪 Test Validation Results

✅ Discovery Endpoint Tests (CRITICAL)

Endpoint: /.well-known/mcp-server Status: ✅ PASSING

✅ Messages Endpoint Tests

Endpoint: /messages Status: ✅ PASSING

✅ Initialize Method

Method: initialize Status: ✅ PASSING Implementation:

✅ Tools List Method

Method: tools/list Status: ✅ PASSING Tool Extraction Logic:
  • ✅ Iterates through all OpenAPI paths
  • ✅ Extracts GET, POST, PUT, PATCH, DELETE operations
  • ✅ Generates tool names from operationId or path+method
  • ✅ Builds input schemas from parameters and request body
  • ✅ Marks required fields appropriately
  • ✅ Comprehensive error handling (returns partial results on error)

✅ Tools Call Method

Method: tools/call Status: ✅ PASSING Implementation:
  1. ✅ Validates tool name exists
  2. ✅ Finds endpoint in OpenAPI spec
  3. ✅ Constructs target API URL
  4. ✅ Injects authentication (Bearer, API Key, Basic)
  5. ✅ Handles path, query, header, body parameters
  6. ✅ Makes HTTP request to target service
  7. ✅ Returns response in MCP content format

✅ Error Handling

Status: ✅ PASSING Error Response Format:

✅ CORS Configuration

Status: ✅ PASSING

✅ Production Readiness

Status: ✅ READY

🔧 Critical Fixes Applied

1. Discovery Endpoint Access (CRITICAL)

Problem: Discovery endpoint was behind authentication layer, violating MCP spec. Fix:
  • Moved discovery check before authentication
  • Returns early with public response
  • Clients can now discover auth requirements before authenticating
Code Location: supabase/functions/mcp-router/index.ts:115-227

2. Tool Extraction Error Handling (CRITICAL)

Problem: extractToolDefinitions could crash on malformed OpenAPI specs. Fix:
  • Added validation for spec structure
  • Safe null/undefined checks
  • Try-catch with graceful degradation
  • Returns empty array on error (server still works)
Code Location: supabase/functions/mcp-router/index.ts:1466-1537

3. Console Output Contamination (CRITICAL)

Problem: Console logs could contaminate HTTP response body. Fix:
  • All logs prefixed with [INTERNAL] or similar
  • console.error for errors (goes to stderr)
  • No output between response creation and return
Verification: All console.log statements reviewed and validated.

4. JSON Response Purity (CRITICAL)

Problem: Any text before/after JSON breaks parsing. Fix:
  • No console output before response
  • Clean JSON.stringify(metadata, null, 2)
  • No trailing newlines
  • Proper Content-Type: application/json; charset=utf-8

🔑 Key Architecture Decisions

Why Single /messages Endpoint?

Per MCP Streamable HTTP specification (2025-03-26):
  • Server MUST provide ONE endpoint for all JSON-RPC communication
  • Simplifies client implementation
  • Enables efficient streaming via SSE
  • Standard approach for remote MCP servers

Why Plain JSON for Discovery?

Per MCP specification and Claude Connectors requirements:
  • Discovery endpoint is NOT part of JSON-RPC communication
  • It’s a metadata endpoint queried before establishing connection
  • Must be parseable without JSON-RPC knowledge
  • Matches all reference implementations

Discovery Optimization for Claude Connectors

  • Discovery returns single /messages endpoint per MCP spec
  • Claude Connectors only need /messages to function
  • Utility endpoints (/health, /docs) available but in _meta section
  • Legacy /tool endpoint remains functional but not advertised
  • Clean, focused discovery response for better client compatibility

📚 API Reference

Discovery Endpoint

Returns PLAIN JSON (optimized for Claude Connectors):

Messages Endpoint (Primary)

Response:

SSE Streaming (Optional)

Returns SSE stream for server-initiated messages.

Base URL Endpoint (mcp-remote compatibility)

Endpoint: POST /
Authentication: Same as /messages endpoint
Description: Base URL accepts JSON-RPC requests and routes them to /messages handler
Purpose: Some MCP clients (like mcp-remote proxy) send JSON-RPC requests to the base URL instead of /messages. This endpoint provides compatibility with those clients while maintaining backward compatibility for discovery requests. Request:
Response:
Behavior:
  • JSON-RPC requests (with jsonrpc: "2.0" and method field) → Routed to /messages handler
  • Non-JSON-RPC POST requests → Returns discovery metadata
  • GET requests → Returns discovery metadata (unchanged)
  • All JSON-RPC methods supported: initialize, tools/list, tools/call
Implementation Note: The base URL handler reads the request body once, detects JSON-RPC format, then reconstructs a new Request object and forwards to /messages. This avoids “Body already consumed” errors while maintaining DRY principles.

🧪 Testing & Integration

Testing with Claude

Add Connector

  1. Go to Claude Settings > Connectors
  2. Click “Add custom connector”
  3. Enter URL: https://nqfciqtsrcjorlqcglmq.supabase.co/functions/v1/mcp-router/{your-slug}/.well-known/mcp-server
  4. Configure OAuth (if required)
  5. Click “Add”

Enable Tools

  1. Start a chat in Claude
  2. Click “Search and tools” (lower left)
  3. Find your connector
  4. Enable specific tools
  5. Use tools in conversation

Step-by-Step Claude.ai Integration

  1. Open Claude.ai
  2. Navigate to Connectors
    • Click Settings (gear icon)
    • Select “Connectors” from the menu
  3. Add Custom Connector
    • Click “Add custom connector”
    • Enter discovery URL: https://nqfciqtsrcjorlqcglmq.supabase.co/functions/v1/mcp-router/{your-slug}/.well-known/mcp-server
  4. Complete Authentication (if required)
    • For OAuth: Follow OAuth flow
    • For JWT: Enter Bearer token
    • For public (none): No auth needed
  5. Enable Tools
    • Review available tools
    • Toggle on/off as needed
    • Click “Save”
  6. Start Using
    • Tools are now available in conversations
    • Claude can invoke them automatically
    • Monitor usage in dashboard

Test Execution

Run Test Suite:
Expected Results:
  • Total Tests: 45
  • Passed: 45
  • Failed: 0
  • Pass Rate: 100.0%
  • Status: ✓ ALL TESTS PASSED
Note: Test script uses head -n -2 which is not supported on macOS/BSD systems. Use Linux or modify script to use sed '$d' "$output_file" | sed '$d' instead.

Quick Validation Commands

Common Troubleshooting

Issue: Tools not appearing in Claude
  • ✅ Check OpenAPI spec is valid
  • ✅ Verify tools/list returns tools array
  • ✅ Check authentication is configured correctly
Issue: Tool execution fails
  • ✅ Verify target API credentials
  • ✅ Check API base URL is correct
  • ✅ Review parameter mapping
Issue: Authentication errors
  • ✅ Verify JWT token or OAuth setup
  • ✅ Check token expiration
  • ✅ Validate token in database
Issue: Connector not adding
  • ✅ Verify discovery endpoint is publicly accessible
  • ✅ Check JSON format is valid (not JSON-RPC wrapped)
  • ✅ Ensure HTTPS is enforced

🔒 Security Measures

Implemented Security Features

  1. Row Level Security (RLS)
    • All database tables protected
    • Users can only access their own data
  2. Rate Limiting
    • Enforced via Supabase stored procedures
    • Hourly and monthly limits
  3. Authentication Options
    • OAuth 2.1 with PKCE
    • JWT Bearer tokens
    • Public access (configurable)
  4. No Code Execution
    • Server only routes to target APIs
    • No user code is ever executed
    • OpenAPI specs stored securely
  5. Input Validation
    • JSON-RPC validation
    • Parameter type checking
    • Tool name validation

OAuth 2.1 Requirements

  • ✅ PKCE required (S256 only, plain not supported)
  • ✅ State parameter for CSRF protection
  • ✅ Redirect URI exact matching (no wildcards)
  • ✅ HTTPS required (except localhost)
  • ✅ Rate limiting: 20/hour authorize, 10/min token, 20/hour register

Token Security

  • ✅ Access tokens: 1-hour expiration
  • ✅ Format: mcp_access_{uuid}
  • ✅ Revocation via revoked flag in database
  • ✅ Validation on every request
  • ✅ One-time use authorization codes
For more details, see Security

⚡ Performance Characteristics

Expected Response Times

Optimization Notes

  • ✅ Discovery endpoint caching (Cache-Control: no-store intentional for fresh auth info)
  • ✅ Tool definitions extracted once per request
  • ✅ Database queries optimized with proper indexing
  • ✅ No unnecessary external API calls

📊 Monitoring & Debugging

Edge Function Logs

View logs in Lovable Cloud backend:
  • Look for [MCP-Auth] Authentication events
  • Look for [INTERNAL] Internal processing logs
  • Look for [ERROR-*] Error events with UUIDs
Query Logs:
For detailed monitoring guidance, see User Guide

🔍 Verification Tests

1. Metadata Discovery

Expected: JSON with protocol_version: "2025-03-26"

2. Protocol Headers

Expected: Header MCP-Protocol-Version: 2025-03-26

3. Authentication

4. OAuth Discovery

Expected: JSON with authorization, token, and registration endpoints

OAuth Metadata Response


📖 References


🎯 Success Criteria

Your server is Claude Connector Ready when: ✅ Discovery endpoint returns valid plain JSON
✅ Can be added as custom connector in Claude
✅ OAuth flow completes (if configured)
✅ Tools appear in Claude’s tool selector
✅ Tools can be invoked from conversation
✅ Results display correctly
✅ Error handling works gracefully

🚀 Status & Next Steps

Status:PRODUCTION READY FOR CLAUDE CONNECTORS The server now fully complies with:
  • MCP Protocol Specification 2025-03-26
  • MCP Streamable HTTP Transport
  • Claude Custom Connector Requirements
  • JSON-RPC 2.0 Specification
Next Steps:
  1. Test Discovery: Verify plain JSON response
  2. Test Messages Endpoint: Send JSON-RPC request
  3. Add to Claude: Use discovery URL in Claude Settings > Connectors
  4. Test Tool Execution: Enable tools and use in conversation
  5. Monitor Usage: Check logs and handle errors appropriately

Implementation: supabase/functions/mcp-router/index.ts
OAuth Server: supabase/functions/mcp-oauth-server/index.ts
Last Verified: October 20, 2025