Skip to main content
Glama

PyPI Python 3.11+ License MIT PRs Welcome

Agensi

Also available as an agent skill on Agensi. The skill teaches your agent the full reforge workflow (scan → score → plan → fix → commit). Install reforge-mcp first, then add the skill.

Available on Glama - https://glama.ai/mcp/servers/Codewithaiyan/reforge-mcp

reforge-mcp MCP server – quality and maintenance score on Glama

reforge-mcp MCP server – quality and maintenance score on Glama

reforge-mcp

An MCP server that gives Claude Code structured tools over your codebase — dead code, duplicates, god files, the dependency graph — and tells you what it could not read.

Reports expose their limits: the health result's coverage is the fraction of counted source files analysed, summary.parse_failures counts files the parser could not read, and dep_graph.unresolved_relative_imports counts unresolved relative imports of supported source files. get_health_score returns score: null when no files were analysed. Coverage is not test coverage, and unsupported source extensions are counted from a fixed list.

The skill source is in skills/reforge/SKILL.md.


CI

What it does

Repos built quickly with AI can accumulate unused functions, copied logic, oversized modules and circular imports. reforge-mcp gives Claude Code structured findings so it can inspect the source, prioritize changes, apply patches with optional tests, and create local Git commits. Findings and risk scores are heuristics that need review before deleting or changing code.

The 10 MCP tools

These are the exact registered MCP names; Python wrapper functions have a _tool suffix.

Registered tool

What it does

File effects

scan_repo

Reports dead-code candidates, duplicates, oversized modules, dependencies and subprojects for supported source files.

Read-only

get_chunk

Reads an inclusive, 1-indexed line range from a UTF-8 file.

Read-only

get_health_score

Computes health and analysis coverage, then appends a timestamped history entry.

Writes state and backups

write_fix

Patches one existing file, optionally runs tests, and attempts rollback if the patch or tests fail.

Writes source and recovery backups; tests may write files

git_commit

Stages named files and commits the index within session budgets and confirmation checkpoints.

Writes Git index/history; may switch branches and run hooks

infer_architecture

Infers a likely pattern, entry points and modules, then saves architecture_hypothesis.

Writes state and backups

read_memory

Reads a top-level state value, with defaults when state is missing or unreadable.

Read-only

write_memory

Creates or replaces a top-level state value through a staged write.

Writes state and backups

score_risk

Estimates change risk from symbol-name references, referencing tests, file size and cycles.

Read-only

generate_changelog

Writes a timestamped Markdown report from saved health history, fixes and pending work.

Overwrites REFORGE_CHANGES.md

State lives in reforge-state.json. State writes rotate up to five timestamped backups. infer_architecture is a writing tool despite doing analysis first. The server entry point also adds Reforge entries to .gitignore and removes top-level *.tmp files in its working directory at startup.

Status

Verified against 21 open-source repositories across three validation sweeps — django, flask, fastapi, scrapy, pydantic, requests, express, axios, react, vue, svelte, zod, nest, cobra, gin, caddy, prometheus, okhttp, ktor, nowinandroid and ripgrep. Those sweeps found and closed 17 defects, including two languages whose tree-sitter queries had never compiled at all and a Python dependency graph that had been mostly missing for nine releases. Every one is reproduced and documented in IMPROVEMENTS.md.

CI runs lint and the test suite on Linux and Windows with Python 3.11, 3.12 and 3.14.

What is still true, and worth knowing before you trust a number:

  • A Go dependency graph is roughly 1% resolved. Go imports are module paths that need go.mod to resolve; caddy reports 31 edges from 3,321 imports. Treat Go dependency and risk results as incomplete.

  • A whole-repo scan of a large project is summarised, not complete. Long lists are capped to reduce the context needed — a 3,000-file repository comes back around 170 KB instead of 1.2 MB. Every count stays exact, and truncated names each list that was shortened with its real length, so a short list is never mistaken for a complete one.

  • Dead-code detection is name-based, with no type resolution. It is deliberately biased toward missing a finding rather than inventing one, because the advice is "delete this".

  • Successful patches preserve recovery information. write_fix rejects mismatched diff hunks and keeps a byte-exact .reforge-bak copy after a successful patch when the file was modified, untracked or outside Git. When Git already holds the original contents, backup is null.

Also included

  • Health score trending — every get_health_score call appends to health_history so you can chart improvement over time

  • Persistent memory — reforge-state.json survives across Claude Code sessions; stores the architecture hypothesis, fix log and pending work

  • Monorepo support — scan_repo finds subprojects from pyproject.toml, setup.py, package.json, tsconfig.json and go.mod. It suggests a conventional test command; it does not verify that command or detect Kotlin/Gradle subprojects. When markers overlap, the first matching marker wins.

  • Changelog generation — REFORGE_CHANGES.md is written on demand with score deltas, applied fixes, and pending items


Related MCP server: codex-dobby-mcp

Installation

Prerequisites: Python 3.11+, Git, and Claude Code or Claude Desktop.

API keys: Reforge does not require ANTHROPIC_API_KEY or another model API key. Its analysis and state tools run locally without calling an external model; Claude Code or Claude Desktop manages its own model access. Test commands launched by write_fix and Git hooks invoked by git_commit may have their own network activity.

Claude Code

pip install reforge-mcp
claude mcp add reforge-mcp -- reforge-mcp

Run claude mcp list to check that reforge-mcp is registered, then start a new session to use its ten tools. The executable must be on the client's PATH. To request an upgrade, run pip install --upgrade reforge-mcp; the selected version also depends on your Python version and configured package index.

Claude Desktop

pip install reforge-mcp

Add this to claude_desktop_config.json, merging it with any existing mcpServers entries:

{
  "mcpServers": {
    "reforge-mcp": {
      "command": "reforge-mcp",
      "args": []
    }
  }
}

The config is in ~/Library/Application Support/Claude/ on macOS or %APPDATA%\Claude\ on Windows. Restart Claude Desktop after saving. Its process must be able to find reforge-mcp on PATH; a terminal's activated virtualenv does not automatically change a desktop application's environment.

From source

git clone https://github.com/Codewithaiyan/reforge-mcp
cd reforge-mcp
python3 -m venv venv
source venv/bin/activate          # PowerShell: .\venv\Scripts\Activate.ps1
pip install -e .

For a source install in a virtualenv, the executable is venv/bin/reforge-mcp (Windows: venv\Scripts\reforge-mcp.exe). If the client cannot find it, use its absolute path as the Claude Desktop command or after -- in the Claude Code registration command. which reforge-mcp (PowerShell: Get-Command reforge-mcp) shows the executable from an activated environment.


Usage

Example session with Claude Code

Illustrative session; the counts and commit hash below are examples.

You: Use reforge-mcp to scan my repo at /home/me/myproject and fix the top issues.

Claude: I'll start with a full scan.

[calls scan_repo("/home/me/myproject")]

The scan found:
- 14 dead functions across 6 files
- 3 duplicate implementations of `calculate_discount`
- 1 god file: src/api/handlers.py (847 lines, 23 exports)
- 1 circular dependency: auth → middleware → auth

[calls get_health_score(repo_path="/home/me/myproject")]
Health score: 47/100

Let me fetch the duplicate implementations to confirm they're identical.

