receipts
The MCP server reads the transcript corpus from a running Cloudflare Worker deployment (set API_URL to point at it), which stores transcripts and lines in Cloudflare D1; by default it otherwise indexes the shipped sample interviews in-process.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@receiptsfind quotes about pricing and cite speaker/timestamp"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Receipts
Interview transcripts in. Themes and answers out, where every claim cites a verbatim quote with speaker and timestamp, or it is dropped, visibly.

Most tools that summarise research quietly invent the connective tissue: a paraphrase presented as a quote, a theme one person mentioned reported as "users want", a confident answer to a question nobody in the corpus addressed. Receipts refuses all three, and shows you the refusal.
Live demo: https://receipts.alexjpower74.workers.dev (eight sample interviews loaded; Themes and Ask run the real model, so please be kind to the owner's API bill).
The rule
A claim reaches the screen only with a citation the verifier has checked against the transcript text:
the quote must be a verbatim substring of exactly one spoken line (whitespace and curly quotes
normalised, case-sensitive). A theme survives only with at least two verified quotes from at least
two different interviews. Everything the model wanted to say that failed goes to the Dropped
panel with its reason: no citation, line not found, quote not in line, single source.
The model is not trusted to quote from memory. It has to fetch the lines it cites, through tools
(search_quotes, get_line), and the verifier re-checks the output anyway.
Related MCP server: call-copilot
What it does
Transcripts. Paste or upload
[mm:ss] Speaker: textor WebVTT. Eight fictional sample interviews ship with it, every one labelledSAMPLE TRANSCRIPT — fictional interview.Themes. One click. A live ticker shows each tool call as the model searches the corpus. Theme cards carry their quotes with speaker and timestamp; click a quote and the reader scrolls to the line. The Dropped panel lists what was thrown out and why.
Ask. "What did people say about pricing?" Every sentence of the answer is a link to its source lines. A sentence with no source renders as dropped, not as text. When nobody said it, it says so, and shows the searches it ran.
MCP server. Any agent can query the same corpus as tools (below).
Evals, with a negative control
evals/negative-control.test.ts runs in CI on every push with no model at all: 21 planted attacks
(fabricated quotes, paraphrases, ghost lines, ghost transcripts, quotes from the wrong line, case
changes, single-source themes padded with fabricated second sources) go through the verifier as if
the model had emitted them. The suite fails if any survives. The positive path, a fully supported
payload, must come through byte-for-byte. It was shown red three separate ways before it was trusted.
npm run evals runs seven scenarios against the real model and prints a scorecard; it re-verifies
every surviving citation independently of the app code.
Scorecard, 2026-09-12, claude-sonnet-5, main 2c8fb2f → a6e88c4, three runs:
run | passed | what failed |
1 | 6 / 7 | "trust in AI summaries": cited the line after the expected refusal ("if it's wrong, it's my name on it") |
2 | 6 / 7 | "do incentives matter": cited both sides across four interviews, but not the one phrase the scenario named |
3 | 6 / 7 | "does anyone read the deck": cited the deck-sceptic and the deck-reader, ten lines across six interviews, none of them the two phrases the scenario named |
Every miss is quote selection, not fabrication: every citation in all three runs re-verified against
the corpus, no sentence shipped without a source, no forbidden claim ("everyone agrees", "dark mode",
"several participants" about a single source) was asserted, and the nobody-said-that scenario
answered nothingFound. The scenarios accept alternative lines that make the same point; they still miss when the model picks yet another line that does. We publish the three runs rather than tune the scenarios until one run reads 7 / 7.
The stub model scores 0 / 7 on content by design; its run only proves the wiring.
Architecture
flowchart LR
UI[React UI<br/>Transcripts · Themes · Ask] -- SSE --> W[Cloudflare Worker]
W --> D1[(D1<br/>transcripts, lines)]
W --> A[Agent loop<br/>tool use, 8-call cap]
A -- search_quotes / get_line --> IDX[Corpus index]
A --> M[Claude<br/>or scripted stub]
A --> V[Verifier]
V -- themes + dropped --> W
MCP[MCP server<br/>stdio] --> IDX
MCP -. API_URL .-> Wsrc/corpusparser, index, D1 schema and seed.src/verifythe verifier.src/agentmodel interface (Anthropic + stub), tool loop, themes and ask.src/workerHTTP API and stores.src/uiReact.mcp/the MCP server.evals/scenarios, scorer, negative control.src/contract.tsis the seam: every type the slices share, and the only place a field is added.Without
ANTHROPIC_API_KEYthe scripted stub runs and every result saysmodel: "stub"; the UI shows it. The stub plants one fabricated theme per run so the Dropped panel always has a demo.
MCP server
Any agent can query the same corpus the UI shows, as tools, over stdio:
tool | input | returns |
| – |
|
|
| ranked lines with |
| – | the verified |
|
| one line with speaker, timestamp, text and transcript title |
By default it indexes the shipped samples in-process. Set API_URL=http://localhost:5402 to read
from a running Worker instead. Claude Code, in .mcp.json:
{ "mcpServers": { "receipts": { "command": "npx", "args": ["tsx", "mcp/server.ts"],
"cwd": "/path/to/receipts", "env": { "API_URL": "http://localhost:5402" } } } }Run it yourself
git clone https://github.com/alexjpower74-create/receipts && cd receipts && npm install
cp .dev.vars.example .dev.vars # add ANTHROPIC_API_KEY, or leave it empty for the stub
npm run build && npm run dev:worker # API + built UI on http://localhost:5402
npm run dev # or the Vite dev server on :5403, proxying /api
npm run test:all # typecheck, unit + negative control, D1 inside workerdnpm run test:e2e runs Playwright on Chromium and WebKit at desktop and phone width.
How it was built
Three Claude Code sessions built this in parallel under rig,
each owning a file slice enforced by a commit guard, against a shared src/contract.ts written
first; a fourth session led, graded every checkpoint from a worktree pinned to the commit, and merged.
Every suite was made red once before it counted. That habit found what code review would not have:
The unit tests could not see a seed deadlock; the first real
wrangler devrequest hung. Now a workerd test.A stateful stub answered the second request mid-script. Caught by curling the live Worker twice.
A negative control that did not go red (a delete that SQLite's
INSERT OR REPLACEcascade was already doing) was recorded as a finding and replaced with a break that did.A test double that accepted anything hid that real D1 rejects the schema file as written. The suite running the real binding failed on the first statement; the fake now rejects it too.
Merging one slice's eight samples broke another slice's tests that assumed five. Counts now come from the data.
Build reports, per slice, are in docs/.
MIT © Alexander Power
This server cannot be deployed
Maintenance
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Ingest and search LogsLoom logs from coding agents.
Read a project's prompts, logs and agents, and send new work to the agent on your own machines.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceProvides a stdio MCP bridge for coding agents to query and record engineering knowledge locally, preserving debugging history, failed attempts, and verified solutions.2 npmMIT
- AlicenseNot gradedqualityAmaintenanceSearch and read locally-recorded meeting transcripts over stdio. Read-only, no network. Exposes list_sessions, get_session, and search_transcripts to any MCP client.46 PyPI7MIT
- AlicenseAqualityBmaintenanceEnables an AI agent to run local tools on the user's own machine via stdio, including command execution, workspace file read/write, and system status checks.52MIT

openrhyme-mcpofficial
AlicenseAqualityBmaintenanceEnables any MCP-compatible agent to query a local OpenRhyme activity timeline, search history, and issue control commands over stdio while keeping all data on-machine.5MIT