mcp-flow
A safe, local MCP server that lets Claude drive a controlled software-development loop (inspect, read, plan, patch, apply, check, analyze, fix, summarize) on a project, using deterministic tools and real diffs/test runs.
README
mcp-flow
A safe, local MCP server that lets Claude (or any MCP client) drive a controlled software-development loop on a project on your machine:
inspect → read → plan → patch → apply → check → analyze → fix-loop → summarize
The goal is simple: after every model turn, the code stays understandable, tested, reviewed, and corrected — through real diffs, real test/lint/typecheck runs, and an iterative fix loop, all behind hard safety rails.
- SDK:
@modelcontextprotocol/sdk^1.29.0 - Runtime: Node.js ≥ 18 (developed and tested on Node 22)
- Language: TypeScript (strict), ESM
- Transport: stdio (works with Claude Desktop, Cursor, and any standard MCP client)
1. What it does
mcp-flow exposes 10 tools:
| Tool | Purpose | Writes to disk? |
|---|---|---|
inspect_project |
Analyze structure: tree, stack(s), package manager, scripts, tests, linter/typechecker, config files. | No |
read_relevant_files |
Read only the files relevant to a task (explicit list or lexical ranking), truncated & secret-masked. | No |
create_change_plan |
Assemble a structured plan (likely files, steps, risks, checks to run) from deterministic context. | No |
generate_patch |
Turn concrete edits into a guaranteed-valid unified diff. Without edits, returns a generation brief. |
No |
apply_patch |
Apply a unified diff. Dry-run by default, path-confined, mass-deletion-guarded, backups before writing. | Yes (only when dryRun:false) |
run_project_checks |
Auto-detect and run test / lint / typecheck / build using allowlisted commands with timeouts. |
No |
analyze_check_failures |
Parse compiler/linter/test output into structured issues (file, line, code, priority) + fix guidance. | No |
fix_loop |
Controlled verify→analyze→fix loop, up to maxIterations. Closes the loop when the client supports sampling. |
Yes (only when allowApply:true) |
git_status |
Branch, staged/modified/untracked files, last commit, clean/dirty. | No |
summarize_changes |
User + technical summary, suggested conventional-commit message, checks performed, limitations. | No |
How the "thinking" tools work (important)
An MCP server is not a language model. So mcp-flow is deliberately honest
about the split of work:
- Deterministic tools do real work locally: scan the filesystem, build and apply diffs, run checks, parse errors, read git. These never need an LLM.
create_change_plan,generate_patch(brief mode),analyze_check_failures,summarize_changesassemble precise, structured context and hand the reasoning back to the calling model (Claude). They never fabricate code from a non-existent embedded model.generate_patchbecomes fully deterministic the moment you give itedits: it converts your intended changes into a clean unified diff thatapply_patchis guaranteed to accept.fix_loopruns the deterministic verify/analyze cycle. If the connected client supports the optional MCP sampling capability (sampling/createMessage), it asks the client's own model for corrective edits and applies them automatically. If the client does not support sampling (some desktop clients don't),fix_loopreturns a precise advisory with the next actions, and the orchestrating assistant drives the loop by calling the other tools — which Claude does naturally.
This design means the server is safe, deterministic where it matters, and never lies about having capabilities it doesn't.
2. What it does not do
- It does not run arbitrary shell commands. Only an allowlist of base
executables (npm/pnpm/yarn/bun/npx/node, tsc/vitest/jest/eslint/biome/prettier,
python/pytest/ruff/mypy, git) can ever be spawned, with
shell: false. - It does not touch anything outside the
projectPathyou give it. - It does not run destructive commands (
rm -rf,sudo,chmod -R,curl | bash,git push --force,git reset --hard, fork bombs, …). - It does not read
.envand other sensitive files unless you explicitly passallowSensitive: true. - It does not apply patches by default —
apply_patchis dry-run unless you setdryRun: false. - It does not embed or call any external LLM on its own.
3. Install
git clone <your-fork-or-path> "mcp flow"
cd "mcp flow"
npm install
4. Build
npm run build # compiles src/ -> dist/ with tsc
npm run typecheck # tsc --noEmit (strict)
npm test # vitest run (unit tests)
Quick manual run (it speaks MCP over stdio and waits for a client):
npm start # node dist/index.js
# or, without building, for development:
npm run dev # tsx src/index.ts
5. Add it to Claude Desktop
Build first (npm run build), then edit your Claude Desktop config:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add an entry (see claude_desktop_config.example.json):
{
"mcpServers": {
"mcp-flow": {
"command": "node",
"args": ["/absolute/path/to/mcp flow/dist/index.js"]
}
}
}
Restart Claude Desktop. You should see the mcp-flow tools appear.
Cursor / other MCP clients
Any client that supports stdio MCP servers works. Point it at
node /absolute/path/to/mcp flow/dist/index.js. Clients that implement the
sampling capability unlock fully-autonomous fix_loop; others use it in
advisory mode.
6. Example prompts
Once connected, talk to Claude normally — it will pick the right tools:
- “Analyse ce projet et dis-moi comment il est structuré.”
→
inspect_project - “Ajoute une route API pour créer un utilisateur, puis lance les tests.”
→
create_change_plan→read_relevant_files→generate_patch→apply_patch→run_project_checks - “Corrige les erreurs TypeScript jusqu’à ce que le typecheck passe.”
→
run_project_checks(typecheck) →analyze_check_failures→fix_loop - “Implémente cette fonctionnalité, applique le patch, lance lint et tests,
puis résume les changements.”
→ full chain ending in
summarize_changes - “Fais une revue du diff actuel et propose un patch correctif.”
→
git_status→analyze_check_failures→generate_patch
A typical safe sequence Claude follows:
inspect_project(projectPath)
read_relevant_files(projectPath, taskDescription)
create_change_plan(projectPath, taskDescription)
generate_patch(projectPath, taskDescription, edits=[…]) # real unified diff
apply_patch(projectPath, patch, dryRun=true) # validate
apply_patch(projectPath, patch, dryRun=false) # apply + backup
run_project_checks(projectPath, checks=["test","lint","typecheck"])
analyze_check_failures(projectPath, checkResults=…) # if anything failed
# …iterate generate_patch/apply_patch until green…
summarize_changes(projectPath, checkResults=…)
7. Security rules (enforced in code)
All of these live in src/core/security.ts and are
covered by tests in tests/security.test.ts:
- Path confinement: every path is normalized and must resolve inside
projectPath. Traversal (../…), absolute escapes, and symlink escapes are rejected with a clear error. - Command allowlist: only known base executables run; everything else is
refused. Commands run with
shell: false(no interpolation), and arguments containing shell metacharacters (; & | \$ > <` …) are rejected. - Dangerous-command blocklist:
rm -rf,sudo, recursivechmod/chown,mkfs,dd if=,curl|bash, force-push, hard-reset, fork bombs, etc. - Mass-deletion guard: a patch that removes a huge number of lines while adding none, or deletes many files at once, is refused.
- Backups:
apply_patchcopies every touched file into.mcp-flow-backups/<timestamp>/before writing (unlesscreateBackup:false). - Sensitive files:
.env, keys,credentials,secrets.*are skipped unlessallowSensitive:true..env.example/.sample/.templateare allowed. - Secret masking: output is scrubbed for
KEY=…secrets, provider tokens (sk-…,ghp_…, AWSAKIA…, GoogleAIza…), JWTs, and PEM private keys. - Bounded everything: per-file read size, aggregate read budget, per-stream output size, and per-command timeout are all capped.
- No crashes: every tool catches its errors and returns a clean error result instead of taking the server down.
8. Known limitations
- Reasoning lives in the client.
mcp-flowstructures and validates work; it does not invent code by itself. Patch quality depends on the model driving it. - Autonomous
fix_looprequires client sampling support. Without it, the loop runs deterministically and returns precise next actions for the assistant to execute. (Claude follows these naturally.) - Check detection is heuristic. It covers common Node and Python setups well;
Rust/Go/PHP are detected but only get a
build/testmapping where obvious. You can always pass an explicitpackageManagerorcheckslist. apply_patchuses exact-context matching. If a file changed since the diff was generated, application fails with a clear message rather than guessing.- Patches are content-based, not git-blob-based: renames are modeled as delete + create.
9. Roadmap
- Optional
outputSchema/structuredContentfor clients that prefer it. - Resource endpoints (expose the scan / last diff as MCP resources).
- Smarter relevance ranking (symbol/import graph instead of lexical only).
- Configurable allowlist and limits via env vars.
- Rename/move detection in
generate_patch. - Pluggable check adapters for more ecosystems (Rust
cargo, Gogo test, etc.).
Project layout
src/
index.ts # MCP entrypoint: registers all 11 tools over stdio
types.ts # shared result/structure types
core/
security.ts # path confinement, allowlist, masking, limits
walk.ts # bounded, ignore-aware directory walking
projectScanner.ts # stack / pm / scripts / tests / config detection
fileReader.ts # task-aware, bounded, masked file reading
patchManager.ts # unified-diff build + safe apply (backups, guards)
commandRunner.ts # safe spawn (no shell, timeout, bounded output)
checkDetector.ts # map test/lint/typecheck/build -> concrete commands
failureAnalyzer.ts # parse tsc/eslint/ruff/mypy/pytest output
git.ts # read-only git status & diff
sampling.ts # optional MCP sampling for autonomous fix_loop
toolResult.ts # uniform ok()/fail() result helpers
tools/ # one file per tool, each exports register<Tool>()
tests/ # vitest unit tests (+ helpers)
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.