Skip to content

labkit mcp: one mode, and only the tools - #612

Merged
danbarua merged 2 commits into
mainfrom
mcp-no-read-only-no-docs
Oct 1, 2026
Merged

danbarua merged 2 commits into
mainfrom
mcp-no-read-only-no-docs

Conversation

@danbarua

@danbarua danbarua commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Two removals from the MCP server.

The read-only mode (4080b5e). labkit mcp --read-only, its paths in server.ts and docs.ts, its tests, and the read-only default and MCP_CALL_WRITE switch in the mcp-in-context skill's mcp-call.sh are gone. The read tools keep their readOnlyHint annotations.

The docs tool and the labkit://docs/tools resource. An agent already has every tool's description and schema from tools/list; a second copy in prose was something to reach for instead of the schema. docs.ts keeps only the handshake instructions, which name the registered tools. The server no longer declares the resources capability. CLAUDE.md now points at tools/list.

Verified

  • bun run typecheck: clean.
  • bun test tests/mcp packages/app-acp: 338 pass, 0 fail.
  • bun run check:quick: all 25 passed.
  • A test asserts the handshake instructions and that no resources capability is declared.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY

danbarua and others added 2 commits October 1, 2026 02:02
The --read-only flag, its paths in the server and docs, and the
read-only default in the skill's mcp-call.sh are removed. The read
tools keep their readOnlyHint annotations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY
The `docs` tool and the `labkit://docs/tools` resource are removed.
Each tool's description and schema in `tools/list` are its
documentation; the handshake instructions name the registered tools.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY
@danbarua
danbarua enabled auto-merge (squash) October 1, 2026 01:05
@github-actions github-actions Bot added the area:record The record: core-domain, core-db, the CLI, the MCP server, the domain model and workspaces label Oct 1, 2026
@danbarua
danbarua merged commit a1ed227 into main Oct 1, 2026
10 checks passed
@danbarua
danbarua deleted the mcp-no-read-only-no-docs branch October 1, 2026 01:07
danbarua added a commit that referenced this pull request Oct 1, 2026
Removes everything in the record's model that no verb writes: the
`Review` label, six edge labels, nine endpoint pairs, the `retracted`
property and its RLS policy, `"undecided"` as a claim kind, and the
reads and the property-change path that only served them.

## What was removed, item by item

1. **`Review` label.** Removed from `NODE_LABELS`, `NODE_TYPES` (prefix
`REV`), `NodePropsByLabel`, `SEARCHABLE_TEXT` and `ReviewProps` in
`packages/core-db/domain.ts`; provisioning no longer creates the label.
The `review` kind is gone from `LABEL_BY_KIND`, `WalkedKind`, the `why`
explainers and the `explanation` schema, from `search`'s handle type,
and from the CLI `why` view. `labkit_get_label_for_handle` no longer
maps `REV`.
2. **Edge labels `REVERIFIES`, `GRADES`, `KEEPS`, `SHARPENS`,
`EVALUATES`, `INVALIDATED_BY`.** Removed from `EDGE_LABELS`,
`EDGE_SCHEMA` and the `why` phrase table.
3. **Endpoint pairs.** Each measured against
`packages/core-domain/write/*.ts`; no live write produces any of them,
so all nine are removed:
- MOTIVATES Decision→Question: `pose --from` and `openEnquiry` take a
`NoteRef` (`asking.ts:37`, `:187`).
- MOTIVATES Decision→Computation, SUPERSEDES Decision→Computation: a
decision MOTIVATES only a Claim (`shared.ts:255`) or a Criterion
(`counting.ts:207`), and SUPERSEDES only a Claim, Criterion or Decision.
- CLOSES Decision→Gate: CLOSES targets only an enquiry
(`stopping.ts:118`) or work (`stopping.ts:220`).
- BASED_ON Decision→Review: every BASED_ON target is evidence or a
claim.
- GATES Gate→Computation: `protecting` is `ref("work")`, which is a Task
(`counting.ts:98`).
- PRODUCES Task→Computation, Task→Artefact: PRODUCES sources are only a
unit or a computation (`work.ts:45`, `shared.ts:176-177`, `:243`).
- CONCERNS/MENTIONS Note→Review: both are built from `NODE_LABELS`, so
they go with the label.
4. **`retracted` and `"undecided"`.** Provisioning no longer installs
`<label>_hide_retracted` or enables row-level security on label tables.
Migration `0020_hal_reads_drop_review_and_retracted` (from `bun run
db:generate:custom`) replaces `labkit_get_label_for_handle`,
`labkit_get_entity_as_hal` and `labkit_get_collection_as_hal` with their
latest bodies minus the `retracted IS NULL` filters and the `REV`
prefix. `ClaimProps.kind` is `"exploratory" | "confirmatory"`.
5. **Dead reads.**
- `reverifiedBy`, the REVERIFIES query in `whySupported` and the
"Re-checked by" view.
- `analysisRevision` as a whole: its query, schema, report type and
read-surface method. Only its first-run branch was reachable, so `why
<analysis>` keeps that output (`is: "a first run"` and the live-edge
walk) and loses `report`. The CLI and MCP `why` descriptions no longer
say "what it revised" or list "review".
- `UnitOfWork.set` and `setEdge`, which had no callers. With them go
`NodePropsChanged` and `EdgePropsChanged` (from `GraphChange`, the zod
change schemas, `applyDelta`, `touchedIn` and the `touching` filter),
`snapshotPriorValues`, and the four `TenantGraph` methods only they
called: `setNodeProperty`, `nodePropertiesOf`, `edgePropertiesOf`,
`setEdgeProperties`.

