# lema-mcp [Health: Active]

**Category:** ☁️ Cloud Platforms  
**Repository:** https://github.com/lemahq/lema-mcp  
**GitHub Stars:** 1  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/lema-mcp

## Description
Cited 'why was this decided?' answers for your repo and for React, Kubernetes, and Rust.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "lema-mcp": {
    "command": "npx",
    "args": ["-y","lema-mcp"]
  }
}
```

## Documentation & README

# lema-mcp

**Your coding agent can read the code. It can't read the _argument_ behind it.**
`lema-mcp` gives your agent the recorded *why* — and the alternatives a project
already ruled out — cited to the source. For React, Kubernetes, and Rust out of
the box, and for your own repo with one command.

[![npm](https://img.shields.io/npm/v/lema-mcp)](https://www.npmjs.com/package/lema-mcp)
[![license](https://img.shields.io/npm/l/lema-mcp)](./LICENSE)
[![MCP](https://img.shields.io/badge/MCP-server-111)](https://modelcontextprotocol.io)

A local [MCP](https://modelcontextprotocol.io) server. No account, no database, no
network for your own repo — install it in 30 seconds and ask why a project decided
something, or whether the approach you're about to take was already rejected.

---

## ❌ Without lema

- The agent invents the **why** from training recall — fluently, and sometimes
  wrongly. The rationale lives in RFC / KEP / PR threads; it was never in the code.
- It re-proposes the approach the maintainers **already rejected** two years ago —
  because a rejected alternative leaves *no trace* in the source.
- Ask "was this ever ruled out?" and you get a confident guess, with no way to tell
  a real ruling from a hallucinated one.

## ✅ With lema

- One **cited** answer from the project's actual recorded deliberation — every `[n]`
  links to the RFC / PR where the call was made.
- A typed **`ruled_out`** verdict when a project already rejected your approach,
  with the recorded reason *and* a pointer to where the docs say to do it instead.
- A typed **`settled`** verdict when your approach *is* the project's in-force
  recorded choice — the governing decision cited, with a docs pointer for the how.
- An honest **"no recorded ruling"** when the record is silent — which means
  *unknown*, **not** *approved*. lema never fills the gap with a guess.

> lema holds **reasoning** — why a decision was made, what was rejected — not API
> syntax or code samples. For those, reach for a docs tool. lema is the right place
> for *why*.

---

## Try it in 30 seconds — no account

```bash
npx lema-mcp try react        # or: kubernetes · rust
```

That writes a read-only public server to your project's `.mcp.json`. Reload your
agent's MCP servers (in Claude Code: `/mcp`) and try the flagship tool,
**`check_approach`** — name a direction, get the recorded verdict:

```text
> "Let's add a delayMs prop to Suspense to debounce the fallback."   (repo: react)

  ⛔ ruled_out — the React team considered and rejected this.
     "<the recorded rationale, summarized — not a quote>"  [1]
     Where to look instead →  https://react.dev/reference/react
     [1] reactjs/rfcs#212

> "I'll add a global event bus for cross-component communication."   (repo: react)

  ◦ no_recorded_ruling — React's public record doesn't settle this.
     (Unknown — not approved.)