[calls get_chunk(file_path="/home/me/myproject/src/billing/utils.py", repo_root="/home/me/myproject", start_line=12, end_line=28)]
[calls get_chunk(file_path="/home/me/myproject/src/cart/helpers.py", repo_root="/home/me/myproject", start_line=5, end_line=21)]

Confirmed — identical bodies. I'll keep the one in src/billing/utils.py and have
src/cart/helpers.py import it.

[calls write_fix(file_path="/home/me/myproject/src/cart/helpers.py", repo_root="/home/me/myproject", diff_str="...", test_command="pytest")]
[calls git_commit("/home/me/myproject", files=["src/cart/helpers.py"], message="refactor: drop duplicate calculate_discount")]

Committed: a3f91c2. Running next fix...

Sample scan_repo output

Illustrative excerpt from a four-file repository; additional summary and graph diagnostics are omitted here for brevity. The example has calculate_discount copy-pasted into src/pricing.py and src/cart.py, an unused parse_legacy_csv and _old_validate, and auth.py and middleware.py importing each other.

{
  "summary": {
    "total_files": 4,
    "total_functions": 7,
    "total_classes": 0,
    "total_imports": 3,
    "total_lines": 41,
    "languages_detected": ["python"]
  },
  "dead_code": [
    { "symbol": "_old_validate",    "file": "auth.py",        "line": 8 },
    { "symbol": "checkout",         "file": "src/cart.py",    "line": 10 },
    { "symbol": "parse_legacy_csv", "file": "src/pricing.py", "line": 7 }
  ],
  "duplicates": [
    {
      "hash": "0a764010605b675494ce6d70c89bb5da7bf02f63589dd69d232c1b057c76569f",
      "locations": [
        { "file": "src/cart.py",    "line": 4, "name": "calculate_discount" },
        { "file": "src/pricing.py", "line": 1, "name": "calculate_discount" }
      ]
    }
  ],
  "god_files": [],
  "dep_graph": {
    "nodes": ["auth.py", "middleware.py", "src/cart.py", "src/pricing.py"],
    "edges": [
      { "from": "auth.py", "to": "middleware.py" },
      { "from": "middleware.py", "to": "auth.py" }
    ],
    "circular": [["auth.py", "middleware.py", "auth.py"]]
  },
  "subprojects": []
}

checkout is a dead-code candidate because nothing in those four files references its name. A finding is a question for Claude to check, not a deletion instruction. On a monorepo, subprojects fills in from the marker files it finds:

{
  "subprojects": [
    { "root": "frontend",        "language": "javascript", "test_command": "npm test" },
    { "root": "services/worker", "language": "go",         "test_command": "go test ./..." }
  ]
}

Paths use your platform's separator, so they come back with backslashes on Windows.

Sample REFORGE_CHANGES.md

# Reforge Changes

*Generated: 2025-05-02T14:33:00+00:00*

**Health score:** 73.5 (+26.5 from previous scan)

## Fixes Applied

- refactor: consolidate duplicate calculate_discount
- fix: remove dead parse_legacy_csv from src/importers/csv.py
- refactor: split handlers.py into auth_handlers.py and order_handlers.py

## Pending Fixes

- resolve circular dep: src/auth/__init__.py ↔ src/middleware/auth.py
- remove _old_validate from src/models/user.py

How it works

Reforge works in three phases:

1. Scan

scan_repo walks the repository with parse_directory, feeding each source file to the appropriate tree-sitter adapter (Python, JavaScript/TypeScript, Go or Kotlin). Tree-sitter builds a full AST — unlike regex, it understands nested scope, decorators, arrow functions, and generics. The adapters extract functions, classes, and imports into typed dataclasses.

When Git reports a nonempty tracked-file list, only those files are analysed; outside Git or with an empty index, all eligible files are analysed. languages can filter supported languages. include_tests is currently accepted but does not filter test files, whether true or false.

A missing root or a root that is a file returns an explicit error report. Existing directories without Git are still supported, including empty directories and extracted source archives.

Each parsed file also collects reference names from the AST while skipping each definition's own name and the contents of comments and strings. From the parse results, three analyses run:

  • Dead code — functions whose name appears in nobody's reference set. Matching is by name, not resolved symbol, so a repo-wide name collision hides a finding: a missed one costs nothing, a wrong one costs you working code. Exempt: dunder methods, conventional entry points, test_*, anything listed in __all__, and anything carrying a decorator that is not a pure modifier like @property — a framework calls its registered functions without naming them anywhere a parser can see

  • Duplicates — functions whose normalised bodies share the same SHA-256 hash. One-line methods that several classes implement identically are treated as interface conformance, not copy-paste

  • God files — non-test files over 500 lines or with more than 10 top-level definitions. Methods do not count towards that total

A dependency graph is built from resolved imports — from x import y, bare import x, relative from ..pkg import y, and JS/TS ./path forms — and checked for cycles with DFS. Imports that resolve outside the repository are external and get no edge. Monorepo subprojects are discovered by scanning subdirectories for marker files (pyproject.toml, package.json, go.mod, tsconfig.json).

2. Plan

Claude Code receives the structured scan report and uses get_chunk to read specific line ranges before deciding what to fix and in what order. infer_architecture saves its hypothesis, and get_health_score appends history. The agent must use write_memory to maintain its fix log and pending queue; patches and commits do not update those lists automatically. read_memory retrieves saved values in later sessions.

3. Fix

write_fix validates a unified diff before writing the target:

  1. Creates a unique byte-for-byte backup ending in .reforge-bak beside the existing target file

  2. Parses the diff into hunks and checks every hunk's context and removed lines against the file at the position its header claims

  3. Applies the hunks with line-offset tracking — or, if any hunk failed that check, writes nothing at all

  4. Runs the optional test command (validated against the allowlist)

  5. On a mismatched diff or test failure, attempts to restore the backup and returns rolled_back: true. This flag records the rollback path, not independent verification that restoration succeeded; filesystem failures can prevent recovery.

git_commit stages the listed files and commits the Git index via GitPython. It returns an error when the staged index has no changes to commit; a refused empty commit does not consume the session budget. Previously staged changes are also included, so review the index first; files_committed echoes the requested file list, not the full commit contents. The tool reads session_budget and confirm_every from reforge.toml: commits are blocked when the budget is reached, and the next call after each confirm_every group returns needs_confirmation: true until retried with confirmed: true. The count is held per repository for the life of the server process, so restarting the server starts a new session. This tool does not push.


Security

Boundary

Mechanism

Source-file boundaries

Parsing, get_chunk and write_fix validate source paths against the supplied repository boundary. Relative file_path values resolve from the server working directory, not repo_root. State/report tools use the caller-supplied repo_path as their destination

File guards

Parsing skips configured binary/lock/minified files and files over 500 KiB. get_chunk retains the file-type guards but permits large files. write_fix does not apply those file-type/size guards

Test command injection

write_fix validates test_command against an explicit allowlist (pytest, python3 -m pytest, npm test, go test ./..., etc.) before executing

Staged state writes

State is serialized to reforge-state.tmp, the previous file is backed up and removed, then the temporary file is renamed. This is not a fully atomic replacement: a crash between removal and rename can leave no state file. Startup removes top-level *.tmp files in its working directory

Mismatched diffs

apply_diff rebuilds each hunk's expected old lines from its context and - lines and compares them against the file before mutating anything — a stale or wrong diff is rejected whole, leaving the file byte-identical

