Skip to content
Back to skills

Nodetool Api Reference

ASecurity

Integrate with NodeTool over REST, tRPC, MsgPack WebSocket, MCP, or the OpenAI-compatible Chat API, including the document surfaces and workflow execution.

  • 552 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 1, 2026
ai-agentsjavascripttypescriptpythonjavabashnodeapi

Works with

  • claude code
  • claude desktop
  • terminal
  • cli
  • api
  • mcp

Security analysis

A96/100
  • mediumUses curl or wget to download content

Pro shows the line behind each finding and how to fix it

Scanned October 3, 2026

npx -y skills add nodetool-ai/nodetool --skill nodetool-api-reference --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Nodetool Api Reference?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Nodetool Api Reference
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nodetool-ai-nodetool-api-reference/badge)](https://www.skillsdirectory.com/skills/nodetool-ai-nodetool-api-reference)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: nodetool-api-reference
description: "Integrate with NodeTool over REST, tRPC, MsgPack WebSocket, MCP, or the OpenAI-compatible Chat API, including the document surfaces and workflow execution."
---

You help users integrate with NodeTool's HTTP + WebSocket server (default `http://localhost:7777`). Start it with `nodetool serve` (flags: `--host`, `--port`).

# Surfaces

| Surface | Path prefix | Use case |
|---------|-------------|----------|
| **REST** | `/api/...` | Workflows, assets, collections, models, bundles, health |
| **tRPC** | `/trpc/...` | The document surfaces: timelines, storyboards, sketches, scripts, applications, JS scripts, projects, skills, settings |
| **OpenAI-compatible** | `/v1/...` | Chat completions + model list |
| **WebSocket** | `/ws` | Run/cancel/stream jobs, live chat, live editor tools |
| **MCP** | `/mcp` | Agent tools over streamable HTTP, for Claude Desktop and CLI agents |

The server mode (`desktop` / `private` / `public`) and auth are controlled by
environment variables (`NODETOOL_SERVER_MODE`, `AUTH_PROVIDER`), not CLI flags.

**Pick the right surface.** REST covers workflows, assets and the portable
bundles. Everything that is a *document* someone edits (a timeline sequence, a
storyboard, a sketch, a script, a mini app, a JS script) is a tRPC router, and
the REST routes for those kinds cover only import, export and build. An
integration that reads or writes a document calls tRPC, or calls the agent
capability of the same name over `/mcp`.

# Authentication

Authenticated endpoints use a Bearer token:
```
Authorization: Bearer <TOKEN>
```

The server picks its mode from the Supabase credentials:
- Supabase mode (`SUPABASE_URL` and `SUPABASE_KEY` both set): send a Supabase
  JWT. Every non-public endpoint requires it.
- Local mode (default): loopback requests need no token and run as user
  `"1"`. Other sources get `401`.

The server does not accept `SERVER_AUTH_TOKEN` as a bearer token.

# REST Endpoints

## Workflows

```bash
# List workflows
curl http://localhost:7777/api/workflows \
  -H "Authorization: Bearer TOKEN"

# Get a workflow
curl http://localhost:7777/api/workflows/<id> \
  -H "Authorization: Bearer TOKEN"

# Export helpers
curl http://localhost:7777/api/workflows/<id>/dsl-export      # TypeScript DSL
curl http://localhost:7777/api/workflows/<id>/export-bundle   # .nodetool bundle (zip)
```

> **Running a workflow is done over WebSocket** (`/ws`, see below), not via a REST
> `/run` endpoint. From a terminal you can also run with the CLI:
> `nodetool workflows run <id> --params '{"key":"value"}'`.

## Documents (tRPC)

The routers under `/trpc`, one per document kind:
`timeline`, `storyboards`, `sketch`, `scripts`, `applications`, `jsScripts`,
`workflows`, `projects`, `assets`, `collections`, `jobs`, `models`, `nodes`,
`memories`, `messages`, `threads`, `settings`, `skills`, `storage`, `packs`,
`costs`, `credits`, `files`, `fonts`, `games`, `integrations`, `triggers`,
`users`, `worker`, `workspace`.

Each follows the same shape: `list`, `get`, `create`, `update` (compare-and-swap
on `updated_at`), `delete`, plus sub-routers. Whole-document snapshots are
`timeline.versions`, `sketch.documentVersions` and `jsScripts.documentVersions`
(`sketch.versions` is a different thing: the per-layer generation takes).
`applications` also carries `publish`, `released`, `deploy`, `budget` and
`usage`, because publishing an app locks in the current graph of every workflow
it runs and caps what it may spend. Read the router in
`packages/websocket/src/trpc/routers/` for the exact procedure names rather than
guessing them. `/trpc/healthz` answers without auth.

An agent reaches the same data through the capability tools, which need no
client: `list_timelines`, `get_storyboard`, `edit_sketch`, `save_js_script`,
`edit_app`, and so on.

## Document REST routes

The REST side of the document kinds is import, export and build.

```bash
# Mini apps
curl http://localhost:7777/api/applications/:id/export-bundle       # app + every bound graph
curl -X POST http://localhost:7777/api/applications/import-bundle
curl -X POST http://localhost:7777/api/applications/build           # {prompt|spec, provider, model, ...}
curl -X POST http://localhost:7777/api/applications/debug
curl http://localhost:7777/api/applications/examples
curl -X POST http://localhost:7777/api/applications/examples/:slug/install

# Timelines and storyboards
curl http://localhost:7777/api/timelines/:id/export-zip
curl -X POST http://localhost:7777/api/timelines/import-zip
curl http://localhost:7777/api/storyboards/:id/export-zip
curl -X POST http://localhost:7777/api/timelines/:id/isolate-subject

# JS scripts
curl -X POST http://localhost:7777/api/js-scripts/:id/run
```

A build or an interactive debug runs for minutes, so those routes accept
`poll: true`, return a session id, and are read at
`GET /api/debug/sessions/:id` until they settle. Cancel with
`POST /api/debug/sessions/:id/cancel`.

## Collections (RAG)

```bash
# Index a file into a collection
curl -X POST http://localhost:7777/api/collections/<name>/index \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"file_path": "/path/to/document.pdf"}'
```

## Models

```bash
# OpenAI-compatible model list
curl http://localhost:7777/v1/models -H "Authorization: Bearer TOKEN"
```

## Storage / Assets

```bash
# Asset bytes are served under /api/storage/...
curl http://localhost:7777/api/storage/<path>
```

## Health

```bash
curl http://localhost:7777/health      # liveness (no auth)
curl http://localhost:7777/ready        # readiness
curl http://localhost:7777/api/health   # detailed health
```

# Chat API (OpenAI-Compatible)

## HTTP

```bash
# Chat completion
curl -X POST http://localhost:7777/v1/chat/completions \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Hello!"}
    ],
    "stream": false
  }'

# Streaming (Server-Sent Events)
curl -X POST http://localhost:7777/v1/chat/completions \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-5.4", "messages": [{"role": "user", "content": "Hi"}], "stream": true}'
```

## Python Client (OpenAI SDK)

```python
import openai

client = openai.OpenAI(api_key="TOKEN", base_url="http://localhost:7777/v1")

response = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)

# Streaming
stream = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
```

## JavaScript Client

```typescript
const response = await fetch("http://localhost:7777/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-5.4",
    messages: [{ role: "user", content: "Hello!" }],
    stream: false,
  }),
});
const data = await response.json();
console.log(data.choices[0].message.content);
```

# WebSocket API — Running Jobs

**Endpoint**: `ws(s)://<host>/ws`. Messages are an envelope `{ command, data }`.
(In the editor, MsgPack is used; JSON also works for simple clients.)

```typescript
const socket = new WebSocket("ws://localhost:7777/ws");

// Start a workflow run
socket.send(JSON.stringify({
  command: "run_job",
  data: {
    type: "run_job_request",
    api_url: "http://localhost:7777/api",
    workflow_id: "<uuid>",
    job_type: "workflow",
    auth_token: "<token>",
    params: { input_name: "value" },
    job_id: "<uuid>",
    user_id: "1",
    execution_strategy: "threaded",
  },
}));

socket.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  switch (msg.type) {
    case "job_update":
      console.log(`Job ${msg.status}`); // running | completed | failed | cancelled | suspended
      if (msg.result) console.log("Result:", msg.result);
      break;
    case "node_update":
      console.log(`Node ${msg.node_name}: ${msg.status}`);
      break;
    case "node_progress":
      console.log(`Progress: ${msg.progress}/${msg.total}`);
      break;
    case "output_update":
      console.log(`Output ${msg.output_name}:`, msg.value);
      break;
    case "chunk":
      process.stdout.write(msg.content);
      break;
    case "log_update":
      console.log(`[${msg.severity}] ${msg.content}`);
      break;
  }
};
```

## Job Control Commands

```typescript
socket.send(JSON.stringify({ command: "cancel_job",  data: { job_id: "...", workflow_id: "..." } }));
socket.send(JSON.stringify({ command: "pause_job",   data: { job_id: "...", workflow_id: "..." } }));
socket.send(JSON.stringify({ command: "resume_job",  data: { job_id: "...", workflow_id: "..." } }));

// Stream input into a running node, then close the stream
socket.send(JSON.stringify({ command: "stream_input",     data: { input: "name", value: "data", handle: "..." } }));
socket.send(JSON.stringify({ command: "end_input_stream", data: { input: "name", handle: "..." } }));
```

# Server Message Types

| Type | Key fields | Purpose |
|------|-----------|---------|
| `job_update` | `status`, `result`, `error`, `cost` | Job lifecycle |
| `node_update` | `node_id`, `node_name`, `status`, `error`, `result` | Node lifecycle |
| `node_progress` | `progress`, `total`, `chunk` | Progress tracking |
| `output_update` | `output_name`, `value`, `output_type` | Node output values |
| `log_update` | `content`, `severity` | Log messages |
| `chunk` | `content`, `done` | Streaming text |

# MCP

`/mcp` serves the agent capability tools over streamable HTTP, so an outside
agent drives NodeTool with the same calls the in-product agent uses. Reach it
three ways:

- `nodetool mcp install` configures a CLI agent (Claude Code, Codex).
- In a NodeTool checkout, `npm run build:mcpb` builds `dist/nodetool.mcpb`, a one-file bundle Claude
  Desktop installs by drag-and-drop. It is a stdio-to-HTTP bridge against a
  running server's `/mcp`, and it starts in offline mode when the server is
  down, then hot-attaches when it appears.
- A deployed server is reached by pointing the client at `/mcp` with a token
  minted in **Settings → MCP → Connect an agent remotely**.

# Server Management (CLI)

```bash
nodetool serve                        # Start server (default 127.0.0.1:7777)
nodetool serve --host 0.0.0.0          # Bind all interfaces
nodetool serve --port 8080             # Custom port
nodetool workflows list                # List saved workflows
nodetool workflows get <id>            # Get workflow details
nodetool workflows run <id>            # Run a workflow (uses the local DB)
nodetool jobs list                     # List execution jobs
nodetool secrets store OPENAI_API_KEY  # Store an API key
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.