```

Or just ask in plain language — *"why did React adopt Hooks over mixins?"* — and
get one cited answer, with an honest abstain when the record is silent.

Covered today: **React · Kubernetes · Rust**, served from lema's public API
(`api.lema.sh`). Tokenless. It's a curated three-project demo corpus — not
analytics over a graph you own.

---

## Install

**No-account public demo** (React's recorded decisions, zero setup):

[![Add lema to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lema&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImxlbWEtbWNwQGxhdGVzdCJdLCJlbnYiOnsiTEVNQV9NQ1BfTU9ERSI6InB1YmxpYyIsIkxFTUFfUFVCTElDX1JFUE8iOiJyZWFjdC1yZmNzIn19) &nbsp; [![Install lema in VS Code](https://img.shields.io/badge/VS_Code-Install_lema-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522lema%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522-y%2522%252C%2522lema-mcp%2540latest%2522%255D%252C%2522env%2522%253A%257B%2522LEMA_MCP_MODE%2522%253A%2522public%2522%252C%2522LEMA_PUBLIC_REPO%2522%253A%2522react-rfcs%2522%257D%257D)

If the Cursor button doesn't open an install prompt (common when the browser can't hand off the `cursor://` deeplink), paste this into `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "lema": {
      "command": "npx",
      "args": ["-y", "lema-mcp@latest"],
      "env": { "LEMA_MCP_MODE": "public", "LEMA_PUBLIC_REPO": "react-rfcs" }
    }
  }
}
```

That drops you into React's public record — ask *"why did React rule out X?"* and get a cited answer, no account. To wire **your own repo** for capture, or point the demo at Kubernetes or Rust, use the per-client setup below.

`npx` needs only Node — no Go toolchain, no account. Two commands cover both ways
to use lema:

```bash
npx lema-mcp try react   # read-only: ask React/Kubernetes/Rust why + what's ruled out
npx lema-mcp init        # your repo: decision capture + the never-reopen guard
```

Both are **non-destructive and idempotent** — they merge into existing config and
re-running changes nothing. `init` and `try` share the same `lema` server key; the
authed `init` server is a superset (it serves the public tools too), so the two
coexist and `try` never downgrades it.

<details>
<summary><b>Claude Code</b></summary>

Easiest — let lema write the config and hooks for you:

```bash
npx lema-mcp init        # or: npx lema-mcp try react
```

Or add it by hand to `.mcp.json` (this gets the read + capture tools, but not the
guard/nudge hooks that `init` installs):

```json
{
  "mcpServers": {
    "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
  }
}
```
</details>

<details>
<summary><b>Cursor</b></summary>

Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
  }
}
```

For the no-account public demo instead, add the env block:

```json
{
  "mcpServers": {
    "lema": {
      "command": "npx",
      "args": ["-y", "lema-mcp@latest"],
      "env": { "LEMA_MCP_MODE": "public", "LEMA_PUBLIC_REPO": "react-rfcs" }
    }
  }
}
```
</details>

<details>
<summary><b>Claude Desktop</b></summary>

Settings → Developer → Edit Config, then add to `mcpServers`:

```json
{
  "mcpServers": {
    "lema": {
      "command": "npx",
      "args": ["-y", "lema-mcp@latest"],
      "env": { "LEMA_MCP_MODE": "public", "LEMA_PUBLIC_REPO": "react-rfcs" }
    }
  }
}
```
</details>