Runaway test commands

The test command runs with no shell, with stdin closed and its output going to a file rather than a pipe. A prompt it cannot answer, or a grandchild process holding a pipe open, used to hang the server past its own timeout

Local analysis

Reforge's analysis and state tools make no outbound API calls. The AI client's model requests, user-supplied test commands and Git hooks have their own network behavior


Contributing

# Clone and install
git clone https://github.com/Codewithaiyan/reforge-mcp
cd reforge-mcp
python3 -m venv venv && source venv/bin/activate
pip install -e ".[dev]"

# Run the full test suite
pytest

# Run with coverage
pytest --cov=src --cov-report=term-missing

Project structure

reforge-mcp/
├── src/reforge_mcp/
│   ├── server.py              # FastMCP server — registers all 10 tools
│   ├── tool_results.py        # TypedDict output schemas for MCP results
│   ├── tools/
│   │   ├── scan.py            # scan_repo, get_health_score, monorepo detection
│   │   ├── chunk.py           # get_chunk — line-range file reads
│   │   ├── fix.py             # write_fix — diff apply + rollback
│   │   └── git.py             # git_commit — atomic commits with budget enforcement
│   ├── scanner/
│   │   ├── parser.py          # tree-sitter adapters (Python, JS/TS, Go, Kotlin) + reference collection
│   │   ├── dead_code.py       # unreferenced symbol detection
│   │   ├── duplicates.py      # body-hash duplicate detection
│   │   ├── architecture.py    # project-shape inference
│   │   ├── risk.py            # per-symbol change risk
│   │   └── adapters/          # per-language project-detection stubs
│   └── utils/
│       ├── state.py           # reforge-state.json load/save, gitignore, changelog
│       ├── security.py        # path validation, file guard, command allowlist
│       └── diff.py            # unified diff parser and applier
├── tests/                     # one file per module, plus test_end_to_end.py
│   ├── test_parser.py         #   which drives scan -> fix -> commit for real
│   ├── test_dead_code.py
│   ├── test_duplicates.py
│   ├── test_dep_graph.py
│   ├── test_god_files.py
│   ├── test_diff.py
│   ├── test_fix.py
│   ├── test_git.py
│   ├── test_chunk.py
│   ├── test_memory.py
│   ├── test_monorepo.py
│   ├── test_scanner.py
│   └── test_security.py
├── pyproject.toml
└── reforge.toml               # optional per-repo config

reforge.toml reference

[scan]
ignore = ["generated", "vendor"]   # added to the built-in skip list

[fix]
confirm_every  = 5       # pause for confirmation every N commits
session_budget = 20      # max commits per session, per repo, before a hard stop

Those three keys are the whole file. Every one of them is read.


Changelog

See CHANGELOG.md. If you used any earlier version, re-scan. Three validation sweeps changed what the analyses report: TypeScript and Go parsed nothing at all before 0.3.0, Python dependency graphs were mostly missing before 0.4.0, and dead-code findings in Go, Kotlin and TypeScript included whole classes of false positive.

License

MIT — see LICENSE.

Available Tools

10 tools
generate_changelogA

Write REFORGE_CHANGES.md from saved health history, fixes and pending work. Use when: you need a human-readable report of state recorded during cleanup. Don't use when: you only need one raw saved state value (use read_memory instead).

Returns {success, path}, with error if the Markdown file could not be written. Reads health_history, fix_log and pending_fixes; it does not rescan, infer fixes from Git or populate those lists. Overwrites the report with a fresh UTC generation timestamp, so repeated calls are not idempotent.

NameRequiredDescriptionDefault
repo_pathYesExisting repository directory containing reforge-state.json and the output REFORGE_CHANGES.md; prefer an absolute path. Existing output is overwritten, and each successful call adds a fresh UTC timestamp.

Output Schema

NameRequiredDescription
pathYes
errorNo
successYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false and destructiveHint=false, but the description goes further: it says the report is overwritten with a fresh UTC timestamp so repeated calls are not idempotent, that it errors when the Markdown file cannot be written, and that it only reads health_history, fix_log and pending_fixes without inferring fixes from Git. That is exactly the kind of context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the artifact name, then organized into explicit 'Use when' / 'Don't use when' blocks and a short behavior paragraph. Every sentence adds a fact an agent needs (side effects, data sources, error condition); nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter write tool with an output schema already declaring {success, path}, the description covers the remaining gaps: which state files are read, what is not inferred, overwrite/non-idempotency, and the failure mode. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single repo_path parameter already documents the required state file, the overwrite behavior and the timestamp. The description adds no path-format or validation detail beyond that, so the baseline 3 is appropriate when the schema carries the parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb (write) and named artifact (REFORGE_CHANGES.md) plus the exact data sources: saved health history, fixes and pending work. An agent can distinguish it immediately from read_memory and from the scanning siblings because the description explicitly says it does not rescan.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides both a positive trigger ('Use when: you need a human-readable report of state recorded during cleanup') and a negative one with a named alternative ('Don't use when: you only need one raw saved state value (use read_memory instead)'). The routing decision between this tool and a sibling is fully specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_chunkA
Read-onlyIdempotent

Read an inclusive line range from a UTF-8 file without modifying it. Use when: you need to inspect a finding or obtain context for a patch. Don't use when: you need repository-wide findings (use scan_repo instead).

Returns {source, language, start_line, end_line, total_lines} on success, or {error} on failure. Source joins the selected lines with newlines; start_line/end_line report the clamped inclusive range. Large files can be read in slices; binary, lock and minified-file guards still apply.

NameRequiredDescriptionDefault
end_lineNoLast line, 1-indexed and inclusive; default null reads through EOF. An inverted range returns the start line; values beyond EOF clamp to EOF.
file_pathYesUTF-8 text file to read, e.g. /work/app/src/main.py. Relative paths resolve from the server working directory, not repo_root; the resolved file must remain inside repo_root. Binary/lock/minified files are skipped.
repo_rootNoRepository boundary used to validate file_path. Default null uses the server working directory; prefer an absolute path, e.g. /work/app.
start_lineNoFirst line, 1-indexed and inclusive; default 1. Values below 1 clamp to 1; a request beyond EOF returns the last line.

Output Schema

NameRequiredDescription
errorNo
sourceNo
end_lineNo
languageNo
start_lineNo
total_linesNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds value beyond that: binary/lock/minified guards still apply, large files can be sliced, and failure returns {error}. It does not reintroduce the safety hints redundantly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then when/when-not, then return shape and guards — every block is scannable and largely earns its place. The explicit return-object breakdown is slightly redundant given an output schema exists, keeping it short of a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read tool with full annotation and schema coverage plus an output schema, the description supplies the remaining behavior an agent needs: guards, slicing for large files, and the error case. The redundant return-shape sentence is the only mild over-explanation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so clamping and defaults are already documented per-parameter, and the description largely restates the clamping rule ('start_line/end_line report the clamped inclusive range'). The one genuinely additive note is that source joins lines with newlines, but overall it adds little beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Read an inclusive line range from a UTF-8 file without modifying it.' The read-only, single-file, line-range framing immediately separates it from scan_repo, which is named directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Uses explicit 'Use when' (inspect a finding, get context for a patch) and 'Don't use when' (repository-wide findings → scan_repo) clauses, naming the alternative sibling and the condition that selects it. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_health_scoreA

