Peckboard Graphify

Peckboard Graphify

Enables agents to build and query code knowledge graphs for repositories in a folder — finding shortest paths between concepts, explaining concepts with neighbours and community context, and visualizing per-repo graphs through MCP tools.

Category
访问服务器

README

Peckboard Graphify plugin

A Peckboard WASM plugin that turns each repo in a folder into a queryable knowledge graph, hands that graph to the agent as MCP tools, and ships a per-repo visualizer.

  • Deterministic buildsgraphify's tree-sitter AST pass plus its cross-file call-graph second pass. No LLM, no network, no tokens spent.
  • MCP tools — the agent builds a graph, walks the shortest path between two concepts, and explains one concept with its neighbours, community, and centrality.
  • A session system prompt — every session in the folder is told the graph exists, how big it is, and when querying it beats opening files.
  • Off until you say otherwise — a folder carries a Graphify switch, and each repo inside it carries its own. Both start off.
  • Visualizer — a sidebar page ("Graphify") that lists every repo in the folder, carries those switches, shows its headline numbers, and draws the graph.

graphify runs as a Python library, not a service: the plugin ships a driver program it executes through the peckboard_exec host function, so nothing is installed globally and no daemon is left running.

MCP tools

Tool What it does
graphify_build Build or refresh the graph → graphify-out/graph.json + GRAPH_REPORT.md. Returns node/edge/community counts, the god nodes, and the confidence split. update (default true) reuses graphify's per-file SHA256 cache; false forces a full re-extract.
graphify_path Shortest path between two concepts, hop by hop, with the relation and confidence on each edge, plus a diagram of the chain the chat renders inline. source/target match loosely against node labels and source files, so partial names work.
graphify_explain One concept: where it is defined, every direct neighbour with relation + confidence, the community it belongs to with its other members, and its degree rank.

Every tool takes an optional repo — a path relative to the folder root (. = the folder itself), because core pins command execution to that root. graphify_path and graphify_explain need a graph; both answer with an explicit "call graphify_build first" when there isn't one.

Edges carry a confidence: EXTRACTED (stated in the source), INFERRED (deduced by the cross-file pass), AMBIGUOUS (uncertain).

Switching it on

Nothing runs until it is switched on, at two levels:

Switch Where Default
Graphify in this folder top bar of the Graphify page off
One repo inside that folder the repo's card off

Installing the plugin therefore changes nothing on its own — including for a folder that was already using it before the switches existed, which goes quiet until someone turns it back on.

While a folder or repo is off:

  • all three MCP tools answer {enabled: false, error, next_step} naming the switch to flip. mcp_tools is manifest-level, so a tool cannot be hidden per folder — refusing is the honest equivalent, and the refusal is a normal tool result the agent can act on;
  • the session system prompt is not written (and an existing one is taken back off) — advertising tools that will refuse is worse than saying nothing;
  • the page still lists repos, because that is how you choose one to enable, but it will not build or draw them.

The switches are written only from the authed page, under the operator's authority. The agent reads them and stops; it cannot turn itself on.

Both live in the plugin document store, keyed by folder (folders/<folder id>) and by folder-and-repo (repos/<folder id>|<repo path>). The folder id is part of the key because core scopes that store by plugin, not by folder — which is also why the old build records, keyed on the bare repo path, collided between two folders that each had a . repo.

The path diagram

A found graphify_path also comes back as a PNG: the hop chain drawn as a lit polyline zig-zagging across a dim constellation, each node named and each segment labelled with its relation and confidence. The tool result carries it as _image_base64, which core (peckboard/src/routes/mcp.rs) turns into an MCP image content block: the chat shows it in the tool card and a vision model sees the route rather than parsing JSON. Turn it off with the Draw the path in chat setting when the vision tokens aren't worth it.

The renderer (src/pathimage.ts, inlined into the driver) is standard-library Python — zlib for the PNG stream, and antialiased lines, radial glows and a 5x7 bitmap font written by hand on a byte buffer. That is deliberate: the venv is graphify's, and matplotlib only lands in it as a graspologic dependency. Two things the layout does that are worth knowing before editing it:

  • Rows are serpentine, bands follow the column. Five nodes a row, running left-to-right then right-to-left, and because PER_ROW is odd every row both starts and ends on the lower band — so a row change is a clean vertical drop rather than a diagonal across the labels.
  • Labels are placed, not just drawn. Every node label reserves a box; each edge label then takes the first offset along its segment's perpendicular that lands clear of what is already there. Without it the row-seam labels stack.

The background field is decorative — a seeded LCG lays it out, not real neighbours — so the picture is deterministic per query without pretending to show graph structure it hasn't got. A render failure is swallowed, so a diagram bug can never cost the caller the answer, and paths longer than 14 nodes are drawn to that cap with the remainder stated in the footer.

What the graph does not contain

