Skip to main content

Module protocol

Module protocol 

Source
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 — StatusStatusResult, 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§

ActiveSession
One live mesh session, in a StreamFrame::Snapshot. Surface-clean: peer is the user_id-or-petname the audit records carry, never an endpoint-id. opened_at is epoch seconds.
AuditRecord
One audit record — the union of the event classes, and the record payload of a StreamFrame::Event. ONE schema for the on-disk JSONL log and the live stream. Every field beyond ts/kind is optional and elided when absent (skip_serializing_if), so each class serializes to just its relevant keys (a session record has no method; a trust record has no bytes_out).
AuditSummaryResult
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 one SessionOpen record. per_peer / per_service are sorted ascending by name (deterministic). Tuples mirror kb’s InsightResponse::per_peer_contribution["bob", 2] on the wire.
BlobFetchParams
Params of Request::BlobFetch: the mcpmesh/blob/1 ticket and the LOCAL export path.
BlobFetchResult
Result of Request::BlobFetch: the verified hash + byte length written to dest_path. Additive-only.
BlobGrantParams
Params of Request::BlobGrant: the scope and the flat-namespace principal to grant it to.
BlobPublishParams
Params of Request::BlobPublish: the scope to publish into and the LOCAL file to add.
BlobPublishResult
Result of Request::BlobPublish: the copyable mcpmesh/blob/1 ticket + 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.
BlobScopeList
Result of Request::BlobList: the daemon’s scopes. Additive-only.
Hello
The first exchange on any *-local/N socket (the family’s hello convention).
InviteParams
Params of Request::Invite: the services the minted invite grants. services is defaultable — an absent list grants nothing (the documented server-side tolerance).
InviteResult
Result of an Request::Invite request: the copyable mcpmesh-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).
OpenSessionParams
Params of Request::OpenSession: the peer/service target to dial. Both fields are defaultable — an empty target simply fails the dial (a clean -32055 error).
OrgJoinParams
Params of Request::OrgJoin: the [identity] pin. user_key is a LOCAL path — the key never crosses the API.
OrgJoinResult
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.
PairParams
Params of Request::Pair: the copyable mcpmesh-invite: line. Defaultable — an absent field reads as an empty line, which simply fails to decode (a clean pair error).
PairResult
Result of a Request::Pair request: 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.
PeerAddParams
Params of Request::PeerAdd (reserved/internal — see the variant): a raw endpoint_id (iroh base32) plus the petname and service allow list to install it under.
PeerInfo
A known peer as reported by status (petname only — never the EndpointId).
PeerReachability
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.
PeerRemoveParams
Params of Request::PeerRemove: the petname to unpair.
PeerRenameParams
Params of Request::PeerRename: the contact to rename — every device sharing user_id when given, else the single provisional petname entry — and the new nickname to.
PresencePeer
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 — a user_id, a human device_label, its role word, and an online boolean. It carries NO EndpointId / pubkey / hash / ALPN or any transport vocabulary.
RecentPairing
One recently completed INVITER-side pairing, surfaced by status so 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 its PairResult; 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.
RegisterServiceParams
Params of Request::RegisterService: the [services.*] entry to write/update.
RosterInstallParams
Params of Request::RosterInstall: the LOCAL roster file path, plus the org-root pin on FIRST install (b64u:; omit once pinned — config carries it).
RosterInstallResult
Result of a Request::RosterInstall request (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.
RosterStatus
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.
ScopeInfo
One scope in a BlobScopeList: its name + the hashes it contains + the principals it grants. Flat vocabulary ONLY — no EndpointId/pubkey/ALPN. Additive-only.
ServiceInfo
A registered service as reported by status (no transport vocabulary).
SetRosterUrlParams
Params of Request::SetRosterUrl: the HTTPS roster URL to pin.
StatusResult

Enums§

AuditKind
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.
BackendKind
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).
BackendSpec
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).
StreamFrame
One frame of the Request::Subscribe stream (pairing liveness & health telemetry). Tagged on type (snake_case), so a frame is {"type":"snapshot",...} / {"type":"event",...} / {"type":"lagged",...}. Event.record is the AuditRecord verbatim, so the stream and the on-disk log carry ONE schema. The daemon serializes these; an embedding consumer deserializes them (see docs/local-protocol.md “Live event stream”).

Constants§

API_NAME
API_VERSION

Functions§

method_of
Extract the method tag from a raw request value without deserializing the whole message. The daemon’s dispatcher uses this: match on the method string, then deserialize params per-method — which tolerates omitted / null / {} params for parameterless methods (adjacent tagging rejects params:{} on unit variants).