Compute repository health from scan metrics and append a timestamped state entry. Use when: you need a before/after health metric and persisted history. Don't use when: you only need findings without writing state (use scan_repo instead).

Returns {score, coverage, breakdown, scan_summary}, plus caveat for limited coverage or parse failures. score is 0-100 (higher is healthier), or null when no files were analysed. coverage is the analysed fraction (0-1, three decimal places), not test coverage. Breakdown contains dead_code_ratio, duplicate_ratio (fractions rounded to three decimals), god_file_count and circular_count. Deductions cap at 30/30/20/20 points respectively; only Python/JS/TS-sensitive cycles reduce health. The history entry is appended on every call, so repeated calls are not idempotent.

NameRequiredDescriptionDefault
repo_pathYesExisting repository directory to scan and persist health_history in reforge-state.json; prefer an absolute path, e.g. /work/app. Every call appends a UTC-timestamped entry and rotates state backups.

Output Schema

NameRequiredDescription
scoreYes
caveatNo
coverageYes
breakdownYes
scan_summaryYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false and destructiveHint=false, yet the description still adds real value: it states that a UTC-timestamped history entry is appended on every call, that repeated calls are therefore not idempotent, and that caveats appear for limited coverage or parse failures. It stops short of saying where state lives or how backups rotate, which only the parameter schema hints at.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, when-to-use and when-not-to-use are front-loaded and tightly written. The trailing 'Returns {...}' block is informative but partly redundant with the existing output schema, making the definition longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with full annotation coverage and an output schema, the description covers the write side effect, side-effect caveats and scoring semantics well. The detailed return-value enumeration duplicates the output schema, so it is complete but not optimally scoped.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter, and the schema description already covers path expectations, persistence to reforge-state.json and backup rotation. The description adds no parameter-level detail beyond what the schema supplies, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource — computing repository health from scan metrics — and adds the persistence side effect. It explicitly differentiates from the sibling scan_repo, so an agent can pick between them without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit 'Use when' condition (need before/after metric plus persisted history) and an explicit 'Don't use when' that names the alternative (scan_repo for findings without writing state). Both directions of the routing decision are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

git_commitA
Destructive

Stage the named files and create a Git commit within the session budget. Use when: edits have been reviewed and should be recorded in local Git history. Don't use when: you need to apply or test a patch first (use write_fix instead).

Returns {success, commit_hash, branch, files_committed, error}. A checkpoint additionally returns needs_confirmation=true and message; retry with confirmed=true after approval. files_committed echoes the requested list, not an inventory of the commit: previously staged changes are also committed. Refuses an empty commit when the staged index matches HEAD; refusals do not consume the session budget. Initial commits with staged content are allowed. May create/check out a branch and invoke Git hooks; does not push.

NameRequiredDescriptionDefault
filesYesRequired nonempty list of files to stage, relative to repo_path or absolute within it; e.g. ['src/main.py']. Already staged changes are also included by Git's index commit; inspect the index first.
branchNoBranch name to check out before staging; default null stays on the current branch. Must exist unless create_branch is true.
messageNoCommit message; null (default) or an empty string uses 'refactor: automated fix #N', with N the next per-repository session count.
confirmedNoDefault false. Set true on retry after needs_confirmation is returned and the user approves. Does not bypass session_budget (default 20 commits); checkpoints default to every 5 commits via reforge.toml.
repo_pathYesGit repository directory to commit in; prefer an absolute path, e.g. /work/app.
create_branchNoDefault false. When true and branch is supplied, create and check out that branch; without branch this flag has no effect.

Output Schema

NameRequiredDescription
errorYes
branchYes
messageNo
successYes
commit_hashYes
files_committedYes
needs_confirmationNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the mutation/open-world profile; the description goes well beyond them by disclosing the checkpoint confirmation flow (needs_confirmation plus retry with confirmed=true), that refusals do not consume the session budget, that empty commits are refused, that initial commits are allowed, that Git hooks may run, and that nothing is pushed. The one omitted behavior is what 'destructive' concretely means here (e.g. whether rewriting history is possible), which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Strong structure: purpose first, then labeled use/don't-use, then return shape, then caveats. Every sentence carries information, but the return-value enumeration is partly redundant given an output schema exists, and the tail-end caveats are packed densely into long sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, open-world mutation with six parameters and an approval gate, the description covers the confirmation retry loop, budget interaction, index semantics, branch switching and hook invocation. Combined with the output schema, an agent has everything needed to call it correctly and to handle the refusal and checkpoint paths.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains files, branch, message, confirmed, repo_path and create_branch in detail. The description mostly restates those semantics, with the only genuinely additive note being that files_committed echoes the requested list rather than being an inventory of the commit. Baseline 3 is appropriate when the schema carries the parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb-plus-resource pair ('Stage the named files and create a Git commit') and adds a scoping constraint ('within the session budget'). It also explicitly names the sibling it is not for ('use write_fix instead'), so an agent can distinguish it from the patch-application tool without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a labeled 'Use when' condition (edits reviewed and should be recorded in local history) and a labeled 'Don't use when' condition that names the alternative tool write_fix. This is the explicit when/when-not/alternative structure an agent needs for routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

infer_architectureA

Infer a repository's architectural pattern and save its hypothesis to reforge-state.json. Use when: you need an initial map of the project's likely shape and entry points. Don't use when: you only need the previously saved hypothesis (use read_memory instead).

Returns {pattern, evidence, entry_points, inferred_modules, confidence, hypothesis}. Pattern is REST API, CLI tool, web frontend, library or unknown; confidence is a heuristic fraction from 0 to 1. Classification uses imported modules, with filename-based entry-point/module guesses. Scans without an external model, then writes architecture_hypothesis and rotates state backups.

NameRequiredDescriptionDefault
repo_pathYesRepository directory to scan and save architecture_hypothesis in reforge-state.json; prefer an absolute path. Existing state backups rotate.

Output Schema

NameRequiredDescription
patternYes
evidenceYes
confidenceYes
hypothesisYes
entry_pointsYes
inferred_modulesYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false but say nothing about what actually gets written. The description fills that gap: it writes architecture_hypothesis into reforge-state.json, rotates existing state backups, and scans without an external model using imported modules plus filename-based heuristics. It also discloses the heuristic nature of confidence, which sets correct expectations about the output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then use/don't-use, then behavior and return shape — a clean progression with no filler. The return-value enumeration is slightly redundant since an output schema exists, which keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, non-open-world scan-and-write tool, the description covers the trigger condition, the alternative, the mutation of state with backup rotation, the classification method, and confidence semantics. Nothing an agent needs in order to call it correctly or interpret results is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single repo_path parameter is fully documented in the schema, including the absolute-path preference and backup rotation note. The description adds no parameter-level meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Infer a repository's architectural pattern") plus the persistence side effect, and explicitly distinguishes itself from read_memory as the read-only alternative for the saved hypothesis. An agent can separate this from scan_repo or read_memory without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit "Use when" (need an initial map of likely shape and entry points) and "Don't use when" (only need the previously saved hypothesis → use read_memory instead), naming the sibling to route to. No inference required from the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_memoryA
Read-onlyIdempotent

Read one top-level value from persisted repository state without writing files. Use when: you need a saved hypothesis, fix queue, fix log or health history. Don't use when: you need to replace a stored value (use write_memory instead).

