IDENTITY

title: "TICKET_049: Build & Deploy Bus MCP Server (Relay A)"
type: ticket
subtype: execution
purpose: "Build the STRUXIO Bus MCP Server from BLUEPRINT_Bus_MCP_Server_v1.md and deploy to Hetzner. This is the central nervous system for multi-brain communication."

GOVERNANCE

status: ready
priority: P0
sprint: S001_base_and_mvp1
assignee: "Claude Code CLI (Mac terminal for build, Hetzner terminal for deploy)"
estimated_hours: 4
depends_on: [TICKET_048, TICKET_050]
blocks: [TICKET_051, TICKET_052, TICKET_053]
last_updated: "2026-03-21 23:00"
blueprint: "STRUXIO_Design/02_devxio_architecture/BLUEPRINT_Bus_MCP_Server_v1.md"

TICKET_049: Build & Deploy Bus MCP Server (Relay A)

Objective

Build and deploy the STRUXIO Bus MCP Server — a remote Streamable HTTP MCP relay that connects all Claude surfaces (B0-B5, CLI, Hetzner agents). Deploy to Hetzner with Postgres, Caddy TLS, and bearer token auth.

Context

Execution Plan

Phase A: Scaffold + Build (Mac CLI)

A1. Initialize project

mkdir -p /opt/struxio/bus && cd /opt/struxio/bus
npm init -y
npm install fastmcp fastify @fastify/cors pg ulid zod dotenv
npm install -D typescript @types/node @types/pg tsx
npx tsc --init --target ES2022 --module NodeNext --moduleResolution NodeNext --outDir dist --rootDir src --strict true

A2. Create directory structure

Per BLUEPRINT Section 6.1 (see blueprint for full tree).

A3. Implement core files

src/store/migrations/001_initial.sql — SQL schema from BLUEPRINT Section 4.

src/store/postgres.ts — Connection pool, parameterized queries: insertEvent, pollEvents, ackCursor, upsertSession, insertAuditLog.

src/auth/tokens.tsvalidateBearerToken(): SHA256 hash, lookup in api_tokens.

src/mcp/tools/bus.ts — 5 tools from BLUEPRINT 3.1-3.5: send_message, poll, ack, presence_heartbeat, status.

src/mcp/tools/paperclip.ts — 8 tools from BLUEPRINT 3.6-3.13: REST client wrappers. Credentials SERVER-SIDE ONLY.

src/mcp/mcpServer.ts — Register all tools with FastMCP. Server name: "struxio-bus".

src/server.ts — Fastify on BUS_PORT (8088). Mount FastMCP at /mcp. Mount /hooks/event, /healthz, /readyz. CORS. Auth middleware. Run migrations on startup.

src/hooks/ingest.ts — POST /hooks/event for Claude Code hook package.

A4. Create Dockerfile, docker-compose.yml, Caddyfile, .env.example

Copy from BLUEPRINT Sections 6.3, 6.4. See blueprint for exact content.

A5. Create bootstrap_tokens.sh

Generates bearer tokens for each principal, inserts SHA256 hashes into DB, outputs raw tokens once.

A6. Build and test locally

npm run build
docker run -d --name bus-pg -e POSTGRES_PASSWORD=test -e POSTGRES_DB=bus -p 5433:5432 postgres:15
export BUS_DATABASE_URL=postgresql://postgres:test@localhost:5433/bus
node dist/server.js
curl http://localhost:8088/healthz

A7. Git init, commit, and push (Mac CLI)

cd /opt/struxio/bus
git init
cat > .gitignore << 'GITIGNORE'
node_modules/
dist/
.env
*.log
GITIGNORE
git add -A
git commit -m "feat: TICKET_049 — Bus MCP Server scaffold"
git remote add origin git@github.com:STRUXIO/struxio-bus.git
git push -u origin main

Phase B: Deploy to Hetzner (Hetzner CLI)

B1. Pull code from GitHub on Hetzner

# On Hetzner — clone the repo that Mac CLI just pushed:
cd /opt/struxio
git clone git@github.com:STRUXIO/struxio-bus.git bus
cd bus
# For subsequent updates after Mac pushes:
# git pull origin main

B2. Create .env on Hetzner

cd /opt/struxio/bus
cp .env.example .env
# Generate strong passwords:
openssl rand -base64 32  # POSTGRES_PASSWORD
openssl rand -base64 32  # BUS_PAPERCLIP_TOKEN
# Edit .env with generated values

B3. Build and start

cd /opt/struxio/bus
docker compose up -d --build
docker compose logs -f bus

B4. Run migrations

docker compose exec bus node -e "require('./dist/store/postgres').runMigrations()"

B5. Bootstrap tokens

docker compose exec bus node scripts/bootstrap_tokens.js
# Save the output tokens securely!

B6. Smoke test

curl https://bus.struxio.ai/healthz
curl https://bus.struxio.ai/readyz
curl -X POST https://bus.struxio.ai/mcp  # expect 401
curl -X POST https://bus.struxio.ai/mcp \
  -H "Authorization: Bearer <B0_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"bus.status","arguments":{}},"id":1}'

Acceptance Criteria

Critical Constraints

Rollback

docker compose down
# Existing services unaffected (separate Docker network)

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