# ContextVM Rust SDK Overview
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.
## The main mental model
For native Rust applications, ContextVM is primarily a transport for `rmcp`.
That means the usual shape is:
1. define an `rmcp` server or client
2. create a ContextVM Nostr transport
3. 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.
## Choose the right API
Most users should start with one of these entry points:
| 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 | `serve_handler()` or `serve_client_handler()` |
## Architecture
The crate is organized in layers:
- `core`: protocol types, validation, serialization, errors
- `relay`: relay pool abstraction
- `signer`: key generation and signer helpers
- `encryption`: NIP-44 and gift-wrap helpers
- `transport`: native ContextVM client and server transports
- `gateway`: wrapper for exposing an existing MCP server flow on Nostr
- `proxy`: wrapper for connecting to a remote server without the full `rmcp` client model
- `discovery`: announcement and capability discovery
The application-facing `rmcp` layer provides the `ServiceExt` integration point together with the usual server and client startup flow.
## Protocol model
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` or `21059`
- public discovery uses kinds `11316` through `11320`
- routing is done with `p` tags and request/response correlation with `e` tags, as reflected in the repository root README
## Core types you should know
- `EncryptionMode`: `Optional`, `Required`, `Disabled`
- `GiftWrapMode`: `Optional`, `Ephemeral`, `Persistent`
- `ServerInfo`: announcement metadata
- `CapabilityExclusion`: allowlist bypass rules for specific methods or capabilities
## Typical workflows
### Build a native server
1. generate keys with `signer::generate()` or load an existing private key with `from_sk()`
2. configure `NostrServerTransportConfig`
3. create `NostrServerTransport`
4. attach it to an `rmcp` server with `ServiceExt`
5. optionally publish announcements with `announce()`
### Build a native client
1. generate keys with `signer::generate()` or load an existing private key with `from_sk()`
2. configure `NostrClientTransportConfig`
3. create `NostrClientTransport`
4. attach it to an `rmcp` client with `ServiceExt`
### Bridge an existing server or client
If you are not building a native `rmcp` service directly, use the wrapper layer:
- `NostrMCPGateway` for server-side bridging
- `NostrMCPProxy` for client-side bridging
### Discover servers
1. create a `RelayPool`
2. query `discover_servers()`
3. fetch public tools, resources, and prompts with the discovery helpers
## What is important in this implementation
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.