Returns {key, value, found}; an unknown key returns value=null and found=false. Built-in default keys may return found=true even when no state file exists.

NameRequiredDescriptionDefault
keyYesTop-level state key to read, e.g. architecture_hypothesis, fix_log, pending_fixes or health_history. Arbitrary strings are accepted; built-in default keys count as found even without a state file.
repo_pathYesDirectory containing reforge-state.json; prefer an absolute path. Missing/unreadable/invalid JSON state is replaced by in-memory defaults.

Output Schema

NameRequiredDescription
keyYes
foundYes
valueYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description still adds genuine behavioral nuance beyond them: unknown keys return value=null with found=false, and built-in default keys report found=true even when no state file exists — a non-obvious quirk an agent would otherwise misread as real persisted data. It loses a point because the {key, value, found} return summary is largely duplicated by the existing output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the core action, then the when/when-not routing, then return and edge-case semantics. No filler, and each sentence carries distinct information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read tool with an output schema, full annotations and 100% schema coverage, the description covers action, alternatives, return shape, and the missing-state and default-key edge cases. Nothing material is left for the agent to guess before calling it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema, including the top-level key examples and the repo_path defaults behavior. The description adds only the 'one top-level value' framing, which the schema's key description already conveys, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'read one top-level value from persisted repository state' — plus a scoping qualifier ('without writing files') that pins down what it does not do. The contrast with write_memory makes it immediately separable from the nearest sibling, and 'one top-level value' rules out nested-path reads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Uses explicit 'Use when' / "Don't use when" framing, and the exclusion names the alternative tool (write_memory) together with the condition that selects it (replacing a stored value). It also enumerates the concrete key categories (hypothesis, fix queue, fix log, health history) that motivate a call, so no inference is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scan_repoA
Read-onlyIdempotent

Scan source files for dead code, duplicates, oversized modules, and dependencies. Use when: you need repository-wide findings before planning changes. Don't use when: you only need source lines from a known file (use get_chunk instead).

Returns {summary, dead_code, duplicates, god_files, dep_graph, subprojects}. Summary includes file/symbol/line counts, languages, parse_failures and unscanned-source counts. Findings carry file paths and 1-indexed lines; dep_graph has nodes, {from, to} edges, circular paths, external_imports, unresolved_relative_imports and package_imports counts. A missing/non-directory root or a path-validation failure returns error, empty findings/graph and a zero summary, without subprojects. Lists are capped at 200 items, duplicate groups at 50 and their locations at 10; shortened lists gain _total, with truncated listing shortened top-level/graph lists. Summary counts remain complete. In a nonempty Git index, only tracked files are analysed; outside Git, all eligible files are.

NameRequiredDescriptionDefault
languagesNoOptional case-insensitive language filter: python, javascript, typescript, go, kotlin. Default null (or []) scans all supported languages; unknown names are ignored. Example: ['python', 'typescript'].
root_pathYesExisting source directory to scan; prefer an absolute path, e.g. /work/app. Relative paths resolve from the server working directory.
include_testsNoDefaults to true. Currently accepted for compatibility but does not filter test files: both true and false include them.

Output Schema

NameRequiredDescription
errorNo
summaryYes
dead_codeYes
dep_graphYes
god_filesYes
truncatedNo
duplicatesYes
subprojectsNo
dead_code_totalNo
god_files_totalNo
duplicates_totalNo
subprojects_totalNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), and the description goes well beyond them: it discloses the truncation caps (200 items, 50 duplicate groups, 10 locations), the <key>_total companion fields, the guarantee that summary counts stay complete, the Git-index-only-tracked-files rule, and the degraded error response for a bad root. These are non-obvious behaviors an agent could not infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then a when/when-not pair, then return shape, then edge cases and caps — a logical order with no filler sentences. It loses a point for density: the truncation sentence ('shortened lists gain <key>_total, with truncated listing shortened top-level/graph lists') is syntactically tangled and would benefit from restructuring.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter, read-only analysis tool this covers purpose, alternatives, failure modes, and truncation, leaving little an agent needs missing. Since an output schema exists, the detailed return-field enumeration and summary-contents description are partly redundant, which keeps it just short of a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so root_path, languages, and include_tests are already fully documented in the schema, including the include_tests no-op caveat. The description adds indirect meaning by explaining that Git index state changes which files under root_path are analysed, but it adds no new detail about the parameter values themselves. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Scan source files') and enumerates exactly what is detected: dead code, duplicates, oversized modules, dependencies. It also explicitly positions itself against the sibling get_chunk, so an agent can distinguish the two without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit 'Use when' (repository-wide findings before planning changes) and an explicit 'Don't use when' that names the alternative tool (get_chunk) and the condition selecting it. This is the strongest form of routing guidance available.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

score_riskA
Read-onlyIdempotent

Estimate the risk of changing one symbol on a heuristic 0-to-100 scale. Use when: you need to prioritize a specific proposed change before patching. Don't use when: you need an overall repository health trend (use get_health_score instead).

Returns {score, breakdown, basis, referenced_by, recommendation}. Breakdown contains point contributions: inbound_refs (0-30), has_tests (0 or 20 for no referencing test), lines_changed (5/10/17/25 based on file length, not patch size), is_circular (0 or 25). basis is symbol, or file when reference sets are unavailable. referenced_by contains at most 10 sorted paths. Recommendation is safe to fix (<=30), fix with caution (<=60), or manual review recommended (>60); this is not a guarantee of correctness or coverage.

NameRequiredDescriptionDefault
fileYesRepository-relative file path exactly as reported by scan_repo, e.g. src/pricing.py. Use native separators or forward slashes; absolute paths do not match the scan's relative paths. Used for file size and cycles.
symbolYesExact case-sensitive unqualified symbol name, e.g. calculate_discount. Matches AST reference names across files, not fully resolved symbols; the implementation does not validate that the symbol exists.
repo_pathYesRepository directory to rescan with per-file symbol references enabled; prefer an absolute path. No source or state files are written.

Output Schema

NameRequiredDescription
basisYes
scoreYes
breakdownYes
referenced_byYes
recommendationYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description discloses the scoring internals (inbound_refs 0-30, has_tests 0/20, lines_changed 5/10/17/25 based on file length not patch size, is_circular 0/25), the caps (at most 10 referenced paths), the basis fallback (symbol or file when references unavailable), and an explicit caveat that the score is not a guarantee. This is the kind of context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Usage guidance is front-loaded before the return explanation, and every clause carries real information. The returns block is long and partly duplicates what the output schema may already convey, which keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter, read-only heuristic scorer, the definition covers triggering conditions, internal weighting, output shape, interpretation thresholds, and explicit limitations. Nothing an agent needs to call it correctly or interpret the result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains file, symbol, and repo_path semantics including the case-sensitivity and no-validation caveats. The description adds only the framing that exactly one symbol is assessed, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Estimate the risk of changing one symbol') plus the output scale (0-to-100 heuristic), which immediately separates it from the aggregate-health sibling get_health_score. An agent can distinguish it from every sibling without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Use when' gives the triggering condition (prioritizing a specific proposed change before patching) and 'Don't use when' names the alternative tool (get_health_score) with the condition that selects it. Both directions of routing are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_fixA
Destructive

