Skip to content
Foldcase
On this pagePaste into your AGENTS.md

Wire it into your agent

One command does the wiring:

bash
npx foldcase init        # or: bunx foldcase-bun init

It adds the server entry below to .mcp.json — choosing bunx or npx by your lockfile, and setting FOLDCASE_SHOWCASE_DIR=src when src/ exists — and appends the AGENTS.md block. Both edits are idempotent and merge-safe: an existing .mcp.json keeps its other servers, a foldcase entry already there is left alone, and a second run reports kept and changes nothing. By hand, the same entry (Claude Code and most MCP hosts) is:

json
{
  "mcpServers": {
    "foldcase": {
      "command": "npx",
      "args": ["foldcase", "mcp"],
      "env": { "FOLDCASE_SHOWCASE_DIR": "src" }
    }
  }
}

Or in one line: claude mcp add foldcase -e FOLDCASE_SHOWCASE_DIR=src -- npx foldcase mcp. Under Bun the command is bunx with args ["foldcase-bun", "mcp"].

FOLDCASE_SHOWCASE_DIR (default .) is read by mcp only. A relative value resolves against the directory the host launches the server in — for Claude Code, the project root — and becomes the server's root: foldcase_load_catalog resolves relative directories against that root, never against the currently served one, so no sequence of loads can walk away from it.

The six tools, all annotated readOnlyHint: true, destructiveHint: false, openWorldHint: false — a host does not prompt for confirmation to list a catalog:

ToolWhat it does
foldcase_list_showcasesEnumerate every Showcase — which Schemas it carries, which Messages it dispatches, the directory served — and per-component gaps: the Messages no play dispatches.
foldcase_get_showcase_schemaIntrospect a Showcase's Message union into a JSON Schema document, so the agent builds a valid payload by construction.
foldcase_get_showcase_model_schemaThe same for the Model — the shape a play asserts on, which an agent has to know before it writes one.
foldcase_run_showcaseRun one Showcase's play — in a fresh subprocess, from the code on disk — and return the typed pass/fail report, naming the file it came from.
foldcase_run_catalogRun the whole catalog into one suite report, or the part of it under an id prefix: counter/ runs one component. Fresh from disk, like foldcase_run_showcase.
foldcase_load_catalogRefresh the listing after files appear or vanish, or point the server at another directory under the root. Reports how many Showcases came back and which files would not load. A run never needs it.

The loop an agent runs:

  1. foldcase_list_showcases — which components exist, in which states; the hasMessageSchema / hasModelSchema flags say which introspection call is worth making, and gaps names, per component, the Messages no play dispatches — the next Showcase to write.

  2. foldcase_get_showcase_schema — the Message union as a draft-2020-12 JSON Schema document: a valid payload by construction, not by reading the source.

  3. foldcase_get_showcase_model_schema — the shape a play asserts on; read it before writing one.

  4. Edit the code, or add a Showcase.

  5. foldcase_run_showcase for one state, or foldcase_run_catalog with id_prefix: "counter/" for one component. A run executes in a fresh subprocess and reads the disk, so the edit it is verifying — even a brand-new file — is already in it, no reload needed. A failing play is status: "failed" with a full SerializedError — data, never a tool error — and a mistyped id returns every available id, so it corrects itself in one round trip.

  6. foldcase_load_catalog to refresh the listing after files appear or vanish. The listing and the two schema tools read modules the server already imported, so after an edit inside a loaded file their metadata can lag until the server restarts; the run tools never lag.

No MCP host? The same loop is the CLI: foldcase test --json prints one typed JSON document on stdout, diagnostics on stderr, and every report names its file.

Foldcase is the static half of a two-server loop. @foldkit/devtools-mcp drives the live runtime — it needs a Vite dev server and an open browser tab; Foldcase needs only a directory of files, so it also runs in CI. The verbs pair up:

questionlive — @foldkit/devtools-mcpdeclared — foldcase mcp
what existsfoldkit_list_runtimes (open tabs)foldcase_list_showcases
Message shapefoldkit_get_message_schemafoldcase_get_showcase_schema
the Modelfoldkit_get_model (the value now)foldcase_get_showcase_model_schema (the type)
actfoldkit_dispatch_messagefoldcase_run_showcase

devtools-mcp answers what the app is doing right now; Foldcase answers what the app is supposed to do.

Paste into your AGENTS.md

markdown
## Showcases (Foldcase)

- Components are described by Showcases: `export const showcases: ReadonlyArray<Showcase>`
  in `*.showcase.ts` files. The record is `{ id, play, message?, model?, dispatches? }`;
  an id is `component/state`.
- To learn a component, use the `foldcase_*` MCP tools or `npx foldcase test --json`
  do not parse `*.showcase.ts` files or crawl the source for the same facts.
- When you add a component state, add a Showcase for it, and name the Message tags its
  play sends in `dispatches` — the listing's `gaps` then says which Messages still have
  no Showcase.
- When you change a Message or Model Schema, regenerate the tables: `npx foldcase docs
  src docs/schemas`. In CI, `--check` fails on drift instead of writing.
- The run tools execute what is on disk, edits included. Only the listing and schema
  tools can lag behind an edit inside a loaded file; restart the server to refresh them.
- Exit 1 means a failed Showcase, an unloadable file, or an empty catalog. All three are
  reported as data; one bad file never hides the rest.

Last updated Aug 4, 2026