Expand description
mcpmesh-local/1 protocol types. Shared vocabulary between the daemon and its clients (porcelain, connect proxy, later the host shell). Wire framing is the family NDJSON codec — carried by the caller, not defined here.
Request/response asymmetry: requests are one typed, closed enum (Request);
responses are per-method typed structs deserialized from the JSON-RPC result
Value — Status → StatusResult, RegisterService → an ack, OpenSession →
no JSON-RPC result at all: the socket STOPS being JSON-RPC and becomes a raw
byte pipe.
Additive-only: new fields (capabilities on Hello, groups/user_id on
PeerInfo, device on OpenSession) MUST land as
#[serde(default, skip_serializing_if = ...)] so older payloads still deserialize.
Structs§
- Active
Session - One live mesh session, in a
StreamFrame::Snapshot. Surface-clean:peeris the user_id-or-petname the audit records carry, never an endpoint-id.opened_atis epoch seconds. - Audit
Record - One audit record — the union of the event classes, and the
recordpayload of aStreamFrame::Event. ONE schema for the on-disk JSONL log and the live stream. Every field beyondts/kindis optional and elided when absent (skip_serializing_if), so each class serializes to just its relevant keys (a session record has nomethod; a trust record has nobytes_out). - Audit
Summary Result - Result of
Request::AuditSummary: LOCAL per-peer / per-service session counts aggregated from this node’s OWN audit log — NEVER transmitted (local-only). Surface-clean: peer names are petnames / user_ids (NEVER EndpointIds), service names are the registered service names (NEVER transport vocabulary). A “session” is oneSessionOpenrecord.per_peer/per_serviceare sorted ascending by name (deterministic). Tuples mirror kb’sInsightResponse::per_peer_contribution—["bob", 2]on the wire. - Blob
Fetch Params - Params of
Request::BlobFetch: themcpmesh/blob/1ticket and the LOCAL export path. - Blob
Fetch Result - Result of
Request::BlobFetch: the verified hash + byte length written todest_path. Additive-only. - Blob
Grant Params - Params of
Request::BlobGrant: the scope and the flat-namespace principal to grant it to. - Blob
Publish Params - Params of
Request::BlobPublish: the scope to publish into and the LOCAL file to add. - Blob
Publish Result - Result of
Request::BlobPublish: the copyablemcpmesh/blob/1ticket + the blob’s blake3 hash. A ticket/hash here is blob-reference vocabulary (NOT a transport-vocab leak — the same carve-out as the pairing invite line). Additive-only. - Blob
Scope List - Result of
Request::BlobList: the daemon’s scopes. Additive-only. - Hello
- The first exchange on any
*-local/Nsocket (the family’s hello convention). - Invite
Params - Params of
Request::Invite: the services the minted invite grants.servicesis defaultable — an absent list grants nothing (the documented server-side tolerance). - Invite
Result - Result of an
Request::Inviterequest: the copyablemcpmesh-invite:artifact (the ONE pairing artifact deliberately carved out of the transport-vocabulary blocklist, so this is NOT a transport-vocab leak) plus its absolute expiry in epoch seconds (≤ now + 24h). - Open
Session Params - Params of
Request::OpenSession: thepeer/servicetarget to dial. Both fields are defaultable — an empty target simply fails the dial (a clean-32055error). - OrgJoin
Params - Params of
Request::OrgJoin: the[identity]pin.user_keyis a LOCAL path — the key never crosses the API. - OrgJoin
Result - Result of
Request::OrgJoin— the pinned org id echoed back (surface-clean; the fingerprint is computed porcelain-side from the invite’s org_root_pk). Additive-only. - Pair
Params - Params of
Request::Pair: the copyablemcpmesh-invite:line. Defaultable — an absent field reads as an empty line, which simply fails to decode (a clean pair error). - Pair
Result - Result of a
Request::Pairrequest: the inviter’s suggested petname (the redeemer’s local name for the new peer) plus the display-only short authentication code (SAS) — a few words the human reads aloud to a second channel to catch a whole-invite forgery / address-swap MITM. The SAS is a pairing-ceremony artifact (like the invite line), NOT a transport-vocabulary leak. - Peer
AddParams - Params of
Request::PeerAdd(reserved/internal — see the variant): a rawendpoint_id(iroh base32) plus the petname and service allow list to install it under. - Peer
Info - A known peer as reported by
status(petname only — never the EndpointId). - Peer
Reachability - Advisory reachability of a paired peer (pairing-mode liveness). Surface-clean: a petname + a bool + latency/age NUMBERS — never an endpoint-id, key, or transport path.
- Peer
Remove Params - Params of
Request::PeerRemove: the petname to unpair. - Peer
Rename Params - Params of
Request::PeerRename: the contact to rename — every device sharinguser_idwhen given, else the single provisionalpetnameentry — and the new nicknameto. - Presence
Peer - One reachable roster peer device as reported by
status(the advisory presence read). ADVISORY — this is a display convenience, never an authorization surface. Surface-clean: FLAT vocabulary ONLY — auser_id, a humandevice_label, itsroleword, and anonlineboolean. It carries NO EndpointId / pubkey / hash / ALPN or any transport vocabulary. - Recent
Pairing - One recently completed INVITER-side pairing, surfaced by
statusso the inviter’s human can read the short authentication code (SAS) and compare it with the redeemer’s out-of-band — the pairing ceremony is “both humans compare the code”: the redeemer sees it in itsPairResult; this is the inviter’s porcelain surface for the same words. DISPLAY-ONLY ceremony state: held in-memory by the daemon (a small ring), lost on restart, NEVER an authorization input or trust data. Surface-clean: a petname + the SAS wordlist words + an epoch — never an EndpointId. - Register
Service Params - Params of
Request::RegisterService: the[services.*]entry to write/update. - Roster
Install Params - Params of
Request::RosterInstall: the LOCAL roster filepath, plus the org-root pin on FIRST install (b64u:; omit once pinned — config carries it). - Roster
Install Result - Result of a
Request::RosterInstallrequest (the manual install path): the installed roster’s org id + serial (roster-status vocabulary the confirmation line is permitted to render) plus how many live sessions the install severed. Surface-clean: NO keys / EndpointIds / paths. - Roster
Status - Roster-mode status. Surface-clean roster VOCABULARY only: org_id, serial, a plain state word, and the pinned org-root FINGERPRINT in short words — never raw keys/EndpointIds/serials- as-transport-vocab. Absent in a pure-pairing daemon.
- Scope
Info - One scope in a
BlobScopeList: its name + the hashes it contains + the principals it grants. Flat vocabulary ONLY — no EndpointId/pubkey/ALPN. Additive-only. - Service
Info - A registered service as reported by
status(no transport vocabulary). - SetRoster
UrlParams - Params of
Request::SetRosterUrl: the HTTPS roster URL to pin. - Status
Result
Enums§
- Audit
Kind - The event class of an
AuditRecord(the four audit event classes). An additive discriminant on top of the base record schema: it removes no field and makes the JSONL self-describing so a consumer can filter by class without guessing from which optional fields are present. - Backend
Kind - The kind of backend answering a service — the two valid values, enforced at the
type level and kept in lockstep with
BackendSpec’s variants. Status reports the kind only, never the command/path (no transport vocabulary). - Backend
Spec - How a service is answered. Mirrors the config
[services.*]kinds; Config→BackendSpec is a hand-written match, not a serde passthrough. - Request
- Control-API requests. Serialized as
{ "method": "...", "params": {...} }(JSON-RPC-shaped; the id/jsonrpc envelope is added by the transport layer). - Stream
Frame - One frame of the
Request::Subscribestream (pairing liveness & health telemetry). Tagged ontype(snake_case), so a frame is{"type":"snapshot",...}/{"type":"event",...}/{"type":"lagged",...}.Event.recordis theAuditRecordverbatim, so the stream and the on-disk log carry ONE schema. The daemon serializes these; an embedding consumer deserializes them (seedocs/local-protocol.md“Live event stream”).
Constants§
Functions§
- method_
of - Extract the
methodtag from a raw request value without deserializing the whole message. The daemon’s dispatcher uses this: match on the method string, then deserializeparamsper-method — which tolerates omitted / null /{}params for parameterless methods (adjacent tagging rejectsparams:{}on unit variants).