Skip to content

Specialized suites: CanonWorks, Manus & nodes

Serial-fiction canon management, Manus web research, image generation, live canvas rendering, and remote IoT nodes.

Beyond core orchestration, the Operator MCP ships several purpose-built tool suites that turn Revka into a domain platform: a serial-fiction canon manager, a live web-research bridge, image generation, a real-time dashboard canvas, and a registry for remote hardware. Each is exposed as Operator MCP tools your agent can call directly from chat or wire into a workflow step. This page is the reference for all five.

All of the tools below live in the Operator MCP server, so they require the operator to be installed and running. See Operator MCP for setup and Install the Python MCP sidecars for the prerequisites.

CanonWorks: serial-fiction canon management

Section titled “CanonWorks: serial-fiction canon management”

CanonWorks manages serialized fiction — characters, timelines, relationships, storylines, and foreshadow threads — as a Kumiho graph project. Once a series is initialized, you run an episode-factory workflow to draft new episodes and a state-sync workflow to keep canon consistent as the story grows. It is built primarily for Korean web-serial production, so the default language is ko-KR and the default cadence is web_serial.

There are two paths: a one-shot programmatic init, or an interactive interview that previews the graph before committing.

canonworks_init builds the full project in a single call: it creates Kumiho spaces, canon bundles, the initial series/character/relationship/timeline items, artifacts, and graph edges, then returns the generated project_config_yaml the workflows consume.

{
"title": "Quantum Soul",
"project": "quantum-soul",
"story_slug": "quantum-soul",
"premise": "A courier discovers her implant hosts a dead AI.",
"language": "ko-KR",
"cadence": "web_serial",
"target_length": "6000",
"characters": [
{ "id": "rin", "name": "Rin", "role": "protagonist", "summary": "..." }
],
"relationships": [
{ "from": "rin", "to": "the-ai", "type": "hosts", "label": "..." }
]
}

Only title is required. Everything else (project, story_slug) defaults to a slug of the title.

With a committed project, two tools drive ongoing production. Both hide the project_config_yaml plumbing — pass the session_id (or project + story_slug) and they resolve the rest.

ToolRuns workflowKey inputs
canonworks_run_episodecanonworks-serial-episode-factoryepisode_goal, target_length, must_include, avoid, continuity_context, pacing_mode, initial_episode_number
canonworks_sync_statecanonworks-serial-canon-state-syncapply_mode, review_focus, target_episode_number, target_episode_kref, bootstrap_mode

These map to the builtin workflows of the same names. See Built-in workflows & orchestration patterns for the full catalog and how builtin workflows are structured.

manus_create_task runs an ad-hoc research task on the Manus hosted web agent, which has real browser access for live research and structured data extraction. Use it mid-conversation when a question benefits from live web browsing rather than the model’s training data. It mirrors the manus: workflow step type and shares its auth precedence.

{
"prompt": "Find the three most-cited papers on graph memory published in 2025, with links.",
"structured_output_schema": {
"type": "object",
"properties": { "papers": { "type": "array" } }
},
"agent_profile": "manus-1.6",
"timeout_seconds": 600,
"credentials_ref": "manus:work"
}
FieldTypeDefaultMeaning
promptstring(required)The research prompt for Manus.
structured_output_schemaobjectJSON schema for Manus to populate; when set, the result includes structured_output.
connectorsstring[]Manus connector ids to attach (e.g. google_drive).
agent_profilestringmanus-1.6Manus agent profile id.
timeout_secondsinteger600Max seconds to poll the task.
poll_interval_secondsinteger5Seconds between poll calls.
credentials_refstringAuth-profile id (e.g. manus:work). When unset, falls back to the MANUS_API_KEY environment variable.

Authentication resolves in this order: the credentials_ref auth profile first, then the MANUS_API_KEY env var. The task returns task_id, task_url, final_state, the assistant message, attachments, and the optional structured_output.

generate_image_codex generates PNG images using the OpenAI Codex CLI’s built-in image_generation tool. It can produce up to 5 images in parallel in one call (independent Codex sessions via asyncio.gather); for more, call it repeatedly in batches. Optionally it pushes a gallery frame to the Live Canvas and registers each PNG as a Kumiho artifact.

