Skip to content

ContextVM/rs-sdk

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

103 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

contextvm-sdk

License: MIT Rust

Rust SDK for the ContextVM protocol β€” MCP over Nostr.

A complete implementation enabling Model Context Protocol (MCP) servers and clients to communicate over the Nostr network with decentralized discovery, cryptographic identity, and optional end-to-end encryption.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Your Application                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Gateway    β”‚     Proxy     β”‚        Discovery           β”‚
β”‚  (server β†’   β”‚  (nostr β†’     β”‚  (find servers &           β”‚
β”‚    nostr)    β”‚    client)    β”‚   capabilities)            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                    Transport Layer                         β”‚
β”‚            NostrServerTransport / NostrClientTransport     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Core          β”‚  Encryption     β”‚  Relay    β”‚  Signer    β”‚
β”‚  (types,       β”‚  (NIP-44,       β”‚  (pool    β”‚  (key      β”‚
β”‚   JSON-RPC,    β”‚   NIP-59        β”‚   mgmt)   β”‚   mgmt)    β”‚
β”‚   validation)  β”‚   gift wrap)    β”‚           β”‚            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                   Nostr Network (relays)                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Protocol

ContextVM maps MCP's JSON-RPC 2.0 messages onto Nostr events:

Kind Name Type Description
25910 ContextVM Messages Ephemeral MCP request/response/notification
1059 Gift Wrap (NIP-59) Regular Encrypted MCP messages
11316 Server Announcement Addressable Server identity & metadata
11317 Tools List Addressable Published tool capabilities
11318 Resources List Addressable Published resource capabilities
11319 Resource Templates Addressable Published resource template list
11320 Prompts List Addressable Published prompt capabilities

Messages are routed using Nostr p tags (recipient pubkey) and correlated with e tags (request event ID).

Installation

Add to your Cargo.toml:

[dependencies]
contextvm-sdk = { git = "https://github.com/k0sti/rust-contextvm-sdk" }

Or clone and use as a path dependency:

[dependencies]
contextvm-sdk = { path = "../rust-contextvm-sdk" }

Quick Start

Gateway β€” Expose a Local MCP Server via Nostr

use contextvm_sdk::gateway::{NostrMCPGateway, GatewayConfig};
use contextvm_sdk::transport::server::NostrServerTransportConfig;
use contextvm_sdk::core::types::{ServerInfo, EncryptionMode};
use contextvm_sdk::signer;

#[tokio::main]
async fn main() -> contextvm_sdk::Result<()> {
    let keys = signer::generate();

    let config = GatewayConfig {
        nostr_config: NostrServerTransportConfig {
            relay_urls: vec!["wss://relay.damus.io".into()],
            encryption_mode: EncryptionMode::Optional,
            server_info: Some(ServerInfo {
                name: Some("My MCP Server".into()),
                about: Some("Tools via Nostr".into()),
                ..Default::default()
            }),
            is_announced_server: true,
            ..Default::default()
        },
    };

    let mut gateway = NostrMCPGateway::new(keys, config).await?;
    let mut requests = gateway.start().await?;
    gateway.announce().await?;

    while let Some(req) = requests.recv().await {
        println!("Request: {:?}", req.message);
        // Process and respond:
        // gateway.send_response(&req.event_id, response).await?;
    }
    Ok(())
}

Proxy β€” Connect to a Remote MCP Server via Nostr

use contextvm_sdk::proxy::{NostrMCPProxy, ProxyConfig};
use contextvm_sdk::transport::client::NostrClientTransportConfig;
use contextvm_sdk::core::types::EncryptionMode;
use contextvm_sdk::signer;

#[tokio::main]
async fn main() -> contextvm_sdk::Result<()> {
    let keys = signer::generate();

    let config = ProxyConfig {
        nostr_config: NostrClientTransportConfig {
            relay_urls: vec!["wss://relay.damus.io".into()],
            server_pubkey: "abc123...server_hex_pubkey".into(),
            encryption_mode: EncryptionMode::Optional,
            ..Default::default()
        },
    };

    let mut proxy = NostrMCPProxy::new(keys, config).await?;
    let mut responses = proxy.start().await?;

    // Send an MCP request
    let request = contextvm_sdk::JsonRpcMessage::Request(contextvm_sdk::JsonRpcRequest {
        jsonrpc: "2.0".into(),
        id: serde_json::json!(1),
        method: "tools/list".into(),
        params: None,
    });
    proxy.send(&request).await?;

    // Receive response
    if let Some(msg) = responses.recv().await {
        println!("Response: {:?}", msg);
    }
    Ok(())
}

Discovery β€” Find MCP Servers on Nostr

use contextvm_sdk::{discovery, signer, RelayPool};

#[tokio::main]
async fn main() -> contextvm_sdk::Result<()> {
    let keys = signer::generate();
    let pool = RelayPool::new(keys).await?;
    let relays = vec!["wss://relay.damus.io".into()];
    pool.connect(&relays).await?;

    let servers = discovery::discover_servers(pool.client(), &relays).await?;
    for server in &servers {
        println!("Server: {} ({:?})", server.pubkey, server.server_info.name);

        let tools = discovery::discover_tools(pool.client(), &server.pubkey_parsed, &relays).await?;
        println!("  Tools: {}", tools.len());
    }
    Ok(())
}

Module Overview

Module Description
core Protocol constants, JSON-RPC types, error types, validation
transport Client/server Nostr transports with event loop and correlation
gateway High-level gateway bridging local MCP servers to Nostr
proxy High-level proxy connecting to remote MCP servers via Nostr
discovery Server/capability discovery via addressable Nostr events
encryption NIP-44 encryption and NIP-59 gift wrapping
relay Nostr relay pool management (connect, publish, subscribe)
signer Key generation and management utilities

Configuration

Encryption Modes

Mode Behavior
Optional Encrypt responses if the incoming request was encrypted
Required All messages must be encrypted (rejects plaintext)
Disabled No encryption; all messages sent as plaintext kind 25910

Encryption uses NIP-44 for payload encryption and NIP-59 (Gift Wrap) for metadata-private delivery. Server announcements (kinds 11316–11320) are always public.

Server Transport Config

Field Default Description
relay_urls ["wss://relay.damus.io"] Nostr relays to connect to
encryption_mode Optional Encryption policy
server_info None Server metadata for announcements
is_announced_server false Whether to publish announcements (CEP-6)
allowed_public_keys [] (allow all) Client pubkey allowlist (hex)
excluded_capabilities [] Methods exempt from allowlist
session_timeout 300s Inactive session expiry

Client Transport Config

Field Default Description
relay_urls ["wss://relay.damus.io"] Nostr relays to connect to
server_pubkey (required) Target server's public key (hex)
encryption_mode Optional Encryption policy
is_stateless false Emulate initialize locally
timeout 30s Response timeout

References

License

MIT

About

Rust SDK for the ContextVM protocol

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 100.0%