<details>
<summary><b>Windsurf</b></summary>

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
  }
}
```
</details>

<details>
<summary><b>VS Code (GitHub Copilot)</b></summary>

Add to `.vscode/mcp.json` — note VS Code uses the `servers` key:

```json
{
  "servers": {
    "lema": { "command": "npx", "args": ["-y", "lema-mcp@latest"] }
  }
}
```
</details>

<details>
<summary><b>Go install / pinned binary</b></summary>

```bash
go install github.com/lemahq/lema-mcp/cmd/lema-mcp@latest
```

For the public demo, set `LEMA_MCP_MODE=public` and `LEMA_PUBLIC_REPO=react-rfcs`
(`k8s-enhancements` · `rust-rfcs`). The public API URL is baked into the binary.
</details>

The public config sets only `LEMA_MCP_MODE` + `LEMA_PUBLIC_REPO`
(`react-rfcs` · `k8s-enhancements` · `rust-rfcs`) — the API URL is compiled in.

### Hosted teams: sign in once; the repository resolves automatically

After you sign in to Lema, save one Organization-scoped credential outside your
repositories. The normal setup contains identity credentials, not a copied
workspace UUID:

```text
# ~/.config/lema/credentials
LEMA_API_URL=https://api.lema.sh
LEMA_API_TOKEN=lema_live_...
```

```bash
chmod 600 ~/.config/lema/credentials
npx lema-mcp@latest doctor context
```

Restart the coding agent after changing MCP configuration. From then on, Lema
matches the checkout's verified Git remote to a Repository, finds its Project,
and passes one immutable target receipt to every operation. Opening two
repositories in parallel does not create a mutable “active repository,” and
each user keeps their own Organization-scoped credential.

For multi-repo Projects, ambiguity recovery, repositories without a remote,
worktrees, and compatibility overrides, read
[Target context: Projects, repositories, and Runs](https://github.com/lemahq/lema-mcp/blob/HEAD/docs/target-context.md).

---

## Two ways to use it

### 1. The public record — React, Kubernetes, Rust (read-only, no account)

Ask why a popular project decided something, or check whether a direction was
already rejected, over its recorded RFC/KEP deliberation. This is the `try` server.

### 2. Your own repo — capture + never-reopen (local, no account)

Most "context" tools are read-only — a nicer way to grep your docs. lema reads too,
but its real job is **never-reopen**:

- Your agent settles a choice → it calls **`record_decision`** with the option it
  chose **and the alternatives it rejected, with why each was killed** (the part
  that never survives into the code).
- Before anyone proposes a direction → **`check_decided`** returns the prior
  decision if that option is **CLOSED**.
- On every edit, a **PreToolUse guard hook** (installed by `init`) reads the draft
  change and surfaces a CLOSED decision *before* the dead option gets re-proposed —
  enforced off both your captured decisions **and the repo's own ADRs**.

Decisions are captured to `.lema/decisions.jsonl` — a plain append-only file you
commit, so your whole team's agents share the same memory through git. No key, no
LLM call on our side: your agent forms the decision; lema stores it and serves it
back.

#### What never-reopen looks like

Your agent reaches for an option you already killed — and it comes back **CLOSED**,
with the original reason attached:

> ⛔ **CLOSED — do not propose "SWR":** no first-class mutation / cache
> invalidation — we'd hand-roll it *(decided 2026-06-04 · "Data fetching for the
> web app" · chose TanStack Query)*

So the agent surfaces the prior decision instead of re-litigating it. Supersede a
decision and the *previously chosen* option goes CLOSED too — enforced both ways.
(That's the real output of `npx lema-mcp demo`, run against a throwaway temp dir.)

The guard is **advisory and fail-open**: in its default `context` mode it injects
that note as a non-blocking nudge — it never hard-blocks and never auto-approves an
edit. `LEMA_GUARD_MODE=ask` prompts *you* on a strong match; `off` is a kill switch.
Any error → it emits nothing and gets out of the way.

---

## Available tools

Your agent calls these over MCP.

### The public record (no account)

| Tool | What it does |
|------|--------------|
| **`check_approach`** ★ | Name an approach → a three-valued verdict: `ruled_out` (rejected, with the recorded **why** synthesized and cited), `settled` (it *is* the project's in-force recorded choice, the governing decision cited), or an honest `no_recorded_ruling`. Every verdict carries a pointer to where the docs cover the how. The one public door — it folds in the cited "why was this decided?" answer (the former `why_decided`) and the `settled` check. |

### Your own repo

| Tool | What it does |
|------|--------------|
| **`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. |
| **`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. |
| **`search_decisions`** | Natural-language query → the most relevant atomic claims (chosen / rejected / constraint / consequence) with their source ADR, under a token budget. |
| **`get_decision`** · **`list_decisions`** · **`get_decision_graph`** | One decision's full body; the list by status; traversal of typed edges (`supersedes`, `depends_on`, …). |
| **`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. |
| **`ask`** | One cited, synthesized answer over your team's **hosted** decision graph (hosted mode). |
| **`get_state_brief`** | Resume a hosted Run with a Project-scoped brief: primary-repository state first, then ACL-filtered context from other visible repositories. |

In your own repo the full server registers the read + capture tools (and the public
`check_approach` too); the `npx lema-mcp try` server runs the public door only.

### `lema settle` — rule from the terminal (hosted mode)

The package also installs a `lema` command. `settle` is the terminal half of
adjudication: it **drafts** a ruling on a hosted decision and prints the deep
link where your **browser click binds it** — a terminal credential never
binds anything (that split is structural: programmatic principals cannot
create binding rulings, by design).

```
lema settle accept <decision-id>...              # draft an accept, print the bind link
lema settle reject <decision-id> --reason <why>  # proposed drafts only; takes effect immediately
lema settle supersede <decision-id> --by <decision-id>  # takes effect immediately
```

`accept` drafts; `reject` and `supersede` apply on the server in the same
request (no browser confirm step exists for them — the command says so).
Decision ids are full UUIDs or unique 6+ character UUID prefixes (`d_xxxxxx`
locators are content hashes and are refused). Requires hosted identity
credentials (`LEMA_API_URL` and `LEMA_API_TOKEN`). `LEMA_WORKSPACE_ID` is an
optional CI, recovery, or ambiguity override—not normal repository setup.

---

## Why lema is different (the honest part)

lema's brand *is* its honesty — that's what makes a "why" tool trustworthy:

- **Abstain ≠ approval.** Silence is reported as silence. lema would rather say
  "no recorded ruling" than manufacture one.
- **Cited, summarized — not quoted.** Answers are grounded in recorded decisions and
  paraphrased ("the record indicates …"), each claim tied to a followable ref.