graphify_build is graphify's code-only pass: source files parsed by tree-sitter (.py .ts .js .go .rs .java .cpp .c .rb .swift .kt .cs .scala .php .cc .cxx .hpp .h .kts). It does not read docs, PDFs, or images. For a multimodal graph, run graphify's own /graphify skill — the session prompt says so, so the agent doesn't ask this graph for prose it never ingested.

Visualizer

The manifest contributes the same Graphify page three ways — a project menu entry, a session menu entry, and a button on each row of the Folders page — served at /plugin-api/v1/graphify and framed in a sandboxed iframe. Never a global sidebar entry: a global page carries no scope header, so core resolves no folder for it and every route below refuses. All three surfaces read the same state — the switches are keyed by folder id — so a folder enabled from a project reads back enabled on the Folders page. It reads its data from the authenticated /api/plugin-ui/graphify/* routes through the standard parent-proxied fetch bridge:

Route Returns
GET …/status {graphify_installed, python_bin, version, folder_known, folder_enabled}
GET …/repos Every graph target in the folder with its switch, counts, confidence split, god nodes, and build time — plus folder_known / folder_enabled.
GET …/graph?repo= Nodes (with degree), edges, communities, and whole-graph stats; a refusal when that repo is switched off.
POST …/build Same summary graphify_build returns — routed through the tool, so page and agent obey one gate.
POST …/enable {scope: "folder" | "repo", repo?, enabled} → the flipped state plus a fresh repo list.
POST …/install {installed, timed_out, output, manual_command}.

/graph returns the highest-degree slice of a large graph and flags it with truncated; stats always describes the whole graph, so a capped drawing never misreports its size.

Installing graphify

The plugin runs python3 -m pip install --user graphifyy on the first build when the auto_install setting is on. A cold install pulls graspologic (scipy/numba) plus ~14 tree-sitter wheels and can legitimately outrun core's 600-second command ceiling; when it does, the result carries the exact command to run by hand rather than reporting a success that never happened:

python3 -m pip install --user graphifyy

python_bin must name an interpreter on core's exec allowlist — python3 or python.

Security

  • The repo argument is plugin-supplied, so it is jailed twice: once in TypeScript before the driver is invoked, and once in the driver against the real filesystem. Relative segments only; an absolute path or a .. that climbs above the folder root is refused either way.
  • Commands run through peckboard_exec: a bare executable name from core's allowlist, an argv array (never a shell string, so there is nothing to interpret metacharacters), cwd pinned to the folder root, output capped at 1 MiB per stream, and the child killed past the timeout.
  • The driver reaches the network only when installing graphify. Building and querying a graph are local and offline.
  • The plugin writes into the folder it is pointed at (graphify-out/) and reads nothing outside it.

Settings

Key Type Default Description
python_bin enum python3 Interpreter that runs the driver. Must be on core's exec allowlist.
auto_install boolean true Run pip install --user graphifyy when graphify is missing.
prompt_mode enum when_graph_exists Whether to tell the agent about the graph: only when one exists, always, or never.
path_image boolean true Return a found graphify_path as a diagram the chat renders inline.
build_timeout_secs integer 600 How long one build may run before core kills it.

How it works

src/driver.ts holds one Python program, run as python3 -c "<driver>" <subcommand> [args]. Its subcommands are probe, repos, build, summary, graph, path, and explain; the last line of stdout that parses as a JSON object is the result, so a chatty dependency can't confuse the reader, and every failure path emits {"error": …} rather than letting a traceback be the only output.

graphify ships no build CLI — its __main__ only offers install / benchmark / hook — so the driver reimplements graphify.watch._rebuild_code: extract → build → cluster → analyze → report → export. Reimplementing rather than calling it buys three things: a build can target a subdirectory, a full rebuild can drop the extraction cache, and files are filtered on their path relative to the repo (graphify's own filter drops any file whose absolute path contains a dotted part, which silently empties a repo checked out under .peckboard/worktrees/).

Aggregate counts are computed in Python, because a large graph does not fit through the 1 MiB stdout cap. src/graph.ts owns everything that can be done on the TypeScript side, and is pure so it can be unit-tested without an Extism host.

Build

Targets the Extism js-pdk. Requires extism-js on PATH and Node/npm.

./build.sh
# or:
npm install && npm run build
# → dist/plugin.wasm

Run the unit tests with npm test. They need the page bundle generated first (npm run bundle), because src/page.ts imports it.

Install

Copy the built module into Peckboard's plugins directory, named to match its config key (the file stem is the plugin id):

cp dist/plugin.wasm <dataDir>/plugins/graphify.wasm

Restart Peckboard, then approve the plugin (Settings → Plugins) — it declares provide_mcp_tools, process_exec, project_files_read, data_store, session_read, session_prompt_write, user_authority, and contribute_sidebar.

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选