# FlowGraph

> Agent-native knowledge-graph canvas. Read and write a local graph through ONE governed,
> lock-aware write path — a human-approved atom is immutable to AI. AI proposes, you decide,
> your agents can trust it.

FlowGraph exposes an MCP server so AI agents read and write your knowledge graph through the
SAME governed path a human edit takes: every write is provenance-stamped and lock-aware. A
write to a human-approved (locked) atom — or one the agent lacks the `modify` capability for —
is REJECTED. **Mermaid diagrams are accepted as input and output**, so an LLM can hand FlowGraph
a diagram it already knows how to emit (https://flow-graph.com/tools/mermaid-to-flowgraph).

## Docs
- [API reference](https://flow-graph.com/docs/api): the human-readable API reference — assistant tools, the .fgraph data model, REST endpoints, plan tiers, and a plain-language connection guide.
- [api.md](https://flow-graph.com/api.md): the raw-markdown mirror of the API reference (fewer tokens than the HTML page).
- [AGENTS.md](https://flow-graph.com/AGENTS.md): the full agent guide — connect the MCP server, the write contract, every tool with read/write annotations, the .fgraph data model.
- [OpenAPI](https://flow-graph.com/openapi.json): machine-readable schema for every MCP tool + REST endpoint.
- [MCP server metadata](https://flow-graph.com/.well-known/mcp/server.json): the registry descriptor.
- [Mermaid → FlowGraph](https://flow-graph.com/tools/mermaid-to-flowgraph): paste Mermaid, get a living graph — no upload.

## MCP tools
- `get_connection_status` (read): FIRST CALL — prove the user-approved local mirror matches the current portal-owned graph count AND exact content fingerprint. Only a matched receipt returns visible graph names. Missing, empty, or stale returns counts only: it is a CRITICAL CONNECTION FAILURE, so do not use a stale fallback; call request_assistant_connection with the person's original request. A match permits asking for write approval; it is not approval by itself.
- `list_writeup_visual_requests` (read): List pending write-up visual requests the connected FlowGraph app explicitly queued for Codex. Read-only; returns labels and states, not image bytes.
- `get_writeup_visual_request` (read): Read one exact queued write-up section, its optional human direction, source fingerprint, and current state before generating anything.
- `claim_writeup_visual_request` (write): Claim one queued visual request for this Codex task. This records work ownership only; it does not change the write-up. Ask before spending image-generation usage.
- `submit_writeup_visual_candidate` (write): Submit a bounded PNG/JPEG/WebP candidate plus the typed visual brief after Codex ImageGen finishes. This stages preview bytes only; FlowGraph still requires the person to choose Append or Replace before any write-up mutation.
- `report_writeup_visual_failure` (write): Finish a claimed write-up visual request with an honest failure reason so FlowGraph can stop waiting and offer retry.
- `get_card_visual_context` (read): Read the exact bounded source for a card visual: either the card alone or the card plus direct links. Returns a source hash and diagram catalog. Call this immediately before authoring so the later candidate can be rejected if the card changed.
- `submit_card_guided_visual_candidate` (write): Stage a structured card diagram authored from get_card_visual_context. FlowGraph rechecks the source hash, then its own deterministic renderer creates the pixels. This does not mutate the card: the person must review and press Add to card, which uses the normal governed Visual-section/gallery path.
- `submit_card_image_candidate` (write): Upload a PNG/JPEG/WebP that Codex already created in the chat for the exact get_card_visual_context hash. The full bytes go to FlowGraph’s image store, not graph JSON. This only stages a preview; the person must press Add to card before the normal governed Visual-section/gallery write occurs.
- `request_assistant_connection` (control): When the first connection check is unconnected, pass the person's ORIGINAL request here. The open local FlowGraph app will proactively show its permission-based connection guide while this call waits briefly. If the person connects, continue the same request in this task; never ask them to restate it. This only notifies the app and waits for the existing receipt: it grants no permission and changes no canvas.
- `list_canvases` (read): List current canvases (id, name, node count) only after the approved portal mirror passes its count + content-fingerprint check. A stale or unpaired mirror returns an error and no graph names.
- `get_canvas` (read): Get a canvas — its nodes and edges — by id. MCP Apps-capable clients also receive a Live Canvas UI resource that frames the paired production FlowGraph renderer in Gold; the component never redraws the graph from tool JSON. Without a paired app route or UI-capable client, the complete data result remains available.
- `control_live_app` (control): Control the CURRENT paired FlowGraph tab through the same typed AppAction registry as in-app Chat and Live Voice. Covers live 2/3-pane layouts, exact pane resizing and return-to-single; presentation next/previous; lens/diagram changes; fit/zoom/pan; tidy layout; card/group/section/item edits; Offload actions; effort/workflow/review status; findings; and relationship create/rename/delete. The subscription-backed client interprets natural language and supplies a typed action—FlowGraph adds no phrase parser. Requires the local companion and a fresh connected browser tab. The browser returns the observed result; confirmation-tier actions run nothing until the person explicitly agrees and the tool is called again with confirmed:true. Use create_canvas + submit_knowledge_draft for substantial pasted meeting notes instead of squeezing them through UI control.
- `query_graph` (read): Edge-aware query: text · facet · tags · relType · traverse(up/down). Returns matching node ids + titles.
- `flowgraph_retrieve` (read): Graph-CCR retrieval (READ-ONLY): pull exactly the sub-graph you need. Give a `query` (semantic/keyword seed → structural expansion) OR a `handle` (a retrieval handle "canvasId::nodeId" from an assembled context packet) → its original atom + neighbourhood. A STALE handle returns a recovery hint, never an error. Output is governance-aware (atoms without an AI use-as-context grant come back degraded, no body) and provenance-stamped.
- `create_canvas` (write): Create a new empty canvas; returns its id. This is a WRITE and requires the person’s explicit approval.
- `apply_graph_patch` (write): Apply a GraphPatch (ops[]) through the GOVERNED, provenance-stamped, lock-aware write path. A write to a human-approved (locked) atom — or one the AI lacks the "modify" capability for — is REJECTED.
- `refresh_codebase_map` (write): Refresh a multi-repo (fleet) codebase map: pass each repo's label + package name + declared dependencies (with the manifest line each is declared on), and this stages a governed ghost-draft that (re)builds one card per repo and the typed `depends` cross-repo edges, each carrying its manifest-line receipt. Reconciled against the target canvas — existing repo cards update, new repos add, the edge set recomputes — so a scheduled re-run is idempotent and never duplicates. A human accepts it in the Review Inbox (agents never auto-apply). Use it as the cron/agent codebase-refresh recipe.
- `get_canvas_digest` (read): Read a canvas as an FDG digest (READ-ONLY): the anchored knowledge grammar the in-app AI reads and writes. Every card, section, entry and group carries a short anchor ([c3], [c3.f2], [c3.f2.i4], [g1]) you cite when you write back with `submit_knowledge_draft`. `nodeIds` focuses the read (those cards + their neighbours render in FULL, the rest as an outline); `hops` widens that full-fidelity ring; `budget` caps the characters (an honest tail line says what was withheld — never a silent truncation). Returns the digest text, the anchor→atom map, per-card fidelity, stats, and a `digestId` — pass that back to `submit_knowledge_draft` so your anchors mean the atoms you actually read. The cheap way to orient before writing; complements `flowgraph_retrieve`.
- `submit_knowledge_draft` (write): WRITE KNOWLEDGE, NOT OPS — the preferred way to write anything content-bearing. Submit a draft in FDG (the markdown grammar `get_canvas_digest` speaks) and a DETERMINISTIC compiler turns it into a GraphPatch applied through the same governed, lock-aware, provenance-stamped path as every other write; a locked atom is refused. `mode:"apply"` (default) writes it; `mode:"stage"` lands it as a Review-Inbox ghost-draft for a human to accept. On ANY compile or validation problem NOTHING is written — you get indexed errors[], every dropped block with its line and reason, and a fix hint, so you can correct and resubmit. Returns applied/newCards/anchorMap/dropped/depth/questions/suggestions, so your [anchors] stay addressable and you can relay the AI's questions or chain its suggested next moves. `apply_graph_patch` remains for surgical, programmatic ops.
- `add_card` (write): Convenience: add one governed card. For the Ideation lens, optionally classify it as work or personal, organize it by category/subcategory, supply evidence-aware 1–5 Difficulty/Reach/Revenue/Product–market-fit AI estimates, make it a large main idea, or grow it from a parent thought. Agent-created ideas retain AI provenance and appear as Codex suggestions until the person adopts them.
- `create_idea_drop` (write): Create one researched Ideation drop as a single governed, undoable patch. Use after the person asks you to turn supplied material (a direct idea, a YouTube/source URL, or screenshots) into a Work or Personal constellation. Per idea: keep exact sources, optional bounded inline screenshot bytes when the client exposes them, category/subcategory, and evidence-aware 1–5 Difficulty/Reach/Revenue/Product–market-fit AI estimates with concise evidence bullets. If the client cannot provide original screenshot bytes, retain derived notes and explicitly say the image was not stored—never invent an attachment. Every card stays a labeled Codex suggestion until adopted.
- `connect` (write): Convenience: connect two cards with a typed relationship.
- `list_skills` (read): List reusable SKILLS (promoted action items) — name, the card/canvas they live on, their inner-canvas id, and whether they are READY (inner canvas non-empty). The agent capability catalog.
- `list_due_reviews` (read): The ranked review agenda — scheduled reviews across the vault joined with attention state, bucket (overdue/today/week/later), blast-radius and owner. The same agenda the human sees.
- `schedule_review` (write): Propose a review date on an atom (ISO date or relative like "in 2 weeks"). A GOVERNED write: stamped provenance.kind=ai, REJECTED on human-approved (locked) atoms, surfaced for the human in the calendar / Review Inbox — agents never silently sign off.
- `reschedule_review` (write): Move an atom’s existing review to a new date WITH A REQUIRED REASON (lands in the atom’s history). Governed; rejected on locked atoms. Use to sequence a review after an upstream one resolves.
- `complete_review` (write): Propose marking a scheduled review DONE plus optional findings — as a governed write the human sees. NEVER approves or locks (only a human signs off); just records that the agent did a first-pass review.
- `list_actions` (read): EVERY action across the vault (not just promoted skills): its address 4-tuple {canvasId,nodeId,facetId,itemId}, text, binding, current test status, unmet prerequisites, and strategy. The agent’s runnable-work catalog.
- `get_action` (read): One action’s FULL contract (binding + schemas, test, inputs, loop policy, strategy) plus its recorded runs, by address 4-tuple.
- `run_action_test` (write): Run the DRY-RUN pipeline (precondition → contract-check → deterministic; no world touched, no network) against an action. Returns the full ActionRun; writes `action.test` through the governed patch and records the run in the agent ledger. It can never approve, lock, or execute live.
- `report_action_run` (write): Driver B: report a run YOU executed with your own tools — steps, verdict, artifacts, tokens/cost, and your identity. Schema-validated; recorded as ActionRun{driver:"agent"} + a RunSummary. A “live” claim is labeled AGENT-CLAIMED (never presented as app-verified execution). Requires the `execute` AI capability on the action atom — WITHOUT it the report stages as a ghost-draft for human accept. Idempotent on runId.
- `list_runs` (read): The Control-Tower read: recorded runs (app + agent) filtered by canvas / action address / verdict / driver, newest first.
- `ifc_inventory` (read): A Smart IFC model’s data-first inventory (READ): schema, element/storey/space/type counts, per-class counts, storeys, and materials — DERIVED from the parsed model (never AI-guessed). `modelId` is a registered model id OR the model’s sha256 (content identity).
- `ifc_query` (read): Run the FlowGraph model query grammar over an IFC or Autodesk metadata index (READ): e.g. `category:"Electrical Fixtures" level:"Level 2" room:"210" Voltage=120`. Level uses authored storey/level evidence; Room uses explicit Room/Space properties only (never an object-name or level fallback); bare property keys search instance, parent, type and parts scopes. Returns matched elements, stable ids, quantities and honest warnings. Pure — no geometry, no AI, no network.
- `ifc_model_network` (read): Project a model index into the SAME bounded, source-aware Model Data Network shown in Studio (READ). Revit/Navisworks defaults to Revit Level/Room or Space/Revit Category/Revit Family/Revit Type; IFC defaults to IFC Storey/IFC Space/IFC Class/IFC Type/IFC Instance and never invents Revit Family. Ordered System/Trade, Source property/Mapping rule/Required answer, and parameter columns are also supported, with exact aggregate counts, grouped tails and adjacent links. Optional `query` first narrows the source rows with `ifc_query` grammar. Parameter tokens use `parameter:<any|self|type|parent|parts>:<property name>`. Trade appears only when a saved AI/human trade mapping exists; Room/Space uses authored properties and IFC spatial containment. Data-only — never wakes 3D or calls AI.
- `control_3d_viewer` (control): Control the CURRENT live 3D viewer through the same AppAction registry as in-app Voice (RENDER-ONLY): select/focus/isolate an exact BIM query, show all, open Studio, or switch Studio between Data first and Linked 3D. Requires the local FlowGraph companion and a fresh connected browser tab; a folder snapshot or stale tab is refused. Actions that open/wake geometry require `confirmed:true` after the person explicitly agrees to the stated memory/performance consequence. Returns the browser-observed AppAction result plus run id, wall-clock times, and ordered StepTrace; never treats delivery as execution.
- `ifc_element` (read): One element’s full properties/psets/quantities by GlobalId (READ), derived from the parsed model. Absent properties are honestly absent, never fabricated.
- `ifc_qa` (read): Read the SAME Model QA ledger and remediation analysis the app renders: in-scope object count, must-have readiness, AI/file/human/review/missing answer partition, per-key coverage, held/rejected rules, and what the model author should add. Requires a saved mapping in the mirrored vault metadata (`vault.json`); optional `packId` selects one saved Domain. Data-only — it never loads geometry or runs AI.
- `ifc_create_set` (write): Create a selection set on a model card (WRITE → staged for human accept). Give a `query` (a dynamic set — the query IS the set) OR explicit `globalIds` (a static snapshot). Lands as an IfcAnchor set item on the card’s model facet — never applied directly; a locked atom is refused.
- `ifc_link` (write): Link a model item (a pin/set/viewpoint) to another card with a typed relationship (WRITE → staged for human accept). A governed edge from the item’s handle → the target card; default relType `appears_in`. Never applied directly; a locked atom is refused.
- `ifc_viewpoint` (write): Save a named viewpoint on a model card (WRITE → staged for human accept): an engine-neutral IfcAnchor view item (BCF-shaped `camera` optional). Never applied directly; a locked atom is refused.
- `ifc_project` (write): Project a model’s structure INTO the graph (WRITE → staged ghost-diff for human accept): deterministic storey cards + top type-summary cards + contains/located_at edges, every atom provenance `derived`. Never applied directly; reject leaves the vault unchanged.
- `aps_translate` (write): Request an APS (Autodesk cloud) translation of a proprietary model (.rvt/.nwd/.dwg/.dgn) so it can be viewed + graphed (WRITE → staged for human accept). It NEVER translates directly: cloud translation sends bytes off-device and may use the deployment’s configured allowance or Autodesk billing, so it always stages a ghost-draft the human accepts in the app. Returns the staged request. Once translated, query it with the `ifc_*` tools.
- `aps_browse` (read): Browse Autodesk Construction Cloud / BIM360 (READ): hubs → projects → folders → items. Answers from an OPTIONAL cached browse file (`_aps-browse.json`) in the vault when present (the tool stamps source:"cached" itself, so the cache can’t forge the label); absent ⇒ an honest not-configured notice — the 3-legged OAuth session is managed by the FlowGraph worker, never the folder-vault MCP server, so hubs are never fabricated (charter #8).
- `object_story` (read): One object’s biography (READ): the nine spine answers in reading order — What it is · Why · Where · Part of and made of · Feeds and fed by · Who is responsible · State and history · If it fails · How we know — each with its plain answer, provenance TIER (from the model / from documents / confirmed / computed / AI guess, unconfirmed) and the RECEIPTS backing it (the record or lifecycle card, its link tier, and the element GlobalId), plus the record + lifecycle timeline. Pure projection — nothing is written. `nodeId` is the model card, `globalId` the element.
- `object_coverage` (read): One object’s coverage + ranked open questions (READ): the story-coverage score (answered / askable weight over the asked spine slots) and the OPEN questions ranked by severity (blast radius × importance × answerability), each with its honest one-line why and — when the bank can ask it in-app — the `qid` you answer with `object_answer`. A question with no `qid` (answerableInApp:false) has no in-app form yet: route it to a person with `object_route_ask`. Pure — nothing is written.
- `object_answer` (write): File an answer to one OPEN spine question (WRITE → staged for human accept). Give the `qid` from `object_coverage` (answerableInApp:true) + your `answer`. It NEVER writes a fact directly: an agent-supplied answer stages as a Review-Inbox ghost-draft with provenance kind:"ai" (labeled AI, unconfirmed at every depth — provenance never launders, docs/50 §8), which a human accepts to turn into a fact with a receipt. Refused honestly for an unknown/already-answered qid or a locked atom.
- `object_lifecycle_event` (write): Record a lifecycle event about an object (WRITE → staged for human accept): installed / inspected / replaced / commissioned … As an ordinary FACT — a small card carrying the event + a `documented_in` element receipt, so it interleaves into the SAME Story timeline + Lifeline ribbon the app shows (never a parallel surface). `validTime` = when it happened (ISO or a plain date). Staged with provenance kind:"ai", tier ai-confirmed; a human accepts it. A locked model card is refused.
- `object_route_ask` (write): Route ONE open question about an object to the person who knows it (WRITE → staged for human accept). It NEVER sends directly: the recipient link + email ride the app’s authenticated session (the /s/* rails), which the folder-vault MCP server does not hold — so the routed ask stages as a ghost-draft {audience, question, object} the human sends from the app (the aps_translate pattern). Use it for a high-severity question `object_coverage` reports as answerableInApp:false. Returns the staged request.

## Notes
- Honest expectations (docs/31 §P5b): `llms.txt` is near-useless for search ranking (~97% of such files get zero requests); it exists to serve docs-navigating coding agents, and it cost an hour. We ship it as a cheap option, not a growth plan.
