Knowledge-lifecycle MCP: turn agent work into memory, recall it across projects, promote to org.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Part of the xylem stack.
The knowledge-lifecycle MCP that turns work your agents already did into compound, org-wide knowledge. cambium bridges two substrates that already exist β agentsync (what happened: claims, finishes, notes, changed files) and context-keeper (why: decisions, constraints) β and adds the three things neither has:
distill() β turn events into memory automatically (passive capture)recall() β one federated read endpoint for every agent type
(coding agent, Slack KB bot, SRE bot β same store, same call)promote() β graduate knowledge local β team β org as it earns trustNamed for the cambium layer of a tree: the thin living tissue where all growth happens.
Knowledge layers fail because they're a side system nobody calls. cambium's
bet: capture and recall must be native tools in the agent's loop, and state
must live in the substrate the work already lives in β git β not a separate
service. Storage is an implementation detail behind recall():
| Scope | Lives in | Trust gate |
|---|---|---|
local | <repo>/.cambium/knowledge.json | none β it's yours |
team | knowledge.json on a dedicated cambium branch of the shared repo | recalls β₯ N or an endorsement |
org | knowledge.json in a dedicated org knowledge repo | an endorsement required; optionally lands as a pull request β review is the gate, git revert is the undo |
Team writes use the agentsync pattern: a private worktree under .git/ and
git push as compare-and-swap, so concurrent agents never clobber each other.
gh (GitHub CLI) is only needed for pull-request-mode org promotion.
Point an MCP client at the server β no env required to start:
First contact is helpful, not cold. MCP servers can't start a conversation,
so cambium teaches you through its own responses. Call status() (or any
tool) before it's configured and instead of a bare env error you get structured
guidance β what's set, what's missing, what each gap costs in plain terms, and
the exact setup() call that fixes it:
setup(project_repo, agent_id, org_repo?, org_pr?, team_branch?) finishes
the job: it validates the paths, scaffolds .cambium/ (and adds it to the
repo's .gitignore), and writes a fallback config at ~/.cambium/config.json
that the server reads when env vars are absent. It takes effect immediately β no
restart. No secrets are written: the file holds only paths, ids, and flags,
and lives outside any repo. If org_repo is a GitHub owner/name you haven't
cloned locally, setup offers the exact gh/git commands to stand it up
and leaves org scope off β it never creates or pushes a repo for you.
Env still wins. Any of the variables below, set in the MCP client config, overrides the config file per-key β the table is the full reference layer:
| env var | required | default | meaning |
|---|---|---|---|
CAMBIUM_REPO | yes | β | your project clone (local scope, agentsync + context-keeper substrates) |
CAMBIUM_AGENT_ID | yes | β | your unique agent id |
CAMBIUM_REMOTE | no | origin | git remote |
CAMBIUM_GIT_TIMEOUT | no | 25 | per-invocation git/gh timeout (seconds) so a stuck call fails fast instead of hanging the server |
CAMBIUM_TEAM_BRANCH | no | cambium | team-scope branch |
CAMBIUM_AGENTSYNC_BRANCH | no | agentsync | coordination branch name distill reads |
AGENTSYNC_BOARD_REPO | no* | β | which repo holds the board β the same setting agentsync reads, so the two servers cannot disagree (see below) |
CAMBIUM_ORG_REPO | no | β | path to the org knowledge repo clone (org scope off without it) |
CAMBIUM_ORG_PR | no | direct push | 1 = org promotion opens a pull request |
CAMBIUM_PROMOTE_RECALLS | no | 3 | recalls needed for localβteam |
CAMBIUM_RELEASE_CAPTURE | no | off | 1 = also capture agentsync claims at their done/released transition (see below) |
CAMBIUM_CONFIG_FILE | no | ~/.cambium/config.json | override the fallback config path (mainly for tests) |
* distill() reads finished agentsync claims off a coordination board. That
board is a shared, long-lived team artifact β not a property of whichever
project this session happens to be in β so cambium resolves its address
independently of the session, using exactly the order agentsync itself uses:
AGENTSYNC_BOARD_REPO β the explicit board address (env, or the same key
in ~/.cambium/config.json). One setting configures both servers.AGENTSYNC_REPO β agentsync's legacy explicit pin.CAMBIUM_REPO β but only if that repo actually holds the coordination
branch (real ref lookup: local head β remote-tracking ref β ls-remote).Why. Before this, cambium looked for the coordination branch in
CAMBIUM_REPO while agentsync (unpinned) followed
~/.xylem/active_project.json. The two could point at different repos, and
whenever the current project had never been provisioned neither found anything.
distill() reported that as the bland string "no coordination branch found",
callers treated it as normal, and the result was that distill imported zero
agentsync claims across its entire lifetime β a three-legged design silently
running on two legs.
distill()'s return now makes a miss impossible to read as a success:
status becomes "distilled_with_warnings" (not "distilled");warnings carries a plain-language line per skipped substrate;sources.agentsync is an object β {status, board_repo, board_source, branch, claims_seen, done_claims, imported, reason, fix} β so "there is no board",
"the board is here and nobody has finished anything", and "imported 3" are
three visibly different results rather than one empty number.status() reports the same under substrates.agentsync_board.
Org setup: create one (private) repo, e.g. github.com/you/knowledge, with
an empty {"items": []} in knowledge.json; everyone who should read org
knowledge clones it and points CAMBIUM_ORG_REPO (or setup(org_repo=β¦)) at
their clone. cambium manages that clone (it hard-syncs it) β dedicate it, don't
work in it.
capture(content, type, kind, why, tags, valid_while) β save a knowledge
item to local scope (types: memory | need | skill). Manual path.
valid_while optionally names the premise the item depends on, so a dead
assumption is spottable later (see Machine-maintained documentation entropy).
record_need(content, why, tags) β first-class needs ("we're missing X"),
promotable like anything else so recurring wants surface at team/org level.
distill() β the automatic path. Reads agentsync's coordination branch
(every currently done claim: task + note + changed files β an outcome
memory) and context-keeper's .context/ (active decisions & constraints,
rationale and dec-NNN provenance preserved). Idempotent β wire it to a
session-end or post-commit hook and capture becomes passive.
Release-time capture (opt-in, CAMBIUM_RELEASE_CAPTURE=1). agentsync keys
claims by agent id and deletes a claim from live state the instant it is
released or re-claimed β it exposes no hook or event, only the rewritten
claims.json on the branch. So a claim that completes and then churns before a
full distill runs against it is silently lost. With the flag on, each distill
also remembers the last-seen claim per agent and captures any that has churned
away since the previous run β reconstructing it from that snapshot, through the
same dedupe watermark, so a claim captured at release time and again in a
later full distill never double-imports. Fire distill() on completion events
(a post-commit / session-end hook) and completed work is captured at its
transition instead of only when a distill happens to catch it live.
What this is not: it is passive capture at the moments distill runs, not
exhaustive reconstruction. The guarantee is precise β if a distill sweep
observes a claim while it is done (or carries a note), that knowledge is
captured even if the claim later churns. The residual gap: a done state that is
created and churned away entirely between two sweeps (e.g. cambium wasn't
running) is never observed, and only agentsync's git log still holds it.
Walking that log to reconstruct such claims exhaustively is a possible
follow-up (the history survives β agentsync's history() reads it), deliberately
left out of this change.
import_memory(source, path) β ingest an external memory export into
cambium as local-scope, provenance-tagged knowledge items (see Import
below). Read-only against the source; imported items are not auto-promoted.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/cambium)<a href="https://allmcps.com/mcp/cambium"><img src="https://allmcps.com/api/badge/cambium?style=directory" alt="Cambium on AllMCPs" /></a>