Skip to content

Latest commit

 

History

History
552 lines (394 loc) · 45.2 KB

MCP_TOOLS.md

File metadata and controls

552 lines (394 loc) · 45.2 KB

MCP Tools Reference

repowise serves its codebase intelligence to AI coding assistants (Claude Code, Codex, Cursor, Cline, Windsurf and any other Model Context Protocol client) as a set of MCP tools. The tools answer questions from the index: the dependency graph, git history, generated docs, decision records, health and dead-code analysis. None of them edits your code. Two opt-in tools go further: set_finding_status records a triage verdict in the index, and generate_refactoring_code calls your configured LLM to draft a diff.

18 tools are registered in total. A single-repo server advertises 10 by default: exactly the canonical tools. Workspace mode adds the list_repos discovery utility, for 11. 7 specialist tools are opt-in where eligible.

This page tells you which tool to call and with what arguments. Every response field, the full _meta envelope and the truncation rules are in MCP_RESPONSE_FIELDS.md.

Contents

Canonical tools (default in both modes, 10) get_answer · get_context · get_symbol · search_codebase · get_risk · get_change_risk · get_why · get_overview · get_health · get_dead_code

Workspace discovery utility (default in workspace mode, 1) list_repos

Opt-in specialists (7; workspace eligibility still applies) get_dependency_path · get_execution_flows · generate_refactoring_code · set_finding_status · get_blast_radius · get_architecture · get_conformance


Starting the server

repowise mcp                              # stdio, for Claude Code, Codex, Cursor
repowise mcp --transport streamable-http  # HTTP on port 7338
repowise mcp --transport sse --port 7338  # legacy SSE transport

repowise init registers the server with Claude Code and installs its hooks; repowise init --codex writes project-local Codex MCP config and hooks. Pass --no-editor-setup (or set REPOWISE_SKIP_EDITOR_SETUP=1) for a scratch clone, worktree or CI run you do not want registered. Each Claude config holds a single repowise entry, so indexing a second repo repoints it; init prints a notice before it does.


Configuring the tool surface

Tool Default Mode
get_answer, get_context, get_symbol, search_codebase, get_risk, get_change_risk, get_why, get_overview, get_health, get_dead_code on single-repo and workspace
list_repos on workspace only
get_dependency_path, get_execution_flows, generate_refactoring_code, set_finding_status opt-in single-repo and workspace
get_blast_radius, get_architecture, get_conformance opt-in workspace only

Change the surface in .repowise/config.yaml under mcp.tools:

mcp:
  tools: ["+get_execution_flows", "-get_dead_code"]   # adjust the default set
# tools: ["get_answer", "get_context"]                 # explicit allowlist
# tools: all                                           # every tool usable in this mode
# tools: lean                                          # the agent-lean profile

Or per launch, which overrides the config block:

repowise mcp --tools "+get_execution_flows"   # default set plus one
repowise mcp --tools "get_answer,get_context"  # explicit allowlist
repowise mcp --tools lean                      # agent-lean profile
repowise mcp --all                             # every tool usable in this mode

The dashboard Settings page has a per-repo toggle for each tool and writes the same mcp.tools block.

  • Tokens prefixed + or - adjust the default set. A list without prefixes is an allowlist.

  • Unknown names are ignored with a warning. A workspace-only tool named outside workspace mode is ignored too: it has no workspace graph to read.

  • Raw MCP clients see the surface resolved when the server started. Restart the server after changing it.

  • Default (single-repo): 10 tools, exactly the canonical intelligence set.

  • Default (workspace): those 10 plus list_repos, the workspace discovery utility.

The lean profile is get_answer, get_context, get_symbol, search_codebase, get_risk and get_why, plus list_repos in workspace mode. It is small enough to keep every schema loaded, so when a repo sets mcp.tools: lean, repowise init skips the Claude Code tool-search recommendation.

See CONFIG.md for the config block itself.


Reading a response

Every tool returns a JSON object with a _meta envelope. Most fields appear only when they carry a signal. An agent should check these:

Field What to do with it
stale_warning Present only when the index is behind in a way that changed served files, or a served file has uncommitted edits or was indexed from edits since reverted (working_tree_dirty counts the edited ones; run repowise update --working-tree). Run repowise update before trusting file-level detail. Its absence means current.
indexed_commit, live_head, index_behind Which commit the answer describes and whether HEAD has moved since.
complete Symbol bodies or whole files served verified against the live file. Do not re-read them.
state degraded, partial or truncated when something fired, with reasons. A degraded empty result is a failed read, not an empty repository.
omitted Refs to content cut for size. Restore with repowise expand <ref> or get_symbol("repowise#<ref>").
response_budget The character ceiling that applied and the size delivered. Present when the budget cut something.

