# Codemap MCP — tool selection

Operational playbook injected into the MCP initialize handshake. Full schema, recipe catalog, and query patterns live in **`codemap://skill`** and **`codemap://rule`** (same content as `codemap skill` / `codemap rule` on CLI).

## Session start

1. **`context`** — project root, schema version, file count, language breakdown, **`start_here`** (index summary + recipe cards + hub leaders), **`map_id`** + **`codebase_map`** (hub paths + codemap CLI/MCP routing hints), recipe catalog, **`index_freshness`** (one call replaces 4–5 queries). Pass **`include_snippets: true`** for one-line export previews on hub leaders (ignored with **`compact: true`**). Omit map fields with **`compact: true`** or **`include_codebase_map: false`**. Prefer **`start_here.hub_leaders`** over legacy **`hubs`** for signatures. Compare **`map_id`** across sessions to detect structural summary drift without re-fetching full **`start_here`**.
2. **`codemap://rule`** — always-on priming: query the index for structure, don't grep.
3. When you need the catalog or DDL: **`codemap://recipes`**, **`codemap://schema`**.

## Index freshness

Every successful JSON tool response carries index-level freshness metadata (not a pass/fail verdict):

| Surface                                          | Where to read it                                                                                                                                                                    |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`context`**                                    | `index_freshness`; **`start_here`** when not `compact` (optional `include_snippets`); **`map_id`** + **`codebase_map`** when not `compact` (optional `include_codebase_map: false`) |
| **Object payloads** (`show`, `query` summary, …) | `index_freshness` merged inline                                                                                                                                                     |
| **Array payloads** (`query` rows)                | second `content` block prefixed `@codemap/index_freshness`                                                                                                                          |
| **HTTP**                                         | `X-Codemap-Pending-Sync`, `X-Codemap-Commit-Drift`, `X-Codemap-Warning` headers (JSON body unchanged)                                                                               |

Key fields: `pending_sync` (watcher debounce queue or in-flight reindex), `commit_drift` (`HEAD` ≠ `last_indexed_commit`), `warning` (single agent-readable line when anything is off).

**Agent guidance**

- If **`pending_sync: true`** — wait ~250ms (debounce) and retry, or call **`validate`** for per-file drift.
- If **`commit_drift: true`** or **`warning`** is set — run **`codemap`** (or rely on watch prime) before treating structural queries as authoritative.
- Prefer **`context`** at session start for the full disk-drift picture; use **`validate`** / snippet `stale` for individual files.

## Common tasks

