MeshPlugin gives AI agents a clean, consistent API for navigating and modifying the mesh data graph. Every path argument supports the @ shorthand prefix — @graph/org1 resolves to graph/org1.
Six tools give AI agents complete read, search, display, and write access to the mesh data graph.
Get
Reads a node from the mesh and returns its JSON representation.
Single node
Get('@path')
Returns the full MeshNode JSON, including all properties and the typed content object.
Children list
Get('@path/*')
Returns a JSON array of direct children, each with { path, name, nodeType, icon }. Useful for browsing a namespace before diving deeper.
Unified Path prefixes
Get understands reserved path prefixes that expose type metadata alongside node data:
| Syntax | Returns |
|---|---|
Get('@path/schema/') |
JSON Schema for the node's content type |
Get('@path/schema/TypeName') |
JSON Schema for a specific named type |
Get('@path/model/') |
Full data model with all registered types |
These schema prefixes work on any address — not just NodeType paths. Use them before creating or updating a node to discover the exact fields expected.
For the complete Unified Path reference:
Examples
Get('@graph/org1') // Read a specific organisation node
Get('@NodeType/*') // List all available node types
Get('@ACME/ProductLaunch/schema/') // Content schema for ProductLaunch
Get('@ACME/ProductLaunch/model/') // Full data model
Search
Searches the mesh using a GitHub-style query syntax. Returns a JSON array of up to 50 matching nodes.
Parameters
| Parameter | Required | Description |
|---|---|---|
query |
Yes | Filter string with field filters, wildcards, scoping, and sorting |
basePath |
No | Limits the search to a specific subtree |
Common patterns
Search('nodeType:Agent') // All agents
Search('namespace:ACME') // Direct children of ACME
Search('path:ACME scope:descendants') // Everything under ACME recursively
Search('namespace:Doc scope:descendants') // Browse all documentation
Search('name:*sales* nodeType:Organization sort:name') // Complex filtered query
Search('laptop', '@graph') // Free-text search within graph
Full query syntax
NavigateTo
Opens a node's visual layout area inside the chat UI — the mesh's equivalent of "Show me this page."
CRITICAL: When a user asks to "show", "display", or "view" something, always prefer
NavigateToover dumping raw JSON. Call it, then keep your text response short — just confirm what was displayed.
Workflow
- Call
NavigateTo('@path'). - Respond with one sentence — e.g., "Here's the organisation chart."
Example
User: "Show me the organisation chart."
Action: NavigateTo('@ACME/Organization')
Response: "Here's the organisation chart."
RenderArea
MCP surface only.
RenderAreais declared onMcpMeshPlugin, not on the in-portalMeshPlugin— so it is available to an agent connected over MCP, and not in the tool set an in-portal agent round receives. In-portal, useNavigateToorGet('.../area/Name').
Returns a live, interactive layout area as an MCP-UI embedded resource.
Hosts that support MCP-UI (Claude.ai web/desktop, ChatGPT Apps) render it inline as an iframe widget. Text-only hosts (such as the Claude Code CLI) receive a fallback URL instead.
Parameters
| Parameter | Required | Description |
|---|---|---|
path |
Yes | Path to the node hosting the area (e.g., @Systemorph/FutuRe/EuropeRe/AcmeSubmission2025) |
areaName |
Yes | Name of the layout area on that node (e.g., Triangle) |
Choosing the right display tool
| Tool | Use when … |
|---|---|
RenderArea |
The user benefits from a live interactive view embedded in the conversation — charts, grids, dashboards, triangles. Best for MCP-UI hosts. |
NavigateTo |
You want to give the user a clickable link to open in a new browser tab. |
Get('.../area/Name') |
You need structured JSON of the rendered payload for programmatic use. |
Example
RenderArea('@Systemorph/FutuRe/EuropeRe/AcmeSubmission2025', 'Triangle')
Create
Creates and persists a new node in the mesh. The node is validated before it is saved.
Parameter
node (string, required) — A JSON string representing a MeshNode object.
MeshNode schema
| Property | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Simple slug — no slashes (e.g., "NewOrg", "Task1") |
namespace |
string | For nested nodes | Full parent path (e.g., "ACME", "ACME/Projects"). Omit for root-level nodes. |
name |
string | Yes | Clear, human-readable title. Think of it as a document heading. |
nodeType |
string | Yes | Must match an existing NodeType (e.g., "Organization", "Markdown") |
category |
string | No | Grouping category; overrides NodeType for display purposes |
icon |
string | No | Inline SVG starting with <svg — create a unique, visually appealing icon that matches the node's purpose |
order |
int | No | Sort order; lower values appear first |
content |
object | Depends on type | Type-specific data. Schema varies by NodeType. |
The node's path is derived as {namespace}/{id}, or simply {id} for root-level nodes.
Critical rules
idmust be a simple slug — no slashes. Use only letters, numbers, and hyphens.Correct:
"id": "PricingTool", "namespace": "User/rbuergi"Wrong:"id": "User/rbuergi/PricingTool", "namespace": ""
namemust be a clear, descriptive title — not just the first few words of the content body.iconshould be an inline SVG — a small, clean 24×24 image that visually represents the node's purpose. Use simple shapes and colours that match the content theme.- 🚨
contentfield names must match the registered type EXACTLY — unknown fields are silently dropped. Deserialization ignores members it doesn't recognise (no error), so a mistyped or invented field name produces a node that reports created successfully but renders without values in every typed view — far harder to notice than a failure. Where the content is polymorphic, include the$typediscriminator the schema shows. Two habits prevent it:- Copy a real node as a form template. Before creating instances of a type you have not written before,
Getone existing node of that type and mirror itscontentstructure — exact field names, reference-field shapes, and any$type— rather than guessing from the schema alone. - Read back after a batch. After creating a batch,
Getone node per type and confirm the$type, the reference fields, and the value fields actually persisted. (Do not verify throughSearchimmediately — the index is eventually consistent and can return zero right after a write;Getthe exact path instead.)
- Copy a real node as a form template. Before creating instances of a type you have not written before,
Discovering the content schema
Before creating a node, check what content fields the target type expects:
Get('@Cornerstone/schema/') // Schema for nodes in the Cornerstone namespace
Get('@path/schema/TypeName') // Schema for a specific named type
Get('@path/model/') // Full data model with all registered types
Workflow
- Find an existing node of the same type, or navigate to the target namespace.
- Retrieve its content schema:
Get('@path/schema/'). - Build the
MeshNodeJSON with all required fields. - Call
Createwith the JSON string.
Example
Create('{"id": "NewProject", "namespace": "ACME", "name": "New Project", "nodeType": "Project", "content": {"status": "Active"}}')
Update
Replaces one or more existing nodes with new data. The entire node is replaced — this is not a merge/patch operation.
Prefer
PatchorEditContentfor anything small. Both are part of the same tool set:
Patch(path, fields)— partial update of one node. Only the keys you send change;contentdeep-merges per RFC 7396, so you can set a single content field without resending the rest. Anullmember deletes that one key; setting the wholecontenttonullis rejected.EditContent(path, oldText, newText, replaceAll)— anchored text edit inside a Markdown body or Code source. Send just the snippet plus enough surrounding context to be unique, instead of pushing a whole document throughUpdate. Fails loudly when the text isn't found or isn't unique.
Updateis the right tool only when you genuinely mean to replace the node wholesale.
Parameter
nodes (string, required) — A JSON array of MeshNode objects with updated fields.
Important
Always
GetbeforeUpdateto avoid accidentally erasing fields you did not intend to change. The node at the given path is completely replaced by what you provide.
Path is derived from namespace + id, same as for Create.
Workflow
- Retrieve the current node with
Get('@path')orSearch('...'). - Modify the returned JSON (change
name,contentfields, etc.). - Pass the modified node(s) to
Updateas a JSON array.
Example
// First: result = Get('@ACME/ExistingProject')
// Modify the JSON, then:
Update('[{"id": "ExistingProject", "namespace": "ACME", "name": "Renamed Project", "nodeType": "Project", "content": {"status": "Completed"}}]')
Delete
Removes one or more nodes from the mesh by their paths.
Delete is RECURSIVE. Deleting a parent removes every descendant — pass the subtree root, there is no need to enumerate children, and passing a namespace root removes everything under it.
Parameter
paths (string, required) — A JSON array of path strings to delete.
Example
Delete('["ACME/OldProject", "ACME/ArchivedTask"]')
Reading Documentation
To explore all available documentation, browse the Doc namespace and read any article with Get:
Search('namespace:Doc scope:descendants')
Get('@Doc/Architecture/SomeArticle')