Skip to main content

Request

Enum Request 

Source
pub enum Request {
Show 47 variants RegisterService(RegisterServiceParams), Status, Invite(InviteParams), Pair(PairParams), PeerRemove(PeerRemoveParams), PeerRename(PeerRenameParams), AttestOffer, AttestTo(AttestToParams), PeerRevoke(PeerRevokeParams), PeerUnrevoke(PeerUnrevokeParams), DeviceRevoke(DeviceRevokeParams), DeviceRevocationImport(DeviceRevocationImportParams), PeerAdd(PeerAddParams), PeerIntroduce(PeerIntroduceParams), PeerEndorse(PeerEndorseParams), OpenSession(OpenSessionParams), RosterInstall(RosterInstallParams), RosterMembers, OrgCreate(OrgCreateParams), OrgApprove(OrgApproveParams), OrgRotate(OrgRotateParams), OrgJoinCode(OrgJoinCodeParams), OrgRevoke(OrgRevokeParams), UserKeyExport, UserKeyImport(UserKeyImportParams), OrgJoin(OrgJoinParams), SetRosterUrl(SetRosterUrlParams), SetNickname(SetNicknameParams), SetAppMetadata(SetAppMetadataParams), SetRelays(SetRelaysParams), UnregisterService(UnregisterServiceParams), PeerServices(PeerServicesParams), PeerDiagnostics(PeerDiagnosticsParams), ServiceAllowGrant(ServiceAllowParams), ServiceAllowRevoke(ServiceAllowParams), BlobPublish(BlobPublishParams), BlobGrant(BlobGrantParams), BlobRevoke(BlobRevokeParams), BlobUnpublish(BlobUnpublishParams), BlobRepublish(BlobRepublishParams), BlobList(BlobListParams), BlobFetch(BlobFetchParams), BlobFetchCancel(BlobFetchCancelParams), AuditSummary, AuditPrune(AuditPruneParams), AuditList(AuditListParams), Subscribe,
}
Expand description

Control-API requests. Serialized as { "method": "...", "params": {...} } (JSON-RPC-shaped; the id/jsonrpc envelope is added by the transport layer).

Each param-carrying variant wraps its named *Params struct — the ONE wire truth for that method’s params, shared by clients (which serialize whole Requests) and the daemon (which deserializes params into the same struct after its method-string dispatch). Adjacent tagging serializes a newtype variant’s content as the struct’s fields, so the wire shape is identical to inline variant bodies.

Servers dispatch on the method string and deserialize params per-method — tolerating omitted / null / empty-object params for parameterless methods — rather than deserializing a whole message into Request (adjacent tagging rejects params:{} for unit variants). This keeps the wire tolerant for third-party clients (the versioned, additive-only surface). Use method_of to extract the tag, then match + deserialize params per-method.

Variants§

§

RegisterService(RegisterServiceParams)

Register/update a [services.*] entry idempotently.

§

Status

§

Invite(InviteParams)

