IDENTITY

title: "TICKET_054: Add OAuth 2.1 to Bus MCP Server for Custom Connectors"
type: ticket
subtype: execution
purpose: "Implement MCP-spec OAuth 2.1 on the Bus MCP Server so claude.ai Custom Connectors (B1-B5 web tabs) can authenticate and connect."

GOVERNANCE

status: ready
priority: P0
sprint: S001_base_and_mvp1
assignee: "CM0 (build on Mac) → CC0 (deploy on Hetzner)"
estimated_hours: 2
depends_on: [TICKET_049]
blocks: [TICKET_053]
last_updated: "2026-03-22 01:00"
blueprint: "BLUEPRINT_Bus_MCP_Server_v1.md"

TICKET_054: Add OAuth 2.1 to Bus MCP Server

Problem

Claude.ai Custom Connectors do NOT support raw bearer tokens. They only support:

  1. Authless (no auth)
  2. OAuth 2.0/2.1 with authorization code flow

Our Bus MCP Server currently only has bearer token auth. Web brains (B1-B5) cannot connect via Custom Connectors without OAuth.

Claude Code CLI (CM0/CC0) already works with bearer tokens via claude mcp add. This ticket adds OAuth for web surfaces only.

Solution

Implement the MCP OAuth 2.1 authorization spec on the Bus MCP Server. Claude will act as the OAuth client using our registered Client ID.

Key Facts from Research

Implementation Plan

Step 1: Add OAuth discovery endpoints

GET /.well-known/oauth-authorization-server

{
  "issuer": "https://bus.struxio.ai",
  "authorization_endpoint": "https://bus.struxio.ai/oauth/authorize",
  "token_endpoint": "https://bus.struxio.ai/oauth/token",
  "registration_endpoint": "https://bus.struxio.ai/oauth/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"],
  "code_challenge_methods_supported": ["S256"],
  "scopes_supported": ["bus:read", "bus:write", "paperclip:read", "paperclip:write"]
}

GET /.well-known/oauth-protected-resource

{
  "resource": "https://bus.struxio.ai/mcp",
  "authorization_servers": ["https://bus.struxio.ai"]
}

Step 2: Add OAuth endpoints

POST /oauth/register — Dynamic Client Registration

GET /oauth/authorize — Authorization endpoint

POST /oauth/token — Token exchange

Step 3: New database tables

CREATE TABLE oauth_clients (
  client_id TEXT PRIMARY KEY,
  client_secret_hash BYTEA NOT NULL,
  client_name TEXT NOT NULL,
  redirect_uris TEXT[] NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE oauth_codes (
  code TEXT PRIMARY KEY,
  client_id TEXT NOT NULL REFERENCES oauth_clients(client_id),
  principal_id UUID REFERENCES principals(principal_id),
  redirect_uri TEXT NOT NULL,
  code_challenge TEXT,
  code_challenge_method TEXT,
  scope TEXT,
  expires_at TIMESTAMPTZ NOT NULL,
  used_at TIMESTAMPTZ
);

CREATE TABLE oauth_tokens (
  token_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  access_token_hash BYTEA NOT NULL UNIQUE,
  refresh_token_hash BYTEA UNIQUE,
  client_id TEXT NOT NULL REFERENCES oauth_clients(client_id),
  principal_id UUID REFERENCES principals(principal_id),
  scope TEXT,
  access_expires_at TIMESTAMPTZ NOT NULL,
  refresh_expires_at TIMESTAMPTZ,
  revoked_at TIMESTAMPTZ
);

Step 4: Update auth middleware

The /mcp endpoint should accept BOTH:

Auth flow:

  1. Check Authorization: Bearer <token> header
  2. Try bearer token lookup (existing api_tokens table)
  3. If not found, try OAuth access token lookup (oauth_tokens table)
  4. If neither: return 401 with WWW-Authenticate: Bearer + PRM pointer

Step 5: Auto-approve logic

Since all STRUXIO brains are trusted, the authorize endpoint should auto-approve without showing a consent screen:

Step 6: Files to create/modify

New files:

Modified files:

Step 7: Caddy update

Add OAuth routes to Caddyfile:

handle /oauth/* {
  reverse_proxy bus:8088
}
handle /.well-known/* {
  reverse_proxy bus:8088
}

Execution Workflow

  1. CM0 implements the code on Mac, builds, tests locally, pushes to GitHub
  2. CC0 pulls from GitHub, rebuilds container, runs migration 002, smoke tests
  3. Shai adds Custom Connector in claude.ai: URL = https://bus.struxio.ai/mcp
  4. Claude initiates OAuth flow → auto-approved → tools available in web chats

Acceptance Criteria

Rollback

Remove OAuth routes. Bearer token auth continues to work for CLI agents.


STRUXIO.ai // Confidential & Proprietary // © 2026