Documentation / Tool contract

VDO.Ninja MCP Tool Contract

Read in Markdown

Implemented by:

  • scripts/vdo-mcp-server.js
  • Installer automation: scripts/install-mcp.js
  • Discovery manifest: server.json

Transport

  • JSON-RPC 2.0 over stdio
  • Input:
  • newline-delimited JSON messages
  • Content-Length framed messages
  • Output:
  • framed when framed input is detected
  • newline JSON otherwise

Runtime Limit

  • VDON_MCP_MAX_MESSAGE_BYTES (default 1048576)
  • VDON_MCP_TOOL_PROFILE (default full, values: core|file|state|full)

Server CLI Flags

Supported by scripts/vdo-mcp-server.js:

  • --tool-profile <core|file|state|full>
  • --max-message-bytes <bytes>
  • --join-token-secret <secret>
  • --enforce-join-token <true|false>
  • --allow-peer-stream-ids <a,b,c>
  • --require-session-mac <true|false>

Capability Profiles

  • core: vdo_connect, vdo_send, vdo_receive, vdo_status, vdo_disconnect, vdo_list_sessions, vdo_capabilities, vdo_sync_peers, vdo_sync_announce
  • file: core + all file transfer tools
  • state: core + all state sync tools
  • full: core + file + state tools

Enforcement:

  • tools/list only advertises tools in the active profile.
  • Calling a disabled tool returns validation_error.

Core Session Tools

  • vdo_connect
  • vdo_send
  • vdo_receive
  • vdo_status
  • vdo_disconnect
  • vdo_list_sessions
  • vdo_capabilities

vdo_connect notable options

  • transport: room, stream_id, target_stream_id, transport (webrtc by default or http)
  • WebRTC: host, password, force_turn
  • HTTP relay: relay_url, relay_token, relay_key, with defaults from VDON_MCP_RELAY_URL, VDON_MCP_RELAY_TOKEN, VDON_MCP_RELAY_KEY; see relay setup and delivery semantics
  • resiliency: heartbeat_ms, reconnect_ms, max_reconnect_ms
  • security: join_token, join_token_secret, join_token_ttl_ms, enforce_join_token, allow_peer_stream_ids, require_session_mac
  • file defaults: file_chunk_bytes, file_max_bytes, file_ack_timeout_ms, file_max_retries
  • file spooling: file_spool_dir, file_spool_threshold_bytes, keep_spool_files
  • state limits: state_max_keys, state_max_snapshot_entries

vdo_status identifies the selected transport. HTTP is an explicit peer transport, independent of the HTTP endpoint used to expose MCP. Both participants must use the same transport. WebRTC-only options are rejected in HTTP mode; encryption cannot be disabled on the HTTP relay.

In HTTP mode, vdo_send returns message_id and delivery_stage (queued or rejected). A later relay_receipt event reports relay_accepted or delivery_unknown. Acceptance does not confirm peer consumption. data_received includes the matching message_id. relay_history_lost means a replay gap requires application reconciliation. Ordinary message queues and relay history are in memory; file completion still requires the existing peer acknowledgement.

Sync Tools

  • vdo_sync_peers: peer handshake/auth/state capabilities
  • vdo_sync_announce: force immediate sync hello

File Transfer Tools

  • vdo_file_send: send from data_base64
  • vdo_file_send_path: send directly from local file_path
  • vdo_file_resume: resume outgoing transfer by transfer_id
  • vdo_file_transfers: inspect incoming/outgoing transfer state
  • vdo_file_receive: read completed incoming payload (base64/utf8/json)
  • vdo_file_save: save completed incoming transfer directly to disk

A retained incoming transfer_id is bound to its originating peer UUID and offer metadata (content hash, byte count, chunk layout, name, and MIME type). Identical retries from that peer can resume or confirm completion. Reusing the ID for different content/metadata or from another peer is rejected; use a new ID for a new transfer. Reconnection with a new peer UUID does not transfer ownership of an existing retained ID. Completion acknowledgements must match the sender's content hash and byte count.

State Sync Tools (CRDT-lite)

  • vdo_state_set: update key/value with local monotonic clock
  • vdo_state_get: read key or full state snapshot
  • vdo_state_sync: request/send full snapshot (mode: request|send)

Merge rule is tuple-based last-writer:

  1. higher clock wins
  2. if equal clock, lexicographically higher actor wins

Protocol Envelope Family

Internal control/file/state envelopes use:

{
  "__vdo_mcp": "vdo_mcp_bridge_v1",
  "kind": "sync.* | file.* | state.*",
  "payload": {}
}

Event Types via vdo_receive

Lifecycle:

  • ready, connected, disconnected, connection_failed, sdk_error, reconnect_scheduled
  • peer_connected, peer_disconnected, data_channel_open, data_channel_close
  • data_received, send_error, send_rejected, heartbeat_sent

Sync/security:

  • sync_hello_sent, sync_peer_updated, sync_peer_rejected, protocol_auth_failed

File:

  • file_offer_received, file_chunk_received, file_chunk_rejected, file_received, file_transfer_complete, file_transfer_cancelled

State:

  • state_updated, state_snapshot_merged, state_protocol_unhandled

Error Shape

Tools return isError: true with:

{
  "ok": false,
  "error": {
    "type": "validation_error | tool_error",
    "message": "...",
    "tool": "..."
  }
}

Client Wiring

Automated registration:

npm i @vdoninja/mcp
npx vdon-mcp-install

Preset registrations:

npx vdon-mcp-install --preset core
npx vdon-mcp-install --preset file
npx vdon-mcp-install --preset state
npx vdon-mcp-install --preset secure-core
npx vdon-mcp-install --preset secure-full

Removal:

npx vdon-mcp-install --uninstall

Codex-style:

{
  "name": "vdo-ninja-mcp",
  "command": "node",
  "args": ["node_modules/@vdoninja/mcp/scripts/vdo-mcp-server.js"]
}

Claude Code-style:

{
  "mcpServers": {
    "vdo-ninja-mcp": {
      "command": "node",
      "args": ["node_modules/@vdoninja/mcp/scripts/vdo-mcp-server.js"]
    }
  }
}