FlowMCP

FlowMCP

Turns a codebase into business-language flow diagrams that an AI can read and edit, enabling natural language querying and modification of system architecture.

Category
访问服务器

README

FlowMCP

An MCP server that turns a codebase into business-language flow diagrams an AI can read and edit.

Ask "how does login work?" and get this — not a list of files:

flowchart TD
  n0["POST Login"]
  n1["Authenticate User"]
  n2{"The submitted password matches the stored hash?"}
  n3(["Success"])
  n4(["Failure"])
  n5["Check Password"]
  n6["Bcrypt Compare"]
  n7["Find User By Email"]
  n0 --> n1
  n1 -.-> n5
  n1 --> n2
  n2 -->|yes| n3
  n2 -->|no| n4
  n5 --> n6
  n5 -.-> n7

Then say "insert an OTP step before the password check" and the diagram changes — and stays changed when the code is re-indexed.


Why it exists

An AI assistant reasoning about a system reads raw source files. That is expensive, lossy, and gets worse as the repo grows. FlowMCP builds an architecture graph once, keeps it correct as code changes, and serves flows from it. The graph — not the file tree — becomes what the assistant reasons over.

The server contains no language model. It is a deterministic extractor, a graph store, and a renderer. The calling AI supplies the business language and the server persists it. That is not a cost optimisation: it removes an entire class of failure where two models disagree about what a node means. There is one interpreter of intent, and it is already in the conversation with you.


Requirements

  • Node 24+ (developed on 26). TypeScript runs natively via type-stripping — there is no build step.
  • Nothing else. SQLite is stdlib.

Install

git clone <this repo>
cd FlowMCP
npm install     # also copies the tree-sitter grammars into grammars/

Verify:

npm test          # 111 tests
npx tsc --noEmit  # typecheck

Register it with your client

FlowMCP indexes one project per server instance. The project path is argv[2], falling back to the working directory.

Claude Code:

claude mcp add flowmcp -- node /abs/path/to/FlowMCP/src/index.ts /abs/path/to/your-project

Claude Desktop — in claude_desktop_config.json:

{
  "mcpServers": {
    "flowmcp": {
      "command": "node",
      "args": [
        "/abs/path/to/FlowMCP/src/index.ts",
        "/abs/path/to/your-project"
      ]
    }
  }
}

Use absolute paths. A wrong root silently indexes nothing.

The graph is written to <your-project>/.flowmcp/graph.db. Add .flowmcp/ to that project's .gitignore.


Tutorial

Everything below is what you'd actually say to the AI, followed by the tool it reaches for. You never call these by hand.

1. Index the codebase

"Index this project."

analyze_codebase { }                          // or { "path": "...", "force": true }
{
  "filesScanned": 4, "filesParsed": 4, "filesSkipped": 0,
  "nodes": 7, "edges": 5,
  "unresolvedCalls": 7, "lowConfidenceEdges": 2,
  "durationMs": 67
}

Incremental by content hash — re-running only re-parses files that changed. force: true rebuilds everything derived, and never touches your annotations or edits.

Read the last two numbers. They tell you how much of this graph is inference rather than fact.

2. Ask for a flow

"Show me the login flow."

generate_diagram { "query": "login" }

Matching is full-text over code names, route paths, and any business titles you've written — so once a node is titled Authenticate User, asking for "authentication" finds it even though the code says login.

Reading the diagram

shape meaning
["Step"] a step
{"Condition?"} a decision
(["Outcome"]) a terminal — where the flow ends
--> solid the code definitely does this
-.-> dotted a heuristic guess

Dotted edges matter. Without a type checker, calls through dependency injection (this.authService.verify()) are resolved by naming convention. That is usually right and sometimes wrong, and the diagram says which is which rather than presenting a guess as fact.

3. Give steps business names

This is the step that makes the tool worth using.

"Rename these to business language: the controller is 'Authenticate User', the service method is 'Check Password'."

annotate_nodes {
  "annotations": [
    { "node_key": "controller:src/controllers/auth.controller.ts:AuthController.login",
      "title": "Authenticate User",
      "description": "Takes the submitted email and password." },
    { "node_key": "service:src/services/auth.service.ts:AuthService.verify",
      "title": "Check Password" }
  ]
}

Titles are durable. They survive every future re-index, because they live in a layer that re-indexing never rebuilds. Write them once.

Unannotated nodes fall back to a humanised code name (findByEmailFind By Email), and every node reports whether it was annotated or humanised, so the AI can see what still needs naming.

4. Edit the flow in plain English

"Insert a 'Send OTP' step before Check Password."

edit_diagram {
  "note": "Insert Send OTP before Check Password",
  "ops": [{
    "op": "insert_node",
    "payload": {
      "position": "before",
      "anchor": "service:src/services/auth.service.ts:AuthService.verify",
      "node": { "title": "Send OTP", "type": "service" }
    }
  }]
}

Callers are rewired through the new step automatically. Ask for the diagram again and it's there.

Nine operations are available: insert_node, delete_node, rename_node, describe_node, connect, disconnect, merge_nodes, split_node, set_layout. Every one records the sentence that produced it in note, so the edit log reads as a history of intent.

5. Change the code, keep the diagram

"The code changed — resync."

sync_architecture { }

Re-parses changed files, replays your edits on top, and reports drift:

category meaning
orphaned_op an edit points at code that no longer exists
unimplemented a step you drew that has no code behind it yet
stale_annotation a named node's source changed since you named it
ambiguous_rename one symbol vanished and a similar one appeared — possibly renamed