| Goal                                         | MCP tool                                                                                                                                                                                                   | Recipe twin (`query_recipe`)                                                                                                                                                                                                                |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Exact symbol lookup (fast tier)              | **`show`** / **`snippet`** (`name`, optional `kind`, `in`) — equality index; same rows as lone `query: 'name:Token'` when Token has no `%`/`_` wildcards and no other query fields                         | `find-symbol-definitions` (`name = ?`)                                                                                                                                                                                                      |
| Field-qualified symbol discovery (slow tier) | **`show`** or **`snippet`** (`query` with `kind:` / `name:` / `path:` / `in:` + free text; `name:%pat%` substring LIKE; `with_fts` for file-body search)                                                   | `find-symbol-by-kind` for kind-heavy patterns; CLI `codemap show --query '…' --print-sql` to inspect generated SQL (no MCP `print_sql` arg)                                                                                                 |
| Kind / pattern lookup                        | **`query_recipe`**                                                                                                                                                                                         | `find-symbol-by-kind`                                                                                                                                                                                                                       |
| Source at symbol                             | **`snippet`**                                                                                                                                                                                              | same rows as `show` + disk text                                                                                                                                                                                                             |
| Blast radius                                 | **`impact`** (`target`, `direction`, `via`, `depth`, `in?`) — homonym symbols: unscoped unions per-defining-file graphs; `in` scopes one definition                                                        | `fan-in` for file hubs; symbol call graph via SQL or `impact`                                                                                                                                                                               |
| Call path + snippets                         | **`trace`** (`from`, `to`, `via?`, `max_depth?`, `budget_chars?`) — adaptive snippet caps 15k/10k/6k when omitted                                                                                          | `call-path`                                                                                                                                                                                                                                 |
| Type extends / implements chain              | **`query_recipe`**                                                                                                                                                                                         | `type-ancestors`, `type-descendants` (`file_path` when homonyms; on `type-descendants` also scopes output to that file)                                                                                                                     |
| Multi-symbol survey                          | **`explore`** (`names`, `depth?`, `kind?`, `budget_chars?`) — row cap always adaptive (500/250/125); snippets 15k/10k/6k when `budget_chars` omitted                                                       | `symbol-neighborhood` (once per name)                                                                                                                                                                                                       |
| One-hop symbol card                          | **`node`** (`name`, `kind?`, `in?`, `include_snippets?`, `budget_chars?`) — adaptive snippet caps when snippets enabled                                                                                    | `show` + `symbol-neighborhood` with `depth=1`                                                                                                                                                                                               |
| Affected tests                               | **`affected`** (`paths?`, `changed_since?`, `test_glob?`, `max_depth?`)                                                                                                                                    | `affected-tests` (RS-delimit multiple paths in `query_recipe` params)                                                                                                                                                                       |
| CI / SARIF                                   | **`query_recipe`** + `format: "sarif"`                                                                                                                                                                     | `deprecated-symbols`, `boundary-violations`, …                                                                                                                                                                                              |
| GitLab Code Quality                          | **`query_recipe`** + `format: "codeclimate"`                                                                                                                                                               | `boundary-violations`, … — locatable rows only; flat `minor` severity                                                                                                                                                                       |
| CI badge / issue count                       | **`query_recipe`** + `format: "badge"` (+ `badge_style: "json"` for gates)                                                                                                                                 | presentation only — triage via JSON rows / `--summary`                                                                                                                                                                                      |
| Ad-hoc SQL                                   | **`query`**                                                                                                                                                                                                | —                                                                                                                                                                                                                                           |
| N statements / one round-trip                | **`query_batch`**                                                                                                                                                                                          | **`codemap query batch`**                                                                                                                                                                                                                   |
| Index freshness (index-level)                | **`context`** (`index_freshness`) + tool metadata above                                                                                                                                                    | —                                                                                                                                                                                                                                           |
| Per-file staleness                           | **`validate`**                                                                                                                                                                                             | —                                                                                                                                                                                                                                           |
| Drift vs baseline                            | **`audit`** (`baseline_prefix` and/or per-delta `baselines`) or **`query`** / **`query_recipe`** + `baseline` (one-shot row diff vs `query_baselines`; incompatible with non-`json` `format` / `group_by`) | save via **`save_baseline`**; `summary: true` → count-only diff                                                                                                                                                                             |
| PR merge-base drift                          | **`audit`** `base: <ref>` (git committish; sha-keyed cache)                                                                                                                                                | `attribution: introduced` (branch-new) \| `inherited` (pre-existing at merge base) on each `added` row; `jq '.deltas.deprecated.added[] \| select(.attribution == "introduced")'`; `summary: true` → `added_introduced` / `added_inherited` |
| Load coverage data                           | **`ingest_coverage`** (`path`, optional `runtime` for V8 dirs; auto-detects Istanbul `.json` / LCOV `.info`)                                                                                               | enables `worst-covered-exports`, `files-by-coverage`, `untested-and-dead`, **`coverage-confirmed-dead`** (`confidence: high`); **`high-crap-score`** measured override                                                                      |
| Load churn data (non-git / fixture)          | **`ingest_churn`** (`path`)                                                                                                                                                                                | precomputed `file_churn` JSON — CLI twin `codemap ingest-churn`; enables `churn-complexity-hotspots` when git history is unavailable                                                                                                        |
| Complex + undertested (no ingest)            | **`query_recipe`** `high-crap-score`                                                                                                                                                                       | graph-estimated 85/40/0% tiers — parse `coverage_source` before CI gates; prefer after **`ingest_coverage`** when possible                                                                                                                  |
| Churn × complexity refactor targets          | **`query_recipe`** `churn-complexity-hotspots` (`by_symbol?`, `min_complexity?`, `row_limit?`, `path_prefix?`)                                                                                             | git `file_churn` by default each index; config **`churn.file`** replaces git when set; fixtures: **`ingest_churn`** / `ingest-churn` — **not** the `hotspots` alias (`fan-in`); empty `file_churn` → `context` `churn_hint`                 |
| High-judgment recipe triage                  | **`query_recipe`** `unimported-exports`, `boundary-violations`, `deprecated-symbols`                                                                                                                       | rows include `reason` / `evidence_json` — cite before **`apply`** or deletion                                                                                                                                                               |
| Apply recipe diff rows                       | **`apply`** (`recipe`, `params?`, `dry_run?`, `yes?`, `force?`, `until_empty?`, `max_passes?`, `commit_message?`)                                                                                          | recipe must emit `{file_path, line_start, before_pattern, after_pattern}` rows; `yes: true` required for writes; non-`auto_fixable` recipes need `force: true`                                                                              |
| Apply agent/codemod rows                     | **`apply_rows`** (`rows`, `dry_run?`, `yes?`)                                                                                                                                                              | same row contract; bypasses recipe `auto_fixable` / allowlist gates                                                                                                                                                                         |
| Apply unified diff text                      | **`apply_diff_input`** (`diff_text`, `dry_run?`, `yes?`, `commit_message?`)                                                                                                                                | parses git-style hunks; same executor as `apply_rows`                                                                                                                                                                                       |

