Paste the week's chaos. Get a clean schedule, a fair settle-up, and a neutral message you can actually send. Chaos in → structure out.
Cadence organizes logistics. It is not legal, financial, mental-health, or relationship advice. It turns messages into a schedule, an expense ledger, and a neutral draft you review and send yourself. Always confirm details directly with the other parent. Cadence does not make decisions or store your data.
One engine, two surfaces: a Claude MCP that renders its result inline in the chat, and a standalone web app. Built at Claude Build Day with Claude Code + Opus 4.8 (claude-opus-4-8).
▶ Watch the demo — Cadence untangling a real week of co-parenting logistics, inline in Claude.
Paste a messy week of texts, emails, and notes → four structured artifacts:
| Artifact | What you get |
|---|---|
| 🗓 Schedule | Week-at-a-glance custody/handoff events (+ .ics in the web app) |
| 💸 Settle-Up | A minimal "X owes Y $Z" ledger, itemized, reconciled to the cent — computed in code, never by the model |
| ✉️ Message | One neutral, ready-to-send BIFF message — disputed items are left out and asked about, never assumed |
| Double-bookings, math mismatches, ambiguous dates — found by a validation agent and an independent deterministic backstop |
Every extracted item shows the exact source line it came from — nothing is invented.
cadence-mcp/ is a TypeScript MCP server that wraps the same engine and renders the four cards inline inside Claude, as a sibling to your email / calendar / iMessage MCPs. This is the strategic shape: untangle your logistics without leaving the conversation.
- Tool
untangle({ blob })→ returns the structuredProcessResultand an inlineui://cadence/resultwidget — a self-containedtext/html;profile=mcp-appdocument (MCP-UI / MCP Apps) that paints the four cards right in the chat. - Same engine, zero reimplementation — it imports
lib/orchestrator.ts'srunPipeline; run viatsx(no build step). - Proven live on real data: calendar + email + iMessage pulled from sibling MCPs →
untangle→ inline widget, with a real conflict caught and a sendable message drafted.
# Register it with Claude (absolute paths; runs the live TS source via tsx):
claude mcp add cadence -- \
/ABS/PATH/cadence/node_modules/.bin/tsx \
--tsconfig /ABS/PATH/cadence/cadence-mcp/tsconfig.json \
/ABS/PATH/cadence/cadence-mcp/src/index.tsnpm run mcp:smoke # offline contract test — 13 checks, zero API calls
npm run mcp:inspect # open the MCP Inspector and see the widget renderDetails, the rawHtml-vs-MCP-Apps decision log, and verification live in cadence-mcp/README.md.
Agent timeout knob — one env var,
CADENCE_AGENT_TIMEOUT_MS, raises the per-agent ceiling for every agent + the orchestrator guard. The web app leaves it unset (28s, safe under Vercel's 60s limit);cadence-mcp(a local stdio server with no such limit) defaults it to 90s so larger real-world inputs aren't cut off.
npm install
cp .env.local.example .env.local # add your ANTHROPIC_API_KEY (server-side only)
npm run dev # http://localhost:3000Click "Load demo blob" → Untangle. The demo runs offline from a committed snapshot (Safe Mode), so it works with or without a key; anything you type runs live on Opus 4.8. The UI ships a frosted glass / crystal theme with a 🌙 dark mode toggle.
Note: if your shell forces global npm installs, run installs as
env npm_config_global=false npm_config_location=project npm install. Running scripts is unaffected.
untangle({ blob }) ·or· POST /api/process { blob } (key stays server-side)
│
└─► runPipeline() (lib/orchestrator.ts)
├─ Stage A PARALLEL schedule agent ‖ expense agent [Opus 4.8, structured output]
├─ Stage B OUR CODE settle() → ledger ; overlap() → flags (deterministic, unit-tested)
├─ Stage C PARALLEL comms agent ‖ validation agent
└─ Stage D assemble + merge model & deterministic conflicts → ProcessResult
│ │
web: 4 React cards mcp: ui://cadence/result widget
- Opus 4.8 via
messages.parse()+zodOutputFormat— structured output validated against Zod (the single source of truth inlib/schemas.ts). Adaptive thinking; no sampling params. - The ledger is computed by code, not the model — agents emit line items;
lib/settle.tsnets them, so the money is always correct. - Safe Mode — a blob matching a golden returns a committed snapshot with zero API calls (offline-safe; demo-proof). Add
?live=1(web) /live:true(MCP) to force the real pipeline. - Never a raw failure — always a
{ ok, result?, error? }envelope; per-agent failures degrade gracefully.
cadence-mcp/ src/{index,render,ui-resource,env}.ts · scripts/smoke.ts · README.md ← the MCP surface
app/ page.tsx + api/process + api/health
components/ InputPanel · {Schedule,SettleUp,Message}Card · ConflictBanner · ThemeToggle · ui/
lib/ schemas.ts · settle.ts · ics.ts · overlap.ts (pure, tested)
anthropic.ts · agents/* · prompts/* · orchestrator.ts · grader.ts · fixtures.ts
tests/ settle · ics · overlap · schemas · golden (deterministic) + rubric.llm (graded)
brief.md rubric.md workflow.mjs # the verifiable-done harness
Stack: Next.js 16 (App Router) · TypeScript · Tailwind v4 · @anthropic-ai/sdk + Opus 4.8 · @modelcontextprotocol/sdk + @mcp-ui/server · tsx · Vitest · Vercel.
npm test # deterministic: schema + ledger math + .ics + overlap + golden snapshots
npm run mcp:smoke # the MCP contract: tools/list + untangle + a non-empty ui:// widget (offline)
npm run test:rubric # Opus grades the output against rubric.md (needs ANTHROPIC_API_KEY)
node workflow.mjs verify # tests + a 200 from the live URL + the demo blob flags its planted conflictSeveral rubric criteria (schema validity, calendar correctness, ledger reconciliation) are computed in code, and the Opus grader is told to defer to those verdicts — so a hallucinating grader can't pass genuinely broken math.
The harness is generic: swap brief.md + rubric.md + fixtures/*_input.txt and node workflow.mjs all re-runs scaffold → generate → test → grade → verify on a new problem, no code change.
npx vercel # preview
npx vercel env add ANTHROPIC_API_KEY production
npx vercel --prod # live URLThe key is read only inside app/api/** and is never prefixed NEXT_PUBLIC_.
MIT. See docs/build-narrative.md for how it was directed and where it caught itself.