Developers

Tool protocol

The local NDJSON socket protocol that the CLI, plugins, and agents use to reach the registry.

meith exposes its tool registry over a local newline-delimited JSON socket. The renderer uses Electron IPC, but it calls the same ToolRegistry and receives the same ToolResult shape.

Transport

The socket protocol is NDJSON: each line is one complete JSON frame. The runtime writes its socket path to ~/.meith/config.json and publishes live instance records in ~/.meith/instances/. Every message may include protocol; the current value is PROTOCOL_VERSION = 1. A mismatched version returns a transport error with PROTOCOL_ERROR.

Client messages

tool_call

Calls a registered tool. The response is zero or more tool_event frames, then one final tool_result frame.

json
{
  "type": "tool_call",
  "protocol": 1,
  "requestId": "req_ab12cd34",
  "toolName": "open_browser_tab",
  "arguments": { "url": "http://localhost:3000" },
  "clientInfo": {
    "caller": "cli",
    "cwd": "/work/project",
    "spaceId": "space_1",
    "tabId": "btab_1"
  },
  "timeoutMs": 30000
}

list_tools returns serializable tool descriptors, and cancel_tool_call cancels an in-flight call by request id. Cancellation is cooperative — the registry aborts the call signal and races execution against it so a cancelled call always resolves with a structured failure.

The ToolResult envelope

Every tool resolves to this envelope:

ts
interface ToolResult<T = unknown> {
  ok: boolean
  content?: T
  meta?: Record<string, unknown>
  diagnostics?: Array<{
    level: "info" | "warn" | "error"
    message: string
  }>
  error?: {
    code: ToolErrorCode
    message: string
    details?: unknown
  }
}

Tools may return either a raw value or a full ToolResult.

  • Raw values become { ok: true, content: value }.
  • okResult() and errorResult() create explicit envelopes.
  • Throwing ToolError controls the returned error code; any other throw becomes TOOL_FAILED.

Error codes: UNKNOWN_TOOL, VALIDATION_ERROR, PERMISSION_DENIED, TIMEOUT, TOOL_FAILED, RUNTIME_SHUTTING_DOWN, CANCELLED, and PROTOCOL_ERROR.

Capabilities

Each tool can declare safety metadata that PermissionService treats as authorization inputs.

CapabilityMeaning
read-onlyReads state, files, or metadata without mutating.
writes-filesCreates, modifies, deletes, or persists files or config.
controls-browserOpens, navigates, clicks, types, or screenshots tabs.
starts-processStarts or controls processes, terminals, or dev servers.
accesses-networkCauses network access directly or indirectly.
destructivePerforms high-impact, irreversible actions.

Caller identity

The socket is a local but untrusted boundary. ToolSocketService does not trust security-relevant caller claims from socket peers:

  • socket clients can assert cli or plugin,
  • attempts to assert renderer, agent, or internal are downgraded,
  • client-provided session ids are replaced by a server-assigned per-connection id.

Why it matters

This protects browser automation ownership. A socket peer cannot choose a session id to impersonate another owner. Renderer IPC is in-process and trusted as caller: "renderer", and agents call the registry in-process with their real session id.

Timeouts and auditing

Timeout order is tool_call.timeoutMs, then the tool definition's timeoutMs, then DEFAULT_TOOL_TIMEOUT_MS. Every registry call is logged and passed to PermissionService.auditToolCall; argument and result summaries redact likely secrets and large payloads before writing to audit.jsonl.