workbeast
Reads Gmail messages (read-only) to extract commitments, facts, and open loops into the knowledge base.
Reads Google Calendar events (read-only) to extract commitments and deadlines into the knowledge base.
Click on "Install 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., "@workbeastWhat am I waiting on from Priya?"
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.
Workbeast
A connector-fed commitment ledger with an MCP tap.
Sources you already use flow in; the people, facts, and open commitments in them are extracted onto a small governed knowledge base; one MCP server serves that knowledge to the LLM you already use; and when a commitment looks finished, closing it is suggested with evidence and confirmed with one tap.
Storage is markdown and YAML in a git repo. No database, no embeddings, no web server, no screen capture, no transcription. The only long-running process is a local MCP server on stdio.
For reviewers — start here
Four commands, no credentials, about three minutes.
npm install
npm test # 85 tests
npm run demo # whole pipeline, temp dir, your disk untouched
npm run demo -- --seed # populate the KB so you can query it yourselfNeeds Node ≥ 20 (node --version) and nothing else — no keys, no network,
no Google account.
Then point Claude Desktop at the server (Setup → 6) and ask whatever you
like. --seed writes six fixture events, two open loops, a counterparty, and
one pending close proposal, so all five tools have something real to act on.
npm run demo -- --reset removes them again.
Questions that work, none of them special-cased:
search my memory for the pricing deck · what do you know about Priya? · anything about the Whitefield site survey? · when is the BSB board review? · was an invoice issued? · what am I waiting on? · resolve BSB · resolve BSBX
What to look for, in order of what it demonstrates:
resolve BSBXreturnsfound: false. It refuses to guess an entity that merely resembles a known one — the failure mode that silently corrupts every loop attached to it.what am I waiting on?shows a pending proposal, not a closed loop. A HIGH-confidence match is deliberately withheld from auto-closing until its category earns it. See Why nothing auto-closes yet.Ask Claude to read the workbeast agent contract. The governance rules are served as MCP resources, so the model can load and obey them rather than being told about them.
cat kb/logs/decisions.md— every automatic decision ends withreverse:.
Three things that are honestly not finished, detailed in
Verification status: live extraction needs a funded
Anthropic key (supply your own in .env); the Fireflies mapping has never seen
real data; and retrieval is keyword + IDF with no embeddings, so paraphrase
without shared vocabulary misses — a deferral the spec makes explicit, with the
trigger for lifting it.
Related MCP server: imprint-mcp-server
The two moments this exists to produce
"My AI already knows." You ask Claude "what am I waiting on from Priya?" and it answers without you pasting any context.
"It noticed I finished." You send the deck; the system observes that event, links it as evidence, and offers to close the open loop.
Layout
Path | What it is |
| Tier 0, the event log. One YAML file per ingested event. Append-only, gitignored — raw mail and transcript bodies never leave the machine. |
| The resolution ledger: canonical ids + aliases. Every counterparty reference resolves to one of these. |
| Declared systems of record — which source is allowed to assert each fact type. Plus the conflict-block format. |
| Volatility class × staleness cost per fact type, and the resulting verdict. |
| The trust ladder. Which loop categories may auto-close, and what they must earn first. |
| The small governed list of facts the system may assert. Each carries source, as_of, and stakes. |
| The commitment ledger. |
| Append-only; every automatic decision with its reversal. |
| The eight clauses every runner loads before a governed run. |
| Who this instance belongs to. The only place identity lives. |
Everything under kb/ except events/ is committed. That git history is the
audit trail: git log -p kb/loops/ledger.yaml shows every state change a loop
has ever undergone.
Setup
Everything below step 2 is only for running against your own live accounts.
To evaluate the system, npm run demo needs none of it.
What each credential unlocks
Credential | Without it | Required for |
none | tests + | evaluating the design |
| no mail or calendar is pulled | live Gmail + Calendar |
| the run reports | Fireflies transcripts |
| events ingest but no loops are ever created | extraction + matching |
| — |
|
Trip hazards
Four things that make a correct setup look broken. Each is real, each has been hit on a working machine.
An unfunded Anthropic key silently costs you events. Ingest is idempotent by event id, and extraction only ever runs over events written that run. So a run made before the key is funded writes events to
kb/events/, fails every extraction, and a later run skips those events as already ingested and never extracts from them. The run now printsEXTRACTION DOWNand exits 1 rather than looking like a quiet inbox, but the events are already spent. Confirm the key works before your first real run — see step 5. Recovery is to delete the affected files fromkb/events/and re-run with the same window.No Fireflies account means every run exits 1.
FIREFLIES_API_KEYis read with the samerequireEnvas the rest, so an unset key is a connector failure, not an absent connector — Gmail and Calendar succeed and the run still exits non-zero. Harmless to the KB, but it will look like a broken install and it will fail CI. Set any non-empty value to skip it cleanly.config/user.yamlships with placeholder addresses, and nothing warns you. It is committed, it containsyou@example.com, and no code validates it. Until you put your real addresses there, your address is not recognised as "me" — which is what decidesemail_sentvsemail_received, so every mail you sent is filed as mail you received, and the extraction prompt is told the wrong thing about who the user is. Edit it and the mirrored user entry at the bottom ofkb/rules/entities.yaml; the two must agree, and nothing checks that they do.A solo calendar entry produces nothing, by design. See Verify it yourself → 5.
1. Identity and secrets
cp .env.example .env # then fill in the keys
$EDITOR config/user.yamlThe user's entry in kb/rules/entities.yaml mirrors config/user.yaml. If you
change one, change the other. Both ship with placeholder addresses that nothing
validates — see trip hazard 3.
2. Install and verify
Node ≥ 20 is required (package.json engines); the pipeline uses
node --input-type=module and Node 20+ APIs, and older versions fail in ways
that do not name the cause.
node --version # must be >= 20
npm install
npm run typecheck
npm test # expect 85 passed3. Google OAuth
Create an OAuth client in the Google Cloud Console under APIs & Services →
Credentials → Create credentials → OAuth client ID, application type
Desktop app. Enable the Gmail API and Google Calendar API for the
same project. Copy the client id and secret into .env.
While the consent screen is in Testing mode, add your own address under
OAuth consent screen → Test users, or Google refuses with access_denied.
There is no separate login command. The first run that needs Google will bind a
loopback listener on an ephemeral port, print an authorisation URL to stderr,
wait for you to approve, then cache the token at GOOGLE_TOKEN_PATH
(.tokens/google.json, mode 0600, gitignored). Later runs reuse it silently.
Scopes are read-only (gmail.readonly, calendar.readonly). Workbeast never
sends, deletes, or modifies anything in your Google account, and the scopes make
that enforceable rather than merely intended.
Delete .tokens/google.json to re-authorise; use
https://myaccount.google.com/permissions to revoke.
GOOGLE_TOKEN_PATH resolves against WORKBEAST_ROOT (which defaults to the
current working directory), not against the process's cwd. Running the
pipeline with a different WORKBEAST_ROOT therefore looks for the token under
that root, finds none, and reopens the consent flow. Use an absolute path in
.env if you run against more than one root.
4. Fireflies
API key from Fireflies → Settings → Developer Settings, into .env.
5. Anthropic
API key from https://console.anthropic.com, into .env. The account needs
credits — a Claude.ai Pro or Max subscription does not fund API usage. An
unfunded key does not fail at startup; it fails per event, at billing, with
400 … credit balance is too low.
Confirm the key is funded before the first real run, because a run made with a dead key spends events that no later run will reprocess (trip hazard 1):
npm run extract -- --dry-run --since 1d # pulls, writes nothingA dry run makes no model calls at all — it stops before extraction — so it
proves the connectors and not the key. To prove the key itself, run for real on
the narrowest window you can and read the summary: extraction errors 0 is the
line that matters. If instead you see EXTRACTION DOWN, fix billing, delete the
events that run wrote from kb/events/, and run again.
Reviewing this project? The extraction and matching passes call the Anthropic API, so they need a funded key. Supply your own in
.envasANTHROPIC_API_KEYand runnpm run extract -- --since 7d.To see the pipeline work without any credentials at all, run
npm run demo— see below.
Seeing it work with no credentials
npm run demo # walkthrough in a temp dir — never touches kb/
npm run demo -- --seed # populate the real kb/ so you can query it
npm run demo -- --reset # remove every fixture againnpm run demo runs the real pipeline against fixture events with canned model
responses, in a throwaway temp directory. It demonstrates, in order: idempotent
re-ingest, politeness not being mistaken for a commitment, an unresolvable
counterparty being dropped rather than guessed, and a HIGH-confidence match
being refused an auto-close because its category sits at suggest-only.
--seed exists because kb/events/ is gitignored — it holds real mail — so
a fresh clone has an empty event store and every query returns nothing. Seeding
writes six fixture events, a counterparty, two open loops and one pending
proposal into the real KB, which is what lets someone who has never connected
Gmail exercise all five tools. Every fixture id contains demo, and --reset
removes them (the decision log keeps its lines — it is append-only by design).
This is fixture data, clearly labelled as such. It proves the machinery and the governance rules; it does not prove extraction quality on real mail — that is kill criterion 2, and it needs a funded key.
Exercising the real prompts without Anthropic credits
npm run demo -- --provider deepseek # needs DEEPSEEK_API_KEY in .envTest-only. The fixed stack is Anthropic; DeepSeek is never the default and
is reachable only through this flag. It reuses EXTRACTION_SYSTEM_PROMPT,
MATCH_SYSTEM_PROMPT, and both renderers verbatim, so what it says about
prompt quality transfers. What it does not exercise is Anthropic structured
outputs — DeepSeek has no equivalent, so that path uses JSON mode. A green run
here says nothing about the messages.parse code in production.
Running it found two real bugs, which is the whole reason it exists:
The model returned
due: "2026-08-14T00:00:00.000Z"where the schema's description asked forYYYY-MM-DD.LoopSchemarejects that, and since the ledger is validated whole before writing, one bad date would have rejected the entire run's write. Fixed withnormalizeDueDate, applied on both providers — a description in a schema is a request, not a constraint.With a bare
entities.yaml, a live model names the person ("Priya") and every loop is correctly dropped as an unknown counterparty. Correct behaviour, and a warning: without the day-one declaration pass this product outputs nothing. Seeding entities is not polish.
6. Claude Desktop
npm run buildThen in claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
{
"mcpServers": {
"workbeast": {
"command": "node",
"args": ["/absolute/path/to/workbeast/dist/mcp/server.js"],
"env": { "WORKBEAST_ROOT": "/absolute/path/to/workbeast" }
}
}
}Both paths must be absolute, and WORKBEAST_ROOT is required — Claude Desktop
launches the server with an arbitrary working directory. Restart afterwards.
7. The day-one declaration pass
One sitting, under an hour, ~10 declarations. Skip this and the governance layer is furniture.
Seed
kb/rules/entities.yamlwith the aliases you already resolve in your head.Declare systems of record in
kb/rules/authorities.mdfor the fact types you touch weekly. Money, pricing, and contract terms ship unassigned on purpose — until you declare an authority, the agent refuses to assert them.Check
kb/config/freshness.mdagainst your actual sources.Write 5–15 facts into
kb/canon/facts.md, each withsource,as_of, and astakestier. Only things you would state as true to someone else.
8. The setup gate
Before trusting any of it: a fresh Claude session, pointed at the KB, must resolve "BSB" correctly and be able to say why. If it can't, the trust layer is not real yet.
Running
npm run extract -- --dry-run # pull and report, write nothing
npm run extract -- --since 48h # default window is 24h
npm run extract -- --since 2026-08-01 # or an ISO dateThe run follows: pull → ingest → canonicalize → extract → append loops → match →
report. Everything it writes carries generated_by: agent, and every state
change gets a reversible line in kb/logs/decisions.md.
Re-running is safe — events already in kb/events/ are skipped, so overlapping
windows never duplicate. A failing connector is reported and the run continues,
exiting non-zero so cron notices. A single event that trips a model refusal or
truncation is skipped and counted, not fatal.
Every event failing extraction is treated differently: that is not a run of
awkward events, it is the model being unreachable — no credits, a bad key, no
network. The run prints EXTRACTION DOWN and exits 1. Without that it would be
indistinguishable from a quiet inbox: zero loops, exit 0, cron reporting success
while the ledger silently stops growing.
That distinction matters because skipping is not deferral. Extraction runs
only over events written that run, so an event ingested during an outage is
never revisited. Recovery is manual: delete those files from kb/events/ and
re-run the same window.
The run prints at most one question, about the most frequent unresolved name, and never blocks on it.
The five MCP tools
Canonicalization lives inside the tools, so even a contract-less runner gets clean entities back.
Tool | What it does |
| Keyword + recency search over the event log. No embeddings. |
| The ledger, filtered by |
| Canonical entity for a name or alias, or |
| Acts on one loop. Default action proposes a close with evidence and changes nothing; |
| Appends one reversible line to the decision log. |
No tool ever modifies kb/events/.
The governed KB as MCP resources
Tools serve derived answers; resources serve the rules those answers must
follow. Without them a runner connected only through this connector could not
read the contract it is required to obey, and clause 1 — "load
rules/entities.yaml first" — would be impossible to satisfy.
Six read-only resources are published: workbeast://kb/agent-contract,
/entities, /authorities, /freshness, /canon, /trust-ladder.
Load the contract first, every session.
Why nothing auto-closes yet
Two signals close a loop: observation (a connector event satisfied the
done_means) and acknowledgment (you said so). Both are gated by the trust
ladder in kb/config/trust.yaml.
Every category starts at suggest-only, where even a HIGH-confidence match
becomes a proposal rather than a close. A category graduates to auto-close
only after its measured precision earns it — 20+ proposals at ≥95% — and
graduation is a human edit to that file. The system never promotes itself.
This is deliberate: an unearned auto-close that turns out wrong destroys trust in the ledger permanently, and the ledger is the entire asset.
Workbeast marks resolved; it does not execute. Closing a loop updates the ledger. Sending the email is the connected LLM acting on your explicit tap. The machine prepares; the human commits.
Verify it yourself
Six checks, in order. Each says what you should see and what it proves.
1. The code is sound — no credentials needed
npm install && npm run typecheck && npm testExpect 85 passed. Proves the ledger rules, entity matching, idempotent
ingest, decision-log round-tripping, and the trust ladder all behave.
2. The pipeline runs end to end — no credentials needed
npm run demoExpect 2 loops created, 1 dropped (unknown counterparty), and a HIGH match
that is not closed. Proves the whole sequence works and the governance rules
fire. Your real kb/ is untouched — it runs in a temp directory.
3. Claude Desktop can reach it
After npm run build and the config in step 6 of Setup, restart Claude Desktop
and ask:
resolve BSB
Expect BSB Homes. Then ask resolve BSBX and expect found: false — it
must refuse to guess. This is the setup gate from the MVP spec.
4. It pulls your real mail
npm run extract -- --dry-run --since 7dFirst run opens a browser for consent. Expect a count of real events and
Dry run — nothing written. Proves OAuth and the connectors work.
5. It extracts real commitments
Requires either Anthropic credits, or DEEPSEEK_API_KEY and --provider deepseek.
npm run extract -- --since 2d --provider deepseekIf your inbox is mostly automated mail, expect 0 loops — and that is the
correct answer. Verify it is refusing rather than failing: the summary prints
extraction errors if calls are failing. No errors plus no loops means it read
your mail and declined to invent commitments, which is the behaviour you want.
To see it find something, you need mail that contains a commitment. The honest way to produce that is to send yourself one:
from another address, ask for something with a deadline
reply from this address delivering it
Then npm run extract -- --since 1h --provider deepseek, having first added the
other party to kb/rules/entities.yaml — an unknown counterparty is dropped by
design, not guessed.
Calendar needs the same care, and fails a naive test. A calendar entry only
becomes a loop if it carries an obligation to someone. CommitmentSchema
requires a counterparty, and a loop whose counterparty does not resolve is
dropped rather than guessed. So a solo block on your own calendar — no
attendees, a title like read pnc or commitment for leetcode — correctly
extracts zero commitments no matter how it is worded. That is the system
refusing to invent a second party, not the connector failing.
To test the calendar path properly:
Create an event with a real attendee, and put a commitment in the description ("I'll send the revised quote before this call").
Add that attendee to
kb/rules/entities.yaml.npm run extract -- --since 1d --horizon 14d.
Check the pull line first — gcal N event(s) proves the connector; loops are a
separate question downstream of it. Note the calendar window looks forward
to --horizon (default 14d) while mail looks backward to --since, so an
upcoming meeting is in scope and a long-past one is not.
6. Inspect the evidence by hand
Nothing is hidden in a database. Read the files:
cat kb/loops/ledger.yaml # the commitments
cat kb/logs/decisions.md # every automatic decision + how to reverse it
ls kb/events | wc -l # events ingested
git log -p kb/loops/ledger.yaml # every state change a loop ever underwentEvery line in the decision log ends with reverse:. If a loop changed state
with no matching line, that is a bug — the two must always agree.
Verification status
Honest accounting of what has and has not been exercised against live services.
Area | Status |
MCP server, 5 tools + 6 resources | Verified end-to-end through a real MCP client, and in Claude Desktop |
Trust ladder, ledger, decisions, entities, ingest | 85 unit tests, all passing |
Pipeline composed end-to-end (ingest → canonicalize → extract → append → match → report) | Verified against a temp KB with mocked models |
Match routing + suggest-only gate | Verified with a mocked model: HIGH does not close |
Freshness verdicts, snooze/unsnooze, measured precision | Verified live over MCP |
Fireflies connector | Auth and query verified live against their API; the account holds 0 transcripts, so the transcript→SourceEvent mapping is unproven |
Gmail + Calendar connectors | Verified live. OAuth consent completed, token cached and reused; a real pull returns real mail and real calendar events, ingested idempotently |
Calendar → loops | Unproven, and not yet testable here: every event on the authorising account is a solo block with no attendees, which correctly yields zero commitments. Needs an event with a real attendee — see Verify it yourself → 5 |
Extraction + matching, live | Blocked: the Anthropic account has no credits. The request is built and sent correctly; the API rejects it at billing, per event |
To finish: add Anthropic credits, then npm run extract -- --since 7d. The
Google side is done.
The v0 kill criteria
Grade honestly after two weeks. These, not the test suite, decide whether it works.
# | Question | Pass |
1 | A fresh Claude session resolves "BSB" and says why | ✅ verified |
2 | Extraction caught the commitments I actually made | ≥ 80% of a hand-audited week |
3 | ≥ 1 evidence-based close proposal was correct and I one-tapped it | Yes |
4 | The morning answer changed what I did that day | ≥ 3 days/week |
5 | The governance tax stayed invisible | ≤ 1 question/run |
6 | I stopped keeping the loop list anywhere else | Honest yes |
Criterion 2 is the one that decides whether the product works at all. Fail → the problem is extraction quality; fix that before building any interface.
Deliberately not built
Not building | Trigger that would start it |
Screen / mic capture | Connectors measurably miss loops that matter |
Embeddings / vector lane | Fuzzy recall visibly fails |
Auto-close without confirmation | A category's measured precision earns it |
Auto-execution of replies | Drafts near-zero-edit for a month — then send-with-undo |
Multi-viewer / company mode | A real second person appears |
Desktop app | A capture need the web can't serve |
Transcription | Never — a transcript service owns it |
The four non-retrofittable fields are already in the schema while still solo:
owner and visibility_scope on every record, the append-only event log with
provenance, generated_by: agent on everything a run writes, and canonical
entity ids on every reference.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceEnables semantic search and retrieval of personal and team knowledge from connected sources like Slack, Gmail, Google Drive, and Dropbox, with the ability to save new information for future recall.Apache 2.0
- Alicense-qualityDmaintenanceEnables querying local meeting notes, calendar events, email metadata, and daily digests from Imprint's database via natural language through Claude Desktop and other MCP clients.14MIT
- Alicense-qualityAmaintenanceEnables LLMs to build and explore a cognitive neuroscience-inspired knowledge graph with SQLite, supporting search, graph traversal, temporal sequences, and structured reasoning.23MIT

Rememberizer MCP Serverofficial
Alicense-qualityDmaintenanceEnables querying and managing personal/team internal knowledge from sources like Slack, Gmail, and Drive through semantic search and retrieval.Apache 2.0
Related MCP Connectors
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.
Your company's brain for AI agents. Cited, permission-aware knowledge across every system.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/omarbshah/workbeast'
If you have feedback or need assistance with the MCP directory API, please join our Discord server