@vdoninja/mcp 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -661
- package/README.md +59 -272
- package/assets/browser-agent/audio-worklet.js +17 -0
- package/assets/browser-agent/client.js +124 -0
- package/assets/browser-agent/index.html +50 -0
- package/assets/cloudflare/worker-proxy.js +3 -0
- package/docs/.nojekyll +0 -0
- package/docs/404.html +28 -0
- package/docs/advanced-diagnostics.html +101 -0
- package/docs/assets/apple-touch-icon.png +0 -0
- package/docs/assets/favicon.svg +7 -0
- package/docs/assets/how-it-works.svg +62 -0
- package/docs/assets/icon-192.png +0 -0
- package/docs/assets/icon-512.png +0 -0
- package/docs/assets/icon-maskable-512.png +0 -0
- package/docs/assets/icons.svg +42 -0
- package/docs/assets/logo.svg +7 -0
- package/docs/assets/og-image.png +0 -0
- package/docs/assets/site.css +735 -0
- package/docs/assets/site.js +289 -0
- package/docs/browser-agent.html +122 -0
- package/docs/browser-worker.html +165 -0
- package/docs/client-config-examples.html +254 -0
- package/docs/direction.html +175 -0
- package/docs/favicon.ico +0 -0
- package/docs/guide.html +872 -0
- package/docs/http-relay.html +154 -0
- package/docs/index.html +834 -0
- package/docs/mcp-tool-contract.html +226 -0
- package/docs/quickstart-and-compat.html +222 -0
- package/docs/site.webmanifest +16 -0
- package/docs/sitemap.xml +63 -0
- package/docs/ssapp-integration.html +594 -0
- package/docs/vdo-ninja-p2p-data-notes.html +225 -0
- package/package.json +51 -9
- package/references/advanced-diagnostics.md +2 -0
- package/references/browser-agent.md +53 -0
- package/references/browser-worker.md +142 -0
- package/references/client-config-examples.md +2 -0
- package/references/direction.md +88 -0
- package/references/http-relay.md +107 -0
- package/references/mcp-tool-contract.md +11 -1
- package/references/quickstart-and-compat.md +4 -1
- package/references/ssapp-integration.md +371 -0
- package/references/vdo-ninja-p2p-data-notes.md +2 -0
- package/scripts/demo-file-workflow.js +3 -0
- package/scripts/demo-message-workflow.js +3 -0
- package/scripts/install-mcp.js +5 -2
- package/scripts/lib/bridge-session.js +143 -26
- package/scripts/lib/bridge-utils.js +3 -0
- package/scripts/lib/browser-agent.js +255 -0
- package/scripts/lib/browser-media.js +79 -0
- package/scripts/lib/browser-routes.js +119 -0
- package/scripts/lib/browser-rpc.js +214 -0
- package/scripts/lib/browser-setup.js +133 -0
- package/scripts/lib/browser-worker.js +216 -0
- package/scripts/lib/fake-network-sdk.js +3 -0
- package/scripts/lib/http-relay-transport.js +294 -0
- package/scripts/lib/load-vdo-sdk.js +3 -0
- package/scripts/lib/mcp-stdio-parser.js +3 -0
- package/scripts/lib/ssapp-worker.js +198 -0
- package/scripts/lib/tool-profiles.js +3 -0
- package/scripts/vdo-data-bridge.js +3 -0
- package/scripts/vdo-mcp-browser-agent.js +132 -0
- package/scripts/vdo-mcp-browser.js +218 -0
- package/scripts/vdo-mcp-relay.js +207 -0
- package/scripts/vdo-mcp-server.js +50 -7
- package/scripts/vdo-mcp-ssapp.js +208 -0
- package/scripts/vdo-mcp-streamable-http.js +23 -4
- package/server.json +22 -4
- package/LICENSE-SDK-EXCEPTION +0 -54
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Direction: live tools and perception for MCP agents
|
|
2
|
+
|
|
3
|
+
[Read this guide in HTML](https://steveseguin.github.io/ninjamcp/direction.html)
|
|
4
|
+
|
|
5
|
+
Ninja MCP should give an MCP-capable agent a focused way to reach trusted peers, use authorized remote tools, and see and hear selected live context across computers. Keep setup small, prefer direct peer connections, and preserve useful data interactions when WebRTC is unavailable.
|
|
6
|
+
|
|
7
|
+
The defining experience is an agent working with someone through their existing AI client: the person shows a camera or screen, the agent uses an authorized remote tool or consults a peer, and the result comes back with live context. The person can interrupt speech, change the request, take back control, or stop sharing immediately.
|
|
8
|
+
|
|
9
|
+
Two agents exchanging a short text message must remain easy. Media, a model-provider account, a background daemon, and a workflow engine should be optional.
|
|
10
|
+
|
|
11
|
+
## Complement ninja-p2p
|
|
12
|
+
|
|
13
|
+
| Project | Main responsibility | User's starting point |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| **Ninja MCP** | Active connections, MCP tool contracts, scoped remote operations, and live media access, including an optional shared Chrome worker. | Add an MCP server to an existing AI client and call a tool. |
|
|
16
|
+
| [ninja-p2p](https://github.com/steveseguin/ninja-p2p) | The continuing team workspace: sidecars, identities and profiles, local inbox/outbox, handoffs, receipts, wake hooks, files, and the operator dashboard. | Start a sidecar, join the team, and retain work between agent turns. |
|
|
17
|
+
| [VDO.Ninja SDK](https://sdk.vdo.ninja/) | Reusable peer connectivity, data channels, and audio/video transport. | Build an application or adapter. |
|
|
18
|
+
|
|
19
|
+
ninja-p2p owns the room's continuing conversation and work lifecycle. Ninja MCP owns how an MCP client accesses an active peer or remote capability. A shared Chrome worker belongs with Ninja MCP's remote tool adapters; assigning its work and retaining the team's handoffs belong with ninja-p2p. Voice and vision support both experiences through shared SDK media adapters. See [ninja-p2p's north star](https://github.com/steveseguin/ninja-p2p/blob/main/docs/north-star.md).
|
|
20
|
+
|
|
21
|
+
Keep both usable independently. An optional Ninja MCP adapter should expose ninja-p2p's existing directory, inbox, handoff, and receipt operations, with ninja-p2p remaining the owner of those records. It should preserve origin, request identity, permissions, and the difference between storage acknowledgement and task completion. Extend that integration for background work instead of adding a second inbox, wake scheduler, or team task store to Ninja MCP.
|
|
22
|
+
|
|
23
|
+
Current room and file envelopes differ between the packages. Sharing the SDK or a room name does not provide application interoperability; use matching packages until an explicit adapter is available. Coordinate reusable relay contracts and media adapters across the projects while keeping their storage and execution guarantees explicit.
|
|
24
|
+
|
|
25
|
+
## Available foundation
|
|
26
|
+
|
|
27
|
+
- MCP tools for messages, files, peer discovery, and shared state.
|
|
28
|
+
- Direct WebRTC and optional TURN connectivity.
|
|
29
|
+
- An explicit, self-hosted encrypted HTTP relay for machines and networks without WebRTC.
|
|
30
|
+
- Tool profiles, peer allowlists, join tokens, and per-peer protocol MACs.
|
|
31
|
+
- An optional [Chrome worker](browser-worker.md) with individual client credentials, tab leases, snapshots, screenshots, and SDK tab audio/video.
|
|
32
|
+
- Guided browser setup, connection diagnostics, and automatic WebRTC/HTTP routing with one request identity and worker result cache.
|
|
33
|
+
- An optional [browser companion](browser-agent.md) with OpenAI Realtime speech, selected browser frames, explicit control permission, and interruption.
|
|
34
|
+
- An optional [SSApp bridge](ssapp-integration.md) for the running app's MCP tools, screenshots, input and dialogs, with individual credentials and one controller at a time.
|
|
35
|
+
|
|
36
|
+
The HTTP path uses POST and long polling with bounded replay. It is a live transport, not a durable inbox. Ordinary room sessions choose matching transports explicitly; the browser adapter can use both. Browser media uses WebRTC separately. A compatible ninja-p2p relay can serve both projects, while its hosted mailboxes retain work between agent turns. Relay acceptance, agent wake, and completed work remain separate outcomes.
|
|
37
|
+
|
|
38
|
+
## What to build next
|
|
39
|
+
|
|
40
|
+
1. **Make live tool interactions dependable.** Expose peer capabilities, active connection status, bounded requests, and clear results through a small MCP surface. Distinguish queue acceptance, peer responses, progress, and completion. Bind remote operations to an authenticated caller and an explicit worker permission. Receiving a message never grants permission to execute commands.
|
|
41
|
+
2. **Extend dependable routing beyond browser tools.** Preserve request identity, authentication, and receipt meaning when moving between direct WebRTC, TURN, and the HTTP relay. Carry the browser adapter's direct, relay-only, and automatic policies into other tool adapters where execution can be reconciled. Add SSE where it helps, and make interrupted or uncertain operations visible. Build the optional ninja-p2p adapter for work that must wait in a persistent inbox. Keep large file bytes separate from latency-sensitive events.
|
|
42
|
+
3. **Expand shared perception deliberately.** Build on the browser companion's microphone, selected frames, timestamps, and interruptible speech. Add camera and screen selection before expanding providers, keeping recipients visible and recording off by default. Preserve text and selected snapshots when live media cannot connect. Reuse the media adapter in ninja-p2p's team dashboard.
|
|
43
|
+
4. **Connect to continuing collaboration.** Expose ninja-p2p handoffs and receipts through an optional MCP adapter, preserving the sidecar's state and delivery semantics. Map progress, artifacts, input requests, cancellation, and results to the owning worker or task system. An A2A adapter should share those contracts across the projects. Keep delegation limits and background wake policy with the system that runs them.
|
|
44
|
+
|
|
45
|
+
Transporting a video track does not make a model understand it. Media adapters should support native streaming models or a pipeline of speech recognition, a text/vision model, and speech synthesis. Stop queued speech on interruption; treat cancelling the underlying task as a separate action.
|
|
46
|
+
|
|
47
|
+
## Build on the VDO.Ninja SDK
|
|
48
|
+
|
|
49
|
+
The MCP bridge already uses `@vdoninja/sdk`. Reuse its media publishing and track events for voice, camera, screen, and browser streams. Its request/reply helpers provide a starting point for remote operations; application authorization, stable task IDs, and retry handling still belong to the worker. Keep large transfers on separate data channels and use queue limits so file traffic does not delay controls. See the [SDK API](https://sdk.vdo.ninja/docs/api-reference.html) and [remote-control guide](https://sdk.vdo.ninja/docs/remote-control.html).
|
|
50
|
+
|
|
51
|
+
The SDK's RPC helpers and Ninja MCP's room protocol are separate interfaces. Connect them through a versioned adapter that preserves authentication and request identity across WebRTC and HTTP. Do not assume an SDK request handler inherits the MCP bridge's peer checks.
|
|
52
|
+
|
|
53
|
+
## Optional shared Chrome worker
|
|
54
|
+
|
|
55
|
+
The [browser worker](browser-worker.md) lets people and agents use one isolated remote Chrome tab. The host runs a local Chrome DevTools MCP server and a Ninja room participant. Agents send authenticated tool requests through Ninja MCP; the worker executes them locally and returns results. The host connects outward through WebRTC or the configured HTTPS relay, keeping Chrome's debugging endpoint private. This design needs no VPN, VNC, or VLC. Connectivity still depends on the host's allowed outbound routes.
|
|
56
|
+
|
|
57
|
+
The adapter pins [Chrome DevTools MCP](https://github.com/ChromeDevTools/chrome-devtools-mcp) and Puppeteer as optional dependencies, with explicit page targeting and a separate browser runtime. An extension-based server such as [mcp-chrome](https://github.com/hangwin/mcp-chrome) remains an alternative for an operator's existing browser. [Remote Ninja](https://github.com/steveseguin/remote_ninja) provides an existing VDO.Ninja example of forwarding remote operations to a local application.
|
|
58
|
+
|
|
59
|
+
Allow multiple observers and give one agent a time-limited control lease for a tab. Hold the lease across a multi-step interaction, check its owner and generation before executing queued commands, and reject stale commands after handoff. Use explicit page IDs and require fresh page state after navigation. Operations affecting the whole browser need coordination across tabs. A human can revoke control; disconnected controllers must not retain an indefinite lock.
|
|
60
|
+
|
|
61
|
+
Optional live video and captured tab audio travel through SDK media tracks, separately from commands and file transfers. The host explicitly enables Chrome tab capture for the isolated worker. Snapshots remain available when live media cannot connect, and visual responses carry capture timestamps. The browser companion consumes selected frames and the operator's microphone, with separate controls for live viewing, model sharing, and browser control.
|
|
62
|
+
|
|
63
|
+
The first worker milestone is two agents taking turns on one isolated tab, a human watching its SDK stream, and correlated command results across reconnects. Use bounded requests, enforce permissions at the worker, and reconcile uncertain outcomes before retrying clicks or form submissions. Live audio capture and interruption belong in that milestone's media path; a video recording alone does not provide an interactive call. Shared room membership or possession of a relay key must not automatically grant browser control.
|
|
64
|
+
|
|
65
|
+
## Ideas to carry forward
|
|
66
|
+
|
|
67
|
+
| Project | Useful contribution |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| [Reason Network](https://github.com/reason-machines/reason-network) | A directory of live sessions, context-aware addressing, immediate or deferred delivery, and relay-backed connectivity. |
|
|
70
|
+
| [A2A](https://a2a-protocol.org/latest/specification/) | Capability cards, explicit task lifecycles, streaming progress, and artifacts. |
|
|
71
|
+
| [Agent Relay](https://github.com/AgentWorkforce/relay) | Direct messages, channels, threads, and an inspectable conversation. |
|
|
72
|
+
| [MCP Agent Mail](https://github.com/Dicklesworthstone/mcp_agent_mail) | Durable mail and searchable threads for ninja-p2p's continuing workspace, accessible through an optional MCP adapter. |
|
|
73
|
+
| [agents-party](https://github.com/1gr14/agents-party) | A shared room where people can follow and participate in agent collaboration. |
|
|
74
|
+
| [ntfy](https://docs.ntfy.sh/subscribe/api/) and [NATS JetStream](https://docs.nats.io/learn/jetstream/delivery-and-acknowledgment) | Replay cursors, bounded retrieval, explicit acknowledgements, and redelivery. |
|
|
75
|
+
| [Pipecat](https://github.com/pipecat-ai/pipecat), [LiveKit Agents](https://docs.livekit.io/agents/), and [FastRTC](https://github.com/gradio-app/fastrtc) | Agents as media participants, interchangeable media/model adapters, interruption handling, and short runnable examples. |
|
|
76
|
+
| [Social Stream](https://github.com/steveseguin/social_stream/blob/main/api.md) | Simple POST and SSE interaction patterns for a separately operated agent relay. |
|
|
77
|
+
|
|
78
|
+
Use these as design references. Adopt an idea when it helps participants communicate, retain context, share perception, or control the work. Keep orchestration platforms, public directories, file reservations, and search optional until their value justifies their complexity.
|
|
79
|
+
|
|
80
|
+
## Product boundaries
|
|
81
|
+
|
|
82
|
+
Ninja MCP should stay useful to one MCP client using one remote capability. ninja-p2p should stay useful to a continuing team using its CLI, library, or dashboard. The SDK and shared transport/media adapters support both. A feature belongs in Ninja MCP when it improves tool access, active-session reliability, remote control, or live perception; durable team coordination belongs in ninja-p2p.
|
|
83
|
+
|
|
84
|
+
Privacy needs explicit membership and route visibility. Future invitations should be revocable and scoped. Relay authentication and encryption are separate concerns; a TLS connection alone does not hide plaintext from a relay. Cloud model processing must be visible even when transport to the agent is encrypted.
|
|
85
|
+
|
|
86
|
+
Reliable delivery does not guarantee exactly-once execution of an external action. Preserve request IDs, use idempotency where supported, and expose an uncertain outcome after a crash instead of silently repeating consequential work.
|
|
87
|
+
|
|
88
|
+
Judge progress by successful collaborations with a clear result and less manual context copying. Track time to first exchange, missing or duplicate deliveries, reconnect delay, file integrity, and resource cost. For media, measure transport delay, model response time, and interruption response separately.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Connect without WebRTC
|
|
2
|
+
|
|
3
|
+
[Read this guide in HTML](https://steveseguin.github.io/ninjamcp/http-relay.html)
|
|
4
|
+
|
|
5
|
+
Use the HTTP relay when a machine cannot run the native WebRTC library or its network blocks WebRTC. Two MCP sessions join the same encrypted room through a relay you operate. Messages, file transfers, and shared state use the existing MCP tools.
|
|
6
|
+
|
|
7
|
+
WebRTC remains the default. Select `transport: "http"` on both participants to use the relay. Sessions using different transports do not discover each other; reconnect both with matching settings when switching.
|
|
8
|
+
|
|
9
|
+
## Run the relay
|
|
10
|
+
|
|
11
|
+
The relay needs Node.js 18 or newer and no native dependencies. From a checkout:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
$env:VDON_RELAY_TOKEN = '<a random access token, at least 32 characters>'
|
|
15
|
+
node scripts/vdo-mcp-relay.js
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
From an installed package, use `npx vdon-mcp-relay`. The default listener is `127.0.0.1:8790`. Set `VDON_RELAY_HOST` and `VDON_RELAY_PORT` to change it.
|
|
19
|
+
|
|
20
|
+
Generate the access token and a separate room key by running this command twice:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Keep the room key on the participating clients. The relay receives only the access token. Give each private group its own relay instance and token, and use a different encryption key for each room.
|
|
27
|
+
|
|
28
|
+
For other computers to connect, put the relay behind an HTTPS reverse proxy on your server. Forward `/v1/rooms/` unchanged, preserve the `Authorization` header, disable caching, allow request bodies up to 768 KiB, and allow responses to wait at least 30 seconds. Keep the Node listener private to the proxy. Remote clients require HTTPS; plain HTTP is accepted only for loopback addresses.
|
|
29
|
+
|
|
30
|
+
## Configure each MCP client
|
|
31
|
+
|
|
32
|
+
Install without the optional native WebRTC library if needed:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @vdoninja/mcp --omit=optional
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Set these variables in the environment of each MCP server process. In a client that supports a JSON server configuration:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"command": "node",
|
|
43
|
+
"args": ["/absolute/path/node_modules/@vdoninja/mcp/scripts/vdo-mcp-server.js"],
|
|
44
|
+
"env": {
|
|
45
|
+
"VDON_MCP_RELAY_URL": "https://relay.example.com",
|
|
46
|
+
"VDON_MCP_RELAY_TOKEN": "<relay access token>",
|
|
47
|
+
"VDON_MCP_RELAY_KEY": "<64 hex characters from the second command>"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For two clients on the relay computer, use `http://127.0.0.1:8790`. Both clients need the same relay URL, access token, room key, and room name. Each needs a different `stream_id`.
|
|
53
|
+
|
|
54
|
+
Keep secrets in the server environment where possible. `vdo_connect` also accepts `relay_url`, `relay_token`, and `relay_key` for clients that need separate settings per session. These secrets are omitted from status and connection results.
|
|
55
|
+
|
|
56
|
+
## Join and send
|
|
57
|
+
|
|
58
|
+
Connect the first agent:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{ "name": "vdo_connect", "arguments": { "transport": "http", "room": "project_room", "stream_id": "planner" } }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Connect the second agent:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{ "name": "vdo_connect", "arguments": { "transport": "http", "room": "project_room", "stream_id": "reviewer" } }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use `vdo_sync_peers` to wait for discovery, then address a peer by its stream ID:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{ "name": "vdo_send", "arguments": { "session_id": "<planner-session>", "target": "reviewer", "data": { "text": "Please review the plan." } } }
|
|
74
|
+
{ "name": "vdo_receive", "arguments": { "session_id": "<reviewer-session>", "wait_ms": 1000 } }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
File tools use the same target and retain chunk hashes, acknowledgements, retries, and completion checks. For shared state with `require_session_mac: true`, use the peer UUID from `vdo_sync_peers` as the state operation's `target`; the MAC belongs to that peer connection.
|
|
78
|
+
|
|
79
|
+
## Delivery and recovery
|
|
80
|
+
|
|
81
|
+
The relay accepts encrypted events through POST. Clients receive them through long polling with a cursor. Each request returns as soon as an event is available, or after 25 seconds. This path does not need SSE or WebSockets.
|
|
82
|
+
|
|
83
|
+
| Result or event | Meaning and action |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `vdo_send`: `delivery_stage: "queued"` | The local transport accepted the message. Save its `message_id` if you need to track it. |
|
|
86
|
+
| `relay_receipt`: `stage: "relay_accepted"` | The relay accepted the event. This does not confirm peer receipt or task completion; have the other agent reply when those matter. |
|
|
87
|
+
| `relay_receipt`: `stage: "delivery_unknown"` | POST retries failed. The relay may have accepted a request whose response was lost. Check with the peer before repeating a consequential task. |
|
|
88
|
+
| `data_received` | The receiving bridge accepted a message. Its `message_id` matches the sender's ID. The AI client still needs to poll and act on it. |
|
|
89
|
+
| `relay_connection` | The reader lost or regained connectivity. Use `vdo_status` to inspect the current connection. |
|
|
90
|
+
| `relay_history_lost` | The cursor is no longer available. Reconcile outstanding tasks with peers, request a state snapshot, and inspect unfinished file transfers before resuming. |
|
|
91
|
+
| `relay_message_rejected` | An event failed decryption or validation. Check matching room keys and synchronized clocks. |
|
|
92
|
+
|
|
93
|
+
Retries within the retained history reuse the same encrypted event ID. Distinct messages with identical text keep distinct IDs. Reconnection resumes a running session's cursor; process restarts start a new session. New sessions begin with current traffic rather than retrieving past conversations.
|
|
94
|
+
|
|
95
|
+
The relay keeps at most 512 events or 8 MiB per room for up to five minutes, across at most 16 rooms. It has no disk archive. A restart clears its history. Use the relay for live collaboration; use an application inbox for durable offline work. A busy room or large transfer can exhaust replay before five minutes.
|
|
96
|
+
|
|
97
|
+
Queues and request sizes are bounded. `vdo_send` can return `ok: false` when the transport has no known peer, is disconnected, or its queue is full. Wait for discovery or recovery before retrying. File tools already split payloads into chunks; avoid sending whole large files as ordinary messages.
|
|
98
|
+
|
|
99
|
+
## Trust and privacy
|
|
100
|
+
|
|
101
|
+
Room payloads use AES-256-GCM with a fresh random nonce and a key derived from the shared room key. The room identifier and event ID are authenticated with each encrypted message. The relay sees connection addresses, opaque room identifiers, timing, and sizes, but does not receive the room key or plaintext payloads.
|
|
102
|
+
|
|
103
|
+
Every holder of a room key can decrypt that room's traffic, including messages addressed to another participant, and can claim a participant identity. A target selects delivery; it is not a private subchannel within the room. Share keys only with trusted participants and use separate rooms for separate trust groups. Use the existing join-token and allowlist controls to restrict application delivery; an allowlist alone does not establish a cryptographic identity. Rotate shared keys and reconnect participants when access changes.
|
|
104
|
+
|
|
105
|
+
This group-key mode has no forward secrecy: a disclosed key can decrypt previously captured room traffic. Use WebRTC when its connection-level privacy is required. Keep clocks synchronized; expired or far-future events are rejected.
|
|
106
|
+
|
|
107
|
+
The HTTP relay carries data. The optional [browser adapter](browser-worker.md) supports automatic WebRTC/HTTP routing for its commands and images; live browser audio/video still uses WebRTC. Ordinary room sessions choose their transport explicitly. The `vdon-mcp-http` command exposes MCP itself over HTTP; `vdon-mcp-relay` carries encrypted events between peers. They are different services.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# VDO.Ninja MCP Tool Contract
|
|
2
2
|
|
|
3
|
+
[Read this guide in HTML](https://steveseguin.github.io/ninjamcp/mcp-tool-contract.html)
|
|
4
|
+
|
|
3
5
|
Implemented by:
|
|
4
6
|
|
|
5
7
|
- `scripts/vdo-mcp-server.js`
|
|
@@ -56,13 +58,19 @@ Enforcement:
|
|
|
56
58
|
|
|
57
59
|
### `vdo_connect` notable options
|
|
58
60
|
|
|
59
|
-
- transport: `room`, `stream_id`, `target_stream_id`, `
|
|
61
|
+
- transport: `room`, `stream_id`, `target_stream_id`, `transport` (`webrtc` by default or `http`)
|
|
62
|
+
- WebRTC: `host`, `password`, `force_turn`
|
|
63
|
+
- 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](http-relay.md)
|
|
60
64
|
- resiliency: `heartbeat_ms`, `reconnect_ms`, `max_reconnect_ms`
|
|
61
65
|
- security: `join_token`, `join_token_secret`, `join_token_ttl_ms`, `enforce_join_token`, `allow_peer_stream_ids`, `require_session_mac`
|
|
62
66
|
- file defaults: `file_chunk_bytes`, `file_max_bytes`, `file_ack_timeout_ms`, `file_max_retries`
|
|
63
67
|
- file spooling: `file_spool_dir`, `file_spool_threshold_bytes`, `keep_spool_files`
|
|
64
68
|
- state limits: `state_max_keys`, `state_max_snapshot_entries`
|
|
65
69
|
|
|
70
|
+
`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.
|
|
71
|
+
|
|
72
|
+
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.
|
|
73
|
+
|
|
66
74
|
## Sync Tools
|
|
67
75
|
|
|
68
76
|
- `vdo_sync_peers`: peer handshake/auth/state capabilities
|
|
@@ -77,6 +85,8 @@ Enforcement:
|
|
|
77
85
|
- `vdo_file_receive`: read completed incoming payload (`base64`/`utf8`/`json`)
|
|
78
86
|
- `vdo_file_save`: save completed incoming transfer directly to disk
|
|
79
87
|
|
|
88
|
+
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.
|
|
89
|
+
|
|
80
90
|
## State Sync Tools (CRDT-lite)
|
|
81
91
|
|
|
82
92
|
- `vdo_state_set`: update key/value with local monotonic clock
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# VDO.Ninja MCP Quickstart
|
|
2
2
|
|
|
3
|
+
[Read this guide in HTML](https://steveseguin.github.io/ninjamcp/quickstart-and-compat.html)
|
|
4
|
+
|
|
3
5
|
This is the fast path for users and AI agents.
|
|
4
6
|
|
|
5
7
|
## Transport Truth
|
|
@@ -198,7 +200,8 @@ npm run test:mcp:all
|
|
|
198
200
|
- Registry metadata is in `server.json`.
|
|
199
201
|
- Tool contracts are in `references/mcp-tool-contract.md`.
|
|
200
202
|
- `@vdoninja/mcp` depends on `@vdoninja/sdk`, so SDK is installed transitively.
|
|
201
|
-
-
|
|
203
|
+
- `@vdoninja/mcp` is MIT licensed. Its SDK dependency is separately licensed
|
|
204
|
+
under MPL-2.0, with some separately marked wrappers and adapters under MIT.
|
|
202
205
|
|
|
203
206
|
## Optional Advanced Diagnostics
|
|
204
207
|
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# Integrating remote SSApp control
|
|
2
|
+
|
|
3
|
+
[Read this guide in HTML](https://steveseguin.github.io/ninjamcp/ssapp-integration.html)
|
|
4
|
+
|
|
5
|
+
Use Ninja MCP to let an authorized agent on another computer operate an existing Social Stream Ninja
|
|
6
|
+
Standalone (SSApp) instance: manage sources, diagnose capture, inspect windows, and use browser input.
|
|
7
|
+
The bridge forwards SSApp's `ssapp_*` tool schemas, structured results, and MCP images.
|
|
8
|
+
|
|
9
|
+
## Set up remote access
|
|
10
|
+
|
|
11
|
+
Use SSApp with **API 1.4.1 and MCP adapter 1.3.1 or newer**. Enable **File > Local AI / Automation**,
|
|
12
|
+
restart SSApp, and save **Copy MCP Setup** as a private JSON file on that computer.
|
|
13
|
+
The bridge checks these versions when it connects. If an installed build lacks them,
|
|
14
|
+
run SSApp from its [current source checkout](https://github.com/steveseguin/ssn_app)
|
|
15
|
+
and copy that instance's MCP setup.
|
|
16
|
+
Install Ninja MCP on the host and each agent computer. Node.js 18 or newer is required by the bridge.
|
|
17
|
+
|
|
18
|
+
On the SSApp host:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx vdon-mcp-ssapp --setup ./private-ssapp --adapter-config ./ssapp-mcp.json
|
|
22
|
+
npx vdon-mcp-ssapp --worker --config ./private-ssapp/worker.json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The generated folder contains separate controller credentials for `agent1` and `agent2`, an
|
|
26
|
+
observe-only `viewer`, and a local MCP registration example. Keep `worker.json` on the host.
|
|
27
|
+
Give each agent only its own JSON file through a private channel. Protect the folder with your
|
|
28
|
+
operating system's file permissions; these files grant access to the app.
|
|
29
|
+
|
|
30
|
+
On the agent computer, register a separate stdio MCP server using `vdon-mcp-ssapp --config`
|
|
31
|
+
and the absolute path of that agent's JSON file. When using the generated `mcp-client.json`,
|
|
32
|
+
adjust the executable, script and credential paths to their locations on that computer.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx vdon-mcp-ssapp --doctor --config ./agent1.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
WebRTC is the default. To prefer WebRTC with HTTP fallback, add `--transport auto` and
|
|
39
|
+
`--relay-config ./relay.json` to the setup command. For machines without native WebRTC, install
|
|
40
|
+
with `npm install @vdoninja/mcp --omit=optional` and use `--transport http`.
|
|
41
|
+
The private relay file supplies `url` and `token` for your [HTTP relay](http-relay.md);
|
|
42
|
+
setup generates a new room encryption key. The host needs an allowed outbound route, with no
|
|
43
|
+
public SSApp port, VPN, or desktop sharing server.
|
|
44
|
+
|
|
45
|
+
For a source checkout, use `node scripts/vdo-mcp-ssapp.js` in place of the installed command.
|
|
46
|
+
The copied adapter configuration must contain one SSApp server with an absolute executable path.
|
|
47
|
+
A source adapter can use the absolute path to Node with
|
|
48
|
+
`["/absolute/ssapp/resources/ssapp-mcp.js"]` as its arguments. Set its
|
|
49
|
+
`env.SSAPP_CONTROL_URL` if SSApp uses a non-default loopback port.
|
|
50
|
+
|
|
51
|
+
### Use the remote tools
|
|
52
|
+
|
|
53
|
+
1. Call `ninja_ssapp_status`, then `ssapp_get_capabilities` and `ssapp_list_browser_targets`.
|
|
54
|
+
2. Inspect a target or capture a screenshot. Observations do not require a control lease.
|
|
55
|
+
3. Call `ninja_ssapp_claim` before changing the app. Use the normal `ssapp_*` arguments,
|
|
56
|
+
including `confirm: true` for an authorized action where its schema requires it.
|
|
57
|
+
4. Observe the result, then call `ninja_ssapp_release` so another agent can take over.
|
|
58
|
+
|
|
59
|
+
The lease covers the whole app. It lasts 60 seconds by default; renew with `ninja_ssapp_claim`
|
|
60
|
+
before it expires, or supply `ttl_ms` between 1000 and 120000. Other agents can observe while
|
|
61
|
+
one controls. On the host, enter `revoke` to release control or `stop` to stop the bridge.
|
|
62
|
+
Stopping the bridge leaves SSApp and its sources running.
|
|
63
|
+
|
|
64
|
+
After SSApp restarts, call status again, list fresh targets, inspect them, and reclaim control.
|
|
65
|
+
For an uncertain result, inspect the app and use `ninja_ssapp_result` with the returned
|
|
66
|
+
`request_id` before repeating an action. If control was suspended after an adapter failure,
|
|
67
|
+
claim with `reconciled: true` only after checking its outcome.
|
|
68
|
+
|
|
69
|
+
### Choose permissions
|
|
70
|
+
|
|
71
|
+
In the host's `worker.json`, each client has a `role` of `controller` or `observer`.
|
|
72
|
+
An optional `tools` array restricts that client's allowed `ssapp_*` tool names. Restart the
|
|
73
|
+
worker after changing permissions. Policies apply on the host even to tools omitted from discovery.
|
|
74
|
+
Permissions cover tools across the app, not individual sources or windows; grant controller
|
|
75
|
+
access only to agents allowed to operate that scope.
|
|
76
|
+
|
|
77
|
+
Host file selection is disabled by default. Set `allowHostFiles: true` for a specific client
|
|
78
|
+
to allow the file chooser and dialog tools to use authorized absolute paths on the host.
|
|
79
|
+
Remote file staging is not provided; place a file on the host through a separately authorized
|
|
80
|
+
transfer before selecting it. Use `ssapp_browser_screenshot` for remote viewing: the local
|
|
81
|
+
`ssapp_browser_frame_stream` endpoint is not forwarded, and SSApp audio/video streaming is
|
|
82
|
+
not part of this bridge.
|
|
83
|
+
|
|
84
|
+
## Existing interfaces and responsibilities
|
|
85
|
+
|
|
86
|
+
| Component | Responsibility |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| SSApp | Owns sources, logged-in sessions, Electron windows, capture, diagnostics, and local controls. |
|
|
89
|
+
| SSApp MCP adapter | Exposes the `ssapp_*` schemas, tool results, image content, and runtime compatibility checks. |
|
|
90
|
+
| Ninja MCP | Connects the remote agent to a host, authenticates requests, manages control ownership, and transports results. |
|
|
91
|
+
| VDO.Ninja SDK | Provides WebRTC peer connectivity and data/media transport, with TURN where needed. |
|
|
92
|
+
| ninja-p2p | Optional persistent agent inboxes, handoffs, wake hooks, and team coordination. |
|
|
93
|
+
|
|
94
|
+
The SDK's [existing Social Stream integration](https://sdk.vdo.ninja/#social-stream-ninja) connects to
|
|
95
|
+
SSN's chat stream as a dock peer. ninja-p2p also has a chat bridge using SSN's WebSocket API. Those
|
|
96
|
+
interfaces serve audience messages and existing SSN actions. The new SSApp browser controls are
|
|
97
|
+
available through its local API/MCP interface; a normal chat connection does not expose them.
|
|
98
|
+
|
|
99
|
+
Keep chat access and app-control authorization separate. Joining an SSN session, receiving a chat
|
|
100
|
+
message, or sharing an agent room must not authorize keyboard input into a sign-in window.
|
|
101
|
+
Ninja MCP and ninja-p2p use different application envelopes; a common room name is not an adapter.
|
|
102
|
+
|
|
103
|
+
### Sources of truth
|
|
104
|
+
|
|
105
|
+
Read these files when implementing or updating the adapter; derive schemas from code rather than
|
|
106
|
+
maintaining a second handwritten tool definition list.
|
|
107
|
+
|
|
108
|
+
| Location | Contract or implementation |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| SSApp `resources/ssapp-mcp.js` | Tool definitions, normalization, MCP results, HTTP client, compatibility checks. |
|
|
111
|
+
| SSApp `resources/electron-control-api.js` | API version, command definitions, HTTP routes, operations, SSE. |
|
|
112
|
+
| SSApp `resources/browser-control-service.js` | Shared browser schemas, targets, input, screenshots, menus, files, live frames. |
|
|
113
|
+
| SSApp `resources/source-observation-service.js` | Source diagnostics, captured events, semantic inspection, screenshot capture. |
|
|
114
|
+
| SSApp `resources/app-window-control-service.js`, `resources/app-dialog-service.js` | App-owned window and dialog controls. |
|
|
115
|
+
| SSApp `bootstrap.js`, `main.js` | Packaged MCP launch, opt-in setup, loopback binding, routing and lifecycle. |
|
|
116
|
+
| Social Stream `docs/skills/control-social-stream/` | Canonical operating skill, API/browser references, version history. |
|
|
117
|
+
| Ninja MCP [browser RPC](../scripts/lib/browser-rpc.js) | Per-client encrypted requests, request IDs, deadlines, result chunks and retry cache. |
|
|
118
|
+
| Ninja MCP [browser worker](../scripts/lib/browser-worker.js) | Existing Chrome backend, controller roles and tab leases. |
|
|
119
|
+
| Ninja MCP [browser entry point](../scripts/vdo-mcp-browser.js) | Host/client setup, MCP tool exposure and transport connection. |
|
|
120
|
+
| Ninja MCP [bridge session](../scripts/lib/bridge-session.js) | WebRTC and HTTP transport integration. |
|
|
121
|
+
|
|
122
|
+
Repositories: [SSApp](https://github.com/steveseguin/ssn_app),
|
|
123
|
+
[Social Stream](https://github.com/steveseguin/social_stream),
|
|
124
|
+
[SDK](https://github.com/steveseguin/ninjasdk),
|
|
125
|
+
[ninja-p2p](https://github.com/steveseguin/ninja-p2p).
|
|
126
|
+
Use local source files for capabilities that have not reached the published repository yet.
|
|
127
|
+
The canonical [control skill](https://github.com/steveseguin/social_stream/blob/main/docs/skills/control-social-stream/SKILL.md)
|
|
128
|
+
links its [API reference](https://github.com/steveseguin/social_stream/blob/main/docs/skills/control-social-stream/references/control-api.md),
|
|
129
|
+
[browser controls](https://github.com/steveseguin/social_stream/blob/main/docs/skills/control-social-stream/references/browser-control.md)
|
|
130
|
+
and [version log](https://github.com/steveseguin/social_stream/blob/main/docs/skills/control-social-stream/references/version-log.md).
|
|
131
|
+
|
|
132
|
+
## Connect to the local app
|
|
133
|
+
|
|
134
|
+
1. Start SSApp on the computer whose windows will be controlled.
|
|
135
|
+
2. Enable **File > Local AI / Automation** and restart SSApp.
|
|
136
|
+
3. Use **Copy MCP Setup** from that menu for the installed app's executable and arguments.
|
|
137
|
+
4. Call `ssapp_get_capabilities`, then `ssapp_get_status`.
|
|
138
|
+
|
|
139
|
+
The packaged executable accepts `--ssapp-mcp` to run its stdio adapter, using Electron's bundled
|
|
140
|
+
Node runtime. This mode does not launch the ordinary app or enable its API; SSApp must also be
|
|
141
|
+
running with automation enabled. Installed-app use does not require a separate Node installation.
|
|
142
|
+
For development, `node <ssapp-checkout>/resources/ssapp-mcp.js` runs the same adapter.
|
|
143
|
+
|
|
144
|
+
| Setting | Meaning |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `http://127.0.0.1:17777` | Default API origin; intentionally tokenless and loopback-only. |
|
|
147
|
+
| `--ssapp-control-api` / `SSAPP_CONTROL_API=1` | Enable the local control API. |
|
|
148
|
+
| `--ssapp-control-port=17777` / `SSAPP_CONTROL_PORT` | Select the app's listening port. |
|
|
149
|
+
| `--ssapp-headless-control` / `SSAPP_HEADLESS_CONTROL=1` | Hide app windows; does not enable the API by itself. |
|
|
150
|
+
| `SSAPP_CONTROL_URL` | MCP adapter's API origin; only `http://127.0.0.1:PORT` is accepted, without credentials, path, query or fragment. |
|
|
151
|
+
| `SSAPP_MCP_REQUEST_TIMEOUT_MS` | Local adapter request timeout, bounded to 100–35000 ms; default 35000 ms. |
|
|
152
|
+
|
|
153
|
+
Do not use the legacy `--remote-control` renderer-execution harness as the integration API.
|
|
154
|
+
Do not change the loopback bind or the adapter URL restriction to support a remote client.
|
|
155
|
+
|
|
156
|
+
### Compatibility and wire formats
|
|
157
|
+
|
|
158
|
+
The remote-control baseline is **SSApp 0.4.37 with API 1.4.1 and MCP adapter 1.3.1**.
|
|
159
|
+
Earlier builds sharing the app version can lack the controls. Read `payload.commands` from
|
|
160
|
+
capabilities and keep `ssappVersion`, `apiVersion`, and the MCP server version distinct.
|
|
161
|
+
SSApp's adapter currently reports MCP protocol `2025-06-18` during initialization.
|
|
162
|
+
|
|
163
|
+
The MCP tool list remains discoverable while SSApp is offline. A listed tool is not proof that
|
|
164
|
+
the running app supports it. Preserve the adapter's availability checks and offline errors.
|
|
165
|
+
Browser, app-window and dialog tools can run without first checking renderer-dependent capabilities;
|
|
166
|
+
the bridge must preserve this route so a blocking prompt can be answered.
|
|
167
|
+
|
|
168
|
+
The local HTTP interface includes:
|
|
169
|
+
|
|
170
|
+
| Route | Use |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| `GET /api/v1/instance` | Renderer-independent app instance and versions; the bridge binds local calls with `X-SSApp-Instance-Id`. |
|
|
173
|
+
| `GET /api/v1/capabilities` | Commands, platforms, modes, settings and versions. |
|
|
174
|
+
| `GET /api/v1/status` | App and source state. Status fields are top-level rather than a universal `payload` wrapper. |
|
|
175
|
+
| `POST /api/v1/command` | A JSON object containing `action` and `value`. |
|
|
176
|
+
| `GET /api/v1/operations/OPERATION_ID` | Look up a retained operation. |
|
|
177
|
+
| `GET /api/v1/events` | Bounded SSE history; resume with `Last-Event-ID`. |
|
|
178
|
+
|
|
179
|
+
Command responses normally contain `ok` with `payload` or structured `error`, plus `ssappVersion`,
|
|
180
|
+
`apiVersion`, and `requestId`. Many mutations also return `meta.operationId`. Reload/shutdown and
|
|
181
|
+
navigation acknowledgements may describe an accepted request, not the completed user workflow.
|
|
182
|
+
|
|
183
|
+
MCP results include `content`, `structuredContent`, version `_meta`, and `isError` on failure.
|
|
184
|
+
Screenshots use MCP image content; their base64 bytes are removed from the parallel structured
|
|
185
|
+
result. These fields are forwarded intact. Diagnostics stay off stdout. Ninja MCP preserves caller
|
|
186
|
+
response IDs and adds transport metadata under `_meta.ninja`.
|
|
187
|
+
|
|
188
|
+
## Tool reference
|
|
189
|
+
|
|
190
|
+
Prefer a source/settings command when it directly expresses the task. Use browser input for
|
|
191
|
+
website and app interaction. General browser controls operate existing SSApp targets; they do
|
|
192
|
+
not grant control of other desktop applications or create an independent Chrome session.
|
|
193
|
+
|
|
194
|
+
### Browser targets and input
|
|
195
|
+
|
|
196
|
+
| MCP tool | HTTP action | Purpose |
|
|
197
|
+
| --- | --- | --- |
|
|
198
|
+
| `ssapp_list_browser_targets` | `listBrowserTargets` | Discover main UI, source, sign-in, popup and embedded browser surfaces. |
|
|
199
|
+
| `ssapp_browser_screenshot` | `captureBrowserScreenshot` | Capture a viewport and its coordinate mapping. |
|
|
200
|
+
| `ssapp_browser_inspect` | `inspectBrowserTarget` | Read visible text, frames and opaque element references. |
|
|
201
|
+
| `ssapp_browser_interact` | `interactBrowserTarget` | Click, focus, scroll, fill or press a basic key using an element reference. |
|
|
202
|
+
| `ssapp_browser_input` | `browserInput` | Mouse, keyboard, drag, selection, wheel and touch batches. |
|
|
203
|
+
| `ssapp_browser_navigate` | `navigateBrowserTarget` | HTTP(S) navigation, back, forward, reload and stop. |
|
|
204
|
+
| `ssapp_browser_window` | `setBrowserTargetWindow` | Show, hide, focus, minimize, maximize, restore, resize or close the owning window. |
|
|
205
|
+
| `ssapp_browser_choose_files` | `chooseBrowserFiles` | Select authorized host files for an HTML upload control. |
|
|
206
|
+
| `ssapp_browser_frame_stream` | `getBrowserFrameStream` | Local-only multipart JPEG endpoint; use screenshots remotely. |
|
|
207
|
+
| `ssapp_list_app_menu_items` | `listAppMenuItems` | Discover application menu items and a target's captured context menu. |
|
|
208
|
+
| `ssapp_invoke_app_menu_item` | `invokeAppMenuItem` | Invoke an item using its returned path and exact label. |
|
|
209
|
+
|
|
210
|
+
Discover `targetId` values such as `wc:7`; never invent or persist them across app restarts.
|
|
211
|
+
Target entries include `windowId`, `sourceId` when available, `tabId`, parent window, kind, title,
|
|
212
|
+
redacted URL, loading/visibility/focus state and zoom. Source IDs identify configured sources;
|
|
213
|
+
window, tab and target IDs identify runtime objects and are not interchangeable.
|
|
214
|
+
Re-list after popups open, windows close, or SSApp restarts. Virtual sources can have diagnostics
|
|
215
|
+
and captured events without any browser target or screenshot.
|
|
216
|
+
|
|
217
|
+
Native input targets browser content without moving the operating-system pointer. Hidden targets
|
|
218
|
+
remain controllable. Showing/focusing is explicit and restricted in headless mode. Window resizing
|
|
219
|
+
uses Electron content dimensions, which may differ from CSS viewport dimensions under zoom.
|
|
220
|
+
|
|
221
|
+
### Source, settings, diagnostics, windows and dialogs
|
|
222
|
+
|
|
223
|
+
Keep the existing tools available alongside browser controls:
|
|
224
|
+
|
|
225
|
+
| Task | MCP tools |
|
|
226
|
+
| --- | --- |
|
|
227
|
+
| Discovery | `ssapp_get_capabilities`, `ssapp_get_status`, `ssapp_list_sources`, `ssapp_get_source` |
|
|
228
|
+
| Source configuration | `ssapp_add_source`, `ssapp_update_source`, `ssapp_remove_source`, `ssapp_set_source_connection_mode` |
|
|
229
|
+
| Source lifecycle | `ssapp_start_source`, `ssapp_stop_source`, `ssapp_reload_source`, `ssapp_start_all_sources`, `ssapp_stop_all_sources`, `ssapp_reload_all_sources` |
|
|
230
|
+
| Source presentation | `ssapp_set_source_mute`, `ssapp_toggle_source_mute`, `ssapp_set_source_visibility`, `ssapp_toggle_source_visibility` |
|
|
231
|
+
| Settings and operations | `ssapp_get_settings`, `ssapp_update_settings`, `ssapp_get_operation` |
|
|
232
|
+
| Capture diagnostics | `ssapp_get_source_diagnostics`, `ssapp_get_recent_source_events`, `ssapp_wait_for_source_events` |
|
|
233
|
+
| Source-page workflows | `ssapp_capture_source_screenshot`, `ssapp_inspect_source_page`, `ssapp_interact_source_page`, `ssapp_reload_source_page`, `ssapp_show_source_for_human` |
|
|
234
|
+
| App windows | `ssapp_list_app_windows`, `ssapp_capture_app_window_screenshot`, `ssapp_inspect_app_window`, `ssapp_interact_app_window`, `ssapp_set_app_window_visibility` |
|
|
235
|
+
| Dialogs | `ssapp_get_pending_app_dialogs`, `ssapp_wait_for_app_dialog`, `ssapp_respond_to_app_dialog` |
|
|
236
|
+
| App lifecycle | `ssapp_reload_app`, `ssapp_shutdown` |
|
|
237
|
+
|
|
238
|
+
Use live platform/settings capabilities. Stop an active source before changing inactive-only
|
|
239
|
+
configuration; use dedicated mute/visibility commands for live changes. The local MCP adapter
|
|
240
|
+
defaults a mode-less TikTok add to WebSocket Auto; forwarding through that adapter preserves
|
|
241
|
+
this behavior, while a direct HTTP implementation would need to account for its different defaults.
|
|
242
|
+
|
|
243
|
+
Captured-event queries have cursors, bounded history and a `historyLost` indicator; waits allow up
|
|
244
|
+
to 25 seconds. These are captured-output observations, not an independent record of all incoming
|
|
245
|
+
platform messages. Preserve cursors and gap information and avoid treating a connected or quiet
|
|
246
|
+
source as proof of successful capture.
|
|
247
|
+
|
|
248
|
+
## Observation and interaction rules
|
|
249
|
+
|
|
250
|
+
1. Discover the target and inspect or screenshot it.
|
|
251
|
+
2. If choosing a point from an image, send that screenshot's `screenshotId` with the image pixel
|
|
252
|
+
coordinates. SSApp maps them to the viewport. Without it, coordinates are viewport CSS pixels.
|
|
253
|
+
3. Execute a bounded input batch with `confirm: true` for an authorized workflow.
|
|
254
|
+
4. Inspect the resulting state. Re-observe after navigation, scrolling, layout changes or resizing.
|
|
255
|
+
|
|
256
|
+
Example MCP call after replacing the target, screenshot ID and coordinates with observed values:
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"name": "ssapp_browser_input",
|
|
261
|
+
"arguments": {
|
|
262
|
+
"targetId": "wc:7",
|
|
263
|
+
"screenshotId": "SCREENSHOT_ID_FROM_CAPTURE",
|
|
264
|
+
"actions": [
|
|
265
|
+
{ "action": "click", "x": 180, "y": 120 },
|
|
266
|
+
{ "action": "keypress", "key": "ControlOrMeta+a" },
|
|
267
|
+
{ "action": "type", "text": "Search text" },
|
|
268
|
+
{ "action": "keypress", "key": "Enter" }
|
|
269
|
+
],
|
|
270
|
+
"confirm": true
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
For HTTP, use `{"action":"browserInput","value":{...}}` with the same arguments as `value`.
|
|
276
|
+
|
|
277
|
+
- Input actions: `click`, `doubleClick`, `move`, `scroll`, `drag`, `type`, `keypress`, `keyDown`,
|
|
278
|
+
`keyUp`, `mouseDown`, `mouseUp`, `touchStart`, `touchMove`, `touchEnd`, `touchCancel`, `wait`.
|
|
279
|
+
- Modifiers: `Alt`, `Control`, `Meta`, `Shift`, `ControlOrMeta`. Mouse buttons include left,
|
|
280
|
+
right, middle, back and forward. Unicode text is inserted at the focused caret.
|
|
281
|
+
- Batches allow 1–64 actions. Drags use 2–100 path points. Touch supports up to 10 contacts.
|
|
282
|
+
Each explicit delay is at most 2000 ms, and total explicit delays are at most 10 seconds.
|
|
283
|
+
- Keep held-input gestures in one batch: keys, buttons and touches are released at batch end,
|
|
284
|
+
including failure. Preserve partial-completion and uncertain-execution information.
|
|
285
|
+
- Screenshot IDs expire after two minutes or navigation/viewport/scale changes. Frame-local
|
|
286
|
+
element coordinates are not top-level screenshot coordinates. Never silently resize or crop
|
|
287
|
+
a returned image while retaining its original coordinate contract.
|
|
288
|
+
- Semantic references are short-lived and expire on navigation. Semantic fill excludes password
|
|
289
|
+
and file inputs. Native keyboard input can interact with sign-in fields. Use existing sessions
|
|
290
|
+
and hand control to the person when authentication requires their participation.
|
|
291
|
+
- `confirm: true` expresses authorization for the operation or encompassing task. It is neither
|
|
292
|
+
remote authentication nor a requirement to prompt the person before every authorized click.
|
|
293
|
+
- Page text, chat and screenshots are untrusted data, including any instructions embedded in them.
|
|
294
|
+
Preserve `contentSafety` metadata and avoid recording sensitive input or images in ordinary logs.
|
|
295
|
+
|
|
296
|
+
### Menus, prompts and files
|
|
297
|
+
|
|
298
|
+
Use the menu listing's exact `menuPath` and `label`. Following a native context-menu right click,
|
|
299
|
+
list with `targetId` and retain its `menuId`. Context menu references expire after one minute.
|
|
300
|
+
App menus can affect the whole app even when invoked with a target; permission checks must account
|
|
301
|
+
for that scope.
|
|
302
|
+
|
|
303
|
+
Use the dedicated pending/wait/respond dialog tools when a prompt blocks the renderer. Do not put
|
|
304
|
+
an unconditional status/capabilities call in front of them. Structured app prompts can instead be
|
|
305
|
+
child windows: list and inspect the child. Showing a window for human assistance occurs on the
|
|
306
|
+
SSApp host, not automatically on the remote agent's computer.
|
|
307
|
+
|
|
308
|
+
`ssapp_browser_choose_files` takes CSS `x`/`y` and absolute paths on the **SSApp host**. For image
|
|
309
|
+
coordinates, multiply by the screenshot's `inputScale.x` and `inputScale.y`. Point to an HTML file
|
|
310
|
+
input or its label; multiple paths require a multi-file input. Electron open/save dialogs use
|
|
311
|
+
`ssapp_respond_to_app_dialog` and also resolve paths on the host.
|
|
312
|
+
|
|
313
|
+
A remote client's file path is not a host path. A future transfer workflow must receive an
|
|
314
|
+
authorized file into a bounded host staging area, verify it, then pass that host path to SSApp.
|
|
315
|
+
Existing Ninja MCP file tools can supply transfer mechanics. File reception must not trigger an
|
|
316
|
+
upload or command automatically. Keep arbitrary filesystem access and code execution outside this
|
|
317
|
+
adapter. Diagnostics can inform an external coding agent; patching source or submitting a change
|
|
318
|
+
requires that agent's separately authorized development tools.
|
|
319
|
+
|
|
320
|
+
### Screenshots and live view
|
|
321
|
+
|
|
322
|
+
Use screenshots for remote viewing. Request `format: "jpeg"` and a bounded
|
|
323
|
+
`maxWidth` where needed; SSApp supports widths from 320 to 1600. Return a real MCP image block.
|
|
324
|
+
|
|
325
|
+
The live-view tool returns a relative endpoint such as
|
|
326
|
+
`/api/v1/browser/frames/wc%3A7?fps=2&maxWidth=1280`. It belongs to the host's loopback API;
|
|
327
|
+
handing this URL to another computer does not make it reachable. A remote adapter must explicitly
|
|
328
|
+
transport authorized frames or publish a separately authorized media stream.
|
|
329
|
+
|
|
330
|
+
Current SSApp live view is multipart JPEG, 1–5 fps, at most two connections, and has no audio.
|
|
331
|
+
Capture runs only while connected; close the host stream when its viewer disconnects or loses
|
|
332
|
+
permission. Preserve backpressure and use a fresh screenshot for coordinate input. Ninja MCP's
|
|
333
|
+
Chrome audio/video publisher is specific to its Chrome tab and cannot be assumed to capture SSApp.
|
|
334
|
+
A model needs a compatible media adapter to interpret continuous audio/video; ordinary MCP image
|
|
335
|
+
tools are sufficient for screenshot-based control.
|
|
336
|
+
|
|
337
|
+
## Transport and recovery
|
|
338
|
+
|
|
339
|
+
The external host worker launches SSApp's configured local MCP adapter and forwards authenticated
|
|
340
|
+
requests. Remote callers cannot choose executables, environment variables, API URLs, or raw debug
|
|
341
|
+
commands. SSApp's API remains on loopback. Per-client encryption is separate from the room key;
|
|
342
|
+
an SSN chat session or ordinary Ninja room membership does not grant app control.
|
|
343
|
+
|
|
344
|
+
The worker checks the running app's instance ID before admitting work. The local adapter also
|
|
345
|
+
sends that ID on each HTTP request, so a restart between discovery and dispatch rejects stale
|
|
346
|
+
commands. Local clients that omit the instance header continue using the ordinary local API.
|
|
347
|
+
|
|
348
|
+
Ordinary mutations run in order with at most eight queued calls. Observations and dialog responses
|
|
349
|
+
can run concurrently so a long wait does not prevent prompt recovery. Revocation and lease expiry
|
|
350
|
+
reject queued mutations; an action already dispatched to SSApp may finish. Graceful client shutdown
|
|
351
|
+
releases control. Abrupt disconnects are detected by the transport; lease expiry also bounds control
|
|
352
|
+
ownership while that detection is pending.
|
|
353
|
+
|
|
354
|
+
The `auto` route prefers WebRTC and can retry through the configured HTTP relay using the same
|
|
355
|
+
request identity. The worker returns cached results for duplicate delivery. Its process-local
|
|
356
|
+
cache retains results through the request deadline plus two minutes. This does not guarantee
|
|
357
|
+
exactly-once execution across a worker or app restart: an unknown result requires inspection before
|
|
358
|
+
retrying. Delivery, accepted commands, and completed work are separate outcomes. Use SSApp's
|
|
359
|
+
operation tools when a response returns an operation ID.
|
|
360
|
+
|
|
361
|
+
| Limit | Action |
|
|
362
|
+
| --- | --- |
|
|
363
|
+
| Encrypted request: 65000 base64 characters | Reduce a large input batch before sending. Held-input gestures are never split automatically. |
|
|
364
|
+
| SSApp remote result: 10 MiB; chunks: 24000 bytes | Use JPEG or a smaller screenshot when a result is too large. Results and images are never silently truncated. |
|
|
365
|
+
| Local adapter: 35 s; remote request: 60 s | After timeout, look up the request and inspect app state before repeating a mutation. |
|
|
366
|
+
| At most 16 pending transport requests | Keep concurrent observations bounded and release control when finished. |
|
|
367
|
+
|
|
368
|
+
The separate Chrome adapter retains its own 2 MiB result limit and browser-specific tools.
|
|
369
|
+
Ninja MCP message, file, and shared-state workflows remain separate from SSApp control.
|
|
370
|
+
For continuing agent inboxes and handoffs, use ninja-p2p; receiving a handoff does not automatically
|
|
371
|
+
authorize an SSApp operation.
|