mdgraph
mdgraph
Scan a repo's markdown into a graph, visualize it in the browser, and expose it to Claude (or any MCP host) as a navigation index.
One data model — { nodes, edges } — with three consumer(s):
scan (the only hard part)
│ emits { nodes, edges }
┌──────────┼───────────┐
▼ ▼ ▼
graph.json browser MCP server
(a file) (viewer) (agents read it)Insights, reachability, and orphans are all derived from the model at read time. Nodes and edges stay dumb.
The model
node = { id, label, path, type, cluster, content } // type: root | ai | doc
edge = { source, target, sourceLine, context } // context = the line the link lives ontype is assigned by filename convention (README.md → root, CLAUDE.md/AGENTS.md/*.mdc → ai, else doc). Edges come from actual links in the text — standard [x](./y.md) and [[wikilinks]] — not folder membership, so a file in docs/ that links across the tree still connects across the tree. Folders only drive cluster (coloring/grouping).
Install & run
No install needed — run it straight with npx:
npx @emmd474/mdgraph scan . # print the graph as JSON
npx @emmd474/mdgraph view . # open the interactive graph in a browser
npx @emmd474/mdgraph scan . --out graph.jsonOr install globally to get a plain mdgraph command:
npm install -g @emmd474/mdgraph
mdgraph view ./my-repo
mdgraph scan ./my-repo --out graph.jsondir defaults to the current directory. view takes --port (default 4173).
Commands
Command | What it does |
| Build the graph, print JSON to stdout (or write with |
| Serve the interactive graph at |
| Run the MCP server over stdio, for Claude and other agents. |
Expose to Claude (MCP)
Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"mdgraph": {
"command": "npx",
"args": ["-y", "@emmd474/mdgraph", "mcp", "/abs/path/to/your/repo"]
}
}
}Claude Code:
claude mcp add mdgraph -- npx -y @emmd474/mdgraph mcp /abs/path/to/your/repoRestart the host and Claude gets four tools:
Tool | Purpose |
| Content-free overview: types, clusters, link counts, orphan/reachable flags, edges. The cheap way to orient. |
| Raw markdown of one doc by path. |
| Everything reachable from an entry doc, in read order — the exact set to load to understand it. |
| Docs nothing links to. |
The point: an agent calls get_project_map to orient, then get_context("README.md") to pull only the docs the task needs — instead of dumping every .md into context.
Publishing (for maintainers)
The name mdgraph is taken on npm, so this publishes scoped under your account:
# 1. set the scope to YOUR npm username (edit "name" in package.json if not @emmd474)
npm whoami # confirm you're logged in; else: npm login
npm publish --access publicScoped packages are private by default, so --access public is required the first time. To ship an update, bump the version and publish again:
npm version patch # 0.1.0 -> 0.1.1, also creates a git tag
npm publishnpm pack --dry-run shows exactly what ships (currently 7 files, ~16 kB — no node_modules, no test repo, thanks to the files allowlist).
Try it on the example
git clone <this repo> && cd mdgraph && npm install
node cli.mjs view testrepo
node cli.mjs scan testrepoWhat's real vs. next
Tested and working: the scanner (md + wikilink extraction, code-fence skipping, convention typing, orphan detection), the browser viewer, and all four MCP tools over a live stdio handshake.
Next, roughly in order:
Harden link parsing — the scanner is line-based and skips fenced blocks, but an inline code span (
`[x](y)`) can still yield a false link. Swap in a real markdown AST (remark+unist-util-visit) when you want precision; the emitted shape stays identical.Manual edges — let the viewer write
related:into a file's frontmatter, read as a third edge source.Frontmatter tags as a cluster source alongside folders.
--watchonviewto push graph updates over server-sent events.
MIT licensed.