Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .agents/rules/codemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,24 @@ A local database (default **`.codemap.db`**) indexes structure: symbols, imports
| Save / diff a baseline | — | `bun src/index.ts query --save-baseline -r visibility-tags` then `… --json --baseline -r visibility-tags` |
| List / drop baselines | — | `bun src/index.ts query --baselines` · `bun src/index.ts query --drop-baseline <name>` |
| Per-delta audit | — | `bun src/index.ts audit --json --baseline base` (auto-resolves `base-files` / `base-dependencies` / `base-deprecated`) |
| MCP server (for agent hosts) | — | `bun src/index.ts mcp` — JSON-RPC on stdio; one tool per CLI verb. See **MCP** section below. |

**Recipe `actions`:** with **`--json`**, recipes that define an `actions` template append it to every row (kebab-case verb + description — e.g. `fan-out` → `review-coupling`). Under `--baseline`, actions attach to the **`added`** rows only. Inspect via **`--recipes-json`**. Ad-hoc SQL never carries actions.

**Baselines** (`query_baselines` table inside `.codemap.db`, no parallel JSON files): `--save-baseline[=<name>]` snapshots a result set; `--baseline[=<name>]` diffs the current result against it (added / removed rows; identity = `JSON.stringify(row)`). Name defaults to the `--recipe` id; ad-hoc SQL needs an explicit `=<name>`. Survives `--full` and SCHEMA bumps.

**Audit (`bun src/index.ts audit`)**: structural-drift command; emits `{head, deltas: {files, dependencies, deprecated}}` (each delta carries its own `base` metadata). Reuses B.6 baselines as the snapshot source. Two CLI shapes — `--baseline <prefix>` auto-resolves `<prefix>-files` / `<prefix>-dependencies` / `<prefix>-deprecated`; `--<delta>-baseline <name>` is the explicit per-delta override. v1 ships no `verdict` / threshold config — consumers compose `--json` + `jq` for CI exit codes. Auto-runs an incremental index before the diff (use `--no-index` to skip for frozen-DB CI).

**MCP server (`bun src/index.ts mcp`)**: stdio MCP (Model Context Protocol) server — agents call codemap as JSON-RPC tools instead of shelling out to the CLI on every read. v1 ships one tool per CLI verb plus four lazy-cached resources:

