Skip to content

Expose gateway management tools (cron, sessions, agents, channels) over WebSocket JSON-RPC #27

Description

@smurfy92

Context

The MCP currently wraps /v1/chat/completions (the OpenAI-compatible endpoint) and exposes 7 tools focused on chat and async tasks. Great for delegating turns to a connected agent — but useless when no agent is connected: /v1/chat/completions then returns 404 Not Found, and every MCP call (openclaw_chat, even openclaw_task_list) becomes a dead end while the gateway itself is up and healthy.

Meanwhile the OpenClaw gateway also serves a management plane over a WebSocket JSON-RPC channel (the same channel the Control panel SPA at /api-docs uses). It covers cron jobs, sessions, agents, channels, skills, instances, logs — all the things you'd actually want to introspect from an MCP client when nothing is talking on the chat side.

Concrete scenario: I asked Claude Code to "list my OpenClaw cronjobs". With the current MCP there's no answer possible; the closest tool is openclaw_task_list which only enumerates async chat tasks (always empty for me).

Request

Add a second client (WebSocket JSON-RPC) and expose tools for at least:

  • cron.list, cron.status, cron.add, cron.run, cron.runs, cron.remove, cron.update, cron.wake
  • sessions.list
  • agents.list
  • channels.list

These would naturally live alongside the existing openclaw_* tools and reuse OPENCLAW_GATEWAY_TOKEN.

Reverse-engineered protocol (from the Control panel bundle)

Found in /api-docs/assets/index-*.js, around the new WebSocket(opts.url) site:

  • Transport: WebSocket to gatewayUrlwss://<gateway-host> for the Hostinger-managed deployment, ws://127.0.0.1:18789 or Tailscale ws://100.x.y.z:18789 for self-hosted setups.
  • Connect frame (sent ~750ms after open): { type: "connect", token, password?, clientName, clientVersion, mode, role, scopes, signedAtMs, nonce, ... }. With a stored device identity, an Ed25519 signature is added; without one, the gateway token alone is enough.
  • Request frame: { type: "req", id, method, params } — the panel's client.request("cron.list", { ... }) produces exactly this.
  • Response frames: { type: "res", id, result } and { type: "err", id, error: { code, message } }.

The cron.list params I observed in the bundle: { includeDisabled, limit, offset, query, enabled, sortBy, sortDir }. Returns { jobs, total, offset, nextOffset, hasMore }.

Workaround / prior art

I wrote a small wrapper (openclaw-claw-mcp) that does exactly this for cron — happy to clean it up and contribute as a PR if there's interest in absorbing it into the official package, or it can stay as a separate project. Either way, flagging the gap.

Versions

  • openclaw-mcp@1.4.1
  • Gateway: Hostinger-managed OpenClaw deployment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions