opentool_daemon 0.2.2 copy "opentool_daemon: ^0.2.2" to clipboard
opentool_daemon: ^0.2.2 copied to clipboard

A HTTP Daemon Server to manage native OpenTool Servers.

OpenTool Daemon HTTP API Documentation #

English | 中文

OpenTool Daemon is a lightweight HTTP daemon that keeps track of local OpenTool servers and running tool processes. The daemon listens on http://127.0.0.1:19627/opentool-daemon by default and exposes REST + Server-Sent Event (SSE) endpoints that can be consumed by the CLI or any other automation.


Build & Run #

# install dependencies
dart pub get

# build release binaries
dart compile exe bin/opentool_daemon.dart -o build/opentoold  # macOS / Linux
# dart compile exe bin/opentool_daemon.dart -o build/opentoold.exe  # Windows

# run locally
dart run bin/opentool_daemon.dart --config bin/config.json

The daemon will persist metadata under ~/.opentool (servers, tools, config) and write logs to log/daemon.log.

Configuration #

  • bin/config.json is optional. If the file is missing or only contains null fields the daemon falls back to the defaults (host: 127.0.0.1, port: 19627, prefix: /opentool-daemon, log.level: INFO).
  • Any field you provide overrides the default while other properties stay untouched; e.g. { "server": { "port": 20000 } } keeps the host/prefix unchanged.
  • The daemon always injects the pubspec.yaml version into the in-memory config, so you rarely need to set version manually.

API Overview #

All paths below are relative to the base prefix /opentool-daemon.

Group Method Path Description
Manage GET /version Health check and daemon version
Manage POST /apiKey Create a daemon API key (requires sudo token)
Manage GET /apiKeys List daemon API keys (requires sudo token)
Manage DELETE /apiKey/{apiKey} Delete a daemon API key (requires sudo token)
Server GET /servers/list List cached OpenTool servers
Server POST /servers/build Build a server from an Opentoolfile (SSE stream)
Server DELETE /servers/{serverId} Delete a server record
Server POST /servers/{serverId}/tag Add or reuse a tag for an existing server
Server GET /servers/{serverId}/export Copy an .ots to a destination folder
Server POST /servers/import Import an external .ots file
Server POST /servers/{serverId}/alias Rename a server alias
Tool GET /tools/list List running tools (or all tools)
Tool GET /tools/listWithApiKeys List tools and their API keys (requires daemon API key)
Tool GET /tools/events Subscribe to tool lifecycle events over SSE
Tool POST /tools/create Run a tool from a server definition (SSE stream)
Tool POST /tools/{toolId}/start Restart a previously created tool (SSE stream)
Tool POST /tools/{toolId}/stop Stop a running tool
Tool DELETE /tools/{toolId} Stop and remove a tool
Tool POST /tools/{toolId}/call Call a tool function (JSON RPC)
Tool POST /tools/{toolId}/streamCall Stream tool responses over SSE
Tool GET /tools/{toolId}/load Return the OpenTool JSON spec
Tool POST /tools/{toolId}/alias Rename a tool alias

Notes on Streaming Endpoints #

/servers/build, /tools/create, /tools/{id}/start, and /tools/{id}/streamCall return text/event-stream. Events follow this format:

event:START|DATA|DONE|ERROR
data:{"json":"payload"}

Use the client in lib/src/client/client.dart or any SSE-capable HTTP library to consume them.

Internal daemon endpoints related to OpenTool Hub synchronization are intentionally omitted from this public developer document.

Security Headers & Tokens #

  • x-opentool-sudo-token: single-use header that protects the API key endpoints. Generate a token as an administrator (the CLI calls SudoUtil.ensureSudoAndWriteToken) which writes ~/.opentool/opentool-daemon.sudo. There is no HTTP endpoint to mint this token, so a plain HTTP client cannot call /apiKey* until you first obtain the token via the CLI with sudo/admin privileges. Pass the token value in requests to /apiKey*; without it, API key management calls are rejected (403). The daemon validates the token against the file and deletes it (or expires it) after the first successful call.
  • x-opentool-api-key: persistent API keys created via POST /apiKey. Send the key in this header when accessing /tools/listWithApiKeys or any other API key-gated endpoint. Keys are stored in the Hive database under ~/.opentool/db (box name api_keys) and can be revoked via DELETE /apiKey/{apiKey}.

Manage API Examples #

GET /version #

{
  "name": "OpenTool Daemon",
  "version": "0.1.0"
}

POST /apiKey (requires x-opentool-sudo-token) #

Set the header to the temporary token dropped at ~/.opentool/opentool-daemon.sudo and optionally name the key:

POST /opentool-daemon/apiKey
x-opentool-sudo-token: <temp-token>
{
  "name": "dev-console"
}

Response:

{
  "name": "dev-console",
  "apiKey": "pk_opentool_123",
  "createdAt": "2024-05-01T12:30:00.000Z"
}

GET /apiKeys (requires x-opentool-sudo-token) #

Returns every stored API key using the same sudo header. Pair this endpoint with a secure UI to audit daemon access tokens.

[
  {
    "name": "dev-console",
    "apiKey": "pk_opentool_123",
    "createdAt": "2024-05-01T12:30:00.000Z"
  }
]

DELETE /apiKey/{apiKey} (requires x-opentool-sudo-token) #

Removes the selected key immediately; running tools that relied on that key will fail the next privileged call.


Server API Examples #

GET /servers/list #

[
  {
    "id": "srv-1",
    "alias": "alpha",
    "registry": "native",
    "repo": "native",
    "name": "demo-server",
    "tag": "latest"
  }
]