Apply a unified diff to one file, optionally run tests, and attempt rollback on failure. Use when: you have reviewed the source and prepared a specific patch. Don't use when: you only need to record existing edits in Git (use git_commit instead).

Returns {success, test_output, error, rolled_back}. Successful patches also return git_state (clean, modified, untracked or no_repo) and backup (null when Git holds the original, otherwise a retained .reforge-bak path). Tests are optional; success without test_command does not mean tests ran. No commit is created. Reapplying the same diff is not idempotent.

NameRequiredDescriptionDefault
diff_strYesSingle-file unified diff with @@ -old_start,old_count +new_start,new_count @@ hunks (1-indexed lines). Context and removed lines must match the file at the stated positions; a mismatched patch is rejected.
file_pathYesExisting file to patch, e.g. /work/app/src/main.py; must remain within repo_root. Relative paths resolve from the server working directory.
repo_rootNoRepository boundary and test-command working directory; default null uses the server working directory. Prefer an absolute path.
test_commandNoOptional allowlisted test command, e.g. pytest or npm test. Default null skips tests. Runs without a shell from repo_root, with closed stdin and a 120-second timeout; test failure triggers file rollback.
allowed_test_commandsNoCommand-prefix allowlist; a nonempty list replaces the built-in list. Default null (or []) uses built-ins such as pytest, python -m pytest, npm test and go test. Prefixes match complete shell-split tokens; command chaining remains rejected.

Output Schema

NameRequiredDescription
errorYes
backupNo
successYes
git_stateNo
rolled_backYes
test_outputYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructive, non-idempotent, open-world), the description discloses that no commit is created, that rollback is attempted on failure, that a .reforge-bak file may be retained, and that a diff is not safe to reapply. The caveat 'success without test_command does not mean tests ran' is a non-obvious behavioral trap that annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded (purpose, then when/when-not, then returns) and every sentence carries signal. The enumerated return-value list partially duplicates the output schema, which is the only slack in an otherwise tight definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter destructive patch tool with an output schema, the description covers purpose, gating conditions, rollback behavior, backup artifacts, and result interpretation. Nothing an agent needs in order to invoke it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds meaning on top by clarifying that test_command is optional and that omitting it yields success without test execution, which changes how an agent should interpret results. It does not add nuance about allowed_test_commands beyond the schema, keeping it below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource ('Apply a unified diff to one file') and immediately adds the two bundled behaviors (optional test run, rollback on failure). It also explicitly distinguishes itself from the closest sibling, git_commit, so an agent can route without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides an explicit 'Use when' condition (you have reviewed the source and prepared a specific patch) and an explicit 'Don't use when' with the named alternative (git_commit for recording existing edits). This is the full when/when-not/alternative triad.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_memoryA

Create or replace one top-level value in reforge-state.json via a staged write. Use when: you need to persist a hypothesis, fix log or pending work across sessions. Don't use when: you only need to inspect a stored value (use read_memory instead).

Returns {success, key, previous_value}, with error on an OSError while saving. previous_value is null for an absent key or a previously null value. Repeated calls can change previous_value and rotate timestamped state backups, so this is not idempotent even when the supplied value is unchanged.

NameRequiredDescriptionDefault
keyYesTop-level state key to create or replace; arbitrary strings are accepted, e.g. pending_fixes. This is a literal key, not a dotted path.
valueYesRequired JSON value to store: object, array, string, number, boolean or null. Replaces the entire value at key rather than merging/appending. Example for pending_fixes: ['split handlers.py'].
repo_pathYesExisting directory containing reforge-state.json; prefer an absolute path. Writes through reforge-state.tmp, replaces the state file and rotates up to five timestamped backups; other top-level keys are preserved.

Output Schema

