typescript-sdk
ContextVM TypeScript SDK
Reference guide for using @contextvm/sdk effectively.
Installation
npm install @contextvm/sdk
# or
bun add @contextvm/sdk
Core Imports
// Transports
import { NostrClientTransport, NostrServerTransport } from '@contextvm/sdk';
// Signers
import { PrivateKeySigner } from '@contextvm/sdk';
// Relay Handlers
import { ApplesauceRelayPool } from '@contextvm/sdk';
// Components
import { NostrMCPProxy, NostrMCPGateway } from '@contextvm/sdk';
// Core types and utilities
import {
EncryptionMode,
CTXVM_MESSAGES_KIND,
SERVER_ANNOUNCEMENT_KIND,
createLogger,
} from '@contextvm/sdk';
Core Interfaces
NostrSigner
Abstracts cryptographic signing:
interface NostrSigner {
getPublicKey(): Promise<string>;
signEvent(event: EventTemplate): Promise<NostrEvent>;
nip44?: {
encrypt(pubkey: string, plaintext: string): Promise<string>;
decrypt(pubkey: string, ciphertext: string): Promise<string>;
};
}
Implement for custom key management (hardware wallets, browser extensions, etc.).
RelayHandler
Manages relay connections:
interface RelayHandler {
connect(): Promise<void>;
disconnect(relayUrls?: string[]): Promise<void>;
publish(event: NostrEvent): Promise<void>;
subscribe(
filters: Filter[],
onEvent: (event: NostrEvent) => void,
onEose?: () => void
): Promise<void>;
unsubscribe(): void;
}
Must be non-blocking - subscribe() returns immediately.
Signers
PrivateKeySigner
Default signer using raw private key:
const signer = new PrivateKeySigner('32-byte-hex-private-key');
const pubkey = await signer.getPublicKey();
Security: Never hardcode keys. Use environment variables.
Custom Signers
Implement NostrSigner for:
- Browser extensions (NIP-07)
- Hardware wallets
- Remote signing services
- Secure enclaves
See references/custom-signers.md for examples.
Relay Handlers
ApplesauceRelayPool (Recommended)
Production-grade relay management:
const pool = new ApplesauceRelayPool(['wss://relay.contextvm.org', 'wss://cvm.otherstuff.ai']);
Features:
- Automatic reconnection
- Connection monitoring
- RxJS-based observables
- Persistent subscriptions
Use ApplesauceRelayPool for projects.
For NostrClientTransport, relayHandler can be omitted when the client should resolve operational relays dynamically. The resolution order is:
- explicit operational relays from
relayHandler - relay hints embedded in
nprofile - CEP-17 relay-list discovery via
discoveryRelayUrls fallbackOperationalRelayUrls- SDK bootstrap discovery relays when
discoveryRelayUrlsis omitted
This makes client configuration simpler when the server already publishes kind:10002 metadata.
Use fallbackOperationalRelayUrls when you want non-authoritative operational relays to be probed in parallel with CEP-17 discovery. This is useful for low-latency local relays or known-good operational relays that should only be used when explicit relays and nprofile hints are absent.
Important semantics:
relayHandlerremains the explicit authoritative operational relay set.discoveryRelayUrlsremains discovery-only.fallbackOperationalRelayUrlsis non-authoritative and should not replace publishedkind:10002metadata when that metadata resolves in time.
Encryption Modes
enum EncryptionMode {
OPTIONAL = 'optional', // Use if supported (default)
REQUIRED = 'required', // Fail if not supported
DISABLED = 'disabled', // Never encrypt
}
Oversized Transfer
The SDK supports CEP-22 oversized payload transfer on both client and server transports.
Important consumer-facing behavior:
- oversized transfer is enabled by default
- transports automatically fragment and reassemble large payloads
- most applications do not need to manage chunking directly
- the main decision is whether to keep it enabled or disable it explicitly
Typical configuration:
const clientTransport = new NostrClientTransport({
signer,
serverPubkey,
oversizedTransfer: {
enabled: true,
},
});
Relevant options:
enabled: explicit on/off switch for CEP-22 behaviorthresholdBytes: proactive fragmentation thresholdchunkSizeBytes: per-chunk sizeacceptTimeoutMs: client-side wait time for accept-gated flowspolicy: receiver-side limits for bytes, chunks, concurrency, ordering window, and timeout
Use lower thresholds or chunk sizes when relays are more restrictive. Tighten policy values when operating in resource-constrained or adversarial environments.
Logging
import { createLogger } from '@contextvm/sdk/core';
const logger = createLogger('my-module');
logger.info('event.name', {
module: 'my-module',
txId: 'abc-123',
durationMs: 245,
});
Configure via environment:
LOG_LEVEL=debug|info|warn|errorLOG_DESTINATION=stderr|stdout|fileLOG_FILE=/path/to/fileLOG_ENABLED=true|false
Constants
| Constant | Value | Description |
|---|---|---|
CTXVM_MESSAGES_KIND |
25910 | Ephemeral messages |
SERVER_ANNOUNCEMENT_KIND |
11316 | Server metadata |
RELAY_LIST_METADATA_KIND |
10002 | Relay-list metadata |
TOOLS_LIST_KIND |
11317 | Tools announcement |
RESOURCES_LIST_KIND |
11318 | Resources announcement |
GIFT_WRAP_KIND |
1059 | Encrypted messages |
SDK Patterns
See references/patterns.md for:
- Error handling
- Retry strategies
- Connection lifecycle
- Resource cleanup
API Reference
references/interfaces.md- Complete interface definitionsreferences/constants.md- All exported constantsreferences/logging.md- Logging best practices
More from contextvm/cvmi
overview
Understand ContextVM protocol fundamentals, architecture, and core concepts. Use when users need to learn about ContextVM basics, how it bridges MCP with Nostr, protocol design principles, event kinds, or the relationship between MCP and Nostr in decentralized communication.
32concepts
Understand ContextVM core concepts, architecture decisions, and frequently asked questions. Use when users need clarification on what ContextVM is, why it uses Nostr, decentralization benefits, public vs private servers, network topology, or comparisons with traditional MCP.
32server-dev
Build MCP servers that expose capabilities over the Nostr network using ContextVM. Use when creating new servers, converting existing MCP servers to ContextVM, configuring server transports, implementing access control, or setting up public server announcements.
31client-dev
Build MCP clients that connect to ContextVM servers over Nostr. Use when creating clients, discovering servers, connecting to remote servers, handling encrypted connections, or implementing the proxy pattern for existing MCP clients.
31payments
Implement CEP-8 payments in ContextVM using the @contextvm/sdk payments middleware. Use when building paid servers/clients, configuring priced capabilities, integrating payment processors/handlers, or troubleshooting payment notification flows.
24troubleshooting
Diagnose and resolve ContextVM connection issues, relay problems, encryption failures, authentication errors, and common deployment problems. Use when users report errors, connection failures, timeout issues, or unexpected behavior with ContextVM clients, servers, gateways, or proxies.
17