Mint a pairing invite granting services — single-use unless max_uses says otherwise (#87). The daemon answers an InviteResult carrying the copyable mcpmesh-invite: line. Tag "invite" (snake_case). method_of needs no per-variant arm — it reads the method string generically; the tag comes from rename_all.

§

Pair(PairParams)

Redeem a pairing invite. The daemon dials the inviter named by invite_line on mcpmesh/pair/1, proves the secret, writes the mutual (dial-back) PeerEntry, and answers a PairResult. Tag "pair" (snake_case); method_of reads the method string generically.

PeerEntry — the durable allowlist row — lives in the daemon crate.

§

PeerRemove(PeerRemoveParams)

Remove a paired peer by nickname (mcpmesh pair --remove). The daemon drops the peer’s PeerEntry (identity) AND revokes its access by stripping its stable principals from every [services.*].allow (authorization) — the inverse of the pairing grant. Idempotent: a nickname with no entry / no allow membership is a clean no-op. Live in-flight sessions are NOT severed here: existing sessions run to completion; the peer only loses the ability to establish NEW authorized sessions. Tag "peer_remove" (snake_case); method_of reads the method string generically (no per-variant arm).

PeerEntry — the durable allowlist row — lives in the daemon crate.

§

PeerRename(PeerRenameParams)

Rename a contact’s nickname (nickname) authoritatively. Renames the PERSON — every PeerEntry sharing user_id when given (one op for all their devices), else the single nickname entry (a provisional, no-user_id contact) — to to, AND rewrites the old nickname → to in every [services.*].allow so grants follow the rename. Refuses (error frame) when to is empty or already names/grants a DIFFERENT identity — the same collision guard the pairing rendezvous uses, so a rename can’t inherit another peer’s access. Tag "peer_rename"; host-privileged like the other pair ops.

§

AttestOffer

Mint an attestation OFFER (#85 ask 3): a mcpmesh-attest: line telling another device of a person you already pair with where to dial. Tag "attest_offer".

Carries nothing secret — the offering node’s id and address, both of which an invite line already carries in the clear. It exists because a device freshly restored from a recovery phrase holds no rows and so has no way to find anyone.

Refused unless this node has [identity].admit_attested_devices on: an offer it would not honour is worse than no offer.

§

AttestTo(AttestToParams)

Present THIS device’s identity to a peer, using their mcpmesh-attest: line (#85 ask 3). Tag "attest_to".

The recovery path’s second half: user_key_import restores the b64u: your peers pinned, and this is what gets the machine holding it ADMITTED. Requires a user key — with none there is nothing to attest.

The peer admits this device only if it already holds a row for this person, has opted in, and has revoked neither this endpoint nor the IDENTITY. It cannot admit a stranger.

§

PeerRevoke(PeerRevokeParams)

REVOKE an endpoint locally: “I no longer trust this device” (#85 ask 4). Tag "peer_revoke".

Not the same act as PeerRemove, deliberately. Removal is routine — we are not working together any more — and re-pairing afterwards is normal. Revocation is a claim about COMPROMISE, and it outlives the pair row: a revoked endpoint is refused whether or not it is in the allowlist, so it cannot be undone by a fresh pairing. Making them one verb would either make removal irreversible or make revocation weak.

Takes effect IMMEDIATELY, like service_allow_revoke (#54): live sessions are severed rather than left to end on their own, which for long-lived MCP sessions is unbounded.

A b64u: principal revokes EVERY endpoint this node associates with that person — the “not on any of their devices” case, which an operator will otherwise get wrong doing it device by device.

Reversible with PeerUnrevoke: this list is LOCAL and not authoritative for anyone else, so an operator mistake has to be fixable. Both directions are audited.

§

PeerUnrevoke(PeerUnrevokeParams)

Lift a local revocation (#85 ask 4). Tag "peer_unrevoke". Idempotent.

Restores the peer only if its pair row still exists — revocation never deleted it. A revocation applied from a SIGNED statement can be lifted too: the signature proved who asked, not that this node must obey forever.

§

DeviceRevoke(DeviceRevokeParams)

Sign a revocation of one of THIS node’s own endpoints with THIS node’s user key (#85 ask 4), producing a portable token. Tag "device_revoke".

The direction that matters, and the one local revocation cannot express: my laptop was stolen, and my peers cannot discover that by themselves. I have to tell them, and they have to be able to verify it was me.

Requires a user key — a node with none has no authority to speak for its person. Distribution is out of band: pairing mode has no gossip, so getting the token to your peers is the same problem as getting them an invite line, and has the same answer.

§

DeviceRevocationImport(DeviceRevocationImportParams)

Apply a signed device revocation from a peer (#85 ask 4). Tag "device_revocation_import".

Refused unless this node ALREADY trusts the signing user_id (holds a paired entry carrying it) and the revoked endpoint is one this node associates with that same person, or is entirely unknown to it. That bound is what keeps this from being an “mark any endpoint dead” primitive: a peer may kill their OWN devices in your node, and nothing else.

§

PeerAdd(PeerAddParams)

RESERVED / INTERNAL (docs/local-protocol.md “Reserved / internal methods”): install a peer directly from a raw endpoint_id — the trust-population stand-in for pairing behind mcpmesh internal peer add. A deliberate, documented exception to the surface discipline (raw endpoint identifiers otherwise never cross this socket); NOT part of the stable vocabulary — do not build on it. Tag "peer_add".

§

PeerIntroduce(PeerIntroduceParams)

Install a peer from a SIGNED endorsement by someone you are already paired with (#65) — O(N) onboarding for a small group, without a fresh two-human SAS ceremony per pair.

It installs IDENTITY, never AUTHORIZATION. The subject becomes resolvable; it is granted nothing. Service access stays principal-keyed in config (#38) and an explicit, separate act. That is what bounds the feature: a compromised endorser can make you KNOW about an attacker, it cannot make you SERVE one.

Unlike PeerAdd — which is reserved precisely because the caller merely ASSERTS an id — this is verifiable: the endorsement is checked against a user key you already hold from pairing with the endorser. Tag "peer_introduce".

§

PeerEndorse(PeerEndorseParams)

PRODUCE an endorsement of a peer, for someone else to redeem with PeerIntroduce (#65). The other half of an introduction: without it nothing can generate evidence, and the install half is unusable.

Signs with THIS node’s user key, so the result is only meaningful to someone who has paired with you. Endorsing does not change your own trust in the subject. Tag "peer_endorse".

§

OpenSession(OpenSessionParams)

Open a mesh session to peer/service; the daemon dials and pipes. Distinct from the proxy’s job: this returns a session the client streams. Named open_session rather than connect to avoid colliding with the connect porcelain.

§

RosterInstall(RosterInstallParams)

Install a signed roster from a local file (the manual internal roster install path). path is a LOCAL file the same-uid daemon reads (the daemon runs as the caller’s own uid, so passing a path rather than the bytes crosses no trust boundary). org_root_pk pins the org root on FIRST install (b64u:); omit it once pinned (config carries it). Tag "roster_install".

§

RosterMembers

Read the installed roster’s MEMBERSHIP: the declared groups, and every person with their display name, groups, and devices (#93). Parameterless. Tag "roster_members".

The read half of roster mode. status reports that a roster exists (RosterStatus) and who is currently online (PresencePeer); neither answered “who is in this org” — a person with no live device appeared nowhere at all, so an embedder could not draw a member list, and the only route to one was hand-parsing the daemon-owned roster.json.

ADVISORY and display-oriented, like status: the gate reads the roster document, never this. Empty in a pure-pairing daemon or before the first roster is installed.

§

OrgCreate(OrgCreateParams)

AUTHOR an org: mint this node’s org root key, sign an empty roster (serial 1), install it (which pins the root), and return the copyable org invite (#66). Tag "org_create".

One-time per node — a second call is refused rather than replacing the key, because replacing it would orphan every roster it has signed.

§

OrgApprove(OrgApproveParams)

APPROVE a join code into the roster: verify its device→user-key binding, upsert the member with the given groups, bump the serial, re-sign, install (#66). Tag "org_approve".

The cryptographic half of the ceremony. Verifying that the code came from the PERSON you think it did stays an out-of-band human step, and join_code_fingerprint in the result is what the two humans compare.

§

OrgRotate(OrgRotateParams)

ROTATE the org root (#93 ask c). Tag "org_rotate".

The org’s trust anchor is one pinned key, and nothing could move it: an operator laptop that died took the org with it 90 days later, when the roster expired — and the delay is what made that hard to diagnose. Recovery was O(N) fresh ceremonies with every member.

Publishes a roster signed by the SUCCESSOR carrying a cross-signature by the CURRENT root, so a member still pinned to the current key adopts the successor with the key it already has. The bridge rides every subsequent roster, so a member offline for one publication catches up — but one two rotations behind needs a fresh org_join.

This is not escrow. If the current root key is LOST there is nothing to sign the bridge with. Copying org-root.key to a second operator machine already works and remains the answer for that.

§

OrgJoinCode(OrgJoinCodeParams)

INSPECT a join code without approving it (#66): who it claims to be, and the fingerprint the two humans compare. Read-only — nothing is signed, installed, or persisted. Tag "org_join_code".

This is what makes an “approve this person” button correct rather than merely possible. The fingerprint has to be shown and confirmed out-of-band BEFORE the approval, because a substituted code is caught there or not at all — and reading it off OrgApprove’s result is too late, the member is already in the signed roster. The CLI always had this (it decoded the code locally); an embedder could not, since the join-code format lives in mcpmesh-node and not on this seam.

§

OrgRevoke(OrgRevokeParams)

REVOKE from the roster: remove a person, one device, or a person’s user key, then bump, re-sign, and install — which severs the cut devices’ live sessions (#66). Tag "org_revoke".

§

UserKeyExport

EXPORT this node’s user key as a recovery phrase (#85 ask 2). Parameterless. Tag "user_key_export".

The phrase IS the private key, in a form a human can write down. Anyone who reads it can present this identity. It is deliberately not logged, not audited, and not echoed anywhere but this response.

§

UserKeyImport(UserKeyImportParams)

IMPORT a user key from a recovery phrase (#85 ask 2), so a person’s b64u: survives the hardware. Tag "user_key_import".

§

OrgJoin(OrgJoinParams)

Pin the org root on a JOINER — WITHOUT a roster (the joiner has none yet; its poll loop fetches the first one). Records [identity] org_id / org_root_pk / user_id / user_key. user_key is a LOCAL path (the key never crosses the API). Tag "org_join".

§

SetRosterUrl(SetRosterUrlParams)

Pin the HTTPS roster URL ([roster].url) in config. Written by org create --roster-url (the operator keeps it current) AND by join when the org invite carries one — so the joiner’s poll loop bootstraps its FIRST roster. The daemon writes it under reload_lock (single-writer), then the poll loop picks it up on the next daemon start. Tag "set_roster_url".

§

SetNickname(SetNicknameParams)

Rename this node LIVE (#37): validate + upsert [identity].nickname through the daemon’s own serialized config-write path (no lost-update window against a concurrent grant/registration) and update the in-memory name future invites present — no restart. Ack result. Tag "set_nickname" (snake_case).

§

SetAppMetadata(SetAppMetadataParams)

Set this node’s opaque app-metadata blob (#39): validated (≤256B) and folded, signed, into each outgoing presence heartbeat, so paired roster peers see it in their status presence — no per-peer session. Ack result. Tag "set_app_metadata". In-memory (lost on restart; the embedder re-sets on startup).

§

SetRelays(SetRelaysParams)

Set this node’s CUSTOM relay set LIVE (#53): validate each URL as an iroh RelayUrl, diff against the running endpoint’s current custom relays and apply the delta via iroh 1.0.3 Endpoint::insert_relay/remove_relay (no endpoint rebuild, no dropped sessions), then persist [network] relay_mode="custom" relay_urls=[…] under reload_lock. When the node is currently default/disabled, the config is persisted but the live mode transition isn’t possible — SetRelaysResult::restart_required is true. Answers a SetRelaysResult. Tag "set_relays".

§

UnregisterService(UnregisterServiceParams)

Grant a single stable principal access to a single service’s allow (#44) — the per-peer “sharing on” toggle, idempotent + serialized under the config lock. Ack result. Remove a service registration (#50) — the deregistration mirror of register_service. Removes the whole [services.<name>] entry (allow included) + any ephemeral one, then hot-reloads. Idempotent. Ack result.

§

PeerServices(PeerServicesParams)

Discover which services a paired peer CURRENTLY grants the caller (#52) — dials the peer and returns the service names whose allow admits the caller’s principal. Answers PeerServicesResult.

§

PeerDiagnostics(PeerDiagnosticsParams)

Dump the DURABLE per-peer state this node carries for one peer (#140) — the persisted dial hint, the pairing stamp, and the live reachability row, in one capture. A DIAGNOSTIC verb: unlike every other surface it carries transport vocabulary on purpose. Answers with PeerDiagnosticsResult. api_minor >= 33.

§

ServiceAllowGrant(ServiceAllowParams)

§

ServiceAllowRevoke(ServiceAllowParams)

Revoke a single stable principal from a single service’s allow (#44) — “sharing off” WITHOUT unpairing (the peer’s identity row is untouched; only NEW sessions are refused). Idempotent. Ack result.

§

BlobPublish(BlobPublishParams)

Publish a LOCAL file INTO a scope: the daemon adds the bytes to its gated app-blob store and records the hash in scope. path is a local file the same-uid daemon reads. Answers a BlobPublishResult carrying the mcpmesh/blob/1 ticket + hash. Tag "blob_publish".

§

BlobGrant(BlobGrantParams)

Grant a scope to a principal — any flat-namespace entry: a group name, a user_id, or a nickname (the shared principal_set expansion). Tag "blob_grant".

§

BlobRevoke(BlobRevokeParams)

Tag "blob_revoke": withdraw principals from ONE scope’s grants (#62).

§

BlobUnpublish(BlobUnpublishParams)

Tag "blob_unpublish": remove a hash from ONE scope (#62). Withdraws reachability, not bytes.

§

BlobRepublish(BlobRepublishParams)

#83: make a blob this daemon already holds servable from HERE, in a scope it controls. Answers a BlobPublishResult — same shape as blob_publish, so a client can treat the two interchangeably after a fetch.

§

BlobList(BlobListParams)

List the daemon’s blob scopes (name → hashes + grants). Tag "blob_list".

§

BlobFetch(BlobFetchParams)

Fetch a mcpmesh/blob/1 ticket THROUGH the daemon (BLAKE3-verified streaming) and export the verified blob to dest_path (a local file the same-uid daemon writes). Answers a BlobFetchResult with the verified hash + byte length. Tag "blob_fetch".

§

BlobFetchCancel(BlobFetchCancelParams)

Cancel every in-flight BlobFetch of one hash (#172). Answers a BlobFetchCancelResult; the cancelled fetches themselves answer ERR_CANCELLED. Tag "blob_fetch_cancel".

§

AuditSummary

Summarize this node’s LOCAL audit log into per-peer / per-service SESSION counts (local-only — the daemon reads its OWN audit dir, nothing is transmitted). The host Mesh surface renders these as “who serves me / whom I serve / session counts”. Parameterless (like Status); the server dispatches on the method string. Tag "audit_summary" (snake_case); method_of reads the method string generically (no per-variant arm).

§

AuditPrune(AuditPruneParams)

Delete audit months strictly older than before (#88) — the retention lever the log never had. Local-only and owner-only (the control socket is the daemon owner’s). Answers AuditPruneResult. Tag "audit_prune".

§

AuditList(AuditListParams)

Read this node’s LOCAL audit records, filtered and paged (#88) — the “show me everything you hold about me” verb. Local-only; nothing is transmitted. Answers AuditListResult. Tag "audit_list".

§

Subscribe

Open a live event stream (pairing liveness & health telemetry). Like open_session, the connection STOPS being request/response after this call and becomes a one-way push stream of StreamFrames. Parameterless. Tag "subscribe".

Trait Implementations§

Source§

impl Clone for Request

Source§

fn clone(&self) -> Request

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Request

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Request

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for Request

Source§

impl PartialEq for Request

Source§

fn eq(&self, other: &Request) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Request

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Request

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more