Architecture

Generated from the codebase by scripts/gen_architecture.ts — run npm run docs:arch. Every table below is read out of the source: if a surface is listed, code for it exists in src/ or packages/. Two sections are authored rather than derived — the diagram and Not built — and both say so where they appear, because a shape and an absence cannot be parsed out of code. LESSONS R6: eight prior submissions documented routes that were never built.

_Generated: 2026-09-28T08:34:23.602Z_

Protocol

MCP specification2025-11-25 — LATEST_PROTOCOL_VERSION in the pinned SDK
TransportStreamable HTTP (StreamableHTTPServerTransport), with Last-Event-ID resume
Hostingself-hosted; npm start runs one process on one origin
Track requirementAlexa+ asks for a self-hosted MCP server implementing 2025-11-25 (minimum) over Streamable HTTP

scripts/e2e.ts and scripts/verify.ts §6 both assert the NEGOTIATED version at runtime and exit non-zero below that floor, so this row cannot drift from the wire.

The shape

_Authored, not derived — the tables below are the machine-checked copy._

flowchart LR
  physio["Sarah, physio<br/>web/clinician.html"] -- "POST /write<br/>HMAC over raw bytes" --> http
  subgraph proc["one process · npm start"]
    http["src/http.ts<br/>Streamable HTTP · OAuth resource"]
    server["src/server.ts<br/>10 MCP handlers"]
    store["packages/live-resources<br/>versioned records · hash chain<br/>audience partition"]
    env["src/envelope.ts<br/>AES-256-GCM · AAD binds the slot"]
    http --> server
    server --> store
    store --> env
  end
  store -- "notifications/resources/updated" --> server
  server -- "SSE, resumable by Last-Event-ID" --> echo["Ray, Echo Show<br/>web/echo.html · ui://unsay/echo"]
  echo -- "resources/read · re-read under current scope" --> http
  http -- "GET /verify · public chain replay" --> judge["a judge, no account"]
  store -. "care-internal:// refused<br/>-32002, never a 403" .-> echo

MCP surfaces actually registered

Protocol methodRegistered in
tools/callsrc/server.ts
completion/completesrc/server.ts
prompts/getsrc/server.ts
prompts/listsrc/server.ts
resources/templates/listsrc/server.ts
resources/listsrc/server.ts
tools/listsrc/server.ts
resources/readsrc/server.ts
resources/subscribesrc/server.ts
resources/unsubscribesrc/server.ts
notifications/messagesrc/server.ts
notifications/resources/list_changedpackages/live-resources/src/notifier.ts
notifications/resources/updatedpackages/live-resources/src/notifier.ts

10 request handlers + 3 notification sender(s).

Declaring logging also makes the SDK serve logging/setLevel without a handler of our own, so it is a surface a host can call but is deliberately not listed above — this table only names methods with a sender or handler in the source. It is honoured, not merely served: src/server.ts passes the transport session id to sendLoggingMessage(), which is what the SDK filters the level against, and npm run e2e asserts a notice is suppressed at level emergency while notifications/resources/updated still arrives.

HTTP routes

RouteMethodsAuth
/.well-known/oauth-protected-resourceGETpublic (RFC 9728)
/.well-known/oauth-protected-resource/mcpGETpublic (RFC 9728)
/healthGETpublic
/mcpPOST · GET · DELETEBearer (care.read.user / care.read.assistant)
/verifyGETpublic — a token widens what it lists
/writePOSTHMAC-SHA256 over the raw body, or Bearer care.write
/index.html (and /)GET · HEADpublic — served from web/
/clinician.htmlGET · HEADpublic — served from web/
/echo.htmlGET · HEADpublic — served from web/
/doc/readmeGET · HEADpublic — README.md rendered by src/docpage.ts
/doc/demoGET · HEADpublic — DEMO.md rendered by src/docpage.ts
/doc/architectureGET · HEADpublic — ARCHITECTURE.md rendered by src/docpage.ts
/doc/frictionGET · HEADpublic — FRICTION.md rendered by src/docpage.ts
/doc/specGET · HEADpublic — docs/SPEC.md rendered by src/docpage.ts

6 routes + 3 static pages + 5 rendered documents, all in src/http.ts.

Plus a second read-only allowlist — the documents and receipts the landing page cites, so every link on it resolves against the server a judge is already running:

/README.md · /DEMO.md · /ARCHITECTURE.md · /FRICTION.md · /LICENSE · /docs/SPEC.md · /docs/proof/bench.txt · /docs/proof/bench.remote.txt · /docs/proof/verify.json · /docs/proof/bench.json · /docs/proof/live_run.jsonl · /docs/proof/probe_subscribe.json · /docs/proof/resume.json · /skill/SKILL.md · /icon.svg · /og.png · /docs/assets/readme-hero-animated.svg · /docs/assets/icon-animated.svg · /packages/live-resources/src/store.ts · /src/server.ts · /src/http.ts

Declared capabilities

resources: { subscribe: true, listChanged: true },
completions: {},
prompts: {},
// A second, cheap notification channel. Declaring it also makes the SDK
// serve logging/setLevel, so a host can turn the revision log down.
logging: {},
tools: {},

Modules

FileExports
src/audit.tsAuditLog
src/blobs.tsEXERCISE_CLIP, GAIT_NOTE, CLIPS, blobFor
src/docpage.tsDOC_PAGES, slugify, resolveDocLink, renderMarkdown, renderDocPage
src/envelope.tsEnvelopeError, MasterKeyMissingError, KmsUnavailableError, DecryptionFailedError, EnvelopeKeyMismatchError, describeSealed, Envelope, startupLine, announceOnce, LocalKeyProvider, KmsKeyProvider, envelopeFromEnv
src/http.tsDEV_TOKEN_SECRET, DEV_WRITE_SECRET, SCOPES_SUPPORTED, WRITE_SKEW_MS, mintToken, TokenError, verifyToken, writeSigningMaterial, signWriteBody, urisNamedBy, replayAllowed, MemoryEventStore, createHttpServer
src/retraction.tsGLOSSARY, spokenAge, glossesFor, renderRetraction
src/seed.tsRAY, DEMO_NOW, seed, seedDemo, STAGED_REVISION
src/server.tsSERVER_INSTRUCTIONS, RESOURCE_PAGE_SIZE, BRIEF_CARER, buildServer
src/store.tsCARE_PARTITION, uriFor, parseUri, LiveResourceStore
src/types.tsSCHEME, SCOPE
src/ui_resource.tsUI_ECHO_URI, UI_MIME_TYPE, UI_TEMPLATE_META, UI_FRAME_META, uiHtml, uiResourceDescriptor

Extracted package

The generic half — versioned resources, revision notifications, the hash chain, and the audience/scope partition — lifted out of src/ so it can be depended on without Unsay. Consumed here by relative import; not published to npm.

FileExports
packages/live-resources/src/chain.tshashVersion, AAD_SEPARATOR, recordAad
packages/live-resources/src/codec.ts—
packages/live-resources/src/errors.tsLiveResourceError, NotFoundError, ReservedSeparatorError, PartitionConfigError
packages/live-resources/src/index.ts—
packages/live-resources/src/notifier.tsResourceNotifier
packages/live-resources/src/partition.tsAUDIENCES, AudiencePartition, DEFAULT_PARTITION
packages/live-resources/src/store.tsLiveResourceStore
packages/live-resources/src/types.ts—

Executable scripts

CommandFile
npm run startscripts/serve.ts
npm run probescripts/probe_subscribe.ts
npm run probe:resumescripts/probe_resume.ts
npm run testtest/**
npm run typechecktsc --noEmit
npm run verifyscripts/verify.ts
npm run e2escripts/e2e.ts
npm run benchscripts/bench.ts
npm run seedscripts/seed_dump.ts
npm run fixturesnode --experimental-strip-types fixtures/gen.ts
npm run keygennode -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"
npm run docs:archscripts/gen_architecture.ts

Runtime dependencies

PackageVersionUsed in
@modelcontextprotocol/sdk^1.30.0src/http.ts, src/server.ts, packages/live-resources/src/notifier.ts, scripts/bench.ts, scripts/e2e.ts, scripts/probe_resume.ts, scripts/probe_subscribe.ts, scripts/verify.ts

Not built

The one authored section in this file — every table above is derived from the source, this list is written by hand in scripts/gen_architecture.ts because absence cannot be parsed out of code. Stated so this document cannot imply otherwise:

Rendered from ARCHITECTURE.md in the repository. Source as text: /ARCHITECTURE.md.