{
"prompt": "A fox in a forest, cinematic lighting",
"output_path": "fox.png",
"count": 3,
"canvas": true,
"space": "Marketing/Logos"
}
FieldTypeDefaultMeaning
promptstring(required)Description of the image to generate.
output_pathstring(required)Target PNG path, relative to cwd unless absolute. With count > 1 and no output_pattern, expanded as <stem>-N.<ext>.
cwdstring~/.revka/workspaceWorking directory for Codex.
countinteger (1–5)1Images to generate in parallel.
output_patternstringFilename template with a {n} placeholder, e.g. logo-{n}.png.
input_imagesstring | string[]Local image path(s) passed to codex exec --image as references. [IMAGE:/path] markers in the prompt are also extracted automatically.
canvasbool | stringfalsetrue pushes a gallery frame to the default canvas; a string uses that canvas_id.
register_artifactbooltrueCreate a Kumiho item + revision under <harness>/<space> and attach each PNG.
spacestringImagesKumiho space (relative to the harness project). Multi-segment paths like Marketing/Logos are supported.
item_namestring(filename stem)Name for the Kumiho item.
sandboxenum(auto)Codex --sandbox mode: read-only, workspace-write, or danger-full-access.

The response includes a urls[] array of signed /workspace/... URLs the dashboard can load, and a files[] array of absolute filesystem paths. When composing your own HTML or canvas output, reference urls[] — the browser sandbox can’t read raw filesystem paths. The signed URLs are produced by the gateway’s workspace asset serving, so they work through tunnels.

See Code agents, delegation & pipelines for more on the Codex CLI integration.

The Live Canvas pushes agent-rendered content (HTML, SVG, Markdown, or plain text) to the dashboard’s Canvas page in real time. Multiple named canvases are supported; the dashboard shows the latest frame and every WebSocket subscriber receives new frames instantly.

ToolParametersPurpose
render_canvascontent (required), content_type (html | svg | markdown | text, default html), canvas_id (default default)Push a frame to a canvas.
clear_canvascanvas_id (default default)Clear a canvas and its frame history.
{
"content": "<svg viewBox='0 0 100 100'><circle cx='50' cy='50' r='40'/></svg>",
"content_type": "svg",
"canvas_id": "default"
}

The same canvas system is exposed over the gateway for subscribing browsers and external callers. The dashboard subscribes over WebSocket; you can also drive a canvas from REST.

ws://host:port/ws/canvas/<canvas_id>?token=<bearer>

On connect, the gateway sends the current snapshot (if any), then {"type":"connected","canvas_id":"..."}. New content arrives as {"type":"frame","canvas_id":"...","frame":{}}. A slow subscriber that falls behind the broadcast ring buffer receives {"type":"lagged","missed_frames":N}.

MethodPathAuthPurpose
GET/api/canvasBearerList active canvas IDs
GET/api/canvas/:idBearerGet the current snapshot
GET/api/canvas/:id/historyBearerGet frame history
POST/api/canvas/:idLoopback: none / external: BearerPush a frame
DELETE/api/canvas/:idLoopback: none / external: BearerClear the canvas

A POST body matches the tool shape:

{ "content_type": "html", "content": "<h1>Live status</h1>" }

For the full realtime surface, see Realtime: WebSocket, SSE & Live Canvas. On the dashboard side, see Agents, teams & canvas.

Remote nodes are external processes — phones, sensors, IoT devices, or remote machines — that connect to the gateway over WebSocket and advertise capabilities (for example camera.snap or shell.exec). Each advertised capability becomes a dynamically available agent tool, and the gateway dispatches invocations back to the originating node.

ToolParametersPurpose
list_nodes(none)List connected nodes and their capabilities.
invoke_nodenode_id (required), capability (required), args (default {})Invoke a capability on a node.

Always call list_nodes first to discover what capabilities a node exposes, then invoke one:

{ "node_id": "phone-1", "capability": "camera.snap", "args": {} }

A node connects to the gateway’s dynamic node registry over WebSocket and registers its capabilities:

ws://host:port/ws/nodes?token=<bearer>

Sub-protocol: revka.nodes.v1. The node sends a register frame; the gateway acks with registered:

{
"type": "register",
"node_id": "phone-1",
"capabilities": [
{
"name": "camera.snap",
"description": "Capture a photo from the rear camera",
"parameters": { "type": "object", "properties": {} }
}
]
}

When the agent invokes a capability, the gateway sends the node an invoke frame with a call_id, capability, and args; the node replies with a result frame (call_id, success, output, optional error). Capability parameters are a JSON Schema object, defaulting to {"type":"object","properties":{}}.

Auth and lifecycle:

  • A node-specific auth_token from config takes precedence; if no node token is configured, the gateway falls back to the standard pairing guard.
  • node_id must be 1–128 characters. Re-registering the same node_id updates the existing entry.
  • The registry has a configurable max_nodes capacity. On WebSocket close, the node is automatically unregistered.

For the full node protocol and how capability names become agent tools, see Realtime: WebSocket, SSE & Live Canvas and the Hardware quickstart.