Data Flow: westside-mcp

arch-dataflow-westside-mcp Architecture

architecture active

Data Flow: westside-mcp

Diagram

One primary flow: Marcus asks a natural-language question, MCP loads the catalog, Claude writes SQL, the replica answers, result comes back to Marcus's phone.



          
  

Components

Component Purpose Notes
Marcus (actor) The human asking the question Primary user; iPhone-first
Claude iOS Native iOS Claude app Auto-syncs connectors registered in claude.ai web
claude.ai Claude web backend Where the connector URL is registered; source of truth for iOS sync
Tailscale Funnel Public HTTPS entry into the cluster <code>westside-mcp.tail5b443a.ts.net</code>
westside-mcp pod The MCP server k3s namespace <code>westside-mcp</code>
mcp-remote-auth OAuth token validation Shared infra repo
CNPG -ro replica Read-only Postgres endpoint Physically rejects writes
Loki Audit log sink Query log, duration, row count, errors

Key Decisions

  • First call in a session is always get_catalog(). Prevents Claude from guessing at the schema. Cheap (one information_schema query) and makes every subsequent query() grounded.
  • SQL is parsed at the MCP layer before execution. Non-SELECT statements rejected before the DB sees them. This is belt-and-suspenders with the replica's physical write block.
  • Every query writes an audit log, including failures. Loki is the source of truth for "what did Marcus ask?" — essential for debugging, compliance, and tuning the catalog.
  • Two-layer write protection. Role-level SELECT-only + replica endpoint. A role bug alone wouldn't breach; the replica physically refuses writes.
  • No streaming / no async results. JSON-RPC request/response is simpler than streaming partial results, and query timeouts are short enough that streaming wouldn't help. Revisit if queries ever legitimately need >5s.