================================================================ Files ================================================================ ================ File: docs/getting-started/quick-overview.md ================ --- title: Quick Overview description: An overview of the ContextVM documentation, including the specification and SDK documentation. --- # Quick Overview Welcome to the ContextVM documentation! This guide provides a brief overview of what you'll find in our documentation to help you get started with ContextVM. ## Documentation Structure Our documentation is organized into several main sections: ### 🚀 Getting Started - **Quick Overview**: This page - a brief introduction to what ContextVM offers ### 📋 Specification - **[Specification](/spec/ctxvm-draft-spec)**: The official ContextVM draft specification detailing the protocol - **[CEP - Guidelines](/spec/cep-guidelines)**: ContextVM Enhancement Proposal guidelines for contributing to the protocol ### 🛠️ ts-SDK The TypeScript SDK provides tools and libraries for building applications with ContextVM: - **[SDK Quick Overview](/ts-sdk/quick-overview)**: A comprehensive overview of the SDK's modules and core concepts - **Core Concepts**: Fundamental definitions, constants, interfaces, and utilities - **Transports**: Communication modules for MCP over Nostr - **Components**: Gateway, Relay Handlers, Signers, and Proxy implementations - **Tutorials**: Practical examples and guides ## What is ContextVM? ContextVM is a protocol that bridges the Model Context Protocol (MCP) with the Nostr network, enabling decentralized communication. It allows MCP servers and clients to communicate over the Nostr protocol, leveraging its decentralized infrastructure for secure and private interactions. ## Key Features - **Decentralized Communication**: Use Nostr's decentralized network for MCP communication - **Security First**: Leveraging Nostr's cryptographic primitives for verification, authorization, and additional features - **Easy Integration**: Typescript SDK to work with ContextVM ## Getting Started 1. **Read the Specification**: Start with the [ContextVM specification](/spec/ctxvm-draft-spec) to understand the protocol 2. **Explore the SDK**: Check out the [SDK Quick Overview](/ts-sdk/quick-overview) for development guidance 3. **Follow Tutorials**: Work through practical examples to see ContextVM in action ## Next Steps Choose your path based on your interests: - **Protocol Development**: Dive into the [Specification](/spec/ctxvm-draft-spec) to understand the protocol details - **SDK Development**: Start with the [SDK Quick Overview](/ts-sdk/quick-overview) to begin building with ContextVM - **Contributing**: Learn about contributing to the protocol with [CEP Guidelines](/spec/cep-guidelines) For the latest updates and community discussions, visit our [GitHub repository](https://github.com/contextvm/). ================ File: docs/spec/ceps/cep-4.md ================ --- title: CEP-4 Encryption Support description: End-to-end encryption for ContextVM messages using NIP-17 and NIP-59 --- # Encryption Support **Status:** Final **Author:** @contextvm-org **Type:** Standards Track ## Abstract This CEP proposes optional end-to-end encryption for ContextVM messages to enhance privacy and security. The encryption mechanism leverages a simplified version of NIP-17 (Private Direct Messages) for secure message encryption and NIP-59 (Gift Wrap) pattern with no 'rumor' using NIP-59 gift wrapping for metadata protection. This approach ensures message content privacy and metadata protection while maintaining full compatibility with the standard protocol. ## Specification ### Encryption Support Discovery Encryption support is advertised through the `support_encryption` tag in server initialization responses or public server announcements. The presence of this tag indicates that the server supports encryption; its absence signifies that the server does not support encryption: ```json { "pubkey": "", "content": { /* server details */ }, "tags": [ ["support_encryption"] // Presence alone indicates encryption support // ... other tags ] } ``` Clients can discover encryption support by: 1. **Direct Discovery**: Check for the presence of the `support_encryption` tag in initialization responses 2. **Encrypted Handshake**: Attempt an encrypted initialization ### Message Encryption Flow When encryption is enabled, ContextVM messages follow a simplified NIP-17 pattern with no 'rumor', using NIP-59 gift wrapping. #### 1. Content Preparation The request is prepared as usual, and should be signed: ```json { "kind": 25910, "id": "", "pubkey": "", "content": { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "location": "New York" } } }, "tags": [["p", ""]], "sig": "" } ``` #### 2. Seal Creation The request is converted into a JSON string and encrypted to the recipient's public key, following NIP-44 encryption scheme. #### 3. Gift Wrapping The encrypted request is then gift-wrapped by placing it in the content field of a NIP-59 gift-wrap event. ```json { "id": "", "pubkey": "", "created_at": "", "kind": 1059, "tags": [["p", ""]], "content": "", "sig": "" } ``` Server responses follow the same pattern. The decrypted inner content contains the standard ContextVM response format. The id field used in responses should match the inner id field used in requests, not the id of the gift-wrap event. #### Observations While this encryption scheme is secure and private enough, it has a main limitation in metadata leakage protection, as the recipient's public key is added to the gift-wrap event as a `p` tag. Therefore, the only leaked metadata is the recipient's public key, but not the sender, the kind of event contained in the gift-wrap, or the timestamp of the event. This is a limitation of the NIP-59 gift-wrapping pattern. ## Backward Compatibility This CEP introduces no breaking changes to the existing protocol. Encryption is entirely optional: - **Existing servers** continue to work without modification - **Existing clients** continue to work with existing servers - **New encrypted communication** only occurs when both client and server support encryption The only compatibility issue is that servers or clients might require encrypted communication. Therefore, if encryption is required and one of the participants does not support it, the communication will fail ## Reference Implementation A reference implementation can be found in the [ContextVM sdk](https://github.com/ContextVM/sdk/blob/master/src/core/encryption.ts) ================ File: docs/spec/ceps/cep-6.md ================ --- title: CEP-6 Public Server Announcements description: Public server discovery mechanism for ContextVM capabilities --- # Public Server Announcements **Status:** Final **Author:** @contextvm-org **Type:** Standards Track ## Abstract This CEP proposes a public server discovery mechanism for ContextVM using Nostr replaceable events. The mechanism allows MCP servers to advertise their capabilities and metadata through the Nostr network, enabling clients to discover and browse available services without requiring prior knowledge of server public keys. This enhances discoverability while maintaining the decentralized nature of the protocol. ## Specification ### Overview Public server announcements act as a service catalog, allowing clients or users to discover servers and their capabilities through replaceable events on the Nostr network. This mechanism provides an initial overview of what a server offers, and their public keys to connect with them. Since each server is uniquely identified by its public key, the announcement events are replaceable (kinds 11316-11320), ensuring that only the most recent version of the server's information is active. Providers announce their servers and capabilities by publishing events with kinds 11316 (server), 11317 (tools/list), 11318 (resources/list), 11319 (resource templates/list), and 11320 (prompts/list). **Note:** The examples below present the `content` as a JSON object for readability; it must be stringified before inclusion in a Nostr event. ### Event Kinds for Server Announcements | Kind | Description | | ----- | ----------------------- | | 11316 | Server Announcement | | 11317 | Tools List | | 11318 | Resources List | | 11319 | Resource Templates List | | 11320 | Prompts List | ### Server Announcement Event ```json { "kind": 11316, "pubkey": "", "content": { "protocolVersion": "2025-07-02", "capabilities": { "prompts": { "listChanged": true }, "resources": { "subscribe": true, "listChanged": true }, "tools": { "listChanged": true } }, "serverInfo": { "name": "ExampleServer", "version": "1.0.0" }, "instructions": "Optional instructions for the client" }, "tags": [ ["name", "Example Server"], // Optional: Human-readable server name ["about", "Server description"], // Optional: Server description ["picture", "https://example.com/server.png"], // Optional: Server icon/avatar URL ["website", "https://example.com"], // Optional: Server website ["support_encryption"] // Optional: Presence indicates server supports encrypted messages ] } ``` #### Content Field Structure The `content` field contains structured server information following the [MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle#initialization), it should be a JSON string. #### Tags Field Structure The `tags` field provides additional metadata for discoverability: - **name**: Human-readable server name - **about**: Server description - **picture**: URL to server icon/avatar - **website**: Server website URL - **support_encryption**: Indicates server supports encrypted messages ### Capability List Announcements As in the Server Announcement event, the `content` field contains a JSON string with the list of capabilities. The list is the result of a call to the `list` method of each capability. ### Tools List Event Example ```json { "kind": 11317, "pubkey": "", "content": { "tools": [ { "name": "get_weather", "description": "Get current weather information for a location", "inputSchema": { "type": "object", "properties": { "location": { "type": "string", "description": "City name or zip code" } }, "required": ["location"] } } ] }, "tags": [] } ``` ### Discovery Process #### Client Discovery Flow 1. **Subscribe to Server Announcement**: Clients subscribe to kinds 11316 (Server Announcement) on Nostr relays 2. **Subcribe to Capability List Announcements**: Once the server announcement is fetched and parsed, the client can subscribe to the capabilities events present in the server announcement. 3. **Initialize Connection**: Client proceeds with standard MCP initialization using the server's public key An alternative flow is to subscribe to all announcements published by the server public key, and get all the public announcements at once, instead of first fetching the server announcement and then fetching the capabilities. ### Event Replacement Behavior Since announcement events use kinds 11316-11320 (in the 10000-20000 range), they are replaceable: - **Relay Behavior**: Relays store only the latest event for each combination of kind, and pubkey - **Client Behavior**: Clients should always request the latest version of announcement events - **Server Behavior**: Servers must update announcement events when capabilities change ## Reference Implementation A reference implementation can be found in the [ContextVM SDK server transport implementation](https://github.com/ContextVM/sdk/blob/master/src/transport/nostr-server-transport.ts). It is implemented by calling the list methods from the transport during the initialization of the transport and then publishing the results of those list methods. ## Dependencies - [CEP-4: Encryption Support](/spec/ceps/cep-4) ================ File: docs/spec/ceps/cep-8.md ================ --- title: CEP-8 Capability Pricing and Payment Flow description: Pricing mechanism and payment processing for ContextVM capabilities --- # Capability Pricing and Payment Flow **Status:** Draft **Author:** @Gzuuus **Type:** Standards Track ## Abstract This CEP proposes a standardized pricing mechanism and payment flow for MCP capabilities over ContextVM. The mechanism allows servers to advertise pricing for their capabilities, enables clients to discover and pay for these capabilities through various payment methods, and defines a notification system for payment requests. This creates a sustainable ecosystem for capability servers while maintaining the decentralized nature of the protocol. ## Specification ### Overview ContextVM pricing for capabilities is implemented through a standardized mechanism with three main components: 1. **Pricing Tags**: Servers advertise pricing information using the `cap` tag 2. **Payment Method Identifiers (PMI)**: Both parties advertise supported payment methods using the `pmi` tag 3. **Payment Notifications**: Servers notify clients of payment requirements through the `notifications/payment_required` notification When a capability requires payment, the server acts as the payment processor (generating and validating payment requests) while the client acts as the payment handler (executing payments for supported payment methods). Clients can discover supported payment methods beforehand through PMI discovery, enabling informed decisions before initiating requests. ### New Tags Introduced This CEP introduces two new tags to the ContextVM protocol: #### `cap` Tag The `cap` tag is used to convey pricing information for capabilities. It follows this format: ```json ["cap", "", "", ""] ``` Where: - `` is the name of the tool, prompt, or resource URI - `` is a string representing the numerical amount. For fixed prices, this is an integer (e.g., "100"). For variable prices, this can be a range (e.g., "100-1000") to indicate a variable pricing model. - `` is the currency symbol (e.g., "sats", "usd") #### `pmi` Tag The `pmi` tag is used to advertise supported Payment Method Identifiers. It follows this format: ```json ["pmi", ""] ``` Where `` is a standardized PMI string following the W3C Payment Method Identifiers specification (e.g., "bitcoin-lightning-bolt11", "bitcoin-cashu"). ### Pricing Mechanism Pricing information is advertised using the `cap` tag in server announcements and capability list responses: #### Server Announcements ```json { "kind": 11317, "content": { "tools": [ { "name": "get_weather", "description": "Get current weather information" // ... other tool properties } ] }, "tags": [["cap", "get_weather", "100", "sats"]] } ``` #### Capability List Responses ```json { "kind": 25910, "pubkey": "", "content": { "result": { "tools": [ { "name": "get_weather", "description": "Get current weather information" // ... other tool properties } ], "nextCursor": "next-page-cursor" } }, "tags": [ ["e", ""], ["cap", "get_weather", "100", "sats"] ] } ``` The `cap` tag indicates that using the `get_weather` tool costs 100 satoshis, allowing clients to display pricing to users. ### Payment Method Identifiers (PMI) The protocol supports multiple payment methods through Payment Method Identifiers (PMI) that follow the W3C Payment Method Identifiers specification. #### PMI Format and Registry PMIs MUST follow the format defined by the [W3C Payment Method Identifiers](https://www.w3.org/TR/payment-method-id/) specification, matching the pattern: `[a-z0-9-]+` (e.g., `bitcoin-onchain`, `bitcoin-lightning-bolt11`, `bitcoin-cashu`, `basic-card`, etc). **ContextVM PMI References:** - `"bitcoin-onchain"` - Bitcoin on-chain transactions - `"bitcoin-lightning-bolt11"` - Lightning Network with BOLT11 invoice format - `"bitcoin-cashu"` - Bitcoin via Cashu ecash tokens **Note:** The listed PMIs are reference recommendations for the ContextVM ecosystem. Users can use any PMI that follows the W3C format, propose new PMIs for inclusion, or extend the reference list over time. #### PMI Benefits and Roles Using standardized PMIs provides: 1. **Interoperability**: Clear communication about supported payment methods 2. **Extensibility**: Easy addition of new payment methods 3. **Multi-currency support**: Different PMIs handle different currencies and networks 4. **Clear separation of concerns**: Servers focus on payment processing, clients on payment handling ### PMI Discovery PMI discovery allows clients and servers to determine compatibility with payment methods, similar to encryption support discovery in [CEP-4](/spec/ceps/cep-4). #### PMI Advertisement Servers advertise supported PMIs using the `pmi` tag in initialization responses or public announcements: ```json { "pubkey": "", "content": { /* server details */ }, "tags": [ ["pmi", "bitcoin-lightning-bolt11"], ["pmi", "bitcoin-cashu"], ["pmi", "bitcoin-onchain"] ] } ``` Clients advertise their supported PMIs in initialization requests: ```json { "kind": 25910, "content": { "jsonrpc": "2.0", "id": 0, "method": "initialize", "params": { "protocolVersion": "2025-07-02" // Other initialization parameters } }, "tags": [ ["p", ""], ["pmi", "bitcoin-lightning-bolt11"], ["pmi", "bitcoin-cashu"] ] } ``` #### Discovery Methods Clients can discover PMI support through: 1. **Public Announcements**: Check `pmi` tags in server announcements 2. **Initialization Responses**: Check `pmi` tags in server initialization responses 3. **Stateless Operations**: Handle compatibility at request time when no prior discovery is possible Servers can discover PMI support through: 1. **Client Initialization Request**: Check `pmi` tags in client initialization request ### Payment Flow The complete payment flow for a capability with pricing information follows these steps: #### 1. Capability Request The client sends a capability request to the server: ```json { "kind": 25910, "id": "", "pubkey": "", "content": { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "location": "New York" } } }, "tags": [["p", ""]] } ``` #### 2. Payment Required Notification If the capability requires payment, the server responds with a `notifications/payment_required` notification containing payment details: ```json { "kind": 25910, "pubkey": "", "content": { "method": "notifications/payment_required", "params": { "amount": 1000, "pay_req": "lnbc...", "description": "Payment for tool execution", "pmi": "bitcoin-lightning-bolt11" } }, "tags": [ ["p", ""], ["e", ""] ] } ``` #### 3. Payment Processing The client processes the payment and the server verifies it. When the client receives a payment request notification, it matches the PMI to determine if it supports the specified payment method. If compatible, the client processes the payment using the appropriate method for that PMI. The server verifies the payment according to the PMI implementation. #### 4. Capability Access Once payment is verified, the server processes the capability request and responds with the result: ```json { "kind": 25910, "pubkey": "", "content": { "jsonrpc": "2.0", "id": 2, "result": { "content": [ { "type": "text", "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" } ], "isError": false } }, "tags": [["e", ""]] } ``` ### Payment Request Notification Fields The `notifications/payment_required` notification `params` object contains: - `amount` (required): Numeric payment amount - `pay_req` (required): Payment request data string - `description` (optional): Human-readable payment description - `pmi` (required): Payment Method Identifier string ## Backward Compatibility This CEP introduces no breaking changes to the existing protocol: - **Existing servers** can continue to operate without pricing - **Existing clients** continue to work with existing servers - **New pricing** is additive - capabilities can be free or paid - **Optional participation**: Both providers and clients can choose to participate in pricing ## Reference Implementation // TODO ## Dependencies - [CEP-4: Encryption Support](/spec/ceps/cep-4) - [CEP-6: Public Server Announcements](/spec/ceps/cep-6) - [W3C Payment Method Identifiers](https://www.w3.org/TR/payment-method-id/) ================ File: docs/spec/cep-guidelines.md ================ --- title: ContextVM Enhancement Proposal Guidelines description: Guidelines for proposing changes to the ContextVM protocol --- # CEP Guidelines > ContextVM Enhancement Proposal (CEP) guidelines for proposing changes to the ContextVM protocol ## What is a CEP? CEP stands for ContextVM Enhancement Proposal. A CEP is a design document providing information to the ContextVM community, or describing a new feature for the ContextVM protocol or its processes or environment. The CEP should provide a concise technical specification of the feature and a rationale for the feature. We intend CEPs to be the primary mechanisms for proposing major new features, for collecting community input on an issue, and for documenting the design decisions that have gone into ContextVM. The CEP author is responsible for building consensus within the community and documenting dissenting opinions. Because the CEPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal. ## What qualifies a CEP? The goal is to reserve the CEP process for changes that are substantial enough to require broad community discussion, a formal design document, and a historical record of the decision-making process. A regular GitHub issue or pull request is often more appropriate for smaller, more direct changes. Consider proposing a CEP if your change involves any of the following: - **A New Feature or Protocol Change**: Any change that adds, modifies, or removes features in the ContextVM protocol. This includes: - Adding new event kinds or Nostr integration patterns. - Changing the syntax or semantics of existing data structures or messages. - Introducing a new standard for interoperability between different ContextVM-compatible tools. - Significant changes to how the specification itself is defined, presented, or validated. - **A Breaking Change**: Any change that is not backwards-compatible. - **A Change to Governance or Process**: Any proposal that alters the project's decision-making, contribution guidelines (like this document itself). - **A Complex or Controversial Topic**: If a change is likely to have multiple valid solutions or generate significant debate, the CEP process provides the necessary framework to explore alternatives, document the rationale, and build community consensus before implementation begins. ## CEP Types There are three kinds of CEP: 1. **Standards Track** CEP describes a new feature or implementation for the ContextVM protocol. Standards Track CEPs are maintained as separate documents from the main ContextVM specification and extend or enhance the base protocol. The main specification maintains references to all accepted and finalized Standards Track CEPs. 2. **Informational** CEP describes a ContextVM protocol design issue, or provides general guidelines or information to the ContextVM community, but does not propose a new feature. Informational CEPs do not necessarily represent a ContextVM community consensus or recommendation. 3. **Process** CEP describes a process surrounding ContextVM, or proposes a change to (or an event in) a process. Process CEPs are like Standards Track CEPs but apply to areas other than the ContextVM protocol itself. ## Submitting a CEP The CEP process begins with a new idea for the ContextVM protocol. It is highly recommended that a single CEP contain a single key proposal or new idea. Small enhancements or patches often don't need a CEP and can be injected into the ContextVM development workflow with a pull request to the ContextVM repo. The more focused the CEP, the more successful it tends to be. Each CEP must have an **CEP author** -- someone who writes the CEP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. The CEP author should first attempt to ascertain whether the idea is CEP-able. Posting to the ContextVM community forums (Nostr, Signal, GitHub Discussions) is the best way to go about this. **Important Note**: The CEP process uses both GitHub Issues and Pull Requests: - **GitHub Issues** are used for discussion, review, and tracking the CEP proposal lifecycle - **Pull Requests** are normally used for Standards Track CEPs to contain the actual CEP document and specification changes ### CEP Workflow CEPs should be submitted as a GitHub Issue in the [ContextVM-docs repository](https://github.com/ContextVM/contextvm-docs). The standard CEP workflow varies slightly depending on the CEP type: #### For Standards Track CEPs 1. You, the CEP author, create a [well-formatted](#cep-format) GitHub Issue with the `CEP` and `proposal` tags. The CEP number is the same as the GitHub Issue number, the two can be used interchangeably. 2. **Simultaneously**, create a Pull Request that adds a markdown document draft in the `ceps` directory. This PR should contain the focused specification sections following the [CEP Format](#cep-format) structure. Link to this PR in your GitHub Issue. **Important**: The GitHub Issue and Pull Request serve different purposes and contain different content: - **GitHub Issue**: Initially contains the comprehensive CEP proposal including all sections (abstract, motivation, rationale, specification, security implications, etc.). This is where community discussion happens. Once a Pull Request is opened, the specification section in the issue should be replaced with a link to the PR to avoid redundancy. - **Pull Request**: Contains only the specification-related sections (abstract, specification, backwards compatibility, reference implementation, and dependencies) that will become part of the final specification document. The PR should focus exclusively on technical specification content. 3. Find a Maintainer to sponsor your proposal. Maintainers will regularly go over the list of open proposals to determine which proposals to sponsor. You can tag relevant maintainers in your proposal. 4. Once a sponsor is found, the GitHub Issue is assigned to the sponsor. The sponsor will add the `draft` tag. 5. The sponsor will informally review both the Issue and the Pull Request, and may request changes based on community feedback. When ready for formal review, the sponsor will add the `in-review` tag. 6. After the `in-review` tag is added, the CEP enters formal review by the Maintainers. The CEP may be accepted, rejected, or returned for revision. 7. If the CEP has not found a sponsor within three months, Maintainers may close the CEP as `dormant`. #### For Informational and Process CEPs 1. You, the CEP author, create a [well-formatted](#cep-format) GitHub Issue with the `CEP` and `proposal` tags. The CEP number is the same as the GitHub Issue number, the two can be used interchangeably. 2. Find a Maintainer to sponsor your proposal. Maintainers will regularly go over the list of open proposals to determine which proposals to sponsor. You can tag relevant maintainers in your proposal. 3. Once a sponsor is found, the GitHub Issue is assigned to the sponsor. The sponsor will add the `draft` tag, ensure the CEP number is in the title, and assign a milestone. 4. The sponsor will informally review the proposal and may request changes based on community feedback. When ready for formal review, the sponsor will add the `in-review` tag. 5. After the `in-review` tag is added, the CEP enters formal review by the Maintainers. The CEP may be accepted, rejected, or returned for revision. 6. If the CEP has not found a sponsor within three months, Maintainers may close the CEP as `dormant`. ### CEP Format Each CEP should have the following parts. For Standards Track CEPs, these sections are distributed between the GitHub Issue and Pull Request as described below: #### GitHub Issue Content (for discussion and review): 1. **Preamble** -- A short descriptive title, the names and contact info for each author, the current status. 2. **Abstract** -- A short (~200 word) description of the technical issue being addressed. 3. **Motivation** -- The motivation should clearly explain why the existing protocol specification is inadequate to address the problem that the CEP solves. The motivation is critical for CEPs that want to change the ContextVM protocol. CEP submissions without sufficient motivation may be rejected outright. 4. **Rationale** -- The rationale explains why particular design decisions were made. It should describe alternate designs that were considered and related work. The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. 5. **Security Implications** -- If there are security concerns in relation to the CEP, those concerns should be explicitly written out to make sure reviewers of the CEP are aware of them. 6. **Specification** -- Initially, this section should contain the technical specification describing syntax and semantics of any new protocol feature. Once a Pull Request is opened, this section should be replaced with a link to the PR to avoid duplication. #### Pull Request Content (for specification - Standards Track CEPs only): 1. **Preamble** -- A short descriptive title, the names and contact info for each author, the current status. 2. **Abstract** - A short (~200 word) description of the technical issue being addressed (can reference the Issue for full details) 3. **Specification** - The technical specification should describe the syntax and semantics of any new protocol feature. The specification should be detailed enough to allow competing, interoperable implementations. For Standards Track CEPs, this should include the actual changes to the specification files in the Pull Request. 4. **Backward Compatibility** - All CEPs that introduce backward incompatibilities must include a section describing these incompatibilities and their severity. The CEP must explain how the author proposes to deal with these incompatibilities. 5. **Dependencies** - For Standards Track CEPs, this section should list any CEPs that this proposal depends on. Each dependency should be listed with its CEP number and a brief description of how it relates to the current proposal. This helps maintain a clear dependency map and ensures proper implementation order. 6. **Reference Implementation** - The reference implementation must be completed before any CEP is given status "Final", but it need not be completed before the CEP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of protocol details. **Important**: Once a Pull Request is open, the GitHub Issue's "Specification" section should be updated to simply link to the PR. This ensures the technical specification is maintained in a single location (the PR) while keeping the issue focused on discussion and consensus building. ### Main Specification Integration Once a Standards Track CEP reaches "Accepted" status, it should be referenced in the main ContextVM specification document. When a CEP reaches "Final" status, the main specification should be updated to include a link to the finalized CEP document. This ensures that the main specification maintains an up-to-date record of all protocol extensions and enhancements. ### CEP States CEPs can be one one of the following states: - `proposal`: CEP proposal without a sponsor. - `draft`: CEP proposal with a sponsor. - `in-review`: CEP proposal ready for review. - `accepted`: CEP accepted by Maintainers, but still requires final wording and reference implementation. - `rejected`: CEP rejected by Maintainers. - `withdrawn`: CEP withdrawn. - `final`: CEP finalized. - `superseded`: CEP has been replaced by a newer CEP. - `dormant`: CEP that has not found sponsors and was subsequently closed. ### CEP Review & Resolution CEPs are reviewed by the ContextVM Maintainers on a regular basis. For a CEP to be accepted it must meet certain minimum criteria: - A prototype implementation demonstrating the proposal - Clear benefit to the ContextVM ecosystem - Community support and consensus Once a CEP has been accepted, the reference implementation must be completed. When the reference implementation is complete and incorporated into the main source code repository, the status will be changed to "Final". A CEP can also be "Rejected" or "Withdrawn". A CEP that is "Withdrawn" may be re-submitted at a later date. ## Reporting CEP Bugs, or Submitting CEP Updates How you report a bug, or submit a CEP update depends on several factors, such as the maturity of the CEP, the preferences of the CEP author, and the nature of your comments. For CEPs not yet reaching `final` state, it's probably best to send your comments and changes directly to the CEP author. Once CEP is finalized, you may want to submit corrections as a GitHub comment on the issue or pull request to the reference implementation. ## Transferring CEP Ownership It occasionally becomes necessary to transfer ownership of CEPs to a new CEP author. In general, we'd like to retain the original author as a co-author of the transferred CEP, but that's really up to the original author. A good reason to transfer ownership is when the original author no longer has the time or interest in updating it or following through with the CEP process, or has become unreachable (not responding to email). A bad reason to transfer ownership is when you don't agree with the direction of the CEP. We try to build consensus around a CEP, but if that's not possible, you can always submit a competing CEP. ================ File: docs/spec/ctxvm-draft-spec.md ================ --- title: ContextVM Protocol Specification description: Technical specification for the ContextVM protocol --- **Status:** Draft ## Abstract The Context Vending Machine (ContextVM) specification defines how the Nostr protocol can be used as a transport layer for the Model Context Protocol (MCP), leveraging the Nostr relay network as the underlying communication mechanism. Also benefiting from Nostr's cryptographic primitives for verification, authorization, and additional features. ## Table of Contents - [Introduction](#introduction) - [ContextVM as MCP Transport](#contextvm-as-mcp-transport) - [Public Key Cryptography](#public-key-cryptography) - [Protocol Overview](#protocol-overview) - [Main Actors](#main-actors) - [Transport Layer Architecture](#transport-layer-architecture) - [Message Structure](#message-structure) - [Event Kinds](#event-kinds) - [Server Discovery](#server-discovery) - [Client Initialization Request](#client-initialization-request) - [Server Initialization Response](#server-initialization-response) - [Client Initialized Notification](#client-initialized-notification) - [Capability Operations](#capability-operations) - [List Operations](#list-operations) - [List Request Template](#list-request-template) - [List Response Template](#list-response-template) - [Capability-Specific Item Examples](#capability-specific-item-examples) - [Call Tool Request](#call-tool-request) - [Call Tool Response](#call-tool-response) - [Notifications](#notifications) - [ContextVM Enhancement Proposals (CEPs)](#contextvm-enhancement-proposals-ceps) - [Complete Protocol Flow](#complete-protocol-flow) ## Introduction The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) defines a standardized way for servers to expose capabilities and for clients to consume them. MCP is transport-agnostic, meaning it can operate over various communication channels. The Context Vending Machine (ContextVM) specification defines a Nostr-based transport layer for MCP, and some conventions on top for enabling secure, decentralized communication between MCP servers and clients. ### ContextVM as MCP Transport ContextVM operates at the **transport layer** of MCP, providing a Nostr-based implementation that: - **Transports MCP messages** through Nostr's relay network - **Preserves JSON-RPC semantics** while leveraging Nostr's event structure - **Adds cryptographic verification** and metadata capabilities to standard MCP communication - **Enables decentralized service discovery** and communication without centralized infrastructure This approach allows MCP servers and clients to communicate through Nostr while maintaining full compatibility with the MCP specification and gaining the benefits of Nostr's cryptographic security model. ### Public Key Cryptography ContextVM leverages Nostr's public key cryptography to ensure message authenticity and integrity: 1. **Message Verification**: Every message is cryptographically signed by the sender's private key and can be verified using their public key, ensuring that: - Server announcements are legitimate - Client requests are from authorized users - Responses are from the expected servers 2. **Identity Management**: Public keys serve as persistent identifiers for all actors in the system: - Servers can maintain consistent identities across relays - Clients can be uniquely identified for authorization purposes The cryptographic properties enable secure authorization flows for capability execution without requiring centralized authentication services. ## Protocol Overview ### Transport Layer Architecture ContextVM operates as a transport layer for MCP, meaning it handles the communication channel while preserving the semantics of MCP messages. The architecture consists of: 1. **Transport Layer**: Nostr events and relays serve as the transport mechanism 2. **Message Layer**: JSON-RPC MCP messages are embedded within Nostr event content 3. **Metadata Layer**: Nostr event tags provide addressing and correlation information This layered approach allows ContextVM to: - Transport standard MCP messages without modification - Add Nostr-specific addressing and verification - Maintain compatibility with existing MCP implementations ### Message Structure The protocol uses these key design principles for message handling: 1. **Content Field Structure**: The `content` field of Nostr events contains stringified MCP messages. All MCP message structures are preserved exactly as defined in the MCP specification, ensuring compatibility with standard MCP clients and servers. 2. **Nostr Metadata in Tags**: All Nostr-specific metadata uses event tags: - `p`: Public key for addressing servers or clients - `e`: Event ID references for correlating requests and responses 3. **Unified Event Kind**: ContextVM uses a single event kind for all communication: - `25910`: All ContextVM messages (ephemeral events) The event kind follows Nostr's conventions in [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md#kinds): - For kind n such that 20000 <= n < 30000, events are ephemeral, which means they are not expected to be stored by relays for a long period, but rather just transmitted. ### Main Actors There are three main actors in ContextVM architecture: - **Servers**: MCP servers exposing capabilities, using a public key to sign messages - **Relays**: Core component of the Nostr protocol that enables communication between clients and servers - **Clients**: MCP or Nostr clients that discover and consume capabilities from servers, using a public key to sign messages ## Server Discovery You can connect to MCP servers using ContextVM by knowing their public key and the relay(s) they are listening on. This process follows the standard MCP initialization specification, with ContextVM providing the transport mechanism by embedding JSON-RPC MCP messages in the `content` field of Nostr events. **Note:** The content field of ContextVM events contains stringified MCP messages. The examples below present the content as a JSON object for readability; it must be stringified before inclusion in a Nostr event. #### Client Initialization Request ```json { "kind": 25910, "content": { "jsonrpc": "2.0", "id": 0, "method": "initialize", "params": { "protocolVersion": "2025-07-02", "capabilities": { "roots": { "listChanged": true }, "sampling": {} }, "clientInfo": { "name": "ExampleClient", "version": "1.0.0" } } }, "tags": [["p", ""]] } ``` - Tags: - `p`: Server public key #### Server Initialization Response ```json { "kind": 25910, "pubkey": "", "content": { "jsonrpc": "2.0", "id": 0, "result": { "protocolVersion": "2025-07-02", "capabilities": { "logging": {}, "prompts": { "listChanged": true }, "resources": { "subscribe": true, "listChanged": true }, "tools": { "listChanged": true } }, "serverInfo": { "name": "ExampleServer", "version": "1.0.0" }, "instructions": "Optional instructions for the client" } }, "tags": [["e", ""]] } ``` - Tags: - `e`: Reference to the client's initialization request event #### Client Initialized Notification After receiving the server initialization response, the client MUST send an initialized notification to indicate it is ready to begin normal operations: ```json { "kind": 25910, "pubkey": "", "content": { "jsonrpc": "2.0", "method": "notifications/initialized" }, "tags": [ ["p", ""] // Required: Target provider public key ] } ``` This notification completes the initialization process and signals to the server that the client has processed the server's capabilities and is ready to begin normal operations. **Note:** The initialization process is not required for ContextVM servers to operate as they can work in a stateless fashion. However, it is recommended to use it to ensure that the server is ready to accept requests from clients. ## Capability Operations After initialization, clients can interact with server capabilities. ### List Operations All list operations follow the same structure described by MCP, with the specific capability type indicated in the method name. - Tags: - `p`: Provider public key #### List Request Template ```json { "kind": 25910, "pubkey": "", "id": "", "content": { "jsonrpc": "2.0", "id": 1, "method": "/list", // tools/list, resources/list, or prompts/list "params": { "cursor": "optional-cursor-value" } }, "tags": [ ["p", ""] // Required: Provider's public key ] } ``` #### List Response Template ```json { "kind": 25910, "pubkey": "", "content": { "jsonrpc": "2.0", "id": 1, "result": { "": [ // "tools", "resources", or "prompts" based on capability // Capability-specific item objects ], "nextCursor": "next-page-cursor" } }, "tags": [ ["e", ""] // Required: Reference to the request event ] } ``` ### Capability-Specific Item Examples #### Call Tool Request ```json { "kind": 25910, "id": "", "pubkey": "", "content": { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "location": "New York" } } }, "tags": [["p", ""]] } ``` #### Call Tool Response ```json { "kind": 25910, "pubkey": "", "content": { "jsonrpc": "2.0", "id": 2, "result": { "content": [ { "type": "text", "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" } ], "isError": false } }, "tags": [["e", ""]] } ``` For other capabilities (resources, prompts, completions, ping, etc.), the `content` field follows the same pattern as other MCP messages, containing a stringified JSON-RPC object that adheres to the MCP specification. ## Notifications All notifications in ContextVM follow the standard MCP notification format and conventions, using the unified kind 25910 event type. This includes notifications for payment requests, progress updates, and all other server-to-client or client-to-server communications. Notifications are constructed according to the standard MCP notification template. ## ContextVM Enhancement Proposals (CEPs) The ContextVM protocol is subject to ongoing improvements and enhancements. These improvements are managed through the ContextVM Enhancement Proposal (CEP) process, which is described in detail in the [CEP Guidelines](https://docs.contextvm.org/spec/cep-guidelines/) ### Accepted CEPs The following CEPs have been accepted: ### Final CEPs The following CEPs have been finalized: - [CEP-4: Encryption Support](/spec/ceps/cep-4) - [CEP-6: Public Server Announcements](/spec/ceps/cep-6) ## Complete Protocol Flow ```mermaid sequenceDiagram participant MCP Client participant Relays participant MCP Server note over MCP Client, MCP Server: MCP Initialization over Relays MCP Client->>Relays: Publish kind 25910 (initialize request) Relays->>MCP Server: Deliver MCP initialize message MCP Server->>Relays: Publish kind 25910 (initialize response) Relays-->>MCP Client: Deliver MCP initialize response MCP Client->>Relays: Publish kind 25910 (initialized notification) Relays->>MCP Server: Deliver MCP initialized notification note over MCP Client, MCP Server: MCP Capability Operations over Relays MCP Client->>Relays: Publish kind 25910 (tools/list request) Relays->>MCP Server: Deliver MCP tools/list request MCP Server->>Relays: Publish kind 25910 (tools/list response) Relays-->>MCP Client: Deliver MCP tools/list response ``` ================ File: docs/ts-sdk/core/constants.md ================ --- title: Constants description: A set of constants used throughout the @contextvm/sdk. --- # Constants The `@contextvm/sdk` exports a set of constants that are used throughout the library for event kinds, tags, and other protocol-specific values. These constants ensure consistency and alignment with the ContextVM specification. ## Event Kinds The ContextVM protocol defines several Nostr event kinds for different types of messages. | Constant | Kind | Description | | ----------------------------- | ----- | ----------------------------------------------------------------------------- | | `CTXVM_MESSAGES_KIND` | 25910 | The kind for standard, ephemeral ContextVM messages. | | `GIFT_WRAP_KIND` | 1059 | The kind for encrypted messages, wrapped using the NIP-59 gift wrap standard. | | `SERVER_ANNOUNCEMENT_KIND` | 11316 | A replaceable event for announcing a server's presence and basic info. | | `TOOLS_LIST_KIND` | 11317 | A replaceable event for listing a server's available tools. | | `RESOURCES_LIST_KIND` | 11318 | A replaceable event for listing a server's available resources. | | `RESOURCETEMPLATES_LIST_KIND` | 11319 | A replaceable event for listing a server's available resource templates. | | `PROMPTS_LIST_KIND` | 11320 | A replaceable event for listing a server's available prompts. | ## Nostr Tags The SDK defines an object `NOSTR_TAGS` that contains constants for the various Nostr event tags used in the ContextVM protocol. | Key | Tag | Description | | -------------------- | -------------------- | ---------------------------------------------------------------------- | | `PUBKEY` | `p` | The public key of the message recipient. | | `EVENT_ID` | `e` | The event ID used to correlate requests and responses. | | `CAPABILITY` | `cap` | A tag for specifying pricing metadata for a tool, resource, or prompt. | | `NAME` | `name` | The human-readable name of a server in an announcement. | | `WEBSITE` | `website` | The URL of a server's website in an announcement. | | `PICTURE` | `picture` | The URL of a server's icon in an announcement. | | `ABOUT` | `about` | A tag for providing a short description of a server. | | `SUPPORT_ENCRYPTION` | `support_encryption` | A tag indicating that a server supports end-to-end encryption. | ## Announcement Methods The `announcementMethods` object maps capability types to their corresponding MCP method names for server announcements. ```typescript export const announcementMethods = { server: "initialize", tools: "tools/list", resources: "resources/list", resourceTemplates: "resources/templates/list", prompts: "prompts/list", } as const; ``` This object is used internally by the `NostrServerTransport` to construct announcement events. ## Next Steps With a solid understanding of the core modules, you are now ready to explore the **[Transports](/transports/base-nostr-transport)**, which are responsible for all network communication in the SDK. ================ File: docs/ts-sdk/core/encryption.md ================ --- title: Encryption description: An overview of the encryption mechanism in the @contextvm/sdk. --- # Encryption The `@contextvm/sdk` supports optional end-to-end encryption for all communication, providing enhanced privacy and security. This section explains the encryption mechanism, how to enable it, and the underlying principles. ## Overview ContextVM's encryption leverages a simplified version of [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) to ensure: 1. **Message Content Privacy**: All MCP message content is encrypted using NIP-44. 2. **Metadata Protection**: The gift wrap pattern conceals participant identities and other metadata. 3. **Selective Encryption**: Clients and servers can negotiate encryption on a per-session basis. When encryption is enabled, all ephemeral messages (kind 25910) are wrapped in a kind 1059 gift wrap event. Server announcements and capability lists remain unencrypted for public discoverability. ## How It Works The encryption flow is designed to be secure and efficient: 1. **Content Preparation**: The original MCP message is serialized into a standard Nostr event. 2. **Gift Wrapping**: The entire event is then encrypted using `nip44.v2` and wrapped inside a "gift wrap" event (kind 1059). A new, random keypair is generated for each gift wrap. 3. **Transmission**: The encrypted gift wrap event is published to the Nostr network. The recipient then unwraps the gift using their private key to decrypt the original message. ### Why a Simplified NIP-17/NIP-59 Pattern? The standard implementation of NIP-17 is designed for persistent private messages and includes a "rumor" and "seal" mechanism to prevent message leakage. Since ContextVM messages are ephemeral and not intended to be stored by relays, this complexity is unnecessary. The SDK uses a more direct gift-wrapping approach that provides strong encryption and metadata protection without the overhead of the full NIP-17 standard. ## Enabling Encryption Encryption is configured at the transport level using the `EncryptionMode` enum. You can set the desired mode when creating a `NostrClientTransport` or `NostrServerTransport`. ```typescript import { NostrClientTransport } from "@contextvm/sdk"; import { EncryptionMode } from "@contextvm/sdk"; const transport = new NostrClientTransport({ // ... other options encryptionMode: EncryptionMode.OPTIONAL, // or REQUIRED, DISABLED }); ``` ### `EncryptionMode` - **`REQUIRED`**: The transport will only communicate with peers that support encryption. If the other party does not support it, the connection will fail. - **`OPTIONAL`**: (Default) The transport will attempt to use encryption if the peer supports it. If not, it will fall back to unencrypted communication. - **`DISABLED`**: The transport will not use encryption, even if the peer supports it. ## Encryption Support Discovery Clients and servers can discover if a peer supports encryption in two ways: 1. **Server Announcements**: Public server announcements (kind 11316) include a `support_encryption` tag to indicate that the server is capable of encrypted communication. 2. **Initialization Handshake**: During the MCP initialization process, both the client and server can signal their support for encryption. ## API Reference The core encryption functions are exposed in the `core` module: - `encryptMessage(message: string, recipientPublicKey: string): NostrEvent` - `decryptMessage(event: NostrEvent, signer: NostrSigner): Promise` These functions handle the low-level details of gift wrapping and unwrapping, but in most cases, you will interact with encryption through the transport's `encryptionMode` setting. ## Next Steps Now that you understand how encryption works, let's look at the [Constants](/core/constants) used throughout the SDK. ================ File: docs/ts-sdk/core/interfaces.md ================ --- title: Interfaces description: A deep dive into the core interfaces used in the @contextvm/sdk. --- # Core Interfaces The `@contextvm/sdk` is designed with a modular and extensible architecture, centered around a set of core interfaces. These interfaces define the essential components for signing, relay management, and communication. ## `NostrSigner` The `NostrSigner` interface is fundamental for cryptographic operations within the SDK. It abstracts the logic for signing Nostr events, ensuring that all communications are authenticated and verifiable. ### Definition ```typescript export interface NostrSigner { getPublicKey(): Promise; signEvent(event: EventTemplate): Promise; // Optional NIP-04 encryption support (deprecated) nip04?: { encrypt: (pubkey: string, plaintext: string) => Promise; decrypt: (pubkey: string, ciphertext: string) => Promise; }; // Optional NIP-44 encryption support nip44?: { encrypt: (pubkey: string, plaintext: string) => Promise; decrypt: (pubkey: string, ciphertext: string) => Promise; }; } ``` Any object that implements this interface can be used to sign events, allowing you to integrate with various key management systems, such as web, hardware wallets or remote signing services. The SDK provides a default implementation, `PrivateKeySigner`, which signs events using a raw private key. - **Learn more:** [`NostrSigner` Deep Dive](/signer/nostr-signer-interface/) - **Default Implementation:** [`PrivateKeySigner`](/signer/private-key-signer/) ## `RelayHandler` The `RelayHandler` interface manages interactions with Nostr relays. It is responsible for subscribing to events and publishing events to the Nostr network. ### Definition ```typescript export interface RelayHandler { connect(): Promise; disconnect(relayUrls?: string[]): Promise; publish(event: NostrEvent): Promise; subscribe( filters: Filter[], onEvent: (event: NostrEvent) => void, onEose?: () => void, ): Promise; unsubscribe(): void; } ``` By implementing this interface, you can create custom relay management logic, such as sophisticated relay selection strategies or custom reconnection policies. The SDK includes `SimpleRelayPool` as a default implementation. - **Learn more:** [`RelayHandler` Deep Dive](/relay/relay-handler-interface) - **Default Implementation:** [`SimpleRelayPool`](/relay/simple-relay-pool) ## `EncryptionMode` The `EncryptionMode` enum defines the encryption policy for a transport. ```typescript export enum EncryptionMode { OPTIONAL = "optional", REQUIRED = "required", DISABLED = "disabled", } ``` This enum is used to configure the encryption behavior of the `NostrClientTransport` and `NostrServerTransport`. - **Learn more:** [Encryption](/core/encryption) ## `ServerInfo` The `ServerInfo` interface provides metadata about a server, used by the Nostr server transport to add metadata to server announcements. ### Definition ```typescript export interface ServerInfo { name?: string; picture?: string; website?: string; about?: string; } ``` This interface allows servers to include descriptive information in their announcements, making them more discoverable and providing users with context about the server's purpose and identity. - **name**: A human-readable name for the server - **picture**: URL to an image representing the server - **website**: The server's official website or repository - **about**: A description of the server's purpose or content ================ File: docs/ts-sdk/core/logging.md ================ --- title: Logging description: Logging in the @contextvm/sdk --- ### Logging The SDK uses Pino for high-performance logging with structured JSON output. By default, logs are written to stderr to comply with the MCP protocol expectations. #### Basic Usage [`typescript`](src/content/docs/ts-sdk/core/logging.md:10) ```typescript import { createLogger } from "@contextvm/sdk/core"; // Create a logger for your module const logger = createLogger("my-module"); logger.info("Application started"); logger.error("An error occurred", { error: "details" }); ``` #### Configuration Options [`typescript`](src/content/docs/ts-sdk/core/logging.md:20) ```typescript import { createLogger, LoggerConfig } from "@contextvm/sdk/core"; const config: LoggerConfig = { level: "debug", // Minimum log level (debug, info, warn, error) file: "app.log", // Optional: log to a file instead of stderr }; const logger = createLogger("my-module", config); ``` **Note:** Pretty printing is automatically enabled when logs are written to stderr/stdout (not to a file) for better readability during development. #### Configuring with Environment Variables The logger can be configured using environment variables, which is useful for adjusting log output without changing the code. - **`LOG_LEVEL`**: Sets the minimum log level. - **Values**: `debug`, `info`, `warn`, `error`. - **Default**: `info`. - **`LOG_DESTINATION`**: Sets the log output destination. - **Values**: `stderr` (default), `stdout`, or `file`. - **`LOG_FILE`**: Specifies the file path when `LOG_DESTINATION` is `file`. - **`LOG_ENABLED`**: Enables or disables logging. - **Values**: `true` (default) or `false`. ##### Configuration in Node.js [`bash`](src/content/docs/ts-sdk/core/logging.md:49) ```bash # Set log level to debug LOG_LEVEL=debug node app.js # Log to a file instead of the console LOG_DESTINATION=file LOG_FILE=./app.log node app.js # Disable logging entirely LOG_ENABLED=false node app.js ``` ##### Configuration in Browsers [`javascript`](src/content/docs/ts-sdk/core/logging.md:63) ```javascript // Set this in a