Nothing auto-resolves. An orphaned edit is kept, not dropped — the code may come back, or you may want to re-anchor it. Resolution is your decision, expressed as new edits.

6. Explore

search_architecture { "query": "password", "kind": "service", "limit": 10 }
trace              { "from": "<node_key>", "direction": "forward" }   // or "backward"
get_node           { "node_key": "..." }
get_architecture   { "scope": "src/auth" }

trace forward is the execution path; backward finds everything that depends on a node — the "what breaks if I change this" question.

7. Audit the graph before trusting it

"What's wrong with this architecture?"

diagnose { }    // or { "checks": ["cycles", "unresolved_calls"] }

Six checks: orphans, cycles, dead_flows, low_confidence, unresolved_calls, drift.

Two of them are about the graph's own honesty:

  • low_confidence — edges that exist but were guessed.
  • unresolved_calls — calls the extractor saw and could not attribute at all. No edge was drawn, so the diagram is incomplete there. This is the difference between "this function calls nothing" and "we couldn't work out what it calls", and without this check the second one is invisible.

diagnose reports. It never fixes anything.

8. Export and round-trip

export_diagram { "flow": "login", "format": "markdown", "path": "/abs/path/login.md" }

Six formats: mermaid, markdown (diagram + a prose table), json, plantuml, drawio, excalidraw. The last two honour set_layout positions; Mermaid auto-layouts and ignores them.

You can also edit the exported text by hand and feed it back:

import_diagram { "content": "<edited mermaid>", "format": "mermaid" }

Renames, insertions and removed edges become overlay operations — never direct writes to the derived graph. Exports embed an invisible %% flowmcp:node <id> <key> block so nodes are matched by identity; retyped diagrams fall back to matching by title, and anything ambiguous becomes an insert rather than a guess.


Tool reference

tool arguments
analyze_codebase path? force?
get_flow query depth? save_as?
generate_diagram query mode? format? depth?
annotate_nodes annotations[]{node_key, title, description?}
edit_diagram ops[] note?
sync_architecture
search_architecture query kind? limit?
trace from direction depth?
get_node node_key
get_architecture scope?
diagnose checks?
export_diagram flow format path?
import_diagram content format flow? note?

Diagram modes: business (default — titles only, no filenames, no syntax), system, api, dependency. sequence, database and state are declared but not implemented; they fail loudly rather than silently substituting.


How it works

code ──scan/parse──▶ derived layer    (disposable; rebuilt every index)
                          +
                     overlay log      (append-only; never rebuilt)
                          ▼
                     effective graph  (what every tool reads)

The derived layer is a pure function of your source tree. The overlay is an ordered log of your edits. Everything you read is the two composed.

That is why analyze_codebase is always safe to re-run: it cannot destroy your work, because your work does not live in the layer it rebuilds.

Nodes are keyed {kind}:{path}:{qualified_name} — never line numbers, so an edit above a function doesn't detach anything anchored to it.

Confidence ladder

confidence how the call was resolved
1.0 same file, this.method(), a relative import, new Cls(), or a package import
0.7 member call narrowed to one file by a relative import
0.6 this.field.method() — dependency injection, matched by naming convention
0.5 last resort: exactly one node repo-wide has that name
no edge more than one candidate, or none — recorded as an unresolved call

Languages

TypeScript/JavaScript, Python, Go, Java, C#, PHP.

Frameworks detected from your manifests (package.json, requirements.txt, pyproject.toml, go.mod, pom.xml, build.gradle, *.csproj, composer.json): Express, Fastify, NestJS, Koa, Hono, FastAPI, Flask, Django, Gin, Echo, Chi, net/http, Spring, JAX-RS, ASP.NET Core, Laravel, Symfony, Slim.

Adding a language is one file in src/packs/ plus one line in the registry.

Known limits

Read these before trusting a diagram on a large codebase.

  1. Call resolution is heuristic. Dynamic dispatch, DI containers and interface polymorphism produce gaps. Surfaced through edge confidence and unresolved_calls — never hidden.
  2. Interface-heavy C#/Java lose edges. IAuthService.Verify alongside AuthService.Verify is ambiguous, so no edge is drawn.
  3. Node identity depends on names. Renaming a symbol detaches edits targeting it; reported as ambiguous_rename, never auto-resolved, because auto-resolving a wrong guess silently corrupts the log.
  4. Some routing is detected but not read: Django's urlpatterns, JAX-RS split @GET/@Path, and Spring class-level @RequestMapping prefixes.
  5. Import can't carry everything. Edge kinds, descriptions, and merge/split aren't round-tripped; decision and terminal nodes are computed per-read and can't be addressed by an edit.
  6. Parsing is single-threaded. Fine for normal repos; a worker pool is the upgrade path.
  7. Flow seeding is lexical. A flow whose vocabulary appears nowhere in code or annotations needs annotating first, or an explicit seed.

Development

npm test          # node:test, no framework
npx tsc --noEmit  # typecheck only; there is no build
src/db/        schema, connection, all SQL
src/scan/      file walking and hashing
src/extract/   tree-sitter extraction and call resolution
src/packs/     one file per language
src/graph/     flow computation, overlay replay, drift
src/render/    one file per output format
src/tools/     one thin file per MCP tool
test/fixtures/ a small app per language, each with an EXPECTED.md

Architecture rationale lives in docs/superpowers/specs/2026-07-29-flowmcp-design.md.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选