sh-mcp/servers/sh-mcp-finance/README.md
Adam Moussa 9bf85aef29 Add runnable sh-mcp-ops and sh-mcp-finance servers
Two thin composition-root servers over the shared transport (design.md §3):
- ops: internal-data, knowledge-base, google-maps, gmail, calendar, tasks,
  reminders. finance: qbo, payments (audited + redacted on egress).
- config from env only (no hardcoded ids/issuer/tables); SH_MCP_ENV selects
  LocalAuthProvider + dev clients (local) vs CognitoAuthProvider + real stubs
  (aws). Finance applies the 15-min finance-token TTL ceiling (design.md §2.5).
- index.ts is the only place .listen() is called; a Lambda handler placeholder
  is exported but not depended on.
- synth-only CDK stubs (no real IAM/Cognito/WAF) so 'cdk synth' has a valid app
  (build-plan §6); READMEs document local run, dev tokens, curl, MCP Inspector.
2026-06-26 12:48:26 -04:00

2.6 KiB

sh-mcp-finance

Finance-tier Sea Haven MCP server. Exposes the finance tool registry (qbo search_vendors, payments lookup_payment_by_* — see docs/design.md §3) over the same two interfaces as sh-mcp-ops (MCP Streamable HTTP + OpenAPI 3.1), through the same shared dispatch path.

Finance is sensitive, read-only, and fully audited: every tool call emits a structured audit record and the response is redacted on egress (bank account / routing / card / SSN / tax-id masked) before it leaves the server (docs/design.md §2.5, §7.3).

Run locally (no AWS, no Cognito)

npm install
npm run build

SH_MCP_ENV=local PORT=8082 npm run start -w @sh-mcp/server-finance
# or:  SH_MCP_ENV=local npm run dev -w @sh-mcp/server-finance

Endpoints

Identical shape to sh-mcp-ops: GET /healthz, GET /openapi.json (both unauthenticated), POST /mcp, and POST /tools/:name (both authenticated).

Dev bearer tokens (local only)

Token Identity Scopes
dev-finance accounting@seahavenind.com ops:read, finance:read
dev-finance-admin adam@seahavenind.com ops:read, finance:read, finance:admin

Ops-tier tokens (dev-ops-only, dev-assistant) are rejected by this server (audience binding).

Sample curl — redaction on egress

TOKEN=dev-finance

curl -s -X POST localhost:8082/tools/lookup_payment_by_vendor \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"vendor":"Harbor"}' | jq
# → bankAccountNumber / bankRoutingNumber / cardNumber are "[REDACTED]";
#   vendor, amount, invoice number are intact.

Each call writes one structured audit line to stdout (CloudWatch in Lambda):

{
  "kind": "audit",
  "sub": "...",
  "tool": "lookup_payment_by_vendor",
  "argsHash": "<sha256>",
  "decision": "allow",
  "result": "ok",
  "ts": "..."
}

Args are hashed, never logged raw — secrets never reach the audit log.

MCP Inspector

Point it at http://localhost:8082/mcp (Streamable HTTP) with Authorization: Bearer dev-finance.

Environment

Same as sh-mcp-ops plus PAYMENTS_TABLE (aws mode). Finance additionally applies the 15-minute TTL ceiling on finance:* tokens in aws mode (docs/design.md §2.5). aws mode is not runtime-exercised in Phase 1.

CDK

cdk/app.ts is a synth-only placeholder (no real IAM/Cognito/WAF) — the finance least-privilege role and audit wiring land in a later phase behind the mandatory IAM cross-review.