## Chains

- Rename: `find-symbol-definitions` → `find-symbol-references` (both via **`query_recipe`**).
- Call path: **`trace`** (`from`, `to`) or **`query_recipe`** `call-path`; add snippets via **`trace`** / **`node`** / **`explore`** (adaptive snippet caps 15k/10k/6k; explore row cap 500/250/125 always adaptive) or **`snippet`** per row. Dependency hops may return `snippets_skipped_reason` — fall back to **`query_recipe`** + **`snippet`** per hop.
- Type hierarchy: **`query_recipe`** `type-ancestors` / `type-descendants`; pass `file_path` when symbol names collide across files. On **`type-descendants`**, `file_path` also limits results to descendants defined in that file.
- Refactor risk: `churn-complexity-hotspots` → `fan-in` + `refactor-risk-ranking` → **`snippet`** per row (alias `hotspots` = import fan-in only — not churn×complexity).
- Edit path: **`show`** → **`snippet`**; if `stale: true`, line range may have drifted.
- Apply path: **`query_recipe`** (or audit baseline `added`) with `format: "diff-json"` → **`apply`** `dry_run: true` → **`apply`** `yes: true` (+ `force: true` when recipe is not `auto_fixable`). Pre-built rows: **`apply_rows`**; unified diff: **`apply_diff_input`**. Fixpoint: **`apply`** `until_empty: true`; git: **`commit_message`** on **`apply`** / **`apply_diff_input`**. **`rename-preview` homonyms:** pass `define_in` in `params` (definition `file_path` anchor — not the same as `in_file`).

## Anti-patterns

- Don't grep for "where is X defined" — **`show`** / **`snippet`** fast tier (`name` with optional `kind`/`in`, or lone `query: 'name:Token'` without wildcards) or **`query_recipe`** `find-symbol-definitions`; slow tier for `name:%pat%`, multi-field `query`, or free text.
- Don't hand-roll `WITH RECURSIVE` for impact — **`impact`**.
- Convenience tools are thin composers — fall back to **`query_recipe`** / **`query`** when unsure.
- Don't skip **`context`** at session start.

## Recipe ids cited here

`find-symbol-definitions`, `find-symbol-by-kind`, `find-symbol-references`, `fan-in`, `call-path`, `symbol-neighborhood`, `type-ancestors`, `type-descendants`, `affected-tests`, `deprecated-symbols`, `boundary-violations`, `unimported-exports`, `coverage-confirmed-dead`, `high-crap-score`, `churn-complexity-hotspots`, `refactor-risk-ranking`, `calls-including-heuristic` (opt-in; requires `synthesis.heuristicCalls: true` in config). Default call-graph recipes exclude `provenance = 'heuristic'`. Others: list via **`codemap://recipes`** before **`query_recipe`**.

<!-- codemap-mcp-recipe-refs: find-symbol-definitions, find-symbol-by-kind, find-symbol-references, fan-in, call-path, symbol-neighborhood, type-ancestors, type-descendants, affected-tests, deprecated-symbols, boundary-violations, unimported-exports, coverage-confirmed-dead, high-crap-score, churn-complexity-hotspots, refactor-risk-ranking, calls-including-heuristic -->