get_answer adds a top-level confidence, its one trust signal, graded from the retrieval and from whether the top hit covers what the question asks; include=["diagnostics"] adds retrieval_quality, the rating of the retrieval alone. Diagnostics such as timing_ms and contract_version ride only on get_overview; REPOWISE_MCP_DEBUG_META=1 restores them everywhere. Full envelope: MCP_RESPONSE_FIELDS.md.

Reversible truncation: _meta.omitted

Responses fit 24,000 serialized characters by default and 32,000 when the call passes an expansion argument (a nonempty include, for most tools). Content cut to fit is stored in the repo's omission store, and _meta.omitted lists the refs that restore it. Capped lists carry *_total siblings, so a count is never lost with its rows. Details: MCP_RESPONSE_FIELDS.md.

Unrecognised arguments: ignored_arguments

A value outside a closed vocabulary (a misspelled kind, include key or mode) is dropped, never applied as a filter that matches nothing. The response then names it in ignored_arguments, with the valid values. The key is absent when every argument was understood. Per-tool shapes: MCP_RESPONSE_FIELDS.md.


Which tool for which question

Question Tool
How does X work? Where is Y? Why is Z like this? get_answer
I am new to this repo. What is the shape of it? get_overview
What is in this file, who calls this function, who owns it? get_context
Show me this file's structure without reading all of it get_context(include=["skeleton"])
Give me the body of this one symbol get_symbol
Find the symbol, file or page matching this name or topic search_codebase
Is this file risky to touch? What has broken here before? get_risk
What could my set of changed files break, and which tests should run? get_risk(changed_files=[...])
What did this commit, range or uncommitted diff make worse? get_change_risk
Why was it built this way? Is there a decision governing it? get_why
What should we fix first? Which files are least healthy? get_health
Is the file I just edited healthier or worse? get_health(targets=[...])
What can we delete? get_dead_code
Which repos does this server serve? list_repos (workspace)
How are these two files connected? get_dependency_path (opt-in)
What runs when this entry point is called? get_execution_flows (opt-in)
Turn this refactoring plan into a diff generate_refactoring_code (opt-in)
Record that a refactoring plan is a false positive set_finding_status (opt-in)
Which services in other repos depend on this one? get_blast_radius (workspace, opt-in)
How coupled is the whole system? get_architecture (workspace, opt-in)
Does the system obey our declared dependency rules? get_conformance (workspace, opt-in)

Default tools

get_answer

Answers a how, where or why question in one call: it runs hybrid retrieval over the wiki and the symbol index, then synthesises a cited answer. Use it first for any question about the code. Skip it when you already know the exact file or symbol; go to get_context or get_symbol.

Parameter Type Default Meaning
question string required The question, in plain language
scope string none Path prefix to restrict retrieval to, e.g. "src/auth/"
repo string default repo Workspace repo alias. "all" is not supported
include list[string] none ["evidence"] returns the full evidence projection with a larger budget

Key return fields: answer, confidence (high / medium / low), citations, symbol_bodies (live bodies of symbols the answer names), retrieval, best_guesses and fallback_targets (on low confidence; a low best_guesses row carries functions, lines and size_bytes instead of a page excerpt), candidate_files (ranked file paths the citations do not already name: up to 3 at high, 5 otherwise), episodes (dated facts bearing on the question), degraded (synthesis could not run), _meta.scope_hint (areas the answer did not touch).

A high answer can be cited directly. On low, read the rows the reply names, then candidate_files, before searching again. Without an LLM provider the tool still answers from retrieval, marked degraded. When retrieval is also weak, the reply serves best_guesses and candidate_files with one guidance line in answer, and no citations.

get_answer(question="How does the authentication flow work?")

get_context

A triage card for files, modules or symbols: summary, symbols with signatures and line numbers, hotspot and fix-history cues, ownership and decisions. It returns relationships, not source. Use it before reading or editing code, and batch every target in one call. Do not call get_symbol once per signature; use include=["skeleton"] or read the file.