POST /servers/build?opentoolfile=/path/to/repo&name=demo&tag=latest #

Streams build progress for each command listed in Opentoolfile. event:DATA packets contain:

{
  "script": "dart run build",
  "output": "..."
}

event:DONE closes the stream once the .ots artifact is stored under ~/.opentool/servers.

POST /servers/{serverId}/tag?tag=stable #

Returns the tagged server DTO. If the tag already exists for the same internal build, the existing record is reused.

GET /servers/{serverId}/export #

Provide a JSON body { "path": "/tmp/output" } describing the destination directory. The daemon copies the .ots into that folder using the pattern <repo>-<name>-<tag>-<os>-<cpu>.ots.

POST /servers/import #

{
  "path": "/tmp/server.ots"
}

Response mirrors OpenToolServerDto for the imported build.


Tool API Examples #

GET /tools/list?all=1 #

Returns every tool entry. Omit all or set it to 0 to only receive running tools. Each entry may include serverId and a server object containing repo, name, and tag to identify the source server used when the tool was created. The server object is omitted when the source server is unavailable.

GET /tools/listWithApiKeys?all=0 (requires x-opentool-api-key) #

Send any daemon API key via the header described earlier to receive the same tool list plus the per-tool API keys:

[
  {
    "id": "tool-1",
    "alias": "alpha",
    "host": "127.0.0.1",
    "port": 9001,
    "apiKey": "tool_pk_abc",
    "status": "RUNNING",
    "serverId": "srv-1",
    "server": {
      "repo": "hub/opentool",
      "name": "demo",
      "tag": "1.0.0"
    }
  }
]

GET /tools/events?snapshot=1 (requires x-opentool-api-key) #

Subscribes to daemon-managed tool lifecycle events. This stream is intended for clients that maintain a live set of currently usable tools.

Event semantics:

  • tool.snapshot: initial snapshot for each cached tool when snapshot=1 (default).
  • tool.draining: emitted before a tool is asked to stop or before deletion starts. Remove the tool from your ready set immediately.
  • tool.ready: emitted only after the daemon can successfully call the tool's /version endpoint.
  • tool.unavailable: emitted when the daemon detects a previously running tool has become unreachable.
  • tool.removed: emitted after the daemon removes the tool metadata entry.

Example:

event:ready
data:{"message":"subscribed"}

event:tool.snapshot
data:{"type":"tool.snapshot","reason":"snapshot","tool":{"id":"tool-1","alias":"alpha","host":"127.0.0.1","port":9001,"status":"running"},"occurredAt":"2026-03-07T00:00:00.000Z"}

event:tool.draining
data:{"type":"tool.draining","reason":"stop_requested","tool":{"id":"tool-1","alias":"alpha","host":"127.0.0.1","port":9001,"status":"running"},"occurredAt":"2026-03-07T00:01:00.000Z"}

event:tool.ready
data:{"type":"tool.ready","reason":"started","tool":{"id":"tool-2","alias":"beta","host":"127.0.0.1","port":9002,"status":"running"},"occurredAt":"2026-03-07T00:01:05.000Z"}

POST /tools/create?serverId=srv-1&hostType=local&timeout=20 #

Starts a tool from the selected server. SSE events deliver command output (event:DATA) or errors (event:ERROR). The daemon allocates a new port, API key, and workspace under ~/.opentool/tools/{toolId}. The request only completes successfully after the tool passes the daemon readiness check, and /tools/events emits tool.ready. Optional query parameters:

  • hostType: local, remote, or omitted for any (pass-through to the tool runtime).
  • timeout: number of seconds before the daemon closes the SSE connection even if the tool keeps starting; the process continues in the background.

Optional request body (persisted on the tool and reused on restart):

{
  "args": ["--foo bar", "--baz qux"]
}

args is a string array appended after the Opentoolfile CMD and stored with the tool; /tools/{toolId}/start will reuse them. It must not include --opentoolServerTag / --opentoolServerHost / --opentoolServerPort / --opentoolServerApiKeys, which are injected by the daemon; supplying them returns 400.

POST /tools/{toolId}/start?timeout=20 exposes the same SSE behavior for restarting an existing tool directory. The daemon emits tool.ready only after the restarted tool becomes reachable.

POST /tools/{toolId}/call #

Request body should follow the OpenTool function-call schema:

{
  "id": "call-001",
  "name": "status",
  "arguments": {"depth": 1}
}

Response is a ToolReturn JSON payload produced by the tool process.

POST /tools/{toolId}/streamCall #

Behaves like /call, but emits SSE packets so long-running invocations can stream tokens or intermediate results.

GET /tools/{toolId}/load #

Returns the OpenTool JSON description parsed from the packaged Opentoolfile.json. Use /tools/{toolId}/alias?alias=new-name (POST) to rename a tool entry, /tools/{toolId}/stop to stop the process, and DELETE /tools/{toolId} to remove it entirely. Stopping emits tool.draining before the stop command is sent; deleting emits tool.draining first and tool.removed after the cache entry is deleted.


Client Library #

lib/src/client/client.dart provides a strongly-typed Dart client that wraps the manage/server/tool APIs, handles SSE parsing, and mirrors every endpoint listed above, including /tools/events. Import it in other Dart packages to integrate with the daemon without reimplementing the HTTP/SSE plumbing.


Need more detail? Check lib/src/controller for DTO definitions and lib/src/service for the exact side effects of each endpoint.

1
likes
130
points
113
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A HTTP Daemon Server to manage native OpenTool Servers.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

archive, crypto, dio, hive, json_annotation, logging, opentool_dart, path, shelf, shelf_router, unique_id_dart, uuid, yaml

More

Packages that depend on opentool_daemon