lema-mcp 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +293 -246
  2. package/package.json +12 -7
package/README.md CHANGED
@@ -1,162 +1,103 @@
1
1
  # lema-mcp
2
2
 
3
- Your coding agent reasons well it just doesn't know *your* system, and it keeps
4
- re-proposing the options your team already ruled out. `lema-mcp` is a local
5
- [MCP](https://modelcontextprotocol.io) server that fixes the second problem the
6
- way no read-only context tool can: it **captures the decisions you make** — the
7
- chosen option *and* the alternatives you killed — and then **enforces them**, so a
8
- settled decision stops getting reopened. No account, no database, no network.
9
-
10
- Most "context" tools are read-only: a nicer way to grep your docs. `lema-mcp`
11
- reads too, but its job is **never-reopen**:
12
-
13
- - Your agent settles a choice → it calls **`record_decision`** with what it chose
14
- **and the alternatives it rejected, with why each was killed** (the part that
15
- never survives into the code).
16
- - Before anyone's agent proposes a direction → **`check_decided`** returns the
17
- prior decision if that option is **CLOSED**.
18
- - And on every edit, a **PreToolUse guard hook** (installed for you by `init`)
19
- reads the draft change and surfaces a CLOSED decision *before* the dead option
20
- gets re-proposed — enforced off both your captured decisions **and the repo's
21
- own ADRs**.
3
+ **Your coding agent can read the code. It can't read the _argument_ behind it.**
4
+ `lema-mcp` gives your agent the recorded *why* and the alternatives a project
5
+ already ruled out cited to the source. For React, Kubernetes, and Rust out of
6
+ the box, and for your own repo with one command.
22
7
 
23
- ```bash
24
- npx lema-mcp demo # 30-second never-reopen walkthrough on a throwaway temp dir
25
- npx lema-mcp init # wire this repo for capture + enforcement (idempotent)
26
- ```
8
+ [![npm](https://img.shields.io/npm/v/lema-mcp)](https://www.npmjs.com/package/lema-mcp)
9
+ [![license](https://img.shields.io/npm/l/lema-mcp)](./LICENSE)
10
+ [![MCP](https://img.shields.io/badge/MCP-server-111)](https://modelcontextprotocol.io)
27
11
 
28
- Then open the repo in your agent and ask *"why did we choose X?"* — or just let it
29
- work, and watch it record decisions and get nudged off the ones you settled.
12
+ A local [MCP](https://modelcontextprotocol.io) server. No account, no database, no
13
+ network for your own repo — install it in 30 seconds and ask why a project decided
14
+ something, or whether the approach you're about to take was already rejected.
30
15
 
31
- ## Try it on React, Kubernetes, or Rust — no account
16
+ ---
32
17
 
33
- Before it knows *your* repo, `lema-mcp` can already answer **why a popular project
34
- decided something** — over the recorded RFC/KEP decisions of React, Kubernetes,
35
- and Rust, served from lema's public demo. No account, no token:
18
+ ## Without lema
36
19
 
37
- ```bash
38
- npx lema-mcp try react # or: kubernetes · rust
39
- ```
20
+ - The agent invents the **why** from training recall — fluently, and sometimes
21
+ wrongly. The rationale lives in RFC / KEP / PR threads; it was never in the code.
22
+ - It re-proposes the approach the maintainers **already rejected** two years ago —
23
+ because a rejected alternative leaves *no trace* in the source.
24
+ - Ask "was this ever ruled out?" and you get a confident guess, with no way to tell
25
+ a real ruling from a hallucinated one.
40
26
 
41
- That writes a **read-only** `lema` server (public mode) to `.mcp.json` — and if
42
- you already have the authed `lema` server from `init`, it's left untouched (that
43
- server already serves these public tools). Reload your agent's MCP servers and
44
- ask:
27
+ ## With lema
45
28
 
46
- > *"why did React adopt Hooks over mixins?"* or, before you reach for a pattern,
47
- > *"was a global event bus ever ruled out in Kubernetes?"*
29
+ - One **cited** answer from the project's actual recorded deliberation every `[n]`
30
+ links to the RFC / PR where the call was made.
31
+ - A typed **`ruled_out`** verdict when a project already rejected your approach,
32
+ with the recorded reason *and* a pointer to where the docs say to do it instead.
33
+ - An honest **"no recorded ruling"** when the record is silent — which means
34
+ *unknown*, **not** *approved*. lema never fills the gap with a guess.
48
35
 
49
- You get **one synthesized, cited answer** each `[n]` links to its GitHub source
50
- (the RFC/PR) where available and an honest **"no recorded ruling"** when the
51
- record is silent, instead of a confident guess. Two tools light up (`why_decided`,
52
- `settled`); nothing local is registered. Ready for the same on *your own*
53
- repo? `npx lema-mcp init` adds capture + enforcement.
36
+ > lema holds **reasoning** why a decision was made, what was rejected not API
37
+ > syntax or code samples. For those, reach for a docs tool. lema is the right place
38
+ > for *why*.
54
39
 
55
- Grounded only in recorded decisions; claims are **summarized, not verbatim**;
56
- there are **no** relitigation/blast lenses (a cold import writes no
57
- decision→decision edges) and no source-authored date. It's a curated three-repo
58
- demo corpus, not analytics over your own graph.
40
+ ---
59
41
 
60
- ## What never-reopen looks like
42
+ ## Try it in 30 seconds — no account
61
43
 
62
- Your agent settles a choice and calls `record_decision` with the chosen option
63
- and the rejected alternatives. Later, anyone's agent reaches for a dead option —
64
- in a `check_decided` call, in a `search_decisions` result, or while drafting an
65
- edit the guard inspects — and the killed option comes back **CLOSED**, with the
66
- original reason attached:
44
+ ```bash
45
+ npx lema-mcp try react # or: kubernetes · rust
46
+ ```
67
47
 
68
- > **CLOSED do not propose "SWR":** no first-class mutation / cache
69
- > invalidation — we'd hand-roll it *(decided 2026-06-04 · "Data fetching for the
70
- > web app" · chose TanStack Query)*
48
+ That writes a read-only public server to your project's `.mcp.json`. Reload your
49
+ agent's MCP servers (in Claude Code: `/mcp`) and try the flagship tool,
50
+ **`check_approach`** name a direction, get the recorded verdict:
71
51
 
72
- So the agent surfaces the prior decision instead of re-litigating it. Supersede a
73
- decision and the *previously chosen* option goes CLOSED too never-reopen,
74
- enforced both ways. (That's the real output of `npx lema-mcp demo`, run against a
75
- throwaway temp dir.)
52
+ ```text
53
+ > "Let's add a delayMs prop to Suspense to debounce the fallback." (repo: react)
76
54
 
77
- The guard is **advisory and fail-open today**: in its default `context` mode it
78
- injects that CLOSED note as a non-blocking nudge for the agent it never emits an
79
- `allow` (which would skip your normal Edit/Write confirmation on the very edit
80
- it's flagging) and it never hard-blocks (`deny`) in v1. Opt into
81
- `LEMA_GUARD_MODE=ask` and a strong match prompts *you* before the edit; `off` is a
82
- kill switch. Any error → it emits nothing and gets out of the way.
55
+ ruled_out the React team considered and rejected this.
56
+ "<the recorded rationale, summarizednot a quote>" [1]
57
+ Where to look instead → https://react.dev/reference/react
58
+ [1] reactjs/rfcs#212
83
59
 
84
- Decisions are captured to `.lema/decisions.jsonl` a plain append-only file you
85
- can commit, so your whole team's agents share the same memory through git. No key,
86
- no LLM call on our side: your agent forms the decision; `lema-mcp` stores it and
87
- serves it back.
60
+ > "I'll add a global event bus for cross-component communication." (repo: react)
88
61
 
89
- ## Does enforcement actually change what the agent does?
62
+ no_recorded_ruling React's public record doesn't settle this.
63
+ (Unknown — not approved.)
64
+ ```
90
65
 
91
- We measured it on **two real public repos we didn't write** (Backstage, vite),
92
- transcribing six of their own documented decisions into the `record_decision`
93
- format and running the **real `lema-mcp guard` binary** on the agent's draft edits.
94
- Agent and an arm-blind judge were Claude Sonnet 4.6; 168 trials, 0 errors; a
95
- deterministic code check agreed with the judge on 163/168 (the 5 diffs
96
- hand-verified in lema's favor). Three arms: **blind** (no doc), **docs** (the
97
- decision pre-loaded in context), **lema** (guard only, no doc in context).
98
-
99
- The honest result is an **existence proof**, not "agents are wrong 58% of the
100
- time":
101
-
102
- - Of the six well-documented public decisions, only **one** cut against the 2026
103
- frontier model (`node-fetch` → native `fetch`). On that one contrarian decision,
104
- a blind agent re-proposed the killed library **58.3% of the time (14/24, N=24)**;
105
- lema drove it to **0%** — matching the docs-preloaded arm *without carrying the
106
- doc in context*.
107
- - On the **five decisions the model already gets right**, lema stayed silent: **0%
108
- re-proposal and 0% false-abstain** across 48 trials. The nagging / false-positive
109
- failure people fear about enforcement didn't happen.
110
-
111
- The honest caveats, stated plainly: it's a **single contrarian decision-type**
112
- (node-fetch, N=24) — a solid existence proof, not breadth. And a public-repo
113
- benchmark *structurally understates* enforcement's value: public decisions are
114
- disproportionately the ones the model already absorbed in training (that's why
115
- they're widespread enough to be documented). The decisions where enforcement
116
- actually moves the needle are **proprietary, contrarian, recent, team-specific** —
117
- which by construction aren't in any public repo. That's the capture-forward thesis:
118
- enforcement catches the decisions where your team disagrees with the AI's defaults,
119
- and gets out of the way everywhere else.
120
-
121
- Full method, the result table, and every raw trial: [`./docs/enforcement-lift`](./docs/enforcement-lift).
66
+ Or just ask in plain language *"why did React adopt Hooks over mixins?"* — and
67
+ get one cited answer, with an honest abstain when the record is silent.
68
+
69
+ Covered today: **React · Kubernetes · Rust**, served from lema's public API
70
+ (`api.lema.sh`). Tokenless. It's a curated three-project demo corpus not
71
+ analytics over a graph you own.
72
+
73
+ ---
122
74
 
123
75
  ## Install
124
76
 
125
- `npx` needs only Node — no Go toolchain, no account:
77
+ `npx` needs only Node — no Go toolchain, no account. Two commands cover both ways
78
+ to use lema:
126
79
 
127
80
  ```bash
128
- npx lema-mcp init # one-time: wire this repo for capture + enforcement
81
+ npx lema-mcp try react # read-only: ask React/Kubernetes/Rust why + what's ruled out
82
+ npx lema-mcp init # your repo: decision capture + the never-reopen guard
129
83
  ```
130
84
 
131
- `init` is non-destructive and idempotent — existing config is merged, not
132
- clobbered, and re-running changes nothing. It writes **three files** via five
133
- idempotent steps:
134
-
135
- 1. **`.mcp.json`** — registers the `lema` MCP server (preserving any servers
136
- already there).
137
- 2. **`AGENTS.md`** — appends a short, managed capture-protocol block: *when you
138
- settle a non-trivial decision call `record_decision` with what you chose and
139
- rejected; before proposing a direction call `check_decided`; treat a CLOSED
140
- result as binding.* This protocol is what actually drives capture — a hook
141
- can't form the decision itself.
142
- 3. **`.claude/settings.json`** — installs **three hooks**: a PostToolUse commit
143
- reminder (fires only on `git commit`), the PostToolUse **capture-nudge**
144
- (`lema-mcp nudge`, prompts `record_decision` when you edit a dependency
145
- manifest), and the PreToolUse **never-reopen guard** (`lema-mcp guard`, the
146
- enforcement above).
85
+ Both are **non-destructive and idempotent**they merge into existing config and
86
+ re-running changes nothing. `init` and `try` share the same `lema` server key; the
87
+ authed `init` server is a superset (it serves the public tools too), so the two
88
+ coexist and `try` never downgrades it.
147
89
 
148
- `init` does **not** create `.lema/decisions.jsonl` — the capture store is created
149
- lazily on the first `record_decision`.
90
+ <details>
91
+ <summary><b>Claude Code</b></summary>
150
92
 
151
- Prefer Go, or want a pinned binary?
93
+ Easiest let lema write the config and hooks for you:
152
94
 
153
95
  ```bash
154
- go install github.com/lemahq/lema-mcp/cmd/lema-mcp@latest
96
+ npx lema-mcp init # or: npx lema-mcp try react
155
97
  ```
156
98
 
157
- Or wire it by hand add to your agent's MCP config (Claude Code `.mcp.json`).
158
- Note this gets you the read + capture tools, but not the guard/nudge hooks that
159
- `init` installs:
99
+ Or add it by hand to `.mcp.json` (this gets the read + capture tools, but not the
100
+ guard/nudge hooks that `init` installs):
160
101
 
161
102
  ```json
162
103
  {
@@ -165,144 +106,250 @@ Note this gets you the read + capture tools, but not the guard/nudge hooks that
165
106
  }
166
107
  }
167
108
  ```
109
+ </details>
168
110
 
169
- With no flags, `lema-mcp` auto-discovers a decisions directory in the working
170
- directory (`docs/adr`, `doc/adr`, `docs/adrs`, `docs/decisions`,
171
- `docs/architecture/decisions`, `architecture/decisions`, `adr`, `.adr`) and an
172
- `openspec/` tree if present. You can also point it explicitly:
111
+ <details>
112
+ <summary><b>Cursor</b></summary>
173
113
 
174
- ```bash
175
- lema-mcp --adr-dir docs/adr # a local directory (no account, no network)
176
- lema-mcp --repo github.com/org/name # a public repo (GITHUB_TOKEN for private)
114
+ Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
115
+
116
+ ```json
117
+ {
118
+ "mcpServers": {
119
+ "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
120
+ }
121
+ }
177
122
  ```
178
123
 
179
- Other flags: `--ref` (branch/ref for a remote `--repo`), `--pattern` (ADR filename
180
- regex), `--openspec-dir`, `--capture-file` (override the JSONL path), and
181
- `--http`/`--port` (see *serve mode* below).
182
-
183
- ## The tools
184
-
185
- Your agent calls these over MCP. In the standard server **eight are always on**;
186
- `search_docs` / `get_doc` also register in local mode once a markdown tree is
187
- indexed. (The `npx lema-mcp try` public-demo server runs a public-only subset —
188
- just `why_decided` / `settled`.)
189
-
190
- **Enforce + capture (the part read-only tools don't have):**
191
-
192
- - **`record_decision`** — capture a decision you just settled: the chosen option,
193
- the **rejected** alternatives (with why each was killed), optional rationale /
194
- refs / constraint / consequence, and `supersedes` to retire an earlier one.
195
- Rejected and superseded options come back CLOSED. Appends to
196
- `.lema/decisions.jsonl`.
197
- - **`check_decided`** — before proposing a direction, check whether it's already
198
- decided and CLOSED. Matched off **both** the capture store **and the repo's own
199
- ADRs**, so a documented decision stops a fresh agent even if it was never
200
- captured live.
201
-
202
- **Read (the entry point — query before you write code):**
203
-
204
- - **`search_decisions`** — natural-language query → the most relevant atomic
205
- claims (chosen / rejected / constraint / consequence) with their source ADR,
206
- under a token budget. CLOSED flags surface here too.
207
- - **`get_decision`** — one decision's full body, status, and typed edges.
208
- - **`list_decisions`** — the decisions recorded in the repo, optionally by status.
209
- - **`get_decision_graph`** — traverse typed edges (`supersedes`, `superseded_by`,
210
- `depends_on`, `related_to`) to connected decisions.
211
- - **`search_docs`** / **`get_doc`** *(local mode, when a doc tree is indexed)* —
212
- sectioned, budgeted retrieval over the repo's project markdown (specs, READMEs,
213
- agent instructions, ADR/openspec full text) so the agent reads the sections that
214
- matter instead of whole files.
215
-
216
- **Public demo (no account — `npx lema-mcp try <repo>`):**
217
-
218
- - **`why_decided`** — ask why **React / Kubernetes / Rust** made a decision; one
219
- cited answer over their recorded RFC/KEP decisions, surfacing status and the
220
- ruled-out alternatives, with an honest abstain when the record is silent. The
221
- abstain is also machine-readable (`record_silent: true`), and a grounded answer
222
- carries `caveats` naming what the public demo does *not* cover. Tokenless.
223
- - **`settled`** — before you propose a library / pattern / approach, check whether
224
- one of those projects already ruled it out. Returns a typed `state`
225
- (`settled` / `not_settled` / `unsure`) plus each governing decision's ref and
226
- recorded reasoning; `not_settled` means *not on the record*, **not *approved***.
227
- (`why_not_public` remains as a deprecated alias.)
124
+ For the no-account public demo instead, add the env block:
228
125
 
126
+ ```json
127
+ {
128
+ "mcpServers": {
129
+ "lema": {
130
+ "command": "npx",
131
+ "args": ["-y", "lema-mcp@latest"],
132
+ "env": { "LEMA_MCP_MODE": "public", "LEMA_PUBLIC_REPO": "react-rfcs" }
133
+ }
134
+ }
135
+ }
229
136
  ```
230
- > search_decisions "why did we choose an MCP-first architecture?"
231
- ```
137
+ </details>
138
+
139
+ <details>
140
+ <summary><b>Claude Desktop</b></summary>
141
+
142
+ Settings → Developer → Edit Config, then add to `mcpServers`:
232
143
 
233
- ```jsonc
234
- // illustrative shape — atom text/ids vary by repo
144
+ ```json
235
145
  {
236
- "repo": "docs/adr",
237
- "claims": [
238
- { "id": "16-2", "type": "chosen", "text": "One MCP server is the single surface agents call — all writes route through it.", "ref": "ADR-0016" },
239
- { "id": "27-4", "type": "rejected", "text": "Folding inference into lema was rejected on the serve path: the agent reasoning over the atoms is the customer's own.", "ref": "ADR-0027" }
240
- ],
241
- "tokens_used": 211,
242
- "usage": { "atoms_tokens": 211, "source_decisions": 2, "source_tokens": 1840, "tokens_saved": 1629, "compression_ratio": 8.7 },
243
- "truncated": false
146
+ "mcpServers": {
147
+ "lema": {
148
+ "command": "npx",
149
+ "args": ["-y", "lema-mcp@latest"],
150
+ "env": { "LEMA_MCP_MODE": "public", "LEMA_PUBLIC_REPO": "react-rfcs" }
151
+ }
152
+ }
244
153
  }
245
154
  ```
155
+ </details>
246
156
 
247
- A note on token cost: the read tools return tight, sourced atoms (default
248
- ~1500-token budget, tunable with `max_tokens`) instead of whole documents, and
249
- every `search_decisions` response carries a self-reported `usage` block estimating
250
- the tokens returned versus the source-document tokens for that call (the numbers
251
- above are illustrative). On a large decision record that's a meaningful per-call
252
- saving — but it's a local, self-measured estimate, not an audited benchmark, and
253
- it's a side benefit. The reason to run lema is never-reopen, above.
254
-
255
- ## The subcommands
256
-
257
- - **`init [dir]`** — wire a repo for capture (the three files / three hooks above);
258
- idempotent. The same code path backs the lema Workbench GUI's "enable capture"
259
- button.
260
- - **`demo`** — a ~30-second never-reopen walkthrough using the real capture +
261
- enforce path against a throwaway temp dir that's deleted afterward. Nothing is
262
- written to your repo. This is the fastest way to see the CLOSED behavior.
263
- - **`try <react|kubernetes|rust>`** — wire a **read-only public-demo** server
264
- (`lema-try` in `.mcp.json`, public mode) so your agent can ask why those
265
- projects decided things, no account. Distinct from `init` (which sets up
266
- capture for *your* repo); the two coexist. Reload your agent's MCP servers
267
- afterward.
268
- - **`guard`** — the PreToolUse hook body: reads the tool-call payload on stdin,
269
- emits a never-reopen permission decision on stdout. Advisory, fail-open, always
270
- exits 0. `init` installs it; you don't call it directly.
271
- - **`nudge`** — the PostToolUse hook body: on an Edit/Write/MultiEdit to a
272
- dependency manifest (`go.mod`, `package.json`, `cargo.toml`, `pyproject.toml`,
273
- `requirements.txt`, `gemfile`, `build.gradle`, `pom.xml`), emits a non-blocking
274
- reminder to `record_decision`. Fail-open. Installed by `init`.
275
- - **`serve`** (≡ the `--http` flag) — serve the same engine over localhost HTTP
276
- (default `:4321`, `--port`) for the lema Workbench desktop GUI instead of stdio
277
- MCP.
157
+ <details>
158
+ <summary><b>Windsurf</b></summary>
278
159
 
279
- ## Configuration & privacy
160
+ Add to `~/.codeium/windsurf/mcp_config.json`:
280
161
 
281
- - **`LEMA_GUARD_MODE`** — `context` (default, non-blocking nudge), `ask` (prompt
282
- the human on a strong match), or `off` (kill switch).
283
- - **`LEMA_DISABLE_QUERY_LOGGING=1`** — drop query text from the usage log entirely.
284
- Otherwise queries are scrubbed for credential-shaped substrings before logging.
285
- - **`LEMA_USAGE_LOG` / `LEMA_QUESTION_LOG` / `LEMA_GUARD_LOG`** — opt-in local log
286
- files (tool usage, unanswered questions, guard fires) for measuring and
287
- calibrating; all off unless set.
162
+ ```json
163
+ {
164
+ "mcpServers": {
165
+ "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
166
+ }
167
+ }
168
+ ```
169
+ </details>
288
170
 
289
- ## Hosted retrieval (optional)
171
+ <details>
172
+ <summary><b>VS Code (GitHub Copilot)</b></summary>
290
173
 
291
- By default everything is local and lexical. To point `search_decisions` at hosted
292
- hybrid retrieval over your full decision layer, set two env vars — no other change:
174
+ Add to `.vscode/mcp.json` note VS Code uses the `servers` key:
175
+
176
+ ```json
177
+ {
178
+ "servers": {
179
+ "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
180
+ }
181
+ }
182
+ ```
183
+ </details>
184
+
185
+ <details>
186
+ <summary><b>Go install / pinned binary</b></summary>
293
187
 
294
188
  ```bash
295
- LEMA_API_URL=https://<your-lema-api> LEMA_API_TOKEN=<bearer> lema-mcp
189
+ go install github.com/lemahq/lema-mcp/cmd/lema-mcp@latest
296
190
  ```
297
191
 
298
- In hosted mode `search_decisions` runs against the atom layer over `POST /retrieve`;
299
- this is **search-only** in the MVP, so `get_decision` / `list_decisions` /
300
- `get_decision_graph` return a search-only error and the doc tools aren't
301
- registered. Capture and enforcement (`record_decision` / `check_decided` / the
302
- guard) are **always local**.
192
+ For the public demo, set `LEMA_MCP_MODE=public` and `LEMA_PUBLIC_REPO=react-rfcs`
193
+ (`k8s-enhancements` · `rust-rfcs`). The public API URL is baked into the binary.
194
+ </details>
195
+
196
+ The public config sets only `LEMA_MCP_MODE` + `LEMA_PUBLIC_REPO`
197
+ (`react-rfcs` · `k8s-enhancements` · `rust-rfcs`) — the API URL is compiled in.
198
+
199
+ ---
200
+
201
+ ## Two ways to use it
202
+
203
+ ### 1. The public record — React, Kubernetes, Rust (read-only, no account)
204
+
205
+ Ask why a popular project decided something, or check whether a direction was
206
+ already rejected, over its recorded RFC/KEP deliberation. This is the `try` server.
207
+
208
+ ### 2. Your own repo — capture + never-reopen (local, no account)
209
+
210
+ Most "context" tools are read-only — a nicer way to grep your docs. lema reads too,
211
+ but its real job is **never-reopen**:
212
+
213
+ - Your agent settles a choice → it calls **`record_decision`** with the option it
214
+ chose **and the alternatives it rejected, with why each was killed** (the part
215
+ that never survives into the code).
216
+ - Before anyone proposes a direction → **`check_decided`** returns the prior
217
+ decision if that option is **CLOSED**.
218
+ - On every edit, a **PreToolUse guard hook** (installed by `init`) reads the draft
219
+ change and surfaces a CLOSED decision *before* the dead option gets re-proposed —
220
+ enforced off both your captured decisions **and the repo's own ADRs**.
221
+
222
+ Decisions are captured to `.lema/decisions.jsonl` — a plain append-only file you
223
+ commit, so your whole team's agents share the same memory through git. No key, no
224
+ LLM call on our side: your agent forms the decision; lema stores it and serves it
225
+ back.
226
+
227
+ #### What never-reopen looks like
228
+
229
+ Your agent reaches for an option you already killed — and it comes back **CLOSED**,
230
+ with the original reason attached:
231
+
232
+ > ⛔ **CLOSED — do not propose "SWR":** no first-class mutation / cache
233
+ > invalidation — we'd hand-roll it *(decided 2026-06-04 · "Data fetching for the
234
+ > web app" · chose TanStack Query)*
235
+
236
+ So the agent surfaces the prior decision instead of re-litigating it. Supersede a
237
+ decision and the *previously chosen* option goes CLOSED too — enforced both ways.
238
+ (That's the real output of `npx lema-mcp demo`, run against a throwaway temp dir.)
239
+
240
+ The guard is **advisory and fail-open**: in its default `context` mode it injects
241
+ that note as a non-blocking nudge — it never hard-blocks and never auto-approves an
242
+ edit. `LEMA_GUARD_MODE=ask` prompts *you* on a strong match; `off` is a kill switch.
243
+ Any error → it emits nothing and gets out of the way.
244
+
245
+ ---
246
+
247
+ ## Available tools
248
+
249
+ Your agent calls these over MCP.
250
+
251
+ ### The public record (no account)
252
+
253
+ | Tool | What it does |
254
+ |------|--------------|
255
+ | **`check_approach`** ★ | Name an approach → a typed `ruled_out` verdict with the recorded **why** (cited) **and** a pointer to where the docs cover the supported path — or an honest `no_recorded_ruling`. The Fusion tool. |
256
+ | **`settled`** | Typed `state` (`settled` / `not_settled` / `unsure`) for a direction, plus each governing decision's ref and reasoning. `not_settled` means *not on the record*, **not approved**. |
257
+ | **`why_decided`** | One cited answer to "why did React / Kubernetes / Rust decide X?", surfacing status and ruled-out alternatives — with a machine-readable abstain (`record_silent: true`) when silent. (`why_not_public` is a deprecated alias.) |
258
+
259
+ ### Your own repo
260
+
261
+ | Tool | What it does |
262
+ |------|--------------|
263
+ | **`record_decision`** | Capture a settled decision: the chosen option and the **rejected** alternatives (with why each was killed), plus rationale / refs / `supersedes`. Rejected and superseded options come back CLOSED. Append-only. |
264
+ | **`check_decided`** | Adjudicate one proposed direction against decisions already CLOSED → typed verdict (`ruled_out` / `not_ruled_out` / `incomplete` / `error`), off **both** your capture store **and** the repo's ADRs. |
265
+ | **`search_decisions`** | Natural-language query → the most relevant atomic claims (chosen / rejected / constraint / consequence) with their source ADR, under a token budget. |
266
+ | **`get_decision`** · **`list_decisions`** · **`get_decision_graph`** | One decision's full body; the list by status; traversal of typed edges (`supersedes`, `depends_on`, …). |
267
+ | **`search_docs`** · **`get_doc`** | Sectioned, budgeted retrieval over the repo's project markdown (local mode, once a doc tree is indexed) — the matching sections, not whole files. |
268
+ | **`ask`** | One cited, synthesized answer over your team's **hosted** decision graph (hosted mode). |
269
+
270
+ In your own repo the full server registers the read + capture tools (and the public
271
+ tools too); the `npx lema-mcp try` server runs the public subset only.
272
+
273
+ ---
274
+
275
+ ## Why lema is different (the honest part)
276
+
277
+ lema's brand *is* its honesty — that's what makes a "why" tool trustworthy:
278
+
279
+ - **Abstain ≠ approval.** Silence is reported as silence. lema would rather say
280
+ "no recorded ruling" than manufacture one.
281
+ - **Cited, summarized — not quoted.** Answers are grounded in recorded decisions and
282
+ paraphrased ("the record indicates …"), each claim tied to a followable ref.
283
+ - **Local-first.** Capture and enforcement run entirely on your machine, in a file
284
+ you own. No key, no upload, no model call on our side.
285
+ - **No fabricated graph.** A cold import writes no decision→decision edges and no
286
+ source-authored dates; lema shows what's actually on the record, nothing it can't
287
+ stand behind.
288
+
289
+ ---
290
+
291
+ ## Does enforcement change what the agent does?
292
+
293
+ We measured it on **two real public repos we didn't write** (Backstage, vite),
294
+ transcribing six of their documented decisions into `record_decision` format and
295
+ running the **real `lema-mcp guard` binary** on the agent's draft edits. 168 trials,
296
+ 0 errors. The honest result is an **existence proof**, not "agents are wrong 58% of
297
+ the time":
298
+
299
+ - On the one decision that cut against the 2026 frontier model (`node-fetch` →
300
+ native `fetch`), a blind agent re-proposed the killed library **58.3%** of the
301
+ time (14/24); lema drove it to **0%** — matching a docs-preloaded arm *without*
302
+ carrying the doc in context.
303
+ - On the five decisions the model already gets right, lema stayed silent: **0%
304
+ re-proposal and 0% false-abstain** across 48 trials. No nagging.
305
+
306
+ A public-repo benchmark *understates* the value — public decisions are
307
+ disproportionately the ones the model already absorbed in training. The decisions
308
+ where enforcement moves the needle are proprietary, contrarian, recent,
309
+ team-specific. Full method and every raw trial:
310
+ [`./docs/enforcement-lift`](./docs/enforcement-lift).
311
+
312
+ ---
313
+
314
+ ## Configuration & privacy
315
+
316
+ - **`LEMA_GUARD_MODE`** — `context` (default, non-blocking), `ask` (prompt the human
317
+ on a strong match), or `off`.
318
+ - **`LEMA_DISABLE_QUERY_LOGGING=1`** — drop query text from the usage log entirely.
319
+ Otherwise queries are scrubbed for credential-shaped substrings before logging.
320
+ - **`LEMA_USAGE_LOG` / `LEMA_QUESTION_LOG` / `LEMA_GUARD_LOG`** — opt-in local log
321
+ files; all off unless set.
322
+
323
+ <details>
324
+ <summary><b>Subcommands & flags</b></summary>
325
+
326
+ - **`init [dir]`** — wire a repo for capture: registers the server in `.mcp.json`,
327
+ appends a managed capture-protocol block to `AGENTS.md`, and installs three hooks
328
+ (a commit reminder, the `nudge` capture prompt on dependency-manifest edits, and
329
+ the `guard` never-reopen check). Idempotent.
330
+ - **`try <react|kubernetes|rust>`** — wire the read-only public-demo server.
331
+ - **`demo`** — a ~30-second never-reopen walkthrough against a throwaway temp dir
332
+ (nothing written to your repo). The fastest way to see the CLOSED behavior.
333
+ - **`guard`** / **`nudge`** — the hook bodies `init` installs; advisory, fail-open,
334
+ always exit 0. You don't call them directly.
335
+ - **`serve`** (≡ `--http`, default `:4321`) — serve the same engine over localhost
336
+ HTTP for the lema Workbench desktop GUI instead of stdio MCP.
337
+
338
+ With no flags, lema auto-discovers a decisions directory (`docs/adr`, `doc/adr`,
339
+ `docs/adrs`, `docs/decisions`, `docs/architecture/decisions`,
340
+ `architecture/decisions`, `adr`, `.adr`) and an `openspec/` tree. Point it
341
+ explicitly with `--adr-dir`, `--repo github.com/org/name` (`GITHUB_TOKEN` for
342
+ private), `--ref`, `--pattern`, `--openspec-dir`, or `--capture-file`.
343
+
344
+ **Hosted retrieval (optional).** Set `LEMA_API_URL` + `LEMA_API_TOKEN` to point
345
+ `search_decisions` at hosted hybrid retrieval over your full decision layer
346
+ (search-only in the MVP). Capture and enforcement are always local.
347
+ </details>
348
+
349
+ ---
303
350
 
304
351
  ## License
305
352
 
306
- MIT. `lema-mcp` is the free, local wedge of [**lema**](https://lema.sh) — the
307
- system of record for *why*. The hosted decision graph, the team why-surface, and
308
- the manager-facing Intelligence layer are coming at [lema.sh](https://lema.sh).
353
+ MIT. `lema-mcp` is the free, local wedge of [**lema**](https://lema.sh) — the system
354
+ of record for *why*. The hosted decision graph, the team why-surface, and the
355
+ manager-facing Intelligence layer are at [lema.sh](https://lema.sh).
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "lema-mcp",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "mcpName": "io.github.lemahq/lema-mcp",
5
- "description": "Local, database-less MCP server that makes your repo's decisions — and what it ruled out — queryable by your coding agent, and lets the agent record new ones with enforced never-reopen.",
5
+ "description": "MCP server that gives your coding agent the recorded why behind decisions — and what was already ruled out — cited. Check React, Rust, and Kubernetes out of the box, or capture and enforce never-reopen on your own repo. Local, no account.",
6
6
  "bin": {
7
7
  "lema-mcp": "bin/lema-mcp.js"
8
8
  },
@@ -13,10 +13,10 @@
13
13
  "prepack": "cp ../../README.md ./README.md && cp ../../LICENSE ./LICENSE"
14
14
  },
15
15
  "optionalDependencies": {
16
- "lema-mcp-darwin-arm64": "0.10.0",
17
- "lema-mcp-darwin-x64": "0.10.0",
18
- "lema-mcp-linux-x64": "0.10.0",
19
- "lema-mcp-linux-arm64": "0.10.0"
16
+ "lema-mcp-darwin-arm64": "0.10.1",
17
+ "lema-mcp-darwin-x64": "0.10.1",
18
+ "lema-mcp-linux-x64": "0.10.1",
19
+ "lema-mcp-linux-arm64": "0.10.1"
20
20
  },
21
21
  "engines": {
22
22
  "node": ">=18"
@@ -38,6 +38,11 @@
38
38
  "decisions",
39
39
  "ai",
40
40
  "agent",
41
- "context"
41
+ "context",
42
+ "rfc",
43
+ "react",
44
+ "rust",
45
+ "kubernetes",
46
+ "documentation"
42
47
  ]
43
48
  }