Skip to content

Authentication Endpoints

The MCP endpoint requires authentication via JWT bearer tokens. This page documents the authenticated MCP JSON-RPC endpoint.

Overview

EndpointMethodAuthenticationPurpose
/mcpPOSTRequiredMCP JSON-RPC communication

POST /mcp

MCP JSON-RPC Endpoint - Primary endpoint for Model Context Protocol communication.

Authentication

Required: Valid JWT bearer token in Authorization header.

http
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

The JWT must:

  • Have valid signature (verified via JWKS)
  • Match configured issuer (OIDC_ISSUER)
  • Match configured audience (OIDC_AUDIENCE)
  • Not be expired
  • Include sub (subject) claim

Session Management

Header: mcp-session-id

http
mcp-session-id: 123e4567-e89b-12d3-a456-426614174000

Session Flow:

  1. First request: Send initialize without session ID
  2. Server response: Includes mcp-session-id header
  3. Subsequent requests: Include mcp-session-id from initialization

Initialize Request

Start a new MCP session (first request, no session ID).

Request:

http
POST /mcp
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

{
  "jsonrpc": "2.0",
  "method": "initialize",
  "params": {
    "protocolVersion": "0.1.0",
    "capabilities": {},
    "clientInfo": {
      "name": "Claude Desktop",
      "version": "1.0.0"
    }
  },
  "id": 1
}

Response:

http
HTTP/1.1 200 OK
Content-Type: application/json
mcp-session-id: 123e4567-e89b-12d3-a456-426614174000

{
  "jsonrpc": "2.0",
  "result": {
    "protocolVersion": "0.1.0",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "seed",
      "version": "0.1.3"
    }
  },
  "id": 1
}

Response Fields:

  • protocolVersion: MCP protocol version
  • capabilities.tools: Server supports tool calling
  • serverInfo.name: Server name from package.json
  • serverInfo.version: Server version from package.json

List Tools

Retrieve available MCP tools.

Request:

http
POST /mcp
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
mcp-session-id: 123e4567-e89b-12d3-a456-426614174000

{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "params": {},
  "id": 2
}

Response:

json
{
  "jsonrpc": "2.0",
  "result": {
    "tools": [
      {
        "name": "seed_ping",
        "description": "Ping the Seed server to test connectivity",
        "inputSchema": {
          "type": "object",
          "properties": {
            "message": {
              "type": "string",
              "description": "Optional message to include in the response"
            }
          }
        }
      }
    ]
  },
  "id": 2
}

Tool Schema Fields:

  • name: Tool identifier
  • description: Human-readable description
  • inputSchema: JSON Schema for parameters

Call Tool

Execute an MCP tool.

Request:

http
POST /mcp
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
mcp-session-id: 123e4567-e89b-12d3-a456-426614174000

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "seed_ping",
    "arguments": {
      "message": "Hello from Claude"
    }
  },
  "id": 3
}

Response (Success):

json
{
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Seed MCP Server: Hello from Claude"
      }
    ]
  },
  "id": 3
}

Response (Error):

json
{
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Error: Invalid parameter"
      }
    ],
    "isError": true
  },
  "id": 3
}

Content Types:

  • text: Plain text or markdown
  • image: Base64-encoded image with mimeType
  • resource: Reference to external resource

Error Responses

Authentication Errors

401 Unauthorized - Authentication failed.

http
HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Bearer resource_metadata="https://seed.example.com/.well-known/oauth-protected-resource"

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32001,
    "message": "Unauthorized",
    "data": {
      "reason": "invalid_token",
      "details": "JWT signature verification failed"
    }
  },
  "id": null
}

Error Reasons:

  • missing_token: No Authorization header
  • invalid_format: Not "Bearer <token>" format
  • invalid_token: Signature verification failed
  • expired_token: Token expired
  • invalid_issuer: Issuer mismatch
  • invalid_audience: Audience mismatch
  • missing_claim: Required sub claim missing

Session Errors

400 Bad Request - Invalid or missing session ID.

json
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Bad Request: No valid session ID provided"
  },
  "id": null
}

When this occurs:

  • Session ID not provided (except for initialize)
  • Session ID not found in transport map
  • Session expired or connection closed

Protocol Errors

400 Bad Request - Invalid JSON-RPC request.

json
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32600,
    "message": "Invalid Request",
    "data": {
      "details": "Missing required field: method"
    }
  },
  "id": null
}

JSON-RPC Error Codes:

  • -32700: Parse error (invalid JSON)
  • -32600: Invalid request
  • -32601: Method not found
  • -32602: Invalid params
  • -32603: Internal error

Request Examples

cURL Examples

Initialize:

bash
curl -X POST https://seed.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "method": "initialize",
    "params": {
      "protocolVersion": "0.1.0",
      "capabilities": {}
    },
    "id": 1
  }'

List Tools:

bash
curl -X POST https://seed.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "mcp-session-id: $SESSION_ID" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "params": {},
    "id": 2
  }'

Call Tool:

bash
curl -X POST https://seed.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "mcp-session-id: $SESSION_ID" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "seed_ping",
      "arguments": {"message": "test"}
    },
    "id": 3
  }'

TypeScript Example

typescript
// Initialize session
const initResponse = await fetch("https://seed.example.com/mcp", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${jwtToken}`,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    method: "initialize",
    params: {
      protocolVersion: "0.1.0",
      capabilities: {},
    },
    id: 1,
  }),
});

const sessionId = initResponse.headers.get("mcp-session-id");

// List tools
const toolsResponse = await fetch("https://seed.example.com/mcp", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${jwtToken}`,
    "mcp-session-id": sessionId,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    method: "tools/list",
    params: {},
    id: 2,
  }),
});

const tools = await toolsResponse.json();

// Call tool
const callResponse = await fetch("https://seed.example.com/mcp", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${jwtToken}`,
    "mcp-session-id": sessionId,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    method: "tools/call",
    params: {
      name: "seed_ping",
      arguments: { message: "Hello" },
    },
    id: 3,
  }),
});

const result = await callResponse.json();

Rate Limiting

Currently, no rate limiting is enforced on the MCP endpoint. Authentication via JWT provides implicit rate limiting through token validity periods.

Future Considerations:

  • Per-user rate limiting based on sub claim
  • Per-tool rate limiting
  • Concurrent session limits

Security Considerations

JWT Validation

  • Every request validates JWT signature
  • Tokens must not be expired
  • Issuer and audience claims verified
  • Subject claim required

Session Security

  • UUID session IDs (unpredictable)
  • Sessions isolated per connection
  • No session persistence (memory only)
  • Automatic cleanup on disconnect

User Context

  • User identity from JWT sub claim
  • Optional email, name, groups claims
  • Context available to tools for authorization
  • No server-side user state

Best Practices

Client Implementation

  1. Store session ID: Cache after initialization
  2. Reuse sessions: Don't reinitialize unnecessarily
  3. Handle errors: Implement retry logic for network errors
  4. Token refresh: Renew JWT before expiration
  5. Validate responses: Check jsonrpc version and error codes

Tool Calling

  1. Check tool schema: Validate parameters before calling
  2. Handle isError flag: Check for tool-level errors
  3. Parse content types: Handle text, image, resource appropriately
  4. Timeout handling: Implement client-side timeouts
  5. Error recovery: Retry transient failures

Testing

Health Check

Verify server is running:

bash
curl https://seed.example.com/health

Token Testing

Test JWT validation:

bash
# Should fail with 401
curl -X POST https://seed.example.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}'

# Should succeed
curl -X POST https://seed.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $VALID_JWT" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"0.1.0","capabilities":{}},"id":1}'

Released under the MIT License.