# sh-mcp Sea Haven MCP platform. A TypeScript monorepo of trust-tiered **MCP servers** that expose Sea Haven's proprietary integrations as tools, plus the **Cognito/Google auth broker** and the **rebuilt scheduled jobs**. This service replaces `seahaven-slack-bot` and `exec-aide`, which are deprecated completely; the conversational surface becomes a configurable Slack task agent. > **Status: BUILDING. Platform + auth substrate built; nothing deployed to AWS yet.** > Phase 0b (monorepo + `@sh-mcp/shared` core), Phase 1 (runnable `sh-mcp-ops` / > `sh-mcp-finance` over MCP + OpenAPI), and Phase 2a (the Cognito auth substrate > CDK stack + pre-token/group-sync Lambdas) are on `main`. The servers run > locally (`SH_MCP_ENV=local`); `SH_MCP_ENV=aws` is wired but not yet deployed. > The authoritative spec is [`docs/design.md`](docs/design.md). ## Auth substrate (Phase 2a — `infra/` + `auth/`) `infra/` is the root CDK app; `cdk synth` builds the **`sh-mcp-auth`** stack: a Google-federated Cognito user pool (ESSENTIALS feature plan), per-tier app clients whose `AllowedOAuthScopes` are the trust-tier boundary (`sh-agentforce-ops` / `-finance` / `-exec`), a **suppress-only** V2 pre-token Lambda (`auth/pre-token-gen`), a 5-minute group-sync Lambda (`auth/group-sync`), and the sync-state + deny-list tables. **Revocation has two layers.** Group membership (Google → Cognito, 5-min cadence) is the primary entitlement control, with a fail-**closed** 30-minute freshness window: if group-sync stalls, the pre-token Lambda drops every caller to base `ops:read`. The `sh-mcp-deny-list` table is a hard-kill **overlay** the pre-token Lambda consults on every mint — a `sub` listed there is stripped to no tier scopes immediately (TTL-expiring), ahead of the next sync. The deny-list read is fail-**open** (a DynamoDB blip logs `deny_list_read_failed` and does not lock everyone out, since group membership + its fail-closed window remain authoritative). The finance app client additionally caps its refresh token at 8h (vs 30d for ops/exec) so a stolen finance refresh token cannot ride past the short access-token TTL for a month. **Deploy is gated on two manual prerequisites (owner: Adam):** 1. Google Cloud OAuth 2.0 web client (Cognito federation) → Secrets Manager `sh-mcp/google-oidc` (`{client_id, client_secret}`). 2. Google Workspace service account w/ domain-wide delegation (Directory `groups.readonly`) → Secrets Manager `sh-mcp/google-directory-sa`. **App-client OAuth callback URLs are a placeholder** (`-c callbackUrls=...`) until the conversational surface (Agentforce vs Bolt) is chosen — the substrate is surface-agnostic. The optional `alias/seahaven-logs` CMK for the Lambda log groups is supplied at deploy via `-c logsKmsArn=...`. ## Shape (planned) - **MCP servers** (trust-tiered, remote HTTP, per-server IAM): - `sh-mcp-ops` — read-mostly, agent-facing (WO/PO/site lookups, KB search, Google Maps, Gmail/Calendar, tasks, reminders). - `sh-mcp-finance` — sensitive, read-only, audited (QBO vendor search, payment lookups). - `sh-mcp-physical` — DEFERRED, admin/out-of-band only (Lenel/Yealink/3CX control). - **Auth** — Google Workspace is the single IdP; an Amazon Cognito user pool federated to Google issues scoped, audience-bound JWTs; group → scope mapping via a pre-token Lambda. See design §2. - **Jobs** — rebuilt proactive Lambdas (email classify/digest, KB syncs). - **Language** — TypeScript everywhere (servers, packages, CDK, jobs). ## Open decisions - Task-agent surface: Agentforce (recommended) vs marketplace Claude app vs custom Bolt assistant (design §12). Drives the model + guardrail story. - Endpoint exposure specifics (Slack egress ranges / WAF) — design §9 / §11. ## Layout (target) ``` packages/ shared + one package per integration servers/ sh-mcp-ops, sh-mcp-finance (CDK stacks) auth/ cognito, pre-token-lambda, group-sync-lambda jobs/ rebuilt scheduled Lambdas docs/ design.md (the canonical plan) ``` See [`docs/design.md`](docs/design.md) for the authoritative spec.