The Rust SDK implements ContextVM: MCP over Nostr.
In practice, it lets you transport MCP JSON-RPC messages through Nostr events, add server discovery through announcement events, and optionally encrypt direct traffic with NIP-44 plus gift wrapping.
For native Rust applications, ContextVM is primarily a transport for rmcp.
That means the usual shape is:
- define an
rmcpserver or client - create a ContextVM Nostr transport
- attach the transport with
ServiceExt
This is the same pattern shown by the rmcp server and client examples. The only difference is that this SDK replaces stdio, HTTP, or raw sockets with Nostr transports.
Most users should start with one of these entry points:
| Use case | Start with |
|---|---|
| Build a native ContextVM server | NostrServerTransport + rmcp ServiceExt |
| Build a native ContextVM client | NostrClientTransport + rmcp ServiceExt |
| Expose an already-existing MCP server on Nostr | NostrMCPGateway |
| Connect to a remote ContextVM server with a simpler bridge | NostrMCPProxy |
| Discover public servers and capabilities | discover_servers() and related helpers |
| Work directly with the optional bridge layer | NostrMCPGateway::serve_handler() or NostrMCPProxy::serve_client_handler() |
The crate is organized in layers:
core: protocol types, validation, serialization, errorsrelay: relay pool abstractionsigner: key generation and signer helpersencryption: NIP-44 and gift-wrap helperstransport: native ContextVM client and server transportsgateway: wrapper for exposing an existing MCP server flow on Nostrproxy: wrapper for connecting to a remote server without the fullrmcpclient modeldiscovery: announcement and capability discovery
The application-facing rmcp layer provides the ServiceExt integration point together with the usual server and client startup flow.
ContextVM keeps MCP semantics intact and uses Nostr only as the transport envelope.
- MCP payloads are represented by
JsonRpcMessage - direct plaintext ContextVM traffic uses kind
25910 - encrypted traffic uses gift-wrap kinds
1059(persistent) or21059(ephemeral, CEP-19), negotiated byGiftWrapMode - public server discovery uses announcement kinds
11316through11320(CEP-6) - server relay lists are published as NIP-65 kind
10002events (CEP-17) - optional server profile metadata is published as a NIP-01 kind
0event (CEP-23) - oversized transfers (CEP-22) and open streams (CEP-41) both ride inside
notifications/progressframes on kind25910, separated by acvm.typediscriminant (oversized-transferandopen-stream) - routing is done with
ptags and request/response correlation withetags, as reflected in the repository root README
EncryptionMode:Optional,Required,DisabledGiftWrapMode:Optional,Ephemeral,Persistent(CEP-19 gift-wrap policy: persistent kind1059vs ephemeral kind21059)contextvm_sdk::ServerInfo: announcement metadatacontextvm_sdk::ServerAnnouncement: the discovered-server record returned bydiscover_servers()(CEP-6)contextvm_sdk::ProfileMetadata: optional NIP-01 kind0profile metadata for a human-friendly server identity (CEP-23)CapabilityExclusion: allowlist bypass rules for specific methods or capabilitiesOpenStreamConfig: CEP-41 open-stream settings (disabled by default; see the open-stream guide)ToolStreamCall: the paired live chunk stream and final result returned bycall_tool_stream
- generate keys with
signer::generate()or load an existing private key withfrom_sk() - configure
NostrServerTransportConfig - create
NostrServerTransport - attach it to an
rmcpserver withServiceExt - optionally publish announcements with
announce()
- generate keys with
signer::generate()or load an existing private key withfrom_sk() - configure
NostrClientTransportConfig - create
NostrClientTransport - attach it to an
rmcpclient withServiceExt
If you are not building a native rmcp service directly, use the wrapper layer:
NostrMCPGatewayfor server-side bridgingNostrMCPProxyfor client-side bridging
- create a
RelayPool - query
discover_servers() - fetch public tools, resources, and prompts with the discovery helpers
The Rust SDK already implements behavior that users should rely on:
- stateless client initialization behavior
- announcement publication and deletion
- encryption negotiation and response mirroring
- rmcp conversion and routing flow
Use the task-oriented pages in this directory for those details. Start with the native server and native client guides if you are building ContextVM applications directly.