Parameter Type Default Meaning
targets list[string] required File paths, module paths, "path::Symbol" ids, "component:<name>", "change:<id>", or "package:<name>"
include list[string] none Any of full_doc, ownership, last_change, callers, callees, references, metrics, community, decisions, skeleton, health, doc_drift, symbols, changes, provenance, suspects
compact bool true false adds the structure block, imports and docstrings
repo string default repo Workspace repo alias. "all" is not supported (returns an error)
symptom string none Issue text, an error message or a pasted stack trace for include=["suspects"] to rank against, in place of the words in the target paths

Key return fields: targets keyed by target, each with title, summary, symbols, hotspot, fix_history (files with counted bug fixes), episodes, decision titles, file_preview (for files with no symbols), resolved_to (a symbol miss falling back to its file); dropped_targets and recovery when the budget forced targets out; _meta.complete for whole files served.

A component:<name> target returns the component's declared context (owner, system, criticality, tags) and facts rolled up over its files: health, hotspots, bus factor, test reach and dead code, each with a basis (measured, inferred or unavailable). Components come from .repowise/components.yaml or are derived from the index. With include=["ownership"] a component card adds ownership: declared teams with their activity over the last 90 days, a count of individual owners, and findings (critical_no_active_owner, declared_owner_inactive, critical_bus_factor_one, catalog_entry_no_code). An owner with no identity in the indexed history is unknown and raises no finding, so critical_no_active_owner does not fire when every owner is unknown; individuals match only by exact git email or forge noreply login. No other include applies to component targets. Health and dead code leave out files in gated languages and say how many.

A change:<id> target (change:pr-123, or a commit sha the change landed) returns the Change Record: title, forge ref, merged_at, category, files and provenance with its coverage. On a file target, changes lists the newest Change Records that touched it, and provenance gives the file's commits by source (agent, human-attested, unknown) with coverage; the agent share is withheld below 30% coverage. With attribution off, provenance reads {"unavailable": "attribution_off"} and change rows carry none. suspects adds one top-level block: the changes merged in the last 14 days ranked against the targets' files and the words in their paths, or the symptom text when one is given, at most 5 rows, each with the signals that fired and their evidence, plus the candidate count and window; an order to read changes in, never a cause.

A package:<name> target (package:requests, or package:npm:lodash) returns where that third-party package is imported: its manifest declarations, a summary, the components and declared owner teams, and up to 25 import sites with line, mapping (declared or inferred) and reachability (reachable, unreachable, test or unknown, with a basis). See PACKAGE_USAGE.md.

A file's compact symbol list holds its top 15 symbols: types (classes, interfaces, structs, traits, enums, type aliases, impls, modules) first, then functions and methods, then the rest, each group by centrality. symbols_truncated gives the total, and include=["symbols"] lists them all. When the response budget trims the list further, it keeps symbols by kind and name match, not centrality. A row without symbol_id is path::name; methods and overload variants carry theirs, so pass a row's id to get_symbol when it has one.

full_doc returns the page as content_md, plus digest_md on pages that carry an agent digest: the questions the page answers, its concept index, public API and git signals. Both are dropped first when the response is over budget. skeleton renders a file with bodies elided: every signature, the imports, and the bodies of its most central symbols, with line ranges on every elision. doc_drift lists the documents that name the file and whether they carry drift. An empty callers or callees list comes with a *_basis saying how much of that language's calls the graph resolved; read it before concluding nothing calls a symbol.

references is the edit set for a symbol target: every live line naming it, as {path, line, kind, text} with kind definition, import, call or reference. For a rename, a complete list is the whole edit set. Otherwise reasons says why. It is never complete for:

  • languages other than Python, TypeScript and JavaScript (same-package use needs no import)
  • more than 200 sites, a stale call line, an unreadable file, or an uncommitted edit outside the scanned files
  • a rename on import, export or destructure, a default export, or a CommonJS export
  • a dynamic use the graph recorded; access built from strings is otherwise not seen
  • more than 3 plain reference sites in one file: the rest are counted in sites_omitted_by_file, recoverable from _meta.omitted
get_context(targets=["src/auth/middleware.ts", "src/api/routes.ts"], include=["callers"])
get_context(targets=["src/big_module.py"], include=["skeleton"])

get_symbol

Returns verified, line-numbered source for one symbol, a live line range, or an omission ref. It is a follow-up read, not an entry point: use it on an id another response gave you, for a body that was elided, or to restore truncated output. get_answer already ships symbol_bodies.

