Skip to main content
Glama
README.md
# 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`](https://www.npmjs.com/package/@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_changes`** assemble precise, structured context and hand the
  *reasoning* back to the calling model (Claude). They never fabricate code from
  a non-existent embedded model.
- **`generate_patch`** becomes fully deterministic the moment you give it
  `edits`: it converts your intended changes into a clean unified diff that
  `apply_patch` is guaranteed to accept.
- **`fix_loop`** runs 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_loop` returns 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 `projectPath` you 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 `.env` and other sensitive files unless you explicitly
  pass `allowSensitive: true`.
- It does **not** apply patches by default — `apply_patch` is dry-run unless you
  set `dryRun: false`.
- It does **not** embed or call any external LLM on its own.

---

## 3. Install

```bash
git clone <your-fork-or-path> "mcp flow"
cd "mcp flow"
npm install
```

## 4. Build

```bash
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):

```bash
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`](./claude_desktop_config.example.json)):

```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`](./src/core/security.ts) and are
covered by tests in [`tests/security.test.ts`](./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`, recursive `chmod`/`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_patch` copies every touched file into
  `.mcp-flow-backups/<timestamp>/` before writing (unless `createBackup:false`).
- **Sensitive files:** `.env`, keys, `credentials`, `secrets.*` are skipped
  unless `allowSensitive:true`. `.env.example`/`.sample`/`.template` are allowed.
- **Secret masking:** output is scrubbed for `KEY=…` secrets, provider tokens
  (`sk-…`, `ghp_…`, AWS `AKIA…`, Google `AIza…`), 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-flow` structures and validates work; it
  does not invent code by itself. Patch *quality* depends on the model driving it.
- **Autonomous `fix_loop` requires 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`/`test` mapping where obvious.
  You can always pass an explicit `packageManager` or `checks` list.
- **`apply_patch` uses 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` / `structuredContent` for 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`, Go `go 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

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct stage of the development workflow: inspection, reading relevant files, planning, patch generation, patch application, running checks, analysis, automated fixing, git status, and summarization. Even the similar tools like inspect_project and read_relevant_files are cleanly separated by content vs. structure, and generate_patch vs. apply_patch are clearly distinguished as generate vs. apply.

Naming Consistency4/5

Most tool names follow a consistent verb_noun pattern (inspect_project, read_relevant_files, create_change_plan, generate_patch, apply_patch, run_project_checks, analyze_check_failures, fix_loop, summarize_changes). The only exception is git_status, which uses a noun phrase rather than an imperative verb, slightly breaking the pattern.

Tool Count5/5

With 10 tools, the server is within the ideal 3-15 range. Each tool has a clear and non-redundant role, covering the full lifecycle from initial inspection through planning, editing, verification, iteration, and summarization without unnecessary overlap.

Completeness4/5

The tool surface covers the core development workflow comprehensively: read-only exploration, planning, patch creation and application, running checks, analyzing failures, an automated fix loop, git status, and change summarization. The main gap is the lack of an explicit rollback or revert tool, though apply_patch does back up files, and a commit tool is intentionally absent since committing is a separate concern.

Maintenance

ActivityInactive
ResponsivenessNo issues