## Kept

- **The withdrawn-verdict helper in
`packages/core-domain/read/checks.ts`** (`retracted(v)`, behind
`withdrawn: true` and `no-standing-verdict`). It reads `Decision
-SUPERSEDES-> Claim`, which `write/shared.ts:254` writes, and the S-3c
and `domain-session` withdrawn-verdict tests exercise it. Despite its
name, it does not read the `retracted` property.
- **`retractedArtefacts` in `read/story.ts`.** It is computed from
superseded findings, and S-11e depends on it.

## Beyond the brief

Removing `setEdge` leaves `EdgePropsChanged` and
`TenantGraph.setEdgeProperties`/`edgePropertiesOf`/`nodePropertiesOf`/`setNodeProperty`
with only test callers. Following the brief's rule that a persistence
test is not a caller, they are removed, and so is
`tests/persistence/edge-properties.test.ts`. That file's fixture named
#440, which is closed.

## Not done: `scripts/db/project-museum.ts`

`~/labkit-museum-events.json` holds 2 `Review` nodes, 1 REVERIFIES, 1
KEEPS, 2 EVALUATES, 2 INVALIDATED_BY and 4 `NodePropsChanged` changes,
and the script's `VERB_WORD` maps NARROWS to SHARPENS. The script can no
longer project that file. This PR leaves the script untouched. Deleting
the script or keeping the museum is a decision for Dan.

## Follow-ups

- `bun run db:generate` with `schema.ts` unchanged emits `DROP POLICY
"labkit_event_tenant_isolation"` and `DROP TABLE "labkit_event"`. This
is drift between the snapshot and the schema that was already there; the
generated file was discarded. The next real `schema.ts` edit will
include that DROP TABLE.
- `drizzle/0002` and `0007` create 13 per-label sequences
(`public.labkit_review_natural_id_seq` among them). Nothing has used
them since the workspace sequence replaced them, and no migration drops
them.
- `why <analysis>` still answers "a first run", which no longer
contrasts with anything.

## Evidence

Tests, full `bun test` written to a file:

| | run | pass | skip | fail |
|---|---|---|---|---|
| eaeba66 (before) | 1649 | 1647 | 2 | 0 |
| eaeba66 + this change | 1637 | 1635 | 2 | 0 |
| rebased on a1ed227 (#612) | 1629 | 1627 | 2 | 0 |

The 12 fewer tests are: 7 in `edge-properties.test.ts`, 1 in
`events-are-deltas.test.ts` (property set in place), 2 retracted-node
tests in `app-web/tests/api.test.ts`, and the `Review` case of the two
tests that loop over `NODE_LABELS`. Of the further 8 after the rebase,
#612 removed 9 tests and added 1.

`bun run check:quick`: all 25 passed, before and after the rebase.

`bun run bonsai:record` into a fresh `--db`: `OK: the live event stream
and graph state are exactly what the scripts produce, commit hashes and
clocks aside.` and `OK: record built (…), replay clean.` No tracked file
changed.

CLI (`bun run cli:build`, `LABKIT_DB_URL` unset, every call with
`--db`), on the Bonsai record:

```
$ labkit list Review
labkit: no node type `Review`; the types are Question, LineOfEnquiry, EvidenceUnit, Evidence, Claim, Decision, Criterion, CriterionEvaluation, Gate, Artefact, Computation, Task, Note
exit 1

$ labkit search verdict
Records containing "verdict" — 28
```

`why` on the first handle of every kind, exit 0 for each: Q_1, LOE_2,
EU_3, EV_3, CLM_6, DEC_8, CRIT_4, CEVAL_7, GATE_16, ART_3, COMP_5 ("a
first run because", 11 lines), TASK_14, and NOTE_408. NOTE_408 is a note
written on Q_1 that mentions Q_1 and GATE_16; `why` lists both mentions
and `search "a note on"` finds it.

`labkit dump` (1140KB) then `labkit restore --into` a new directory,
then `why` on the same 13 handles in the restored record: exit 0 for
each, with the same first lines.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:record The record: core-domain, core-db, the CLI, the MCP server, the domain model and workspaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant