# Fallow MCP Server Reference

The fallow MCP server (`fallow-mcp`) exposes fallow's analyses as agent tools. This is the full catalogue: each tool's kind, license, nearest CLI fallback, key params, plus the agent guidance the live tool schemas do not carry (CLI-fallback mapping, runtime-coverage confidence tiers, and `next_steps` dispatch). SKILL.md keeps only a short pointer; load this file when driving fallow through MCP.

The `generated:mcp-tools` table below is regenerated from `fallow schema` by scripts/generate-agent-docs.mjs; edit the curated Description cells in place, never the identity columns.

## Tool catalogue

When using fallow via MCP (`fallow-mcp`), the following tools are available:

<!-- generated:mcp-tools:start -->
| Tool | Kind | License | CLI fallback | Key params | Description |
|---|---|---|---|---|---|
| `code_execute` | composition | free | - | `code`, `timeout_ms`, `max_output_bytes` | Bounded read-only Code Mode for composing multiple fallow analysis calls in one JavaScript snippet. The snippet receives `{ fallow, root }`, returns JSON-serializable data, and can call read-only helpers such as `fallow.projectInfo`, `fallow.audit`, `fallow.checkHealth`, and `fallow.run(tool, params)` for the same allowlist. Mutating fix tools are not exposed. The sandbox has no filesystem, network, imports, `eval`, `Function`, `process`, `require`, `Deno`, `Bun`, or shell access. Params: `code`, optional `root`, `timeout_ms` (capped at 30000), and `max_output_bytes` (capped at 4000000). |
| `analyze` | analysis | free | `fallow dead-code --format json --quiet` | `issue_types`, `production`, `workspace`, `baseline`, `group_by`, `file` | Full dead code analysis (unused files/exports/types/dependencies/members + circular dependencies + re-export cycles (barrel files that form a structural loop, silently breaking re-exports) + boundary violations + rule-pack policy violations (banned calls, imports, and catalogue-derived effects declared via the `rulePacks` config key) + stale suppressions). Private type leaks are an opt-in API hygiene check via `issue_types: ["private-type-leaks"]`. Set `boundary_violations: true` as a convenience alias for `issue_types: ["boundary-violations"]`. Set `group_by` to `"owner"`, `"directory"`, `"package"`, or `"section"` to partition results. The `section` mode reads GitLab CODEOWNERS `[Section]` headers and emits `owners` metadata per group |
| `check_changed` | analysis | free | `fallow dead-code --changed-since <ref> --format json --quiet` | `since`, `baseline`, `fail_on_regression` | Incremental analysis of files changed since a git ref |
| `security_candidates` | analysis | free | `fallow security --format json --quiet` | `gate`, `surface`, `changed_since`, `paths` | Unverified local security candidates, not confirmed vulnerabilities (`fallow security --format json`). Read `security_findings[]` for category, CWE, severity, evidence, trace, optional `reachability`, blind-spot counters, and optional `unresolved_callee_diagnostics` samples for dynamic callee follow-up. `severity` is a review-priority tier, not a verified vulnerability verdict. Each finding also carries an agent-actionable `candidate` (`source_kind`/`sink`/`boundary`), where URL-category sinks may include `url_shape` (`fixed-origin-dynamic-path` or `dynamic-origin`), an optional `taint_flow` source-to-sink triple, and a stable `finding_id` (equal to the SARIF fingerprint) for cross-run correlation; there is no `impact` field (deciding exploitability is the agent's job). Set `surface: true` to include top-level `attack_surface[]` entries with defensive-boundary prompts for a verifier. Set `gate` to `new` for changed-line candidates or `newly-reachable` for candidates that became reachable from entry points; `newly-reachable` requires `changed_since`. `reachability.untrusted_source_trace` is module-level import context only and does not prove value flow; `reachability.taint_confidence` tiers each reachable candidate as `arg-level` (sink argument traces to a same-module source read, strong) or `module-level` (only the module is import-reachable from a source, weak), so tier from this field instead of the evidence text. Verify trace, reachability context, severity, and evidence before editing code. Supports `root`, `config`, `workspace`, `paths`, `changed_since`, `changed_workspaces`, `surface`, `gate`, `no_cache`, and `threads`; `paths` forwards repeated `fallow security --file` filters for finding anchors, trace hops, untrusted-source reachability trace hops, and unresolved-callee diagnostics. See <https://docs.fallow.tools/cli/security-agent-verification> for the verifier packet and verdict recipe. Inherits `FALLOW_DIFF_FILE` from the server environment for line-level diff scoping; raise `FALLOW_TIMEOUT_SECS` for large repos. |
| `inspect_target` | analysis | free | `fallow inspect --format json --quiet` | `target`, `production`, `include_churn` | Compose one evidence bundle for a file or exported symbol. File targets use `target: { type: "file", file }`; symbol targets use `target: { type: "symbol", file, export_name }`. Returns `kind: "inspect_target"`, normalized target identity, `trace_file`, optional `trace_export`, file-scoped dead-code actions, duplication groups filtered to the file, complexity findings filtered to the file, and security candidates scoped to the file. Set `include_churn: true` to add target-level git churn from the health hotspot subsystem. Churn is off by default, and unavailable git history or analysis failures remain explicit section states. Evidence sections carry `status` and `scope`; symbol targets warn when supporting evidence is file-scoped. Supports `root`, `config`, `production`, `workspace`, `include_churn`, `no_cache`, and `threads`; `production` applies to trace, dead-code, and health evidence only. Raise `FALLOW_TIMEOUT_SECS` for large repos. |
| `guard` | introspection | free | `fallow guard <file> --format json --quiet` | `files` | Report the architecture rules that apply to given files before editing them: boundary zone, allowed import zones, forbidden calls, and rule-pack policies |
| `find_dupes` | analysis | free | `fallow dupes --format json --quiet` | `mode`, `near`, `min_tokens`, `min_occurrences`, `top`, `threshold` | Code duplication detection. Set `near: true` for function-level clones with small structural edits. Set `changed_since` to scope to changed files since a git ref. Set `min_occurrences` (≥ 2, default 2) to hide pair-only clones and focus on widespread copy-paste. Each `clone_groups[]` entry carries a normalized `fingerprint` and `spread`; near groups also carry `similarity`. `stats.clone_groups_ignored` reports reviewed groups hidden by config, while `stats.near_candidates_skipped` signals bounded near comparisons that were skipped. Pass the fingerprint to `trace_clone` to inspect the group |
| `check_health` | analysis | free | `fallow health --format json --quiet` | `score`, `css`, `file_scores`, `hotspots`, `targets`, `coverage`, `runtime_coverage`, `max_crap`, `group_by` | Complexity metrics, health scores, hotspots, and refactoring targets. Set `complexity_breakdown: true` to add a per-decision-point `contributions[]` array to each complexity finding (each `else-if`, nested `if`, boolean operator, loop, `case`, etc. with its source line and cyclomatic/cognitive weight) so you can explain WHY a function scored high and pinpoint refactor targets. Optional `runtime_coverage` merges a V8 or Istanbul dump; tune it with `min_invocations_hot` (default 100), `min_observation_volume` (default 5000), and `low_traffic_threshold` (default 0.001). When runtime evidence combines with static usage, test coverage, CRAP/complexity, ownership, or change scope, read `coverage_intelligence` for stable `fallow:coverage-intel:<hash>` recommendations. Set `group_by` to `owner`, `directory`, `package`, or `section` for per-group `vital_signs` / `health_score`; SARIF results gain `properties.group`, CodeClimate issues gain a top-level `group` field |
| `check_runtime_coverage` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `coverage`, `min_invocations_hot`, `min_observation_volume`, `low_traffic_threshold`, `group_by` | Merge V8 or Istanbul runtime-coverage data into the health report. One local capture is free; continuous/cloud or multi-capture runtime monitoring is paid. Required `coverage` param (V8 dir, V8 JSON, or Istanbul `coverage-final.json`). Tuning knobs: `min_invocations_hot` (default 100), `min_observation_volume` (default 5000), `low_traffic_threshold` (default 0.001), `max_crap` (default 30.0), `top`, `group_by`. Cloud runtime rows can expose `resolutionStatus` / `mappingQuality` on function-list JSON and `resolution_status` / `mapping_quality` in runtime-context JSON. Use `coverage_intelligence` and the confidence table below before acting on file-level runtime signals. Long dumps may exceed the 120s MCP timeout; raise `FALLOW_TIMEOUT_SECS`. Pick this over `check_health` when you have a coverage dump. |
| `get_hot_paths` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `coverage`, `top`, `min_invocations_hot` | Runtime-context slice over the same runtime coverage pipeline. Same params as `check_runtime_coverage`; read `runtime_coverage.hot_paths` for production hot paths. |
| `get_blast_radius` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `coverage`, `group_by` | Runtime-context slice for blast-radius review. Same params as `check_runtime_coverage`; read `runtime_coverage.blast_radius` for stable `fallow:blast:<hash>` IDs, caller counts, traffic-weighted caller reach, optional cloud deploy touch counts, and low/medium/high risk bands. |
| `get_importance` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `coverage`, `group_by` | Runtime-context slice for production-importance review. Same params as `check_runtime_coverage`; read `runtime_coverage.importance` for stable `fallow:importance:<hash>` IDs, invocations, cyclomatic complexity, owner count, 0-100 score, and templated reason. |
| `get_cleanup_candidates` | runtime-coverage | freemium | `fallow health --runtime-coverage <path> --format json --quiet` | `coverage`, `group_by` | Runtime-context slice for cleanup review. Same params as `check_runtime_coverage`; read `runtime_coverage.findings` for `safe_to_delete`, `review_required`, `low_traffic`, and `coverage_unavailable`. |
| `get_token_blast_radius` | analysis | free | `fallow health --css --format json --quiet` | - | Design-token blast radius for Tailwind v4 @theme tokens and CSS-in-JS token definitions (StyleX, vanilla-extract, PandaCSS): per token, a consumer_count (static lower bound) and a capped located consumers[] sample tagged theme-var/css-var/utility/apply (Tailwind), js-member (member access), or js-call (Panda token calls); descriptive context for sizing a token change, never a deletion gate |
| `audit` | analysis | free | `fallow audit --format json --quiet` | `gate`, `base`, `css_deep`, `max_crap`, `coverage`, `runtime_coverage` | Combined dead-code + complexity + duplication + styling for changed files, returns verdict. Styling analytics are enabled by default; CSS and CSS-in-JS evidence can add `styling_findings`, `css_analytics`, and `styling_health` under the health sub-result. Set `gate` to `"new-only"` or `"all"`. Set `css_deep: false` to skip project-wide styling reachability while keeping local styling checks, or `css_deep: true` to force it back on when config disables it. Optional `runtime_coverage` (V8 dir / V8 JSON / Istanbul JSON) folds runtime findings into the same call; `min_invocations_hot` tunes the hot-path threshold (default 100). Runtime evidence appears under the audit `complexity` sub-result, including `coverage_intelligence` when combined evidence yields actionable recommendations. |
| `decision_surface` | analysis | free | `fallow decision-surface --format json --quiet` | `base`, `max_decisions`, `workspace` | Surface the few consequential structural decisions a change embeds (coupling, public API, dependency), each as a judgment question with the routed expert; ranked, capped, and signal_id-anchored |
| `fallow_explain` | introspection | free | `fallow explain <issue-type> --format json --quiet` | `issue_type` | Explain one issue type without running analysis. Required `issue_type`; returns rationale, examples, fix guidance, and docs URL |
| `fix_preview` | fix | free | `fallow fix --dry-run --format json --quiet` | `no_create_config` | Dry-run auto-fix preview |
| `fix_apply` | fix | free | `fallow fix --yes --format json --quiet` | `no_create_config` | Apply auto-fixes (destructive) |
| `project_info` | introspection | free | `fallow list --files --entry-points --plugins --format json --quiet` | `entry_points`, `files`, `plugins`, `boundaries` | Project metadata. Set `entry_points`, `files`, `plugins`, or `boundaries` to `true` to request specific sections |
| `recommend` | introspection | free | `fallow recommend --format json --quiet` | `root` | Recommend a project-tailored config from framework/workspace/tooling detection: a loader-validated proposed_config and three-valued auto/default/taste decisions for cold-start onboarding |
| `list_boundaries` | introspection | free | `fallow list --boundaries --format json --quiet` | - | Architecture boundary zones, access rules, and pre-expansion `autoDiscover` `logical_groups[]` (user-authored parent name, verbatim paths, discovered children, `status` enum, summed `file_count`). Returns `{"configured": false}` if no boundaries configured |
| `feature_flags` | analysis | free | `fallow flags --format json --quiet` | `workspace`, `production` | Detect feature flag patterns (env vars, SDK calls, config objects). Set `top` to limit results |
| `list_suppressions` | analysis | free | `fallow suppressions --format json --quiet` | `workspace`, `changed_since`, `file` | List active fallow-ignore suppression markers grouped per file (line, kind, level, reason, and a stale cross-reference); a read-only governance inventory that always exits 0 |
| `impact` | introspection | free | `fallow impact --format json --quiet` | `root` | Read the local, opt-in Fallow Impact value report (`fallow impact --format json`). Runs no analysis: current surfacing counts, trend since the last recorded run, pre-commit gate containment, and (on impact v1.5+) resolved/suppressed attribution. History is read from a per-project file in the user's private config dir (never inside the repo). Read-only and `root`-only; the mutating `enable` / `disable` / `default` lifecycle is not exposed. A never-enabled project returns a populated `{"enabled": false, ...}` report (never `{}`); branch on `enabled` and `enabled_source` (`project` / `user` / `default`) then `record_count`, recommending `fallow impact enable` only when `explicit_decision` is `false` (never asked) and staying silent when `true` (deliberately disabled here). Local-developer signal: fallow never records in CI, so empty there and not a CI metric |
| `impact_all` | introspection | free | `fallow impact --all --format json --quiet` | `sort`, `limit` | Roll every tracked fallow project on this machine into one cross-repo value report (hashed keys plus basename labels, never paths; local-dev only) |
| `trace_export` | trace | free | `fallow dead-code --trace <file:export> --format json --quiet` | `file`, `export_name` | Trace why an export is used or unused (`fallow dead-code --trace FILE:EXPORT_NAME --format json`). Required `file` and `export_name`. Returns file reachability, entry-point status, direct references, re-export chains, and a reason string. If `export_name` is a class / enum / store MEMBER, returns a member trace instead (`member_name`, `member_kind`, `owner_export`, `owner_is_used`) plus a `--unused-<kind>-members` pointer; branch on field presence. Use before deleting a supposedly-unused export or debugging an unused-class-member finding |
| `trace_symbol` | trace | free | `fallow dead-code --type-aware --trace <file:export> --format json --quiet` | `file`, `export_name`, `type_aware_projects`, `type_aware_require` | Trace an exact TypeScript symbol with checker-backed references, namespace identity, aliases, and re-export hops. Root trace fields preserve syntactic context; treat `semantic.references`, `semantic.status`, and `semantic.identity` as the authoritative exact evidence. The proof covers only the lane named by `semantic.target.namespace`, so a root trace that lists a reference the proof does not is wider evidence rather than stale. This is project-wide evidence for Fallow decisions, not a compiler-diagnostic or lint-rule surface. |
| `symbol_impact` | impact | free | `fallow dead-code --type-aware --symbol-impact <file:export-or-class.member> --format json --quiet` | `file`, `export_name`, `class_name`, `member_name`, `type_aware_projects`, `type_aware_require` | Return exact-symbol consumers, affected files, and targeted tests for a TypeScript export or exported class method. Select either `export_name`, or both `class_name` and `member_name`. Advisory change-impact evidence, not a substitute for `tsc` or Oxlint |
| `trace_file` | trace | free | `fallow dead-code --trace-file <file> --format json --quiet` | `file` | Trace all graph edges for a file (`fallow dead-code --trace-file PATH --format json`). Required `file`. Returns reachability, exports, imports-from, imported-by, and re-exports. Use to decide whether a file is isolated, barrel-only, or imported by live entry points |
| `impact_closure` | trace | free | `fallow dead-code --impact-closure <path> --format json --quiet` | `path` | Trace the transitive affected-but-not-in-diff set and coordination gaps for one file. Supports `root`, `config`, `production`, `workspace`, `no_cache`, and `threads`. Use as review-planning evidence for a file contract, not proof that affected files are wrong |
| `trace_dependency` | trace | free | `fallow dead-code --trace-dependency <package> --format json --quiet` | `package_name` | Trace where a dependency is imported (`fallow dead-code --trace-dependency PACKAGE --format json`). Required `package_name`. Returns importing files, type-only importers, total import count, `used_in_scripts` (true when invoked from package.json scripts or CI configs), and `is_used` (combined import + script signal; mirrors the unused-deps detector so build tools like `microbundle` or `vitest` are not falsely flagged as unused). Use before removing a dependency or moving between `dependencies` and `devDependencies` |
| `trace_clone` | trace | free | `fallow dupes --trace <file:line> --format json --quiet` | `file`, `line`, `fingerprint`, `near`, `min_occurrences` | Deep-dive a duplicate-code clone group (`fallow dupes --trace <spec> --format json`). Address by exactly one of: `file` + `line` (a source location), or `fingerprint` (a `dup:<id>` from a prior `find_dupes` `clone_groups[].fingerprint`, usually `dup:<8hex>` and widened only on rare report collisions). Returns the matched clone instance plus every clone group containing it; each traced group carries its `fingerprint`, an extract-function `suggestion` with estimated savings, and a best-effort `suggested_name` (omitted when no confident name). Supports `mode`, `near`, `min_tokens`, `min_lines`, `min_occurrences`, `threshold`, `skip_local`, `cross_language`, `ignore_imports`. Use the same `near` value as the originating `find_dupes` call. Use to consolidate duplication when you need exact sibling locations and a refactor target |
<!-- generated:mcp-tools:end -->

## How type-aware proof relates to the root trace

`trace_symbol` is the only tool that returns a checker-backed `semantic` block
next to a syntactic root trace. The checker resolves actual reads through local
aliases, import types, namespace-qualified names, and barrels to the exact type
or value declaration. Import and re-export declarations alone are not reads.
The root trace stays authoritative for graph reachability and star ambiguity,
and its optional `direct_references_by_namespace` keeps type and value evidence
separate without changing the selected root `namespace`. Type-aware
reconciliation fails closed: unreachable-only, re-export-only, or
different-declaration evidence cannot suppress a syntactic finding. Treat an
ambiguous root as an abstention, and investigate any remaining mismatch before
deleting a symbol.

`symbol_impact` carries no `semantic` block and no root trace. Its top-level
checker evidence uses the same declaration-safe alias and namespace resolution
as `trace_symbol`. A listed consumer's `relation` names the traced symbol's own
lane, not the consumer's syntax. Confirm a clean impact result with
`trace_export` or `trace_symbol` before deletion when the graph reports
ambiguity or reachable references.

`trace_export` never carries a `semantic` block: it is API-backed in-process and answers from the graph alone.

## Runtime source-map confidence for cloud runtime tools

| Values | Meaning | Agent action |
|:-------|:--------|:-------------|
| `resolved` + `high` | The source map resolved the generated position to original source. | Trust the file path and line number. Reference the original source confidently. |
| `fallback` + `medium` | A source map exists, but it did not cover this generated position. | Treat the file-level signal as approximate. Ask the developer to rebuild with denser source maps before making a precise edit. |
| `unresolved` + `low` | No matching source map was uploaded for this bundle and commit. | Ask the operator to upload the source map before acting on file-level coverage signals. |
| `null` + `null` | The row does not include source-map confidence metadata. | Treat the row as missing confidence metadata. Do not downgrade it to `low` without other evidence. |

## Shared params, JSON output, and next_steps

Most tools accept `root`, `config`, `no_cache`, and `threads` params. Exceptions: `impact` takes only `root`; `code_execute` takes `code`, optional `root`, `timeout_ms`, and `max_output_bytes`. The MCP server subprocess timeout defaults to 120s, configurable via `FALLOW_TIMEOUT_SECS`.

All JSON responses include structured `actions` arrays on every finding (dead code, health, duplication), enabling programmatic fix application or suppression.

`health.thresholdOverrides[]` lets projects keep known legacy functions visible as configured local ceilings instead of hiding them with suppressions. Each entry has `files` globs, optional exact `functions`, one or more of `maxCyclomatic`, `maxCognitive`, `maxCrap`, or `maxUnitSize`, and optional `reason`. Health JSON may include top-level `threshold_overrides[]` entries with `active`, `stale`, `insufficient`, or `no_match` status, and complexity findings that use an override carry `effective_thresholds` plus `threshold_source: "override"`. Each entry also names its `dimension` (`complexity` or `crap`), so one configured override yields one entry per dimension it participates in: group on `override_index` to count configured overrides. `insufficient` means the raised ceiling is still exceeded. An entry's `outstanding[]` lists every dimension the matched unit still breaches after the override applied, which is how an `active` override can sit next to a surviving finding.

`dead-code`, `health`, `dupes`, bare `fallow`, and `audit` JSON output also carry a top-level `next_steps` array of read-only follow-up commands computed from the run's findings: each entry is `{ id, command, reason }`. The `command` is runnable as-is (never a placeholder, never `fix` or any other mutating command); the stable kebab-case `id` (`setup`, `impact-report`, `trace-unused-export`, `trace-clone`, `complexity-breakdown`, `scope-workspaces`, `audit-changed`) maps to a verification step you should run BEFORE acting, for example tracing an export before deleting it. A leading `setup` step (command: `fallow schema`) appears only on unconfigured, non-CI projects with findings and doubles as an onboarding trigger; it disappears after setup or `fallow init --decline`. An at-most-weekly `impact-report` step (command: `fallow impact`) carries the local value digest when impact tracking has non-zero results; it may ride a clean run. When running via MCP, dispatch on the `id` to the matching tool / `code_execute` host call (`trace_export`, `trace_clone`, `check_health` with `complexity_breakdown: true`, `audit`) rather than shelling out the CLI string. The array is deduplicated, capped at three, and omitted when empty; set `FALLOW_SUGGESTIONS=off` to suppress it.
