Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Protocols

Pierre implements three protocols on a single http port (8081).

MCP (Model Context Protocol)

Json-rpc 2.0 protocol for ai assistant integration.

Endpoints

  • POST /mcp - main mcp endpoint
  • GET /mcp/sse/{session_id} - sse transport for streaming (session-scoped)

Transport

Pierre supports both http and sse transports:

  • http: traditional request-response
  • sse: server-sent events for streaming responses

Sdk handles transport negotiation automatically.

Authentication

Mcp requests require jwt bearer token in authorization header:

Authorization: Bearer <jwt_token>

Obtained via oauth2 flow (sdk handles automatically).

Request Format

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "name": "get_activities",
    "arguments": {
      "limit": 5
    }
  }
}

Response Format

{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[activity data...]"
      }
    ]
  }
}

Output Format Parameter

Most data-returning tools support an optional format parameter for output serialization:

FormatDescriptionUse Case
jsonStandard JSON (default)Universal compatibility
toonToken-Oriented Object Notation~40% fewer LLM tokens

Example with TOON format:

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "name": "get_activities",
    "arguments": {
      "provider": "strava",
      "limit": 100,
      "format": "toon"
    }
  }
}

TOON format responses include format: "toon" and content_type: "application/vnd.toon" in the result. Use TOON for large datasets (year summaries, batch analysis) to reduce LLM context usage.

See TOON specification for format details.

MCP Methods

  • initialize - start session
  • tools/list - list available tools
  • tools/call - execute tool
  • resources/list - list resources
  • prompts/list - list prompts

Implementation: src/mcp/protocol.rs, src/protocols/universal/

OAuth2 Authorization Server

Rfc 7591 (dynamic client registration) + rfc 7636 (pkce) compliant oauth2 server for mcp client authentication.

Endpoints

  • GET /.well-known/oauth-authorization-server - server metadata (rfc 8414)
  • POST /oauth2/register - dynamic client registration
  • GET /oauth2/authorize - authorization endpoint
  • POST /oauth2/token - token endpoint
  • GET /oauth2/jwks - json web key set
  • GET /.well-known/jwks.json - jwks at standard oidc location
  • POST /oauth2/validate-and-refresh - validate and refresh jwt tokens
  • POST /oauth2/token-validate - validate jwt token

Registration Flow

  1. client registration (rfc 7591):
# local development (http allowed for localhost)
curl -X POST http://localhost:8081/oauth2/register \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_uris": ["http://localhost:35535/oauth/callback"],
    "client_name": "My MCP Client (Dev)",
    "grant_types": ["authorization_code"]
  }'

# production (https required)
curl -X POST https://api.example.com/oauth2/register \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_uris": ["https://client.example.com/oauth/callback"],
    "client_name": "My MCP Client",
    "grant_types": ["authorization_code"]
  }'

Response:

{
  "client_id": "generated_client_id",
  "client_secret": "generated_secret",
  "redirect_uris": ["http://localhost:35535/oauth/callback"],
  "grant_types": ["authorization_code"]
}

callback url security: redirect_uris using http only permitted for localhost/127.0.0.1 in development. Production clients must use https to protect authorization codes from interception.

  1. authorization request:
GET /oauth2/authorize?
  client_id=<client_id>&
  redirect_uri=<redirect_uri>&
  response_type=code&
  code_challenge=<pkce_challenge>&
  code_challenge_method=S256

User authenticates in browser, redirected to:

<redirect_uri>?code=<authorization_code>
  1. token exchange:
curl -X POST http://localhost:8081/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&\
      code=<authorization_code>&\
      client_id=<client_id>&\
      client_secret=<client_secret>&\
      redirect_uri=<redirect_uri>&\
      code_verifier=<pkce_verifier>"

Response:

{
  "access_token": "jwt_token",
  "token_type": "Bearer",
  "expires_in": 86400
}

Jwt access token used for all mcp requests.

PKCE Requirement

Pierre enforces pkce (rfc 7636) for all authorization code flows. Clients must:

  • generate code verifier (43-128 characters)
  • create code challenge: base64url(sha256(verifier))
  • include challenge in authorization request
  • include verifier in token request

Server Discovery (RFC 8414)

Pierre provides oauth2 server metadata for automatic configuration:

curl http://localhost:8081/.well-known/oauth-authorization-server

Response includes:

{
  "issuer": "http://localhost:8081",
  "authorization_endpoint": "http://localhost:8081/oauth2/authorize",
  "token_endpoint": "http://localhost:8081/oauth2/token",
  "jwks_uri": "http://localhost:8081/oauth2/jwks",
  "registration_endpoint": "http://localhost:8081/oauth2/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "code_challenge_methods_supported": ["S256"]
}

Issuer url configurable via OAUTH2_ISSUER_URL environment variable.

JWKS Endpoint

Public keys for jwt token verification available at /oauth2/jwks:

curl http://localhost:8081/oauth2/jwks