- **Local-first.** Capture and enforcement run entirely on your machine, in a file
  you own. No key, no upload, no model call on our side.
- **No fabricated graph.** A cold import writes no decision→decision edges and no
  source-authored dates; lema shows what's actually on the record, nothing it can't
  stand behind.

---

## Does enforcement change what the agent does?

We measured it on **two real public repos we didn't write** (Backstage, vite),
transcribing six of their documented decisions into `record_decision` format and
running the **real `lema-mcp guard` binary** on the agent's draft edits. 168 trials,
0 errors. The honest result is an **existence proof**, not "agents are wrong 58% of
the time":

- On the one decision that cut against the 2026 frontier model (`node-fetch` →
  native `fetch`), a blind agent re-proposed the killed library **58.3%** of the
  time (14/24); lema drove it to **0%** — matching a docs-preloaded arm *without*
  carrying the doc in context.
- On the five decisions the model already gets right, lema stayed silent: **0%
  re-proposal and 0% false-abstain** across 48 trials. No nagging.

A public-repo benchmark *understates* the value — public decisions are
disproportionately the ones the model already absorbed in training. The decisions
where enforcement moves the needle are proprietary, contrarian, recent,
team-specific. Full method and every raw trial:
[`./docs/enforcement-lift`](https://github.com/lemahq/lema-mcp/blob/HEAD/docs/enforcement-lift).

---

## Configuration & privacy

- **`LEMA_GUARD_MODE`** — `context` (default, non-blocking), `ask` (prompt the human
  on a strong match), or `off`.
- **`LEMA_DISABLE_QUERY_LOGGING=1`** — drop query text from the usage log entirely.
  Otherwise queries are scrubbed for credential-shaped substrings before logging.
- **`LEMA_USAGE_LOG` / `LEMA_QUESTION_LOG` / `LEMA_GUARD_LOG`** — opt-in local log
  files; all off unless set.
- **`LEMA_API_URL` + `LEMA_API_TOKEN`** — hosted identity credentials. Environment
  values take precedence over `~/.config/lema/credentials`.
- **`LEMA_WORKSPACE_ID`** — validated explicit target for CI, recovery, or
  ambiguity compatibility. Leave it unset for normal Git-backed repositories.

<details>
<summary><b>Subcommands & flags</b></summary>

- **`init [dir]`** — wire a repo for capture: registers the server in `.mcp.json`,
  appends a managed capture-protocol block to `AGENTS.md`, and installs three hooks
  (a commit reminder, the `nudge` capture prompt on dependency-manifest edits, and
  the `guard` never-reopen check). Idempotent.
- **`try <react|kubernetes|rust>`** — wire the read-only public-demo server.
- **`demo`** — a ~30-second never-reopen walkthrough against a throwaway temp dir
  (nothing written to your repo). The fastest way to see the CLOSED behavior.
- **`guard`** / **`nudge`** — the hook bodies `init` installs; advisory, fail-open,
  always exit 0. You don't call them directly.
- **`doctor context`** — resolve the current target and print only privacy-safe
  evidence, redacted ID suffixes, and one corrective action.
- **`context link --project ID --repository ID`** / **`context unlink`** — add or
  recoverably remove a validated repository-local association for non-Git,
  no-remote, or ambiguous checkouts.
- **`serve`** (≡ `--http`, default `:4321`) — serve the engine over localhost
  HTTP for the Lema Workbench GUI. This is not an MCP Streamable HTTP endpoint;
  the supported MCP transport in this release is local stdio.

With no flags, lema auto-discovers a decisions directory (`docs/adr`, `doc/adr`,
`docs/adrs`, `docs/decisions`, `docs/architecture/decisions`,
`architecture/decisions`, `adr`, `.adr`) and an `openspec/` tree. Point it
explicitly with `--adr-dir`, `--repo github.com/org/name` (`GITHUB_TOKEN` for
private), `--ref`, `--pattern`, `--openspec-dir`, or `--capture-file`.

**Hosted retrieval (optional).** Set `LEMA_API_URL` + `LEMA_API_TOKEN` to point
`search_decisions` at hosted hybrid retrieval over your full decision layer
(search-only in the MVP). Capture and enforcement are always local.
</details>

---

## License

MIT. `lema-mcp` is the free, local wedge of [**lema**](https://lema.sh) — the system
of record for *why*. The hosted decision graph, the team why-surface, and the
manager-facing Intelligence layer are at [lema.sh](https://lema.sh).

