Overview

The Node client is a CLI wrapper around MCP-over-WebSocket to VAGUS relay. It supports pair/connect, read/call/list operations, and long-running subscriptions with JSONL output.

Entry: scripts/vagus-connect.js

Manager: scripts/vagus-manager.js

Session file: ~/.openclaw/vagus-session.json

Transport: wss://relay.withvagus.com/connect/<token>

Related: Server (Android App) for MCP surface and governance, Self-Hosted Relay for infrastructure setup.

Setup

cd ~/.openclaw/skills/vagus/scripts
npm install
node vagus-connect.js pair <PAIR_CODE>
node vagus-connect.js status

CLI Commands

node {baseDir}/scripts/vagus-connect.js <command> [args]
Command Args Description
pair<code>Pair and persist session token.
connectnoneConnect using saved session.
statusnoneGet connectivity and active modules.
read<uri>One-shot resource read.
subscribe<uri>Long-running JSONL stream with lifecycle, stream_state, and update events.
unsubscribe<uri>Stop a resource subscription.
call<tool> '<json>'Invoke a tool call.
list-resourcesnoneList available resource URIs.
list-toolsnoneList available tools + schemas.
disconnectnoneDelete local session file.
vagus-manager.js add<uri>Add a URI to the managed persistent subscription set.
vagus-manager.js remove<uri>Remove a URI from the managed persistent subscription set.
vagus-manager.js listnoneList active managed subscriptions.
vagus-manager.js statusnoneRead managed stream freshness state and lifecycle status.

JSONL Contract

All outputs are line-delimited JSON objects.

{"type":"paired","session_token":"..."}
{"type":"capabilities","resources":["..."],"tools":["..."]}
{"type":"resource","uri":"vagus://device/screen","data":{"screen_on":true,"locked":false}}
{"type":"stream_state","uri":"vagus://device/screen","status":"fresh","freshness_ms":132,"thresholds":{"observed_p95_interval_ms":1000,"delayed_after_ms":2500,"stale_after_ms":6000,"unavailable_after_ms":20000}}
{"type":"result","tool":"notify","success":true,"data":{"content":[{"type":"text","text":"{\"ok\":true}"}]}}

Request Metadata and Trace IDs

MCP response and notification envelopes include a top-level trace_id field when available. This identifier provides end-to-end correlation across request handling, outbound notifications, and server audit logs.

{
  "jsonrpc": "2.0",
  "id": 3,
  "trace_id": "43818824:tools/call:5545a8fa214dd67e:405164970b59034e",
  "result": {
    "content": [ { "type": "text", "text": "{\"ok\":true,\"id\":9098}" } ],
    "isError": false
  }
}
{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "trace_id": "43818824:resources/subscribe:5545a8fa214dd67e:aa3d70c94091b898",
  "params": {
    "sessionId": "5545a8fa214dd67e",
    "uri": "vagus://device/screen",
    "data": { "screen_on": true, "locked": false, "ts": 1772043993616 },
    "ts": 1772043993632
  }
}

The vagus-connect.js wrapper emits normalized JSONL and preserves MCP correlation context (including trace_id) in the mcp object for operational commands (read/call/list/subscribe/unsubscribe and streamed updates). If you need the full raw JSON-RPC envelope, capture raw MCP frames in custom integrations.

Managed Streaming

For persistent field operation, prefer vagus-manager.js over multiple independent subscribe processes. The manager keeps one MCP session alive, auto-reconnects, re-subscribes active URIs, and tracks adaptive freshness per stream.

node {baseDir}/scripts/vagus-manager.js
node {baseDir}/scripts/vagus-manager.js add vagus://sensors/location
node {baseDir}/scripts/vagus-manager.js remove vagus://inference/attention
node {baseDir}/scripts/vagus-manager.js list
node {baseDir}/scripts/vagus-manager.js status

Stale detection is dynamic: thresholds are learned from observed inter-arrival timing only. The manager does not assume a hard-coded cadence per resource.

Resources

  • vagus://session/info
  • vagus://sensors/motion, activity, activity_recognition, location, environment
  • vagus://inference/attention, indoor_confidence, sleep_likelihood, notification_timing
  • vagus://device/connectivity, screen, battery, clipboard, notifications
  • vagus://io/type_* dynamic onboard sensor resources (device-specific)
node {baseDir}/scripts/vagus-connect.js read vagus://session/info
node {baseDir}/scripts/vagus-connect.js subscribe vagus://device/screen