- **Tools:** `query` / `query_batch` / `query_recipe` / `audit` / `save_baseline` / `list_baselines` / `drop_baseline` / `context` / `validate`. Snake_case keys throughout (CLI stays kebab — translation at the MCP-arg layer).
- **`query_batch` (MCP-only):** N statements in one round-trip. Items are `string | {sql, summary?, changed_since?, group_by?}` — string form inherits batch-wide flag defaults, object form overrides on a per-key basis. Per-statement errors are isolated.
- **`save_baseline` (polymorphic):** one tool, `{name, sql? | recipe?}` with runtime exclusivity check (mirrors the CLI's single `--save-baseline=<name>` verb).
- **Resources:** `codemap://recipes` (catalog), `codemap://recipes/{id}` (one recipe), `codemap://schema` (live DDL from `sqlite_schema`), `codemap://skill` (bundled SKILL.md text). Lazy-cached on first `read_resource`.
- **Output shape uniformity:** every tool returns the JSON envelope its CLI counterpart's `--json` would print — no re-mapping. Schema additions to the CLI envelope propagate to MCP automatically.

For developing the MCP server itself: `src/cli/cmd-mcp.ts` (CLI shell) + `src/application/mcp-server.ts` (engine). See [`docs/architecture.md` § MCP wiring](../../docs/architecture.md#cli-usage).

After **`bun run build`**, **`node dist/index.mjs`** matches the published **`codemap`** binary (same flags). **`bun link`** / global **`codemap`** also work when testing the packaged CLI.

Index another project: **`--root /path/to/repo`**, or set **`CODEMAP_ROOT`** or **`CODEMAP_TEST_BENCH`** (e.g. in **`.env`** — see [docs/benchmark.md § Indexing another project](../../docs/benchmark.md#indexing-another-project)). Full rebuild: **`--full`**. Targeted re-index: **`--files path/to/a.ts path/to/b.tsx`**.
Expand Down
23 changes: 23 additions & 0 deletions .agents/skills/codemap/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,29 @@ Replace placeholders (`'...'`) with your module path, file glob, or symbol name.

Each emitted delta carries its own `base` metadata so mixed-baseline audits are first-class. `--summary` collapses each delta to `{added: N, removed: N}`. `--no-index` skips the auto-incremental-index prelude (default is to re-index first so `head` reflects current source). v1 ships no `verdict` / threshold config — `codemap audit --json | jq -e '.deltas.dependencies.added | length <= 50'` is the CI exit-code idiom until v1.x ships native thresholds. Each delta pins a canonical SQL projection and validates baseline column-set membership before diffing — schema-bump-resilient (extras dropped, missing columns surface a clean re-save command).

**MCP server (`bun src/index.ts mcp`)** — separate top-level command that exposes the entire CLI surface to agent hosts (Claude Code, Cursor, Codex, generic MCP clients) as JSON-RPC tools over stdio. Eliminates the bash round-trip on every agent call. Bootstrap once at server boot; tool handlers reuse the existing engine entry-points (`executeQuery`, `runAudit`, etc.) so output shape is verbatim from each tool's CLI counterpart's `--json` envelope.

**Tools (snake_case throughout — CLI stays kebab; translation lives at the MCP-arg layer):**

- **`query`** — one SQL statement. Args: `{sql, summary?, changed_since?, group_by?}`. Same envelope as `codemap query --json`.
- **`query_batch`** — MCP-only, no CLI counterpart. Args: `{statements: (string | {sql, summary?, changed_since?, group_by?})[], summary?, changed_since?, group_by?}`. Items are bare SQL strings (inherit batch-wide flag defaults) or objects (override on a per-key basis). Output is N-element array; per-element shape mirrors single-`query`'s output for that statement's effective flag set. Per-statement errors are isolated — failed statements return `{error}` in their slot; siblings still execute. SQL-only (no `recipe` polymorphism in items).
- **`query_recipe`** — `{recipe, summary?, changed_since?, group_by?}`. Resolves the recipe id to SQL + per-row actions, then executes like `query`. Unknown recipe id returns a structured `{error}` pointing at the `codemap://recipes` resource.
- **`audit`** — `{baseline_prefix?, baselines?: {files?, dependencies?, deprecated?}, summary?, no_index?}`. Composes per-delta baselines into the `{head, deltas}` envelope. Auto-runs incremental index unless `no_index: true`.
- **`save_baseline`** — polymorphic `{name, sql? | recipe?}` with runtime exclusivity check (mirrors the CLI's single `--save-baseline=<name>` verb). Pass exactly one of `sql` or `recipe`.
- **`list_baselines`** — no args; returns the array `codemap query --baselines --json` would print.
- **`drop_baseline`** — `{name}`. Returns `{dropped: <name>}` on success or `isError` if the name doesn't exist.
- **`context`** — `{compact?, intent?}`. Returns the project-bootstrap envelope (codemap version, schema version, file count, language breakdown, hubs, sample markers). Designed for agent session-start — one call replaces 4-5 `query` calls.
- **`validate`** — `{paths?: string[]}`. Compares on-disk SHA-256 to indexed `files.content_hash`; empty `paths` validates everything. Returns rows with status (`ok`/`stale`/`missing`/`unindexed`).

**Resources (lazy-cached on first `read_resource`; constant for server-process lifetime):**

- **`codemap://recipes`** — full catalog JSON (same as `--recipes-json`).
- **`codemap://recipes/{id}`** — single recipe `{id, description, sql, actions?}`. Replaces `--print-sql <id>`.
- **`codemap://schema`** — DDL of every table in `.codemap.db` (queried live from `sqlite_schema`).
- **`codemap://skill`** — full text of bundled `templates/agents/skills/codemap/SKILL.md`. Agents that don't preload the skill at session start can fetch it here.

**Implementation:** `src/cli/cmd-mcp.ts` (CLI shell — argv + lifecycle) + `src/application/mcp-server.ts` (engine — tool registry, resource handlers). Mirrors the `cmd-audit.ts ↔ audit-engine.ts` seam. `--changed-since` git lookups are memoised per `(root, ref)` pair across batch items so a `query_batch` of N items sharing the same ref does one git invocation, not N. v1.x backlog: `codemap serve` (HTTP API) reuses the same tool taxonomy + output shape.

**Determinism:** Bundled recipes use stable secondary **`ORDER BY`** tie-breakers (and ordered inner **`LIMIT`** samples where applicable). Prefer **`--recipe`** over pasting SQL when you need the maintained ordering. **Canonical SQL** is **`src/cli/query-recipes.ts`** (`QUERY_RECIPES`).

The blocks below match **`fan-out`** and **`fan-out-sample`** in **`QUERY_RECIPES`**; other recipes align with “Conditional aggregation”, “Codebase statistics”, and component sections later in this skill.
Expand Down
35 changes: 35 additions & 0 deletions .changeset/agent-transports-mcp-scaffold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
"@stainless-code/codemap": minor
---

feat(mcp): `codemap mcp` — Model Context Protocol server (agent-transports v1)

Adds the `codemap mcp` top-level command — boots an MCP server over
stdio so agent hosts (Claude Code, Cursor, Codex, generic MCP clients)
call codemap as JSON-RPC tools instead of shelling out per query.
Eliminates the bash round-trip on every agent invocation.

Surface (one tool per CLI verb plus `query_batch`, all snake_case):

- `query`, `query_batch`, `query_recipe`, `audit`, `save_baseline`,
`list_baselines`, `drop_baseline`, `context`, `validate`
- Resources: `codemap://recipes`, `codemap://recipes/{id}`,
`codemap://schema`, `codemap://skill` (lazy-cached)

`query_batch` is MCP-only — N statements in one round-trip with
batch-wide-defaults + per-statement-overrides (items are
`string | {sql, summary?, changed_since?, group_by?}`). Per-statement
errors are isolated. `save_baseline` ships as one polymorphic tool
(`{name, sql? | recipe?}` with runtime exclusivity check) mirroring
the CLI's single `--save-baseline=<name>` verb.

Output shape is verbatim from each tool's CLI counterpart's `--json`
envelope (no re-mapping). Bootstrap once at server boot; tool
handlers reuse existing engine entry-points (`executeQuery`,
`runAudit`, etc.) — no duplicate business logic.

New dep: `@modelcontextprotocol/sdk`.

HTTP API (`codemap serve`) stays in roadmap backlog; design points
(tool taxonomy + output shape) are reserved in `docs/architecture.md
§ MCP wiring` so HTTP inherits them when a concrete consumer asks.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ codemap query --recipes-json
codemap query --print-sql fan-out
# `components-by-hooks` ranks by hook count without SQLite JSON1 (comma-based count on the stored JSON array).

# MCP server (Model Context Protocol) — for agent hosts (Claude Code, Cursor, Codex, generic MCP clients)
codemap mcp # JSON-RPC on stdio, one tool per CLI verb
# Tools: query, query_batch, query_recipe, audit, save_baseline, list_baselines, drop_baseline, context, validate
# Resources: codemap://recipes, codemap://recipes/{id}, codemap://schema, codemap://skill (lazy-cached)
# Output shape verbatim from `--json` envelopes (no re-mapping). Snake_case throughout.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# Another project
codemap --root /path/to/repo --full

Expand Down
Loading
Loading