Parameter Type Default Meaning
symbol_id string none "path/file.py::Name", "path/file.py:140-180" (live range, 200 lines max), or "repowise#<ref>"
id string none Alias for symbol_id
reference object none A continuation_reference or fetch_reference this tool emitted; pass it unchanged
context_lines int 0 Extra lines before and after, 0 to 50
depth int 1 2 or 3 also returns the bodies it calls, transitively
query string none Omission refs only: keep stored lines matching this regex or substring. With no symbol_id or id, it is read as symbol_id
repo string default repo Workspace repo alias. "all" is not supported

Key return fields: source (up to about 600 lines, each prefixed with its line number), start and end lines, kind, truncated with a continuation to pass back, ambiguous and candidates when several symbols match, callee_bodies (with depth above 1), not_rendered (bodies past the budget, each with a range read to fetch it), fallback lines from a live grep on a miss. A class or other container too large to serve whole returns outlined: true, its header in source and members (each member's symbol_id, signature and lines, with members_total when the list is capped) in place of the body, and no _meta.complete.

get_symbol(symbol_id="src/auth/service.py::login", depth=2)
get_symbol(symbol_id="repowise#a1b2c3d4e5f6", query="FAILED")

search_codebase

Hybrid search that routes by the shape of the query: identifiers search the symbol index, paths resolve files, prose runs wiki-semantic search, and mixed queries run both, keeping only pages that name a file. Use it when you want ranked hits themselves: enumerating matches, resolving an identifier to a symbol_id, scoping a later get_context. For a question, call get_answer; it runs this retrieval internally.

Parameter Type Default Meaning
query string "" Identifier, path or natural-language text. Required unless pattern is given
pattern string none Alias for query. When both are given, query is used and pattern is named in ignored_arguments
limit int 5 Max results. Outside symbol mode, at most this many distinct files: same-file hits share one row
mode string "auto" auto, concept, symbol, path or hybrid. An unknown mode runs as auto
kind string none implementation, test, config or doc
symbol_kind string none Filter symbol hits, e.g. function, class, method
page_type string none One page type, usually file_page or module_page
repo string default repo Workspace repo alias, or "all" to search every repo

Key return fields: results (every row that names a file carries it in path, and a row naming no file has no path; symbol hits carry symbol_id, line bounds and signature, plus symbols (name:line of up to five other matches in that file, then +N more) when several matched; concept hits carry relevance_score and snippet, plus sources unless it would be ["fts"] on an index without embeddings; a row leaves off page_id and a structural title (File: <path>) where page_type plus symbol_id or path rebuild them; the old file alias is gone, and a page keeps target_path only where it differs from path), candidates (up to limit distinct openable file paths, best first). If your next move is a Read, read candidates: some results are pages that are not files.

Page rows also carry symbols: up to three name:line entries (Owner.member for members) in that file whose names match the query's words. The first three page rows whose file has a matching line also carry matched_lines: a sample of up to three {line, text} source lines read from the live file that share the most query words, code lines before comments and imports. Unlike lines, it is never every match.

An identifier or literal query also returns lines ({path, line, kind, text}, definitions first, at most 50): the get_context references of one to three exact symbols, else a live scan for the token (kind definition or match). complete is true only when they are every match (see references above); otherwise reasons says why. Past 3 plain reference lines in one file, and past 50 lines, rows are counted in lines_omitted_by_file and recoverable from _meta.omitted; test files sort after production files. A query of several words caps lines at 15 (definitions, then calls, then imports) and lists the 5 files with the most omitted rows, with lines_omitted_by_file_total counting all of them.

search_codebase(query="GitIndexer index_repo")
search_codebase(query="login", mode="symbol", symbol_kind="method")

get_risk

What history says about touching a file: hotspot score, bug-fix record, owners, co-change partners, dependents and security signals. Pass changed_files for PR mode, where the response leads with a directive naming what may break and which tests to run. To review a commit or diff itself, use get_change_risk.

Parameter Type Default Meaning
targets list[string] changed_files File paths to assess
changed_files list[string] none Files in a change; switches on PR mode
include list[string] none graph (typed dependents, consumers, cross-repo links), churn, owners (owner percentages, bus factor, contributor count), tests (typed test_recommendations in PR mode), blast (pr_blast_radius in PR mode), scales (units and calibration, identical per call), changes (each file's newest Change Records)
repo string default repo Workspace repo alias. "all" is not supported

Key return fields: per file: hotspot_score (0 to 1), health_score (0 to 10), dependents_count, co_change_partners (file_path, support, conf_ab, has_import_link), primary_owner (detailed owner metrics are opt-in under include=["owners"]), test gaps, security_signals. In PR mode, directive with may_break, missing_cochanges, tests_to_run (the same selection repowise impacted-tests makes), tests_to_run_basis (measured, inferred or none), tests_run_all (with tests_run_all_reasons when every test must run), tests_to_update (test files to edit, each with a name_pair, imports or co_change reason), coverage, recommended_reviewers, next_calls, and reach (localized, moderate or broad; null when no structural score was computed). include=["blast"] adds pr_blast_radius; the raw 0 to 10 structural_impact_score and its scale appear there only with include=["blast", "scales"]. missing_tests appears only when coverage can back it. A target naming no indexed file returns resolved: false with a reason, never zeroed counts.

Dependent counts are a floor over the indexed graph, and structural reach is not proof of runtime breakage. reach bands an uncalibrated heuristic that never sees the diff; it is not a probability.

get_risk(targets=["src/auth/middleware.ts"])
get_risk(changed_files=["src/api/routes.ts", "src/middleware/cors.ts"])

get_change_risk

Reviews one commit, a base..head range, or uncommitted work by comparing the two revisions directly; it needs no index refresh. It reports what the change newly made worse across defect, maintainability and performance, which tests cover the changed lines, and the changed files' bug-fix record. Use it before merging. Use get_risk for an indexed file's history.

Parameter Type Default Meaning
revspec string uncommitted work A commit, base..head, or base...head (from the merge-base). Pass HEAD when the tree is clean
extensions list[string] all File suffixes to count, e.g. [".py", ".ts"]
exclude_patterns list[string] none Gitignore-style paths to omit; combined with a root .riskignore
include_paths list[string] or string all Gitignore-style paths to keep, as a list or one comma-separated string. Like exclude_patterns, it scopes the score, the health delta and every per-file block; impacted_tests still selects over the whole change, less only repowise's own output
baseline int 200 Recent commits sampled for percentile ranking; 0 disables percentiles
include list[string] none findings (every finding), diagnostics (raw score mechanics, plus the delta's analyzer, revisions and limits), scales (units), evidence (the change's evidence checklist, the same record repowise changes show prints), tests (why each listed test runs and the evidence per changed file)
finding_id string none Expand one health_delta finding
repo string default repo Workspace repo alias. "all" is not supported

Key return fields: directive (status of review_required, review_recommended, clear_in_analyzed_scope or unknown, with reasons and next actions), health_delta (introduced, worsened and resolved findings with status and top_findings), impacted_tests, patch_coverage (when coverage is stored), fix_history, branch_overlap, independent_changes, diff_shape, risk_percentile, cross_repo (workspace mode).

directive.status is the verdict. health_delta.status partial means files that may hold code were skipped, so the change is not cleared; docs and config files never cause it. review_priority, classification and diff_shape describe diff size and spread, never danger. An empty diff returns status: "nothing_to_score".

get_change_risk()
get_change_risk(revspec="main..HEAD", exclude_patterns=["tests/"])
get_change_risk(revspec="main..HEAD", finding_id="chf_27a13be11e7ee33f")

get_why

Why code is shaped the way it is: decision records, with git archaeology and mined rationale comments as fallbacks when no decision governs a path. Call it before a refactor or before diverging from an existing pattern.

Parameter Type Default Meaning
query string none A question, or a file or module path. Omit for the decision health dashboard
targets list[string] none Paths to anchor a question to, or to ask about on their own with no query
id string none A decision id or ev_... evidence id from an earlier response
reference object none An evidence reference this tool emitted; pass it unchanged
repo string default repo Workspace repo alias, or "all" (only with a query)

Modes: a question searches decision records; a path returns that file's decisions, candidates and history plus its origin story and alignment; targets alone asks about those files; no arguments returns the health dashboard (stale decisions, conflicts, ungoverned hotspots); id resolves one record directly.

Key return fields: decisions (accepted, binding), candidates (inferred, nobody accepted them: hints, not rules), history (accepted, since withdrawn), answer_basis (the strongest lane served; only decision is a ruling), alignment, git_archaeology, evidence_refs.

get_why(query="why JWT over sessions?")
get_why(query="src/payments/processor.ts")
get_why()

get_overview

Orientation for an unfamiliar repo: summary, key modules, entry points, layers, code health, the riskiest files and this week's top actions. Call it once, first. Skip it afterwards; it does not change within a session.

Parameter Type Default Meaning
include list[string] none Any of content (full essay), outline (wiki page tree), tour (guided tour and reading order), decisions, graph (community clusters), ownership (top owners), components (declared and derived components with file counts), changes (Change Records by category and week, and the agent share of changes with coverage), actions (the quarter's actions too, with done_when), tools (tool_surface: enabled tools, opt-ins and recipes), scope (the whole _meta.index_scope)
repo string default repo Workspace repo alias, or "all" for the cross-repo topology

Key return fields: title, content_md (summary section by default), key_modules (one row per package or top-level directory), entry_points, commands (build, test, lint and similar commands from manifests), architecture (layers in stack order with their root, plus dependencies: the ten heaviest package-to-package edges with from, to, verb and weight, and edges_total when more exist; absent in a single-package repo), code_health, git_health (riskiest_files), next_actions (top three for the week, or the quarter when the week is empty), more (names the opt-in blocks), and a workspace footer in workspace mode.

get_overview()
get_overview(include=["outline", "content"])

get_health

Code-health scores and findings from the stored analysis, across defect risk, maintainability and performance. With no targets it returns a dashboard led by fix_first, one ranked queue of what to fix first. With targets it scores those files. It never recomputes: commit, then run repowise update, to see new numbers. No LLM calls.

Parameter Type Default Meaning
targets list[string] none (dashboard) File paths or module:<name>. Misses are named in unresolved
include list[string] none Blocks: biomarkers, refactoring, trend, coverage, accuracy, signals, churn_complexity, doc_drift, semantics, unverified, recipe (with plan_id), what_if. Dimension filters: performance, defect, maintainability, advisory
only list[string] none Keep just these top-level keys; identity, totals and recovery fields always survive. An unknown key is named in unknown_only_keys with unknown_only_keys_hint
limit int 20 Max rows in every ranked list, capped at 50; 0 for none. fix_first shows five unless limit is passed with only=["fix_first"], which pages up to 25; refactoring_plans up to 25
cursor int 0 Offset into a ranked list (and into fix_first when named in only); the recovery block names the next call
fix_id string none Open one fix_first item (fix1_...) in full, or one get_overview next_actions action (act_...) with its details and commands (mode: "action")
finding_id, plan_id string none Open one finding or refactoring plan by id. With plan_id, include=["recipe"] adds plan.recipe: the plan's preconditions, ordered steps, postconditions and what it must not do
opportunity_id string none Open one opportunity: perf... for performance, refop... for a refactoring
refactoring_view string "diversified" diversified, canonical or file_spread
refactoring_scope string fix_first without targets, all with Which open refactoring opportunities, and their plans, to list
refactoring_type, refactoring_confidence, refactoring_effort string none Refactoring queue filters
performance_view string detail detail or summary
performance_context string production production, tooling, test, unknown or all
performance_boundary, performance_confidence, performance_actionability, performance_sort string none Performance queue filters. The queue lists causes whose cost is measured; unproven ones (loop size unknown) are counted in the proof facet and default_queue.excluded.unmeasured_cost
scope string "all" production drops test files from every figure
counts string "everything" code_shape drops the git-derived half of the score
repo string default repo Workspace repo alias. "all" is not supported

Only one of fix_id, finding_id, plan_id, opportunity_id per call; passing two returns mode: "conflict".

Key return fields: mode, fix_first (lead with its next_call, up to five items, counts, totals; a due lead carries its first_step and verify command, so it can be started without a fix_id call; only=["fix_first"] adds them to the other due items on the page), kpis, gap_analysis, worst_files, high_leverage_files (ranked by weighted_deficit), top_findings, unresolved, and the opt-in blocks you named. _meta.health_analysis says whether stored analysis exists and which commit it describes.

The response is bounded. Pair include with only to keep one block, e.g. get_health(include=["refactoring"], only=["refactoring_opportunities"]).

get_health(only=["fix_first"], limit=25)
get_health(only=["fix_first"], limit=25, cursor=25)
get_health(fix_id="fix1_...")
get_health(fix_id="act_...")
get_health(include=["refactoring"], only=["refactoring_plans"], limit=15, refactoring_scope="all")
get_health(targets=["src/api/server.py"], include=["signals"])
get_health(include=["performance"], only=["performance_summary"])
get_health(include=["coverage"], only=["coverage"])

get_dead_code

Unreachable files, unused exports, unused internals and zombie packages, tiered by confidence. Use it for a cleanup pass, not a targeted fix. safe_only leaves out anything with runtime-load risk such as dynamic imports and framework-registered functions.

Parameter Type Default Meaning
kind string all unreachable_file, unused_export, unused_internal or zombie_package
min_confidence float or string 0.4 Confidence floor; also accepts "high" (0.7), "medium" (0.4), "low" (0.0)
tier string all high (0.7 and up), medium (0.4 to 0.7) or low
safe_only bool false Deletion-ready findings only
limit int 20 Max findings per tier, clamped to 25
directory string none Path-prefix filter
owner string none Primary-owner filter
group_by string none directory or owner rollup
include_internals bool false Also scan private symbols (more false positives)
include_zombie_packages bool true Monorepo package findings
no_unreachable bool false Skip unreachable-file findings
no_unused_exports bool false Skip unused-export findings
finding_id string none Open one finding by its id
repo string default repo Workspace repo alias, or "all" to aggregate across repos

Key return fields: tiers (findings per tier, each with path, kind, confidence, line count and cleanup impact), summary (totals over every open finding, filtered_findings, filters, withheld_types, call_resolution_basis), by_directory or by-owner rollups with group_by. In workspace mode, confidence drops on findings another repo still imports.

get_dead_code()
get_dead_code(tier="high", safe_only=true)
get_dead_code(kind="unused_export", group_by="owner")

Workspace default

list_repos

Lists the repos this server serves. On by default in workspace mode only; a single-repo server is bound to its one repository. No parameters.

Key return fields: workspace (bool), workspace_root, default_repo, and per repo its alias, config-relative path and absolute_path. Any of those can be passed unchanged as repo to other tools.

list_repos()

Opt-in tools

Enable with mcp.tools: ["+name"] or repowise mcp --tools "+name" (see Configuring the tool surface). The last three are workspace-only.

get_dependency_path

The shortest dependency path between two files or modules. When none exists it returns context to debug the gap: nearest common ancestors, shared neighbours, community analysis and bridge suggestions.

Parameter Type Default Meaning
source string required Source file or module path
target string required Target file or module path
repo string default repo Workspace repo alias. "all" is not supported
get_dependency_path(source="src/api/routes.py", target="src/db/models.py")

get_execution_flows

The top-scored entry points and a breadth-first call trace from each, marking where a flow crosses community boundaries. Use it to see what runs end to end.

Parameter Type Default Meaning
top_n int 10 Entry points to trace
max_depth int 8 Max trace depth per flow
entry_point string none Trace from this symbol, overriding top_n scoring
repo string default repo Workspace repo alias. "all" is not supported
get_execution_flows(entry_point="src/cli/main.py::main", max_depth=4)

generate_refactoring_code

Turns one refactoring plan from get_health(include=["refactoring"]) into generated code and a unified diff, grounded on the plan and the source spans it names. Extract Class results include an LCOM4 before-and-after check. It calls the repo's configured LLM provider, and caches by content hash so an unchanged plan never regenerates.

Adding the tool to the surface is the opt-in step. Generation then runs only when .repowise/config.yaml sets refactoring.llm.enabled: true (off by default); otherwise the plan is returned with generation.available: false and reason: "disabled". With no provider configured it returns error: "no_provider".

Parameter Type Default Meaning
suggestion_id string required A plan id from get_health
repo string default repo Workspace repo alias. "all" is not supported
generate_refactoring_code(suggestion_id="a1b2c3d4")

set_finding_status

Records a durable verdict on one refactoring plan in the index, so the triage survives later analysis runs.

Parameter Type Default Meaning
suggestion_id string required A plan id or public_id from get_health
status string required open, acknowledged, resolved or false_positive
reason string "agent" Free-text audit note stored on the row
repo string default repo Workspace repo alias. "all" is not supported

false_positive plans are never re-emitted. acknowledged stays visible but stops counting as unheard. resolved stays resolved even if the detector still fires. open resets. Returns the new status and its timestamp.

set_finding_status(suggestion_id="a1b2c3d4", status="false_positive", reason="the class is a DTO")

get_blast_radius

Workspace only. Which services in other repos are structurally reachable from a changed service, ranked by an uncalibrated 0 to 1 path weight. Structural edges (HTTP, gRPC, events, packages) outrank co-change. It is not a runtime-breakage probability.

Parameter Type Default Meaning
targets list[string] required Node ids (repo or repo::service/path), repo aliases, or the symbol id of a published symbol
max_depth int 3 Reachability depth, 1 to 8
include_behavioral bool true Include co-change edges

Key return fields: impacted services with score, distance and edge kinds, impacted_repos, total_impacted, impact_score_semantics, and symbol_targets naming the consuming symbols across each contract link, with the tests that guard them.

get_blast_radius(targets=["backend"])

get_architecture

Workspace only. Whole-system structure: propagation cost (the share of other services the average service reaches), the largest cyclic core, service roles, and a deterministic 1 to 10 score. Structural edges only. No parameters.

Key return fields: score, architecture_type, propagation_cost_pct, core_members, cycle_count, role_breakdown, summary.

get_architecture()

get_conformance

Workspace only. Cross-repo dependencies that break the rules declared under conformance: in .repowise-workspace.yaml, plus circular service dependencies. Without opting in, the same findings still reach get_risk's PR-mode directive as conformance_violations and dependency_cycles.

Parameter Type Default Meaning
repo string whole workspace Limit findings to those involving this repo

Key return fields: violations (source and target services, the rule that fired, edge_kind), cycles, violation_count, cycle_count, rules_evaluated.

get_conformance(repo="frontend")

Workspace mode

A server started inside a workspace serves every repo in it from one process. repowise mcp --no-workspace forces single-repo mode for a nested repo. Every tool with a repo parameter takes an alias, path or absolute path from list_repos; omitting it targets the default repo.

Only four tools answer across every repo with repo="all". The rest return an error naming the available aliases.

Tool repo="all"
search_codebase Yes: federates the search and merges results
get_overview Yes: the cross-repo topology (co-changes, package dependencies, API contracts), with no single-repo detail
get_dead_code Yes: aggregates findings across repos
get_why Only with a query; not for the dashboard or an id lookup
get_answer, get_context, get_symbol, get_risk, get_change_risk, get_health No
get_dependency_path, get_execution_flows, generate_refactoring_code, set_finding_status No
get_conformance No "all" value; it covers the whole workspace when repo is omitted
get_blast_radius, get_architecture, list_repos No repo parameter; they always read the whole workspace

With repo omitted, get_context, get_symbol, get_risk and get_health route each path or path::Name target to its repo: the default repo when the file exists there, else the one other repo whose checkout has it. Write <alias>:<target> (for example web:src/app.ts::App) to name the repo outright. A path found in several other repos returns its candidates. A path in no repo gets the default repo's usual not-found answer plus a hint naming search_codebase(repo="all") and the <alias>:<path> form; routed results carry repo. get_context takes a batch spanning repos, while get_risk and get_health answer one repo per call and name the per-repo calls when a batch spans several.

get_context and get_symbol route a bare symbol name (render, Client.send) the same way, through the workspace store's symbol index: the default repo keeps a name it has, one other repo that has it gets the call, and several return candidates. A repowise#<ref> omission ref is found in whichever repo's omission store holds it.

A repo="all" call queries up to 4 repos at a time and gives each 60 seconds (REPOWISE_WORKSPACE_CONCURRENCY, REPOWISE_WORKSPACE_REPO_TIMEOUT_S). A repo that fails to open, errors or times out is listed in repos_failed with its reason while the other repos still answer. A repo whose index is behind its checkout is listed in repos_stale with indexed_commit and live_head, and its rows carry stale: true. Both keys appear only when non-empty.

Single-repo tools also gain cross-repo evidence in workspace mode:

  • get_context adds a per-target cross_repo block: co-change partners in other repos and contract consumers or providers.
  • get_risk in PR mode adds will_break_consumers (structural reach only), missing_cross_repo_cochanges, breaking_changes, conformance_violations and dependency_cycles to its directive.
  • get_change_risk adds cross_repo: consumers of the contracts the change touches, breaking changes, and the consumer-side tests to run.
  • get_dead_code lowers confidence on findings another repo still imports.

See WORKSPACES.md for setup, contracts and the system graph.


Hooks complement these tools with passive context: see HOOKS.md and CODEX.md.