mirror of
https://github.com/Sea-Haven-Industries/sh-mcp.git
synced 2026-09-30 07:43:17 +00:00
Remove the push-to-main trigger from .github/workflows/deploy.yaml so merges no longer deploy automatically; deploys now run only via the Actions "Run workflow" button (workflow_dispatch). No job content, permissions, or reusable-workflow inputs changed. README and the auth deploy runbook updated to match.
130 lines
7.1 KiB
Markdown
130 lines
7.1 KiB
Markdown
# sh-mcp
|
|
|
|
[](https://github.com/Sea-Haven-Industries/sh-mcp/actions/workflows/ci.yaml)
|
|

|
|

|
|

|
|

|
|
|
|
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).
|
|
|
|
## Documentation
|
|
|
|
The canonical map of Sea Haven's AWS infrastructure lives in Confluence. This project's `sh-mcp-auth`, `sh-mcp-ops`, and `sh-mcp-finance` stacks are represented there as Mermaid subgraphs.
|
|
|
|
- **[AWS Architecture Map](https://seahaven.atlassian.net/wiki/spaces/IT/pages/1540098)** (Confluence, IT space, page 1540098)
|
|
|
|
## Infrastructure (CDK app)
|
|
|
|
All AWS infrastructure is defined as code with the **AWS CDK** (TypeScript, `aws-cdk-lib` pinned
|
|
in `package.json`). The repo root is the CDK app: `cdk.json` is the app config and points the CDK
|
|
CLI at the app entry point.
|
|
|
|
```jsonc
|
|
// cdk.json
|
|
{
|
|
"app": "tsx infra/bin/app.ts", // entry point (run with tsx, no pre-compile)
|
|
"output": "cdk.out", // synth output dir (git-ignored)
|
|
"context": { "@aws-cdk/core:newStyleStackSynthesis": true }
|
|
}
|
|
```
|
|
|
|
- **Entry point** — `infra/bin/app.ts` constructs the `App` and instantiates the stacks. Every
|
|
stack sets an explicit kebab-case `stackName` and pins `env` to account `328440206208` /
|
|
`us-east-1`, so synth needs no AWS credentials (shared CMKs are referenced by ARN, not
|
|
`fromLookup`).
|
|
- **Stacks** — `infra/lib/`. Currently one: `ShMcpAuthStack` → **`sh-mcp-auth`** (the Cognito auth
|
|
substrate, detailed below). The per-tier `sh-mcp-ops` / `sh-mcp-finance` hosting stacks join the
|
|
same app in Phase 2b. The Lambda handler source the stacks bundle lives in `auth/` (and later
|
|
`servers/` / `jobs/`), not under `infra/`.
|
|
- **Deploy-time context** — the app reads two optional `-c` context inputs: `callbackUrls`
|
|
(per-tier OAuth callback URLs; defaults to a placeholder until the conversational surface is
|
|
chosen) and `logsKmsArn` (the `alias/seahaven-logs` CMK for the Lambda log groups; AWS-managed
|
|
encryption is used if absent).
|
|
|
|
```bash
|
|
# from the repo root
|
|
npm ci
|
|
npx cdk synth # synthesize CloudFormation into cdk.out/
|
|
npx cdk diff sh-mcp-auth # preview changes against the deployed stack
|
|
npx cdk deploy sh-mcp-auth \
|
|
-c logsKmsArn=<cmk-arn> \
|
|
-c callbackUrls='["https://…/oauth/callback"]'
|
|
```
|
|
|
|
CI runs `npx cdk synth` at the repo root on every PR (the `ci-typescript-cdk` reusable workflow with
|
|
`run-cdk-synth: true`); deploys are triggered manually (Actions → deploy → Run workflow on
|
|
`main`, i.e. `workflow_dispatch`) via the `cd-cdk` reusable workflow over the
|
|
per-repo `githubdeploy-sh-mcp` OIDC role. **Nothing is deployed to AWS yet** — see status above.
|
|
|
|
## 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)
|
|
|
|
```
|
|
cdk.json CDK app config (app → infra/bin/app.ts)
|
|
infra/ CDK app: bin/app.ts entry + lib/ stack definitions
|
|
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.
|