# 2026-07-04 — MCP client ergonomics planned (from the library session) Discussion started as "optimize agent traversal of the knowledge graph," reframed by Fritz to the MCP-client perspective (Claude Code/Desktop as the main consumers). Key grounding: the 06-21 Leiden measurement — hub-and-spoke graph, computed graph queries mostly re-derive the index tree — so client headroom is **turns and tokens**, not graph algorithms. Plan recorded + settled: [/plans/mcp-client-ergonomics.md](/plans/mcp-client-ergonomics.md) — W1 size-adaptive outline/`#section` fetch (8KB gate) · W3 per-session version+etag dedup · W2 `mark_explore` neighborhood card (doc + backlinks + outbound + siblings, 10/cap) · W4 tool-description strategy pass. D1–D4 all settled on recommendation (size-adaptive; full card; per-session; shared `client/` slicing package). Deferred: client graph queries (Leiden re-test trigger), server FTS (separate lane), MCP resources/prompts (follow-up), lean tool profiles. Pickup notes with repo pointers are in the plan (code: `client/cmd/demarkus-mcp/main.go`; new package beside `client/{fetch,graph, links}`). Next session in ~/latebit/demarkus starts at W1+W3. (Same day, library side: v0.16.0 UX round + v0.17.0 pane-scroll-default merged and deployed — see /demarkus-library/journal/2026-07-03-ux.md and [ADR 0007](/adr/0007-sni-virtual-world-routing.md).) ## MCP client ergonomics — W1–W4 built (feature/mcp-client-ergonomics) Implemented the whole plan (/plans/mcp-client-ergonomics.md) in one pass on branch `feature/mcp-client-ergonomics`; awaiting Fritz's commit. - **client/mdoutline (new package, D4):** pure functions over markdown — `Headings` (goldmark parse, GitHub-style slug anchors with taken-anchor dedup: Notes/Notes/Notes-1 → notes, notes-1, notes-1-1), `Section` (subtree slice, lenient: accepts raw heading text re-slugged, case-insensitive), `Outline`, `OpeningParagraph`, `Anchors`. Edge cases tested: setext headings, `#` inside code fences and indented blocks, inline code in headings, duplicate anchors. - **W1 (size-adaptive fetch):** mark_fetch returns full body <8KB; above it `mode: outline` (heading tree with anchors + per-section line counts, opening paragraph, `fetch url#` hint). `url#anchor` slices at any size; `force=true` always full body. Section-not-found errors list available anchors. - **W3 (session dedup):** per-process map (host+path → version,etag), recorded ONLY when a full body was actually returned (outline/section fetches never arm it — otherwise the outline→section flow would break). Unchanged re-fetch → `status: unchanged … since vN`; changed → body + `note: changed since this session's earlier fetch (vX -> vY)`; force busts. - **W2 (mark_explore):** neighborhood card in one call — outline head + opening paragraph + outbound links (title'd, deduped) + backlinks (graph store, degrades to a note) + parent-dir siblings (LIST, degrades on failure), all capped at 10 with honest "+N more". New files explore.go / explore_test.go. - **W4:** descriptions for fetch/lookup/list/backlinks/explore now teach the strategy (lookup-first, explore to orient, #section for detail, full bodies rarely needed). Verified live against soul.demarkus.io by driving the built binary over stdio: /demarkus-library/roadmap.md (51,939 bytes) → 5,892-char outline; `#next-phases-queued` slice 874 chars; guidelines.md fetched twice → second gets `status: unchanged` (201 chars), force re-reads; explore card on /demarkus-library/index.md orients in one turn. Acceptance met: project + phase answerable in ≤2 turns, no full roadmap fetch. Gotcha worth remembering: mcp-go serves stdio tool calls concurrently — two same-doc fetches raced and completed out of order, which is exactly why the dedup map is mutex-guarded. Not done (deferred per plan): broker gateway parity for outline/dedup (its mirrored formatResult contract is untouched — new behavior is client-side only), MCP resources/prompts follow-up, library librarian `open` adoption of mdoutline. **Merged:** PR #225 (`8706768`) — the whole MCP client ergonomics phase. Review round fixed two real CodeRabbit findings: dedup could trivially match when a server omits both version and etag (now requires an identity field, and identity-less fetches are never recorded), and etag-only changes now carry a "content changed (still vN, etag differs)" note. Skipped the re-parse/O(n²) nitpick as deliberate (documented on mdoutline.Headings). ## Related documents - [MCP resources and prompts plan](/plans/mcp-resources-prompts.md): the deferred follow-up named in this entry - [Library journal 2026-07-03 UX](/demarkus-library/journal/2026-07-03-ux.md): same-day library UX round referenced above - [ADR 0007 pane scroll room](/demarkus-library/adr/0007-pane-scroll-room.md): the pane-scroll-default decision shipped in v0.17.0