Protocol
cmd-ipc uses a JSON-based message protocol for communication between registries. All messages are sent via channels—either directly (MessagePortChannel, InMemoryChannel) or over HTTP (HTTPChannel) or MCP.
HTTP Endpoints
Section titled “HTTP Endpoints”When using HTTPChannel, two endpoints handle all communication:
GET /cmds.json — Schema Discovery
Section titled “GET /cmds.json — Schema Discovery”Returns all available commands with their schemas. Used for client type generation and service discovery.
GET /cmds.json HTTP/1.1Host: api.example.com{ "cmdschema": "1.0.0", "commands": [ { "id": "user.create", "description": "Creates a new user account", "isLocal": true, "schema": { "request": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string", "format": "email" } }, "required": ["name", "email"] }, "response": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "email": { "type": "string" } } } } } ]}POST /cmd — Message Transport
Section titled “POST /cmd — Message Transport”All protocol messages are sent via POST /cmd. The type field determines how the message is processed.
Default Transport: HTTP Streaming (NDJSON)
By default, HTTPChannel uses NDJSON (Newline-Delimited JSON) streaming for the response. Each message is a complete JSON object on its own line, allowing clients to process responses as they arrive:
{"id":"...","type":"execute.command.response","thid":"...","response":{"ok":true,"result":{...}}}{"id":"...","type":"event","eventId":"user.updated","payload":{...}}This streaming approach enables:
- Real-time event delivery — Events can be pushed to the client as they occur
- Progressive responses — Large results can be streamed incrementally
- Efficient long-polling — Single connection for both command responses and events
Transport Metadata (_meta)
Section titled “Transport Metadata (_meta)”Every message type MAY carry an optional _meta object — a transport-level envelope modelled on HTTP headers. It carries cross-cutting context (trace propagation, routing/correlation) that is orthogonal to the message’s business payload.
{ "id": "550e8400-e29b-41d4-a716-446655440000", "_meta": { "traceparent": "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01", "tracestate": "vendor1=opaque", "baggage": "userId=alice,region=eu-west-1" }, "type": "execute.command.request", "commandId": "user.create", "request": { "name": "John Doe" }}_metais always optional — absent is a valid message.- The reserved field set in v1 is the W3C Trace Context headers (see below). All other keys are free-form and round-trip untouched, so applications can extend
_metawith their own keys. _metais for transport concerns only. Do not put business data, secrets (auth tokens, API keys), or PII in it — treat it like HTTP headers.
Reserved fields
Section titled “Reserved fields”| Field | Type | Spec | Purpose |
|---|---|---|---|
traceparent | string | W3C Trace Context — traceparent | Identifies an incoming request inside a distributed trace. Format: <version>-<trace-id>-<parent-id>-<flags>. Lets a receiver continue the same trace its caller started. |
tracestate | string | W3C Trace Context — tracestate | Vendor-specific trace metadata that travels alongside traceparent. Carries per-vendor key/value pairs (e.g. sampling decisions) without invalidating the trace id. |
baggage | string | W3C Baggage | Application-defined key/value context that propagates with the trace (e.g. userId=alice,region=eu-west-1). Use for cross-cutting context every handler may need. |
Message Types
Section titled “Message Types”The protocol defines seven message types grouped into four categories. Every message type may optionally carry the _meta envelope described above; the field tables below omit it for brevity.
Command Execution
Section titled “Command Execution”execute.command.request
Section titled “execute.command.request”Request to execute a command on a remote registry.
{ "id": "550e8400-e29b-41d4-a716-446655440000", "type": "execute.command.request", "commandId": "user.create", "request": { "name": "John Doe", "email": "john@example.com" }}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "execute.command.request" |
commandId | string | The command to execute |
request | object? | Command arguments (optional) |
execute.command.response
Section titled “execute.command.response”Response from command execution, indicating success or failure.
Success:
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "type": "execute.command.response", "thid": "550e8400-e29b-41d4-a716-446655440000", "response": { "ok": true, "result": { "id": "usr_123", "name": "John Doe", "email": "john@example.com" } }}Error:
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "type": "execute.command.response", "thid": "550e8400-e29b-41d4-a716-446655440000", "response": { "ok": false, "error": { "code": "COMMAND_NOT_FOUND", "message": "Command not found: user.unknown" } }}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "execute.command.response" |
thid | string | Thread ID — matches the request’s id |
response.ok | boolean | Whether execution succeeded |
response.result | any? | Command result (when ok: true) |
response.error | object? | Error details (when ok: false) |
response.error.code | string | Error code (e.g., COMMAND_NOT_FOUND, VALIDATION_ERROR) |
response.error.message | string | Human-readable error message |
Command Registration
Section titled “Command Registration”Used when channels connect to share available commands up the tree.
register.command.request
Section titled “register.command.request”Registers a command from a remote registry.
{ "id": "550e8400-e29b-41d4-a716-446655440000", "type": "register.command.request", "command": { "id": "calc.factorial", "description": "Computes factorial of n", "schema": { "request": { "type": "object", "properties": { "n": { "type": "number" } } }, "response": { "type": "object", "properties": { "result": { "type": "number" } } } } }}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "register.command.request" |
command | object | Command definition |
command.id | string | Command ID (must be globally unique) |
command.description | string? | Optional description |
command.schema | object? | Optional JSON Schema for request/response |
register.command.response
Section titled “register.command.response”Acknowledgment of command registration.
Success:
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "type": "register.command.response", "thid": "550e8400-e29b-41d4-a716-446655440000", "response": { "ok": true }}Error (command already registered):
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "type": "register.command.response", "thid": "550e8400-e29b-41d4-a716-446655440000", "response": { "ok": false, "error": "COMMAND_ALREADY_REGISTERED" }}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "register.command.response" |
thid | string | Thread ID — matches request’s id |
response.ok | boolean | Whether registration succeeded |
response.error | string? | Error code (when ok: false) |
Command Discovery
Section titled “Command Discovery”Used to query available commands from a remote registry.
list.commands.request
Section titled “list.commands.request”Request a list of available commands.
{ "id": "550e8400-e29b-41d4-a716-446655440000", "type": "list.commands.request"}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "list.commands.request" |
list.commands.response
Section titled “list.commands.response”Returns available commands from the remote registry.
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "type": "list.commands.response", "thid": "550e8400-e29b-41d4-a716-446655440000", "commands": [ { "id": "math.add", "description": "Adds two numbers" }, { "id": "math.multiply", "description": "Multiplies two numbers" } ]}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "list.commands.response" |
thid | string | Thread ID — matches request’s id |
commands | array | List of command definitions |
Events
Section titled “Events”Broadcast message to all connected registries. Events are fire-and-forget—they have no response.
{ "id": "550e8400-e29b-41d4-a716-446655440000", "type": "event", "eventId": "user.created", "payload": { "userId": "usr_123", "name": "John Doe" }}| Field | Type | Description |
|---|---|---|
id | string | Unique message ID (UUID) |
type | string | "event" |
eventId | string | Event identifier (e.g., user.created) |
payload | any? | Event data (optional) |