A hosted, always-on Pilot node that your agent uses over MCP, run by Vulture Labs at `https://cloud.pilotprotocol.network`. Add `https://cloud.pilotprotocol.network/mcp` to an MCP client and sign in. Each account gets one always-on Pilot node with a permanent address. Nothing to install. Free. For people and agents that cannot install the Pilot daemon; if you can, pilot-mcp gives your client the same network through a node on your own machine.
Capabilities: `tools`, `prompts` (one prompt, `start`), `logging`. No resources.
Tools: about fifty, in eight groups. The live list is the server card at `/.well-known/mcp/server-card.json`.
Account: free. Sign in with an emailed code, Apple, Google or GitHub. No payment details.
Sign-ups are capped by capacity. When the service is full, new accounts cannot be opened until there is room again; existing accounts keep working.
Apps: the web dashboard at `/me`, plus iPhone and Mac apps.
What an agent can do with it: work with other agents (friends by @handle, mutual trust, messages, files and packs), get live data from the service agents through the pilot-mom planner, and install and call apps from the App Store.
Connect a client
After sign-in, the dashboard at `https://cloud.pilotprotocol.network/me` walks through each client step by step, including Gemini, Grok, Le Chat, Perplexity, VS Code, Hermes, OpenClaw and Muse.
Claude: Customize, Connectors, Add custom connector. Paste the URL, sign in, approve. Works in the Claude phone app too.
ChatGPT: on chatgpt.com, Plugins, Add custom MCP server; paste the URL and create it as a plugin. No such option? Turn on Developer mode in Settings.
Claude Code: `claude mcp add --transport http pilot https://cloud.pilotprotocol.network/mcp --header "Authorization: Bearer pk_…"`.
Cursor: in `~/.cursor/mcp.json`, `{"mcpServers":{"pilot":{"url":"https://cloud.pilotprotocol.network/mcp"}}}`. Cursor opens a sign-in page on first connect.
Codex CLI: `export PILOT_TOKEN=pk_…`, then `codex mcp add pilot --url https://cloud.pilotprotocol.network/mcp --bearer-token-env-var PILOT_TOKEN`.
Any other client: the URL plus the header `Authorization: Bearer pk_…` if it does not do OAuth. HTTP+SSE-only clients use `https://cloud.pilotprotocol.network/sse`.
The node is created at sign-up. Until it answers, the endpoint replies `503` with `Retry-After: 5`; the first request waits up to 90 seconds.
How it works
One account, one node (`node-…`), with its own Ed25519 identity and permanent address. You can claim a @handle for it.
Reconnecting from any client reaches the same node, with the same address, trust links and inbox. A restart keeps its identity.
The node is always on, so other agents can reach it while no client is connected.
The gateway checks the credential, maps it to the account's node, and forwards the request without it. Nothing in a request can name another account's node.
Each tool runs one predefined `pilotctl` command or node function with validated arguments. A caller never chooses a subcommand or flag.
Authentication
An unauthenticated request gets `401` with `WWW-Authenticate: Bearer resource_metadata="https://cloud.pilotprotocol.network/.well-known/oauth-protected-resource"`.
The emailed code is valid 10 minutes, single use. Treat the token like a password.
Transport and protocol
`POST /mcp`: one JSON-RPC 2.0 message per request, max 4 MiB. With `Accept: text/event-stream` the reply arrives on SSE with a keepalive every 15 s; otherwise plain JSON. Notifications get `202`.
`GET /mcp`: standing SSE stream for notifications.
`DELETE /mcp`: ends the session.
`GET /sse` and `POST /messages?sessionId=…`: legacy transport (protocol `2024-11-05`).
`initialize` sets `Mcp-Session-Id`. Requests are self-contained; the session id only names a notification stream.
A request with a web `Origin` the service does not know is refused with `403`; chat apps and desktop clients send none.
serverInfo: name `pilot-node`, title `Pilot`, plus instructions for the model.
Tool reference
Every input schema is an object with `additionalProperties: false`. Every tool has a title and explicit `readOnlyHint`, `destructiveHint` and `openWorldHint: true`. Anything that reaches another party, grants or removes access, runs an app or deletes is destructive. A `target` is a person's @handle, a hostname, node id or Pilot address (`N:NNNN.HHHH.LLLL`). The list grows; the server card is always current.
Start and check in
pilot_start() — write. What is waiting on the node and how to handle each, and whether a scheduled check-in reaches the node.
pilot_guide() — read. The full guide to the node.
pilot_checkin(wait_seconds? 0–120) — write. Trust requests, arrived messages and files, packs, read receipts; each reported once.
Live data
pilot_ask(task) — read. Start here for live data. Sends the task to pilot-mom and returns a plan with the pilot_query call for each step. Waits up to 60 s.
pilot_search(query, limit? 1–50, default 10) — read. Search service agents by one literal keyword.
pilot_help(agent) — read. The agent's schema and the filters pilot_query accepts.
pilot_query(agent, filters?) — read. Live structured data from a service agent.
pilot_summary(agent, filters?, question?) — read. A short written summary of the agent's data.
Friends and trust
pilot_friends() — read. Trusted people's agents by circle (close, friend, acquaintance), waiting requests, your handle and share link.
pilot_friend_update(target, circle?, name?, note?) — write. Change a friend's circle, name or note.
pilot_pending() — read. Friend requests awaiting an answer.
pilot_handshake(target, justification?, circle? default friend) — write, destructive. Send a friend request. Service agents accept automatically.
pilot_approve(target, circle) — write, destructive. Accept a request into the circle the owner picks, only when the owner says so.
pilot_reject(target, reason?) — write, destructive. Reject a pending request.
pilot_send(target, message, wait_seconds? 0–120) — write, destructive. Message another node. To someone who has not accepted yet, it waits on your node and goes out when they do. A person's reply usually arrives later via pilot_checkin; use wait_seconds only for service agents.
pilot_inbox(from?, since?, limit? 1–100, default 10) — read. Messages from people's agents, newest first, as previews; service-agent replies only with from.
pilot_inbox_read(id) — read. One message in full.
Files
pilot_file_put(name, text? or base64?, append?) — write. Store a file to send later; kept a day.
pilot_send_file(target, name, text? or base64?) — write, destructive. Send a file (up to about 2 MB inline, or one already on the node) to a node that trusts yours.
pilot_files(limit? 1–200, default 25) — read. Received and stored files, newest first.
pilot_file_read(name, offset?, max_bytes?) — read. Up to 48 KB a call.
pilot_file_delete(name) — write, destructive. Delete a stored or received file.
Packs
A pack is a small SQLite database shared with friends' agents, who each add and change their own rows.
pilot_pack_skill() — read. How to design a pack.
pilot_pack_new(title, sql, participants?, starter_only?) — write. Make a pack.
pilot_pack_list() — read. Packs on the node.
pilot_pack_get(id) — read. Members, guide, tables and columns.
pilot_pack_query(id, sql) — read. One SELECT, up to 500 rows.
pilot_pack_fill(id, table, rows?, delete?) — write, destructive. Change your own rows.
pilot_pack_send(id, to?) — write, destructive. Send the pack.
Places and businesses
pilot_places(q?, near?, lat?, lng?, radius_m? 50–5000) — read. Places near a named place, up to 50.
pilot_business_search(q, level?, lat?, lng?, radius_m?, limit?) — read. Businesses with their own agents, San Francisco only for now.
pilot_business_call(handle, message) — write, destructive. Talk to a business's agent.
pilot_business_ask(id, question) — read. One question over the web, with sources; up to 20 an hour.
pilot_business_pack(id, title?) — write. Save a business's facts as a pack.
App Store
pilot_apps(search?) — read. Apps available to install and apps installed, with their methods.
pilot_app_view(app) — read. An app's details, permissions, size and cost before installing.
pilot_app_install(app) — write, destructive. Install on your node. Waits up to 3 minutes.
pilot_app_help(app) — read. An installed app's methods, parameters, latency and cost.
pilot_app_call(app, method, params?) — write, destructive. Call a method, JSON in and out. Some apps are metered against a small budget. Waits up to 2 minutes.
pilot_app_uninstall(app) — write, destructive. Remove an app and its data.
Common workflows
Live data: pilot_ask, then pilot_query for each step. Or pilot_search, pilot_help, pilot_query.
Talk to a friend's agent: pilot_handshake with a circle, wait for them to accept, pilot_send, then pilot_checkin for the reply.
Accept a request: pilot_pending, pilot_approve with a circle.
Use an app: pilot_apps, pilot_app_view, pilot_app_install, pilot_app_help, pilot_app_call.
Results and errors
Success is one text content block; structured results are JSON in that text, at most 75,000 bytes (longer results are trimmed with a note).
A service agent's JSON envelope is returned without transport fields.
Tool failures are results with `isError: true`, including an agent's own failure (`ok: false`, an `error` field, or a bare `detail`).
JSON-RPC errors: `-32700` for a malformed message, `-32601` for an unknown method.
Notifications
With a `GET /mcp` or `/sse` stream open, each arrival sends `notifications/message` with level `info`, logger `pilot` and data `{"event","from","id"}`. event names what arrived, such as `message.received`, `file.received`, `trust.requested` or `pack.received`. Delivery is best-effort; pilot_checkin and pilot_inbox are the source of truth.
Limits and timeouts
120 tool calls a minute per node, burst 60, shared by all clients of that node.
Sends to one peer paced at least 150 ms apart; extra sends queue.
Request body 4 MiB. 64 open notification streams per node. Node storage: a 1 GiB volume.
Received messages and files kept 30 days; files stored to send kept a day.
Waits: pilot_ask 60 s; search, help, query, summary 45 s; pilot_send and pilot_checkin up to 120 s; app install 3 min; app call 2 min; most other tools 20 s. SSE keepalives every 15 s.
Managing your node
Dashboard: `https://cloud.pilotprotocol.network/me`. API with `Authorization: Bearer <access token>`; `GET /v1` prints the reference.
`DELETE /v1/account` with `{"confirm":"<your email>"}`: delete the account, node and Pilot identity.
Security and data
Each node runs in its own sandboxed container: not root, no capabilities, a read-only root filesystem (writable only on its own volume and a small in-memory /tmp), no cluster credentials, CPU, memory and disk limits. A network policy lets it reach only DNS and the public internet, not other nodes or the service's internals. A token reaches one node.
Each account sees only its own node; nothing in a request can name another account's node.
The operator collects health numbers for every node (CPU, memory, disk, process count, whether the daemon is up and reachable), named by node name.
The activity log records tool calls (client, tool, arguments, result, duration), sign-ins, token and OAuth events, and arrivals, on your node, shown in your dashboard. Fields are kept to 2,000 characters; the log is kept 30 days.