---
name: graph-viewer
mcp:
  command: node
  args:
    - ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
    - ${PLATFORM_ROOT}/plugins/graph-viewer/mcp/dist/index.js
  env:
    MCP_SPAWN_TEE_NAME: graph-viewer
    LOG_DIR: ${LOG_DIR}
    PLATFORM_ROOT: ${PLATFORM_ROOT}
    ACCOUNT_ID: ${ACCOUNT_ID}
    SESSION_ID: ${SESSION_ID}
mcp-manifest: auto
description: "Inline Neo4j subgraph renderer. Provides graph-render — a Node-side PNG renderer that walks N hops from a starting node, applies the same palette and display strings the live /graph page uses, and returns the image as an MCP image content block. Removes the device-switch otherwise required for the agent to show the operator what a subgraph looks like. Account-scoped: the tool refuses to render nodes outside the caller's accountId. Layout is d3-force with a deterministic seed; drawing is @napi-rs/canvas with a system-font fallback for labels. The fidelity contract is palette and display-string parity — node positions will differ from the live page's vis-network layout. Ships one skill: render-graph."
tools:
  - name: graph-render
    publicAllowlist: false
    adminAllowlist: true
    riskClass: read
---

# graph-viewer

## What it does

A single MCP tool, `graph-render`, takes a Neo4j node ID and a hop depth and
returns an inline PNG of the subgraph rooted at that node. The agent
attaches the PNG to its reply so the operator can see the graph without
opening the admin UI on a different device.

## Why it exists

Before this plugin, the agent had no way to ship the operator a picture
of a subgraph from inside chat. Mermaid and ASCII substitutes were
illegible and bore no resemblance to the live `/graph` page. Operators
otherwise had to leave the chat surface, open the admin UI on whatever
device hosts it, and re-find the same subgraph by hand.

## Surface boundaries

- `graph-render` only accepts a `nodeId + hopDepth` query shape. Arbitrary
  Cypher is not supported and is filed as a follow-up task.
- Pixel-equivalence with `/graph` is not a goal. The layout engine is
  d3-force, not the live page's vis-network port; node positions will
  differ. The colour palette, label precedence, and short-label strings
  are shared with `/graph` via `platform/lib/graph-style/`.
- Subgraphs above 200 nodes return a truncation envelope alongside the
  capped render.
- `:Trashed` nodes are filtered out, matching `memory-search`'s contract.

## Enabling

The plugin is auto-discovered from `platform/plugins/`. Each operator
account must list `graph-viewer` in its `enabledPlugins` (use the admin
`plugin-toggle-enabled` MCP tool) before `graph-render` appears in the
agent's tool surface.