NameRequiredDescription
keyYes
errorNo
successYes
previous_valueYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and idempotentHint=false; the description adds the reason behind the idempotency flag (backups rotate, previous_value changes on repeated calls) plus the OSError failure mode, which is genuinely useful context. It also clarifies that other top-level keys are preserved, easing the destructiveHint=false concern. Minor gap: the return-shape sentence partly duplicates the existing output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then structured 'Use when' / 'Don't use when' blocks, then return and idempotency notes. Every sentence carries information; nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter write tool with full schema coverage and an output schema, the description covers the remaining gaps an agent needs: side effects (backups, replacement semantics), failure mode, and non-idempotency. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents key as a literal (not dotted) key, value as a full JSON replacement, and repo_path's temp-file/backup behavior. The description adds no parameter-level detail beyond what the schema states, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create or replace one top-level value in reforge-state.json via a staged write') and scopes it to a single top-level key, which distinguishes it from read_memory and from other writers in the sibling list. An agent can tell what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit 'Use when' condition (persisting hypothesis, fix log or pending work across sessions) and an explicit 'Don't use when' with the named alternative (read_memory for inspection). Both the positive and negative routing conditions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.4.5
    • Changedgenerate_changelog4 fields changed
      • addedInput schema / properties / repo_path / description
        Added value: +"Existing repository directory containing reforge-state.json and the output REFORGE_CHANGES.md; prefer an absolute path. Existing output is overwritten, and each successful call adds a fresh UTC timestamp."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "error": {
        +    "type": "string"
        +  },
        +  "path": {
        +    "type": "string"
        +  },
        +  "success": {
        +    "type": "boolean"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "success",
        +  "path"
        +]
    • Changedget_chunk6 fields changed
      • addedInput schema / properties / end_line / description
        Added value: +"Last line, 1-indexed and inclusive; default null reads through EOF. An inverted range returns the start line; values beyond EOF clamp to EOF."
      • addedInput schema / properties / file_path / description
        Added value: +"UTF-8 text file to read, e.g. /work/app/src/main.py. Relative paths resolve from the server working directory, not repo_root; the resolved file must remain inside repo_root. Binary/lock/minified files are skipped."
      • addedInput schema / properties / repo_root / description
        Added value: +"Repository boundary used to validate file_path. Default null uses the server working directory; prefer an absolute path, e.g. /work/app."
      • addedInput schema / properties / start_line / description
        Added value: +"First line, 1-indexed and inclusive; default 1. Values below 1 clamp to 1; a request beyond EOF returns the last line."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "end_line": {
        +    "type": "integer"
        +  },
        +  "error": {
        +    "type": "string"
        +  },
        +  "language": {
        +    "type": "string"
        +  },
        +  "source": {
        +    "type": "string"
        +  },
        +  "start_line": {
        +    "type": "integer"
        +  },
        +  "total_lines": {
        +    "type": "integer"
        +  }
        +}
    • Changedget_health_score4 fields changed
      • addedInput schema / properties / repo_path / description
        Added value: +"Existing repository directory to scan and persist health_history in reforge-state.json; prefer an absolute path, e.g. /work/app. Every call appends a UTC-timestamped entry and rotates state backups."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "breakdown": {
        +    "properties": {
        +      "circular_count": {
        +        "type": "integer"
        +      },
        +      "dead_code_ratio": {
        +        "type": "number"
        +      },
        +      "duplicate_ratio": {
        +        "type": "number"
        +      },
        +      "god_file_count": {
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "dead_code_ratio",
        +      "duplicate_ratio",
        +      "god_file_count",
        +      "circular_count"
        +    ],
        +    "type": "object"
        +  },
        +  "caveat": {
        +    "type": "string"
        +  },
        +  "coverage": {
        +    "type": "number"
        +  },
        +  "scan_summary": {
        +    "properties": {
        +      "imported_modules": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "languages_detected": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "parse_failures": {
        +        "type": "integer"
        +      },
        +      "total_classes": {
        +        "type": "integer"
        +      },
        +      "total_files": {
        +        "type": "integer"
        +      },
        +      "total_functions": {
        +        "type": "integer"
        +      },
        +      "total_imports": {
        +        "type": "integer"
        +      },
        +      "total_lines": {
        +        "type": "integer"
        +      },
        +      "unscanned_by_extension": {
        +        "additionalProperties": {
        +          "type": "integer"
        +        },
        +        "type": "object"
        +      },
        +      "unscanned_source_files": {
        +        "type": "integer"
        +      },
        +      "untracked_files_skipped": {
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "total_files",
        +      "total_functions",
        +      "total_lines",
        +      "languages_detected"
        +    ],
        +    "type": "object"
        +  },
        +  "score": {
        +    "anyOf": [
        +      {
        +        "type": "number"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "score",
        +  "coverage",
        +  "breakdown",
        +  "scan_summary"
        +]
    • Changedgit_commit9 fields changed
      • addedInput schema / properties / branch / description
        Added value: +"Branch name to check out before staging; default null stays on the current branch. Must exist unless create_branch is true."
      • addedInput schema / properties / confirmed / description
        Added value: +"Default false. Set true on retry after needs_confirmation is returned and the user approves. Does not bypass session_budget (default 20 commits); checkpoints default to every 5 commits via reforge.toml."
      • addedInput schema / properties / create_branch / description
        Added value: +"Default false. When true and branch is supplied, create and check out that branch; without branch this flag has no effect."
      • addedInput schema / properties / files / description
        Added value: +"Required nonempty list of files to stage, relative to repo_path or absolute within it; e.g. ['src/main.py']. Already staged changes are also included by Git's index commit; inspect the index first."
      • addedInput schema / properties / message / description
        Added value: +"Commit message; null (default) or an empty string uses 'refactor: automated fix #N', with N the next per-repository session count."
      • addedInput schema / properties / repo_path / description
        Added value: +"Git repository directory to commit in; prefer an absolute path, e.g. /work/app."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "branch": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "commit_hash": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "error": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "files_committed": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "message": {
        +    "type": "string"
        +  },
        +  "needs_confirmation": {
        +    "type": "boolean"
        +  },
        +  "success": {
        +    "type": "boolean"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "success",
        +  "commit_hash",
        +  "branch",
        +  "files_committed",
        +  "error"
        +]
    • Changedinfer_architecture4 fields changed
      • addedInput schema / properties / repo_path / description
        Added value: +"Repository directory to scan and save architecture_hypothesis in reforge-state.json; prefer an absolute path. Existing state backups rotate."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "confidence": {
        +    "type": "number"
        +  },
        +  "entry_points": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "evidence": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "hypothesis": {
        +    "type": "string"
        +  },
        +  "inferred_modules": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "pattern": {
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "pattern",
        +  "evidence",
        +  "entry_points",
        +  "inferred_modules",
        +  "confidence",
        +  "hypothesis"
        +]
    • Changedread_memory5 fields changed
      • addedInput schema / properties / key / description
        Added value: +"Top-level state key to read, e.g. architecture_hypothesis, fix_log, pending_fixes or health_history. Arbitrary strings are accepted; built-in default keys count as found even without a state file."
      • addedInput schema / properties / repo_path / description
        Added value: +"Directory containing reforge-state.json; prefer an absolute path. Missing/unreadable/invalid JSON state is replaced by in-memory defaults."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "found": {
        +    "type": "boolean"
        +  },
        +  "key": {
        +    "type": "string"
        +  },
        +  "value": {}
        +}
      • addedOutput schema / required
        Added value: +[
        +  "key",
        +  "value",
        +  "found"
        +]
    • Changedscan_repo6 fields changed
      • addedInput schema / properties / include_tests / description
        Added value: +"Defaults to true. Currently accepted for compatibility but does not filter test files: both true and false include them."
      • addedInput schema / properties / languages / description
        Added value: +"Optional case-insensitive language filter: python, javascript, typescript, go, kotlin. Default null (or []) scans all supported languages; unknown names are ignored. Example: ['python', 'typescript']."
      • addedInput schema / properties / root_path / description
        Added value: +"Existing source directory to scan; prefer an absolute path, e.g. /work/app. Relative paths resolve from the server working directory."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "dead_code": {
        +    "items": {
        +      "properties": {
        +        "file": {
        +          "type": "string"
        +        },
        +        "line": {
        +          "type": "integer"
        +        },
        +        "symbol": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "symbol",
        +        "file",
        +        "line"
        +      ],
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "dead_code_total": {
        +    "type": "integer"
        +  },
        +  "dep_graph": {
        +    "properties": {
        +      "circular": {
        +        "items": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "type": "array"
        +      },
        +      "circular_total": {
        +        "type": "integer"
        +      },
        +      "edges": {
        +        "items": {
        +          "properties": {
        +            "from": {
        +              "type": "string"
        +            },
        +            "to": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "from",
        +            "to"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "edges_total": {
        +        "type": "integer"
        +      },
        +      "external_imports": {
        +        "type": "integer"
        +      },
        +      "nodes": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "nodes_total": {
        +        "type": "integer"
        +      },
        +      "package_imports": {
        +        "type": "integer"
        +      },
        +      "unresolved_relative_imports": {
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "nodes",
        +      "edges",
        +      "circular"
        +    ],
        +    "type": "object"
        +  },
        +  "duplicates": {
        +    "items": {
        +      "properties": {
        +        "hash": {
        +          "type": "string"
        +        },
        +        "locations": {
        +          "items": {
        +            "properties": {
        +              "file": {
        +                "type": "string"
        +              },
        +              "line": {
        +                "type": "integer"
        +              },
        +              "name": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "file",
        +              "line",
        +              "name"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "locations_total": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "hash",
        +        "locations"
        +      ],
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "duplicates_total": {
        +    "type": "integer"
        +  },
        +  "error": {
        +    "type": "string"
        +  },
        +  "god_files": {
        +    "items": {
        +      "properties": {
        +        "exports": {
        +          "type": "integer"
        +        },
        +        "file": {
        +          "type": "string"
        +        },
        +        "lines": {
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "file",
        +        "lines",
        +        "exports"
        +      ],
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "god_files_total": {
        +    "type": "integer"
        +  },
        +  "subprojects": {
        +    "items": {
        +      "properties": {
        +        "language": {
        +          "type": "string"
        +        },
        +        "root": {
        +          "type": "string"
        +        },
        +        "test_command": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "root",
        +        "language",
        +        "test_command"
        +      ],
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "subprojects_total": {
        +    "type": "integer"
        +  },
        +  "summary": {
        +    "properties": {
        +      "imported_modules": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "languages_detected": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "parse_failures": {
        +        "type": "integer"
        +      },
        +      "total_classes": {
        +        "type": "integer"
        +      },
        +      "total_files": {
        +        "type": "integer"
        +      },
        +      "total_functions": {
        +        "type": "integer"
        +      },
        +      "total_imports": {
        +        "type": "integer"
        +      },
        +      "total_lines": {
        +        "type": "integer"
        +      },
        +      "unscanned_by_extension": {
        +        "additionalProperties": {
        +          "type": "integer"
        +        },
        +        "type": "object"
        +      },
        +      "unscanned_source_files": {
        +        "type": "integer"
        +      },
        +      "untracked_files_skipped": {
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "total_files",
        +      "total_functions",
        +      "total_lines",
        +      "languages_detected"
        +    ],
        +    "type": "object"
        +  },
        +  "truncated": {
        +    "additionalProperties": {
        +      "type": "integer"
        +    },
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "summary",
        +  "dead_code",
        +  "duplicates",
        +  "god_files",
        +  "dep_graph"
        +]
    • Changedscore_risk6 fields changed
      • addedInput schema / properties / file / description
        Added value: +"Repository-relative file path exactly as reported by scan_repo, e.g. src/pricing.py. Use native separators or forward slashes; absolute paths do not match the scan's relative paths. Used for file size and cycles."
      • addedInput schema / properties / repo_path / description
        Added value: +"Repository directory to rescan with per-file symbol references enabled; prefer an absolute path. No source or state files are written."
      • addedInput schema / properties / symbol / description
        Added value: +"Exact case-sensitive unqualified symbol name, e.g. calculate_discount. Matches AST reference names across files, not fully resolved symbols; the implementation does not validate that the symbol exists."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "basis": {
        +    "type": "string"
        +  },
        +  "breakdown": {
        +    "properties": {
        +      "has_tests": {
        +        "type": "integer"
        +      },
        +      "inbound_refs": {
        +        "type": "integer"
        +      },
        +      "is_circular": {
        +        "type": "integer"
        +      },
        +      "lines_changed": {
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "inbound_refs",
        +      "has_tests",
        +      "lines_changed",
        +      "is_circular"
        +    ],
        +    "type": "object"
        +  },
        +  "recommendation": {
        +    "type": "string"
        +  },
        +  "referenced_by": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "score": {
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "score",
        +  "breakdown",
        +  "basis",
        +  "referenced_by",
        +  "recommendation"
        +]
    • Changedwrite_fix8 fields changed
      • addedInput schema / properties / allowed_test_commands / description
        Added value: +"Command-prefix allowlist; a nonempty list replaces the built-in list. Default null (or []) uses built-ins such as pytest, python -m pytest, npm test and go test. Prefixes match complete shell-split tokens; command chaining remains rejected."
      • addedInput schema / properties / diff_str / description
        Added value: +"Single-file unified diff with @@ -old_start,old_count +new_start,new_count @@ hunks (1-indexed lines). Context and removed lines must match the file at the stated positions; a mismatched patch is rejected."
      • addedInput schema / properties / file_path / description
        Added value: +"Existing file to patch, e.g. /work/app/src/main.py; must remain within repo_root. Relative paths resolve from the server working directory."
      • addedInput schema / properties / repo_root / description
        Added value: +"Repository boundary and test-command working directory; default null uses the server working directory. Prefer an absolute path."
      • addedInput schema / properties / test_command / description
        Added value: +"Optional allowlisted test command, e.g. pytest or npm test. Default null skips tests. Runs without a shell from repo_root, with closed stdin and a 120-second timeout; test failure triggers file rollback."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "backup": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "error": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "git_state": {
        +    "type": "string"
        +  },
        +  "rolled_back": {
        +    "type": "boolean"
        +  },
        +  "success": {
        +    "type": "boolean"
        +  },
        +  "test_output": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "success",
        +  "test_output",
        +  "error",
        +  "rolled_back"
        +]
    • Changedwrite_memory6 fields changed
      • addedInput schema / properties / key / description
        Added value: +"Top-level state key to create or replace; arbitrary strings are accepted, e.g. pending_fixes. This is a literal key, not a dotted path."
      • addedInput schema / properties / repo_path / description
        Added value: +"Existing directory containing reforge-state.json; prefer an absolute path. Writes through reforge-state.tmp, replaces the state file and rotates up to five timestamped backups; other top-level keys are preserved."
      • addedInput schema / properties / value / description
        Added value: +"Required JSON value to store: object, array, string, number, boolean or null. Replaces the entire value at key rather than merging/appending. Example for pending_fixes: ['split handlers.py']."
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "error": {
        +    "type": "string"
        +  },
        +  "key": {
        +    "type": "string"
        +  },
        +  "previous_value": {},
        +  "success": {
        +    "type": "boolean"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "success",
        +  "key",
        +  "previous_value"
        +]
  2. 1 tool updatev0.4.3
    • Changedscan_repo1 field changed
      • removedInput schema / properties / max_depth
        Removed value: -{
        -  "default": 10,
        -  "type": "integer"
        -}
  3. 20 tool updatesv0.2.9
    • Addedgenerate_changelog
    • Removedgenerate_changelog_tool
    • Addedget_chunk
    • Removedget_chunk_tool
    • Addedget_health_score
    • Removedget_health_score_tool
    • Addedgit_commit
    • Removedgit_commit_tool
    • Addedinfer_architecture
    • Removedinfer_architecture_tool
    • Addedread_memory
    • Removedread_memory_tool
    • Addedscan_repo
    • Removedscan_repo_tool
    • Addedscore_risk
    • Removedscore_risk_tool
    • Addedwrite_fix
    • Removedwrite_fix_tool
    • Addedwrite_memory
    • Removedwrite_memory_tool
  4. 10 tool updatesv0.1.0
    • First observedgenerate_changelog_tool
    • First observedget_chunk_tool
    • First observedget_health_score_tool
    • First observedgit_commit_tool
    • First observedinfer_architecture_tool
    • First observedread_memory_tool
    • First observedscan_repo_tool
    • First observedscore_risk_tool
    • First observedwrite_fix_tool
    • First observedwrite_memory_tool

TDQS

A4.4/5.0

Scored across 10 tools

Disambiguation5/5

Every tool has an explicit 'Use when' / 'Don't use when' clause that names the alternative tool to use instead, e.g. scan_repo vs get_chunk, write_fix vs git_commit, read_memory vs write_memory, score_risk vs get_health_score. Boundaries are crisp even for near-neighbors like infer_architecture (which writes state) and read_memory (which only reads it).

Naming Consistency4/5

Names overwhelmingly follow a snake_case verb_noun pattern (scan_repo, get_chunk, write_fix, read_memory, score_risk, generate_changelog). The only minor deviation is git_commit, which uses a resource prefix rather than a leading verb, but it remains readable and predictable.

Tool Count5/5

Ten tools is well within the ideal range and each maps to a distinct step in a repo-cleanup workflow (scan, inspect, patch, commit, persist state, infer, score, report). No tool feels redundant or padded.

Completeness4/5

The surface covers the full lifecycle: scan_repo discovers findings, get_chunk inspects, write_fix patches, git_commit records, memory tools persist, and scoring/reporting tools close the loop. Minor gaps exist — no standalone test-runner or revert/undo tool, and tests only run bundled inside write_fix — but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    An MCP server that connects Gemini 2.5 Pro to Claude Code, enabling users to generate detailed implementation plans based on their codebase and receive feedback on code changes.
    5
    14
    -
  • A
    license
    A
    quality
    B
    maintenance
    A local MCP server that lets Claude delegate scoped work to Codex with structured results and guardrails, supporting planning, code review, build, reverse engineering, and long-running background tasks.
    11
    MIT