> ## Documentation Index
> Fetch the complete documentation index at: https://reikon.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Tool Reference

> Every MCP tool Reikon exposes, with params and example output.

# MCP Tool Reference

Reikon ships an [MCP](https://modelcontextprotocol.io) server exposing project context
to AI coding agents — Claude Code, Cursor, Windsurf, or anything else that speaks MCP
over stdio. The tool list below is generated from the server's actual tool schema
(`src/main/mcp-server.ts`), so it can't silently drift from what's shipped — the
narrative and examples around each tool are hand-written.

If you haven't set it up yet, see the [MCP setup guides](../guides/mcp-claude-code)
first. This page assumes a connected client.

All tools operate on **the currently active project** in the desktop app — there's no
way to target a different project from a tool call.

***

## Read-only tools

### `get_project_health()`

Returns the current health score, per-signal breakdown, and the delta vs. the previous
snapshot. No parameters.

```
Health score: 78/100
Delta vs previous snapshot: +3

Signals:
  Bus Factor: 60
  Commit Quality: 84
  TODO Density: 71
  Duplicates: 96
  Churn Stability: 88

Analyzed: <ISO timestamp of the last analysis>
Project: /Users/you/projects/your-repo
```

Good first call in any session — gives an agent the lay of the land before it looks at
anything else.

### `get_repo_orientation()`

One call to get oriented in an unfamiliar repo: the health score, the most complex files,
the riskiest files to touch (complex *and* churning), and a dead-code summary — plus a
pointer to the next tools to drill in. A good first call.

### `get_file_context(filePath)`

| Param      | Type   | Required |
| ---------- | ------ | -------- |
| `filePath` | string | yes      |

Complexity, churn count, top owner, and team for one file.

```
File: src/payments/processor.ts
Complexity (max): 18
Churn (changes): 34
Top owner: Alice Chen (62%)
Team: Backend
```

### `get_annotated_diff(staged_only?, file?)`

| Param         | Type    | Required                                 |
| ------------- | ------- | ---------------------------------------- |
| `staged_only` | boolean | no — default `false` (staged + unstaged) |
| `file`        | string  | no — limit to one relative path          |

Git diff hunks enriched with per-file metadata and any human annotations left in the
Review tab. Each hunk header includes a `key` you'll need for `flag_risky_file`. Capped
at 200 hunks — pass `file` to narrow scope if you hit the cap. **Untracked (newly created,
never-staged) files are included** as all-addition diffs unless `staged_only` is set — so a
dispatch that creates new files is visible to review, not just edits to existing ones.

```
=== src/payments/processor.ts [complexity:18 churn:34 owner:Alice Chen(62%)] (+12 -3)
@@ -45,7 +45,16 @@ function processRefund [key:a1b2c3d]
  ⚑ [review] Double-check the rounding here — see comment thread
+  const adjusted = round(amount * (1 - feePct), 2);
...
```

### `get_review_suggestions(staged_only?)`

| Param         | Type    | Required             |
| ------------- | ------- | -------------------- |
| `staged_only` | boolean | no — default `false` |

Same underlying signals as `get_annotated_diff` and `get_file_context`, pre-aggregated
into one review-focused summary: which touched files are high-complexity or have
concentrated ownership, and who the suggested reviewer is — ranked by how much each
contributor has historically touched the changed files. This is the same ranking the
desktop Review tab shows, so the suggested reviewer matches in both places. Use this
instead of chaining the two tools above when all you need is "is this commit risky and
who should look at it."

```
Review suggestions for 3 changed files:
- 1 high-complexity file
- 1 file with concentrated ownership (≥60%)
- Suggested reviewer: Alice Chen

  src/payments/processor.ts — complexity:18, churn:34×, owner:Alice Chen(62%)
  src/utils/format.ts — churn:5×
  README.md — no risk data
```

### `list_annotations(intent?)`

| Param    | Type                                          | Required |
| -------- | --------------------------------------------- | -------- |
| `intent` | string, one of `fix` \| `explain` \| `review` | no       |

All human (and agent-added) notes from the Review tab, including reply threads and
resolution status.

```
src/payments/processor.ts:
  id:ann-1718... [review] (line 52) Double-check the rounding here
    ↳ human: see ticket PAY-204
    ↳ agent(claude-sonnet-4-6): fixed — switched to round-half-even
```

### `get_snapshot_trend(metric, days?)`

| Param    | Type                                                                                                                                                 | Required        |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `metric` | string, one of `healthScore` \| `todoCount` \| `totalLines` \| `busFactor` \| `commitQualityPct` \| `contributors` \| `techDebtHours` \| `vulnTotal` | yes             |
| `days`   | number                                                                                                                                               | no — default 30 |

A time-series of one metric across saved snapshots. Useful for "has this gotten worse
since last week" questions.

```
Trend: techDebtHours (last 30 days)
  <date>  142
  <date>  138
  <date>  151
```

### `get_complexity_hotspots(limit?)`

| Param   | Type   | Required                |
| ------- | ------ | ----------------------- |
| `limit` | number | no — default 10, max 30 |

Top files by cyclomatic complexity, with a churn-derived trend label (rising / active /
stable) and a severity emoji.

```
Complexity hotspots (top 10):
  🔴 critical  complexity:24  churn:18 ↑ rising (high churn)  src/parser/legacy.ts
  🟠 high      complexity:14  churn:3 · stable                src/api/client.ts
```

### `get_rule_progress()`

No parameters. The user's plain-language goals (from the Goals tab, stored in `.reikon/config.json`) and their **deterministic** progress: baseline → current, a status (improving / holding / regressing / met), and — for regressing goals — the files driving the number.

A goal the user **dispatched** ("fix until back to baseline") is marked `⚑ DISPATCHED` with an effort budget (`attempt N/M`): fix it in your own env, Reikon re-checks deterministically on the next analysis. The budget is bounded — once you exhaust it without closing the goal, the line flips to `⚑ GAVE UP after N (closest X, target B)`: **stop retrying** and `open_annotation` a finding explaining how close you got and what's blocking it. The human decides whether to extend the leash.

```
User goals (deterministic, tracked across every analysis):

⚑ DISPATCHED Fewer useEffects over time
  47 → 41 (pattern_count, want it to decrease)
  → Fix until 41 reaches the baseline. Effort budget: attempt 2/5.

[regressing] No file over 500 lines
  2 → 3 (threshold, want it to decrease)
  driving the regression:
    src/main/index.ts (612)
```

Call this to bias your work toward what the user is trying to achieve — e.g. if they want fewer `useEffect`s, don't add more.

### `get_test_gaps()`

No parameters. High-risk files — complex, churning, or single-owner — with little or no
test coverage (the intersection of Reikon's risk signals and the coverage report). The
Verify pillar's core finding: a deterministic "test these first" list, dispatchable —
your agent adds tests in its own environment, you review what it writes. Empty when no
coverage report is configured (Reikon never fabricates a gap from missing data).

```
High-risk files with little or no test coverage — add tests to these first:
  src/payments/processor.ts  complexity:18 churn:34× coverage:none
  src/api/client.ts          complexity:14 churn:9×  coverage:22%
```

### `get_hotspots()`

No parameters. Files where **all three** of Reikon's risk signals converge — high
cyclomatic complexity, high churn, and concentrated single-person ownership. The
intersection a single signal misses: not just "complex," but "complex *and* changing
often *and* only one person understands it." The riskiest places to touch — refactor or
test carefully, and loop in the owner.

### `get_arch_violations()`

No parameters. Returns **layering violations** — imports that cross the architectural layers
you defined in `.reikon/config.json`. The model is an allow-list: each layer (a set of path
globs) declares which other layers it `mayImport`; an import to any other internal layer is a
violation. Catches both a foundational layer reaching *up* into an app layer and two sibling
layers that must not depend on each other. Each violation is an aggregated `from → to` edge with
a count and example offending files — a dispatchable "fix the dependency direction" finding.
Empty when no layers are configured. **Honest about scope:** it appends a caveat when some of the
repo's own imports couldn't be resolved (workspace package names / non-`tsconfig` aliases), and
says "not applicable, not clean" for a non-JS/TS repo — so a "no violations" result is never
mistaken for a guarantee when edges were invisible.

### `get_annotation_history(file?)`

| Param  | Type   | Required                        |
| ------ | ------ | ------------------------------- |
| `file` | string | no — omit for the whole project |

The review notes and decisions recorded on a file — **open, resolved, *and* dismissed** —
with their threads. Call it before flagging or changing a file to see what's already been
raised or decided here, so you don't re-litigate a settled point. This is context a hosted
PR bot structurally can't offer: it discards review history at merge, while Reikon keeps it.

**Consent-gated.** Review history is internal human commentary, and you may be a remote tool,
so it's shared only if the user opted in for this repo (Settings → This repo → "Share review
history with agents"). Off by default — until then this tool returns nothing. The consent is
stored locally and never committed.

### `get_dead_code_summary()`

No parameters. Unused import/export/asset counts plus the top offending files.
Covers JavaScript and TypeScript (AST), plus unused-import detection for Python
(`.py`), PHP (`.php`), and Java (`.java`).

```
Unused imports:  12
Unused exports:  4
Dead asset files: 1

Top files by unused imports:
  5 unused  src/legacy/helpers.ts
  3 unused  scripts/utils.py
```

***

## Write tools — scoped to annotation state only

These tools can never touch your code. They write to Reikon's annotation store
(`userData/diff-annotations.json`) — the same data the Review tab's notes panel reads
and writes. This is a deliberate boundary: agents act through annotation replies and
resolution, you (or another tool) make the actual code change.

### `add_annotation_comment(annotationId, body, model?)`

| Param          | Type   | Required                               |
| -------------- | ------ | -------------------------------------- |
| `annotationId` | string | yes — from `list_annotations`          |
| `body`         | string | yes                                    |
| `model`        | string | no — shown in the UI next to the reply |

Appends a reply thread to an existing annotation. Use this after fixing or reviewing
what a human flagged.

### `resolve_annotation(annotationId)`

| Param          | Type   | Required |
| -------------- | ------ | -------- |
| `annotationId` | string | yes      |

Marks an annotation resolved. Call it once you've confirmed the issue is addressed —
don't call it speculatively.

### `flag_risky_file(filePath, hunkKey, note)`

| Param      | Type   | Required                                      |
| ---------- | ------ | --------------------------------------------- |
| `filePath` | string | yes — must be part of the current diff        |
| `hunkKey`  | string | yes — from `get_annotated_diff`'s hunk header |
| `note`     | string | yes — why you're flagging it, in context      |

Lets an agent *proactively* flag something risky, without being asked — but only within
hard limits, so this can't become a noise generator:

* **Server-verified eligibility.** The call fails outright unless the file already
  crosses a deterministic threshold: tech debt ≥10h, or single ownership ≥60% with
  churn over 10×. An agent's own opinion of "this looks risky" is never trusted —
  it can only surface what Reikon's analyzers already flagged.
* **Scoped to the current diff.** Can't sweep the whole repo, only a hunk that's
  already part of what you're looking at via `get_annotated_diff`.
* **Capped at 3 flags per session.** The counter lives in the MCP server process. In
  the typical case (one agent at a time, stdio transport) this is a real per-session
  limit. If two Claude windows connect simultaneously they share the same process and
  the same counter — the combined cap is still 3, not 3 each.

```
Flagged "src/payments/processor.ts" for review — bus factor risk —
Alice Chen owns 62% with 34× churn. (1/3 flags used this session)
```

***

### `open_annotation(filePath, hunkKey, note)`

Opens a new review note on a hunk in the current diff — the agent leaving the human a note
to see, beyond replying to an existing one. Annotation state only, never code. `intent` is
optional (`fix` / `explain` / `review`, default `review`); get `hunkKey` from
`get_annotated_diff`. Capped at 5 notes per session.

### `mark_fix_returned(annotationId, note?)`

| Param          | Type   | Required                                                          |
| -------------- | ------ | ----------------------------------------------------------------- |
| `annotationId` | string | yes — must currently be `fix-requested`                           |
| `note`         | string | no — what you changed, for the human reviewing the returning diff |

The agent half of **dispatch**. When the human sets a note to **Request fix** (status `fix-requested`),
fix the code in your *own* environment, leave the change in the working tree, then call this to move the
note to `fix-returned` — it re-enters the human's Review inbox to verify. Annotation state only, never
code. **Don't resolve it yourself** — verifying the returning diff is the human's verdict.

**Trust gate:** the status only advances if the flagged file actually has an uncommitted change (staged,
unstaged, or newly added). A call with no working-tree diff is rejected — the same "deterministic re-check,
not the agent's say-so" discipline conditional-dispatch applies to rules, applied here to plain dispatch.

## A typical workflow

1. `get_project_health()` — check overall health and any regression vs. the last snapshot
2. `get_review_suggestions()` — see what's risky in the current diff and who to loop in
3. `get_file_context(file)` on anything flagged high-churn or high-complexity before editing
4. Make the change
5. `list_annotations(intent="fix")` — confirm every fix-intent note is addressed
6. `add_annotation_comment(id, "Fixed in …")`, then `resolve_annotation(id)`
7. If something you touched crosses a risk threshold and nobody's flagged it yet, `flag_risky_file` it