Subscriptions vs Read-Only

Before using subscribe, confirm the URI supports streaming semantics on the server.

URI read subscribe Node-Client Behavior
vagus://session/infoSupportedSupportedUse subscribe for ongoing runtime/session telemetry.
vagus://sensors/motionSupportedSupportedHigh-frequency stream; subscribe for continuous updates.
vagus://sensors/locationSupportedSupportedEvent-driven location updates during movement.
vagus://device/connectivitySupportedSupportedEvent-driven connectivity state changes.
vagus://device/clipboardSupportedNot supportedUse read only; subscribe returns MCP invalid request.
vagus://device/screenSupportedSupportedEvent-driven updates when screen state changes.
vagus://device/notificationsSupportedSupportedEvent-driven updates when notifications post/remove.
vagus://device/batterySupportedSupportedLow-frequency updates (~5 minutes) in subscription mode.
vagus://sensors/activity, activity_recognition, environment, vagus://inference/*SupportedSupportedCadence controlled by Infer resolution in app UI.
vagus://io/type_*SupportedSupportedCadence controlled by I/O resolution in app UI.

Tools

Tool Required Params Constraints / Governance
notifytitle, bodytitle/body max 200/1000; requires notifications capability enabled.
speaktexttext max 5000; optional voice/language/rate/pitch/interrupt values validated server-side.
sms/sendto, bodybody max 2000; Android SEND_SMS and SMS governance policy must allow.
intent/open_urlurlURL must be http/https; policy may enforce HTTPS-only.
calendar/create_eventtitleOptional start/end/location/description/allDay fields; calendar permissions and policy apply.
clipboard/setcontentcontent max 10000; blocked when clipboard capability is disabled.
haptic/pulsenoneOptional durationMs (10-5000, default 120); requires haptics capability and Android vibrate permission.
haptic/patternnoneOptional pattern integer array; requires haptics capability and Android vibrate permission.
agent/set_namenameMax 64 chars; empty string clears the stored name.
io/set_subscription_resolutionresolutionMsAllowed values: 1500, 10000, 30000, 60000, 90000, 120000, 300000; requires Allow agent to set resolution.
infer/set_subscription_resolutionresolutionMsAllowed values: 1500, 10000, 30000, 60000, 90000, 120000, 300000; requires Allow agent to set infer resolution.
node {baseDir}/scripts/vagus-connect.js call sms/send '{"to":"+14388090319","body":"Test message"}'
node {baseDir}/scripts/vagus-connect.js call intent/open_url '{"url":"https://withvagus.com"}'
node {baseDir}/scripts/vagus-connect.js call io/set_subscription_resolution '{"resolutionMs":30000}'
node {baseDir}/scripts/vagus-connect.js call infer/set_subscription_resolution '{"resolutionMs":30000}'
node {baseDir}/scripts/vagus-connect.js call calendar/create_event '{"title":"dayclub","startTimeMs":1771772400000,"endTimeMs":1771776000000,"allDay":false}'

io/set_subscription_resolution controls cadence for all vagus://io/type_* subscriptions and is gated by the device-side toggle Allow agent to set resolution (default off). infer/set_subscription_resolution controls infer cadence and is gated by Allow agent to set infer resolution (default off).

User Permissions (Server-Side)

Permissions are enforced in the VAGUS Android app. The Node client can issue MCP reads and tool calls, but execution is gated by user-configured capability toggles and runtime approval prompts.

Permission Layer Owner Node Client Impact
Module/capability enablementUser in VAGUS app settingsUnavailable capabilities fail at read/call time.
Runtime approval promptsUser on deviceSensitive tool calls may be approved, denied, or timeout.
Agent identity contextagent/set_name + app contextShown in approval/governance context.

Expected automation behavior: on permission denial/timeout, return a clear user action ("approve in VAGUS" or "enable permission"), then retry once.

Timeouts and Liveness

Setting Value
MCP request timeout22000ms
MCP initialize timeout20000ms
WS heartbeat interval30000ms
Pong timeout10000ms

Error Codes

Code Meaning
NO_COMMANDNo subcommand passed.
NO_SESSIONNo saved session file.
PAIR_FAILEDPairing API failed.
SESSION_EXPIREDToken rejected by relay.
CONNECT_FAILEDWSS connect/init failure.
BAD_JSONInvalid tool arg JSON.
READ_FAILEDResource read failed.
CALL_FAILEDTool invocation failed or timed out.
FATALUnhandled client error.