Response (rfc 7517 compliant):

{
  "keys": [
    {
      "kty": "RSA",
      "use": "sig",
      "kid": "key_2024_01_01",
      "n": "modulus_base64url",
      "e": "exponent_base64url"
    }
  ]
}

cache-control headers: jwks endpoint returns Cache-Control: public, max-age=3600 allowing browsers to cache public keys for 1 hour.

Key Rotation

Pierre supports rs256 key rotation with grace period:

  • new keys generated with timestamp-based kid (e.g., key_2024_01_01_123456)
  • old keys retained during grace period for existing token validation
  • tokens issued with old keys remain valid until expiration
  • new tokens signed with current key

Clients should:

  1. Fetch jwks on startup
  2. Cache public keys for 1 hour (respects cache-control header)
  3. Refresh jwks if unknown kid encountered
  4. Verify token signature using matching kid

Rate Limiting

Oauth2 endpoints protected by per-ip token bucket rate limiting:

endpointrequests per minute
/oauth2/authorize60 (1/second)
/oauth2/token30 (1/2 seconds)
/oauth2/register10 (1/6 seconds)

Rate limit headers included in all responses:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1704067200

429 response when limit exceeded:

{
  "error": "rate_limit_exceeded",
  "error_description": "Rate limit exceeded. Retry after 42 seconds."
}

Headers:

Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704067200

Implementation: src/oauth2_server/, src/oauth2_server/rate_limiting.rs

A2A (Agent-to-Agent Protocol)

Protocol for autonomous ai systems to communicate.

Endpoints

  • GET /a2a/status - protocol status
  • GET /a2a/tools - available tools
  • POST /a2a/execute - execute tool
  • GET /a2a/monitoring - monitoring info

Authentication

A2A endpoints use JWT Bearer authentication (same as MCP):

Authorization: Bearer <jwt_token>

Create jwt token via admin endpoint:

curl -X POST http://localhost:8081/api/keys \
  -H "Authorization: Bearer <admin_jwt>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My A2A System", "tier": "professional"}'

Agent Cards

Agents advertise capabilities via agent cards:

{
  "agent_id": "fitness-analyzer",
  "name": "Fitness Analyzer Agent",
  "version": "1.0.0",
  "capabilities": [
    "activity_analysis",
    "performance_prediction",
    "goal_tracking"
  ],
  "endpoints": [
    {
      "path": "/a2a/execute",
      "method": "POST",
      "description": "Execute fitness analysis"
    }
  ]
}

Request Format

{
  "tool": "analyze_activity",
  "parameters": {
    "activity_id": "12345",
    "analysis_type": "comprehensive"
  }
}

Response Format

{
  "success": true,
  "result": {
    "analysis": {...},
    "recommendations": [...]
  }
}

Implementation: src/a2a/, src/protocols/universal/

REST API

Traditional rest endpoints for web applications.

Authentication Endpoints

  • POST /api/auth/register - user registration (admin-provisioned)
  • POST /api/auth/login - user login
  • POST /api/auth/logout - logout
  • POST /api/auth/refresh - refresh jwt token

Provider OAuth Endpoints

  • GET /api/oauth/auth/{provider}/{user_id} - initiate oauth (strava, garmin, fitbit, whoop)
  • GET /api/oauth/callback/{provider} - oauth callback
  • GET /api/oauth/status - connection status

Admin Endpoints

  • POST /admin/setup - create admin user
  • POST /admin/users - manage users
  • GET /admin/analytics - usage analytics

Configuration Endpoints

  • GET /api/configuration/catalog - config catalog
  • GET /api/configuration/profiles - available profiles
  • GET /api/configuration/user - user config
  • PUT /api/configuration/user - update config

Implementation: src/routes.rs, src/admin_routes.rs, src/configuration_routes.rs

SSE (Server-Sent Events)

Real-time notifications for oauth completions and system events.

Endpoint

GET /notifications/sse/:user_id

Event Types

  • oauth_complete - oauth flow completed
  • oauth_error - oauth flow failed
  • system_status - system status update

Example

const eventSource = new EventSource('/notifications/sse/user-123');

eventSource.onmessage = function(event) {
  const notification = JSON.parse(event.data);
  if (notification.type === 'oauth_complete') {
    console.log('OAuth completed for provider:', notification.provider);
  }
};

Implementation: src/sse/routes.rs, src/sse/

Protocol Comparison

featuremcpoauth2a2arest
primary useai assistantsclient authagent commsweb apps
auth methodjwt bearer-api keyjwt bearer
transporthttp + ssehttphttphttp
formatjson-rpc 2.0oauth2jsonjson
implementationsrc/mcp/src/oauth2_server/src/a2a/src/routes/

Choosing a Protocol

  • ai assistant integration: use mcp (claude, chatgpt)
  • web application: use rest api
  • autonomous agents: use a2a
  • client authentication: use oauth2 (for mcp clients)

All protocols share the same business logic via src/protocols/universal/.