ideate MCP Server
OfficialClick 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., "@ideate MCP Serverrecord a decision: use React for frontend"
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.
@ideate/plugin
The public, composable surface of ideate — a Claude Code plugin for AI-augmented software delivery.
ideate decomposes into three functions: a process record (the durable, auditable trail of what was decided and done — append-only, project-local, never curated or ranked by ideate itself), a knowledge graph (memory and retrieval over that trail — developed as a separate project, not part of this plugin), and a delegation board (how work is handed to and coordinated across agents — this plugin ships its LOCAL backend; the hosted, multi-person board is a future sibling service behind the same contract). ideate is deliberately non-prescriptive about workflow: it supplies primitives that fire mechanically, not a process you are told to follow, and it never blocks, redirects, or opines on what you do.
What this plugin provides today
This package ships the Layer-0 floor: the append-only process record and the mechanical capture/priming wiring around it. Nothing here is optional workflow — every piece below fires without requiring an agent to remember to call it.
An append-only process record. Every entry — a decision, a finding, a session outcome, a subagent outcome, a commit boundary, a task completion — is appended, never updated or deleted; a correction is a new record that references the superseded one. Every write passes a capture-time secret-scanning gate before anything touches disk.
Capture hooks.
SessionEnd,PreCompact,SubagentStop,TaskCompleted, andPostToolUse(ongit commit) are wired inhooks/hooks.jsonso records are captured mechanically as you work, with zero required tool calls. Every ideate hook is non-blocking: it exits 0, writes side effects andadditionalContextonly, and never blocks, denies, or halts anything the host is doing.Session priming. At session start, and on subagent start, a bounded, unranked digest of the most recent process records is surfaced as additional context — recency- and scope-selected only, never scored or curated, and explicitly framed as quoted historical data rather than instructions.
Telemetry. Native counters for capture, priming, and failure events, inspectable with the
ideate-telemetryCLI.
Related MCP server: VibeTape MCP Server
Requirements
Node.js >= 22.5 must be installed and on your PATH. Claude Code ships as
a native binary and bundles no runtime, so the plugin's MCP server, hooks, and
CLIs — which run on Node and use the built-in node:sqlite — need Node
available. Install it from https://nodejs.org (or your package manager)
before installing the plugin.
Install
There are two ways to wire this plugin into a Claude Code project. Both land
on the same MCP server and hooks/hooks.json — the manifests below are just
two different ways of pointing Claude Code at them. This section documents the
contracts (what each mechanism provides); it does not prescribe which one to
use or what workflow to run once installed.
(a) Marketplace install
This repo ships .claude-plugin/marketplace.json, a Claude Code
plugin-marketplace manifest listing this plugin (name: ideate, source: "./" — the repo root). From within Claude Code:
/plugin marketplace add ideate-ai/ideate
/plugin install ideateThis is the manifest-driven path — Claude Code resolves the plugin and wires
.mcp.json / hooks/hooks.json for you. On first launch the plugin runs a
one-time setup: because built output (dist/) is not committed, it installs
its single dependency and builds itself, then the MCP server, the mechanical
capture/priming hooks, and the CLIs are live. The first session may pause
briefly while that runs; later sessions start instantly. If Node is missing or
older than 22.5 (see Requirements above), the plugin prints a clear one-line
message and otherwise does nothing — it never blocks your session.
(b) Manual wiring
For a project that wants to point at this plugin directly rather than through the marketplace resolver:
Build the package:
npm install && npm run build(compilessrc/todist/;dist/is not committed). A marketplace install runs this for you on first launch; for manual wiring you run it once yourself.Add an MCP server entry to the consuming project's
.mcp.jsonpointing at the launcher, which runs the first-launch bootstrap before starting the server:{ "mcpServers": { "ideate": { "command": "sh", "args": ["<path-to-this-plugin>/bin/ideate-mcp"] } } }This registers all sixteen MCP verbs: the three record verbs (
record_append,record_read,record_decision) described below, the eleven board verbs in The work-state board, and the two steering verbs in Steering verbs.Wire the mechanical capture hooks by pointing the consuming project's host at this plugin's
hooks/hooks.json. That file declares the actual hook shape this plugin provides —SessionStart(priming viabin/ideate-record prime),SubagentStart/SubagentStop,SessionEnd(bin/ideate-record session-end),PreCompact, andPostToolUseongit commit— each entry acommandhook invoking either${CLAUDE_PLUGIN_ROOT}/bin/ideate-recordor one of thehooks/*.mjsscripts. How a consuming project performs that wiring (copying the file, referencing it, or another host-specific mechanism) is outside this plugin's contract — only the shape ofhooks/hooks.jsonitself is.
Build / test (contributor path)
Prerequisites: Node >= 22.5.
npm install
npm run build # compiles src/ to dist/ (gitignored)
npm test # vitest (fork pool capped — see vitest.config.ts)npm run typecheck (tsc -p tsconfig.test.json) typechecks every
**/*.test.ts in the package with noEmit — tsconfig.json's own build
excludes test files so dist/ stays exactly the compiled-source shape
(no .test.js alongside it), but that means npm run build alone never
typechecks a test. typecheck closes that gap without touching dist/, and
runs automatically before npm test/pnpm run test via the pretest
script — a test file with a type error fails before vitest ever starts.
npm run test:fresh-copy runs scripts/fresh-copy-check.mjs, which copies
this directory to a scratch location with no surrounding project context and
re-runs install/build/test there — the mechanical proof that this package
stands alone.
The process-record surface
The record core has exactly two transports over one implementation: three MCP tools, and a CLI. Both write through the same gated append-only store, so a record captured via one transport is indistinguishable from one captured via the other.
MCP verbs (registered by the ideate MCP server, dist/server.js):
record_append(kind, claim, verification_anchor?, scope?, content, task_id?, supersedes?, references?)— append one process record. Open-vocabularykind(e.g.finding,session-outcome,commit-boundary, …).supersedestakes the id of the record this one replaces (a correction is a new record, never an edit);referencesis the advanced form — a JSON array of typed edges,[{"rel":"refutes","id":"01…"}].record_read(scope?, id?, include_content?, limit?, cursor?)— read records newest-first, optionally filtered by a plain substring match against scope/kind/source or by exactid. Unranked: selection only, no scoring. Returns{ok, records, next_cursor}. Rows are summaries — every field except the prose body, plus a derivedcontent_length;include_content: trueadds the body, and anidwithinclude_content: trueis the single-record fetch. Paged: at mostlimitrows (default 100, clamped into 1..500) and at most ~40,000 characters of rows, so a page can come back shorter thanlimitwhile records remain — only anullnext_cursormeans exhaustion. Pass a page'snext_cursorback ascursor(opaque; tied to the filter it was issued for) to walk a selection to the end.record_decision(claim, rationale?, verification_anchor?, scope?, task_id?, supersedes?, references?)— sugar forrecord_append(kind="decision", ...); the ADR entry point. The decision write is its capture — there is no separate decision store, and an overturned decision is superseded, not rewritten.
The record FILES are the export surface. Each record is one Markdown file
at <record.path>/YYYY/MM/{ULID}.md (record.path from .ideate.json,
default .ideate/record/) — one record per file, never rewritten (files are
written exclusive-create), with the YYYY/MM shard derived from the record
id's own embedded timestamp, so the path of a record is computable from its id
alone. An external consumer — a knowledge-graph ingester, a backup, a grep —
reads that tree directly: durable, stably addressed, and requiring no ideate
process, no MCP session, and no cooperation from this plugin at read time.
record_read (and ideate-record read) is the in-session view for an agent:
a bounded, paged, unranked selection over those same files, not an export
API — do not build an ingester on it, and never read a short page as the end
of the record.
ideate-record CLI (bin/ideate-record, the same gated core as a
standalone executable — this is what the capture hooks invoke):
ideate-record append --kind <k> --claim <c|-> [--anchor <a>] [--scope <s>] [--content <text>|-] [--task <id>] [--supersedes <id>]— append one record directly; exits 1 on failure.--content -reads the prose body from stdin, and--claim -reads the claim from stdin the same way — but only ONE of the two may claim stdin per call.ideate-record read [--scope <substring>] [--id <ulid>] [--limit <n>] [--cursor <c>] [--include-content] [--json]— print records newest-first; exits 1 on failure.--jsonis the agent-facing door and is bounded exactly likerecord_read(summary rows, default page size, opaquenext_cursor, shared payload budget);--include-contentputs the prose bodies back and requires--json. The human-readable listing is unpaged and full-bodied unless you pass--limitor--cursor. There is no "print everything" flag — the record files above are the export surface for that.ideate-record session-end— reads aSessionEndhook payload from stdin and appends a recall-shaped session-outcome record. Hook path: always exits 0 (a capture failure must never look like a hook failure to the host).ideate-record prime [--scope <substring>] [--budget <n>]— print a compact, unranked digest of the most recent records for hookadditionalContext. Hook path: always exits 0.
The work-state board (local backend)
The delegation board's LOCAL backend — the ratified work-state contract
implemented over SQLite in WAL mode. One sentence of model: work items carry
an opaque spec payload the board never parses (bring any methodology — a
plan document, a Spec Kit URI, a plain prompt); claims are
server-authoritative leases with fencing tokens — claim is an atomic
compare-and-set that succeeds only on an open item whose dependencies are
all done, leases expire (default hours-scale) so crashed workers can never
orphan work forever, and a stale token is rejected on
renew/complete/release after a reclaim. Every transition appends an
immutable audit event in the same transaction. For a solo user the
coordination features are degenerate (contention never occurs), never
absent — the same code paths a future hosted team would exercise, proven
by a contention suite that races real OS processes.
Eleven MCP verbs (same server, dist/server.js): work_create,
work_get, work_list, work_update_meta, work_claim, work_renew,
work_release, work_complete, work_cancel, work_reopen,
work_events. renew/complete/release take no actor — the token
proves identity, and the audit event carries the claim's actual holder.
ideate-work CLI (bin/ideate-work): the same eleven verbs as
subcommands plus a CLI-only sweep (the session-boundary expiry pass the
SessionStart/SessionEnd hooks trigger opportunistically). Board location:
work_state.path in .ideate.json (default .ideate-work/). Every
subcommand except sweep exits 1 on failure; sweep is a hook path and
always exits 0, printing nothing to stdout.
ideate-work create --title <t> --spec <s|-> --spec-format <f> --human <h> [--agent <a>] [--depends-on <id1,id2,...>] [--supersedes <id>] [--parent <id>] [--tenant <t>]— create one item; prints it as JSON.--spec -reads the spec body from stdin — the same conventionideate-record append --content -established.--supersedes <id>records a supersedes edge to the item this one replaces, and the superseded item surfaces the replacement as a derivedreferenced_bybacklink.--parent <id>sets the CONTAINMENT parent — a different edge from--depends-on, which is ordering; omit it for a root item.ideate-work get --id <id> [--json]— fetch one item, running the lazy-expiry seam first; a miss prints(not found), ornullunder--json. This is the way to read one item's fullspec.ideate-work list [--tenant <t>] [--status <open|in_progress|done|cancelled>] [--json] [--include-spec] [--limit <n>] [--cursor <c>]— list items with the derived claimability view attached. Rows are summaries — every field except the opaquespecbody, plus a derivedspec_length;--include-specputs the bodies back and requires--json(the human listing has nowhere to print them).--jsonreturns a PAGE, not the board:{"items": [...], "next_cursor": ...}, at most--limititems (default 100, clamped into 1..500) and at most ~40,000 characters of rows — the same payload budget the MCPwork_listtool applies — so a page can come back shorter than--limitwhile items remain, and only anullnext_cursormeans exhaustion. Pass a page'snext_cursorback as--cursor(opaque; tied to the--tenant/--statusfilter it was issued for). The human-readable listing is one line per item, unpaged and unbudgeted unless you pass--limitor--cursor, in which case it prints a resume hint while items remain.ideate-work update-meta --id <id> --expected-version <n> [--title <t>] [--spec <s|->] [--spec-format <f>] [--depends-on <id1,id2,...>] [--supersedes <id>] [--parent <id>] [--clear-parent] [--confirm-shrink]— update metadata via optimistic compare-and-set onversion.--spec -reads the new spec body from stdin. The containment parent is tri-state: pass neither flag to leave it unchanged,--parent <id>to set or move it,--clear-parentto make the item a root again. The two are mutually exclusive. Shrink guard: replacing a spec of 200+ characters with one under 20 characters is refused (almost never intentional — this is the shape of finding 01M2MKGS5PRV7WSD0W4ZQYAG4A) unless--confirm-shrinkis passed; never triggered oncreate.ideate-work claim --id <id> --human <h> [--agent <a>] [--lease-ms <n>]— claim an open, claimable item; mints the fencing token the next three subcommands require.ideate-work renew --id <id> --token <n> [--lease-ms <n>]— extend an active claim's lease. No actor flags — the token proves identity.ideate-work release --id <id> --token <n> [--note <n|->]— hand an active claim back toopen. No actor flags.--note -reads the handoff note from stdin.ideate-work complete --id <id> --token <n> [--note <n|->]— complete an active claim. No actor flags; the note becomes a process record (below).--note -reads the completion note from stdin.ideate-work cancel --id <id> --human <h> [--agent <a>]— cancel an item fromopenorin_progress; voids any active claim.ideate-work reopen --id <id> --human <h> [--agent <a>]— move an item fromdoneback toopen.ideate-work events --id <id> [--json]— every event for one item, oldest first.ideate-work sweep [--tenant <t>]— CLI-only (never an MCP tool): the opportunistic board-wide expiry pass. Hook path: always exits 0, stdout stays silent, diagnostics go to stderr.
Board operations. The board is one SQLite file, board.db, under
work_state.path (workStatePath(), default .ideate-work/) — nothing
else lives there. Deleting that directory resets the board: every claim and
event is gone, and item state re-derives from nothing (there is no
recovery). This is safe to do on purpose because it is a DIFFERENT store
from the append-only process record (record.path, default
.ideate/record/) — deleting the board never touches the record, and vice
versa. board.db also carries a schema version (PRAGMA user_version, checked on every
open). Three things can happen when it does not match this binary's own
version: an older, pre-versioning board is handled with a one-time grace
(stamped on their next write) rather than rejected outright; a board newer
than this binary but still within a compatibility floor its writer stamped
into the file opens successfully but DEGRADED — anything the newer schema
added is invisible to this binary — with a one-time-per-process warning on
stderr and a durable note in the project's own process record (plus a
telemetry counter tallying every such open), so an installed plugin lagging
behind a newer board is quietly noticed rather than silently wrong; and a
board newer than both this binary and its compatibility floor (or with no
floor stamped at all) produces a hard version-mismatch error — that one is
deliberate, not a bug, and this project makes no promises about migration
timelines beyond it.
One item's lifecycle — an example trace. The transcript below runs a work item end-to-end through the board (outputs trimmed for width). It illustrates the shape of the lifecycle — it does not prescribe a workflow, and every verb is equally available over MCP:
$ ideate-work create \
--title "Add retry backoff to the fetch client" \
--spec "<the work-item body — opaque to the board>" \
--spec-format "ideate/wi-v1" --human dan
{"id":"01KXBQDD7P…","status":"open","version":1,…}
$ ideate-work claim --id 01KXBQDD7P… --human dan --agent claude-coordinator
{"status":"in_progress","claim":{"holder":{"human":"dan","agent":"claude-coordinator"},
"claim_token":1,"lease_expires":"2026-07-12T21:53:58.767Z"},…}
# …the actual work happens here…
$ ideate-work complete --id 01KXBQDD7P… --token 1 \
--note "Exponential backoff added with jitter; full suite green."
{"status":"done","claim":null,…}
$ ideate-work events --id 01KXBQDD7P…
2026-07-12T17:53:45.206Z create actor=dan
2026-07-12T17:53:58.767Z claim actor=dan token=1
2026-07-12T17:55:58.126Z complete actor=dan token=1 note="Exponential backoff added…"Completing with a note is also a capture point: the note becomes an
append-only process record (kind work-completion, verification anchor
board:<item>#complete@<time>), retrievable through the record surface
like any other record:
$ ideate-record read --scope <item-id> --json
{"records":[{"kind":"work-completion",
"verification_anchor":"board:01KXBQDD7P…#complete@2026-07-12T17:55:58.126Z",
"claim":"Add retry backoff to the fetch client — Exponential backoff added…",…}],
"next_cursor":null}That --json output is a PAGE, and the real one is indented — the transcript
above is trimmed for width. Read next_cursor, not the row count: a null
is the only statement that the selection is exhausted.
Steering verbs
A smaller seam rides the same MCP server (dist/server.js). It keeps its own
store, separate from the record and the board, and has no CLI — these two
verbs exist over MCP only.
Two steering verbs — steering_read and steering_put — GATED OFF by
default. Steering items are a project's guiding principles and policies, one
file per item under .ideate/steering/. steering_put creates or amends ONE
item: on amend the prior version is appended to the item's amendment history
and the status may flip, and there is no hard delete — you deprecate via
status (active | deprecated | superseded), or name a DIFFERENT item as
supersedes to replace it. steering_read is selection only — by id
(exact), domain (substring), status and kind — unranked by contract, and
bounded the same way the reads above are: the amendment history is projected
away unless you pass include_history (a history_length is always present),
and the result {ok, items, next_cursor} is a page of at most limit items
(default 100, clamped into 1..500) within the same ~40,000-character payload
budget, resumed with an opaque cursor.
Both steering verbs are gated behind steering.enabled in .ideate.json —
absent by default, which means off, with no environment override. While the
gate is off — the only state this package ships in — each verb returns
{"ok":false,"code":"GATED",...} as a tool error and writes NOTHING: the
gate is checked before arguments are validated, so a gated project cannot
even create the steering directory by calling with bad arguments. Steering
shapes what a model attends to, and nothing that shapes attention ships live
here ahead of the evaluation that measures it.
Honest status
Available now: the append-only process record, the five mechanical capture points (
SessionEnd,PreCompact,SubagentStop,TaskCompleted,PostToolUseongit commit), session/subagent priming, the capture-time secret-scanning gate, native telemetry counters, and the work-state board's local backend (the eleven verbs above, with a contention suite racing real OS processes as its correctness evidence).Not yet built: the hosted delegation board (cross-machine, multi-person coordination). Its ratified trigger is a concrete second contributor; the local board implements the identical contract, so that move is configuration, not a rewrite.
Present but gated off: the two steering verbs. They are registered by the shipped server and answer every call with
{"ok":false,"code":"GATED",...}untilsteering.enabledis set to true in.ideate.json— see Steering verbs.Present but off: claim-time priming — the hook point exists in the claim path and a
work_claimstelemetry counter records the denominator, but priming itself is mechanically disabled (work_state.claim_primingconfig flag, default off, no environment override) pending further validation. Same discipline as the rest of the deferred set: planning-time gap identification (designed, not built) and per-prompt priming (deferred). None of this plugin's shipped behavior depends on any of these.This package is
"private": trueinpackage.json. It is distributed as a Claude Code plugin — a git-source marketplace install that builds itself on first launch — not published to npm, soprivatestays set.
License
AGPL-3.0-only — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
- DoneThatOAuthai.donethat
Privacy-first work tracking with summaries, reports, coaching, and AI-ready long-term memory.
Intelligent context infrastructure for AI teams: knowledge graph, sessions, tasks, documents.
The context layer for your company's AI: your team's decisions, meetings and plans, with sources.
Shared, versioned context that humans and AI agents can publish, review, annotate, and continue.
Related MCP Servers
- AlicenseBqualityBmaintenancePersistent memory and session intelligence for AI coding assistants. Auto-tracks mistakes, decisions, and context via hooks. Mines your full session history for patterns, predictions, and cross-session search.2116MIT
- AlicenseCqualityCmaintenanceCaptures key development moments, enables multi-agent traceability, provides intelligent context curation, and facilitates seamless agent-to-agent handoffs.2917MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to track session lifecycles, persist context notes and transcripts, and manage a human-gated memory-promotion pipeline with an append-only audit trail.3 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI coding sessions to persist the reasoning behind work — decisions and their justifications, rejected options, side findings and nuances — as append-only Markdown records with reversible review, archive and human-confirmed purge. Retrieval scores records against the current task and returns only a short, budgeted list of hits, with full text fetched on demand, plus optional session hooks and handoff support.MIT