Executive Summary
The Rust SDK currently has a usable client/server transport, public announcement helpers, discovery helpers, NIP-44 encryption, and partial support for CEP-19 inbound envelopes.
Current Status:
| CEP |
Current status in Rust |
Changes summary |
| CEP-6 |
Implemented at a basic/manual level |
Keep the current functionality, but refactor it into an internal announcement manager and make publishing lifecycle-driven instead of caller-driven |
| CEP-8 |
Not implemented |
Add a dedicated payments module plus transport hooks for tags, notification correlation, and middleware |
| CEP-17 |
Partial foundation only |
Constants exist and generic discovery exists, but relay-list publication and relay resolution are not wired into transport behavior |
| CEP-19 |
Partial |
Inbound support exists, but outbound ephemeral gift-wrap selection and policy control are still missing |
Current limitation pattern:
- Features are present as point capabilities, but often not yet integrated into a lifecycle-managed transport model.
- The Rust SDK tends to expose manual helper functions where the TypeScript SDK (baseline for comparison) embeds the same feature into transport startup, negotiation, routing, and policy decisions.
CEP-6 Status: Public Server Announcements
What exists now
Cuurent SDK already implements the core public announcement event and the public list events.
Current Rust anchors:
- [src/transport/server.rs]:406
announce()
- [src/transport/server.rs]:457
publish_tools()
- [src/transport/server.rs]:467
publish_resources()
- [src/transport/server.rs]:477
publish_prompts()
- [src/transport/server.rs]:487
publish_resource_templates()
- [src/discovery/mod.rs]:53
discover_servers()
- [src/discovery/mod.rs]:80 onward for public list discovery
The existing announce() function does the important CEP-6 job:
- publishes kind
11316
- serializes
server_info
- emits metadata tags like
name, about, website, picture
- emits encryption support tags
Current Status:
- protocol intent: implemented
- proper wiring up in lifecycles: not implemented
What is still missing
The main gaps revolve around lifecycle management. Ideally the lifecycle and startup of transport layer for server should handle publishing automatically. Here is the matrix for gaps found:
Remaining Rust gaps:
| Gap |
Current Rust state |
| Publishing is caller-driven |
Caller must explicitly invoke announce() and each list-publish helper |
| No internal announcement lifecycle |
No announcement manager or startup hook that drives publication |
| No automatic initialize/list snapshot flow |
Rust does not internally query the MCP server to build public capability snapshots |
| No configurable shared tag pipeline |
Tags are assembled ad hoc rather than through reusable common/pricing/extension tag hooks |
| Deletion is coarse |
delete_announcements() publishes kind 5 with a k tag instead of deleting exact event ids |
Why it matters
The current approach is manual and if not called properly can lead to:
- public metadata can drift from actual server capabilities
- announcement freshness depends on application discipline
Basic implementation approach
Proposed CEP-6 work should be a refactor-plus-enhancement, not a rewrite.
Suggested implementation direction:
-
Add an internal announcement module.
-
Keep current helpers as low-level building blocks.
-
Introduce a transport-managed publication flow.
-
Introduce a reusable tag model.
-
Improve deletion semantics.
Expected behaviour finally:
| Deliverable |
Outcome |
| Announcement manager internal module |
Public announcement lifecycle lives in one place |
| Auto-publish on transport startup |
No manual app orchestration required for standard behavior |
| Shared announcement tag builder |
Future CEPs can attach tags without rewriting announcement logic |
| Improved deletion flow |
Public metadata can be replaced and cleaned up reliably |
| Regression tests |
Manual and automatic publication both stay supported |
CEP-17 Status: Relay-List Metadata And Discovery
What exists now
Rust already has some foundation pieces for CEP-17:
- [src/core/constants.rs]:19
RELAY_LIST_METADATA_KIND = 10002
- [src/core/constants.rs]:78 default bootstrap relay URLs
- [src/discovery/mod.rs]:53 generic discovery of public server/list events
Level of implementation
Status: foundational only.
The actual relay-list publication and client relay resolution flow are not yet integrated.
Remaining Rust gaps:
| Gap |
Current Rust state |
Server publication of kind 10002 |
Not implemented |
| Explicit advertised relay list option |
Not implemented |
| Publication to bootstrap/discoverability relays |
Not integrated |
| Client relay-list fetching |
Not implemented |
Operational relay selection from r tags |
Not implemented |
| Identity hint support such as relay hints from richer server identities |
Not implemented |
| Fallback discovery relays vs operational relays distinction |
Not implemented |
Why it matters
Without CEP-17 transport integration:
- clients need explicit relay configuration more often
- public server discovery is less portable
- announced servers have weaker discoverability guarantees
- public announcements and actual operational relays can drift apart
Basic implementation approach
This work should be split into server-side and client-side halves.
Server-side approach
-
Extend NostrServerTransportConfig. Adding fields required for the implementation
-
Add a relay-list publisher.
-
Separate operational relays from discoverability publication relays.
-
Integrate this with the proposed CEP-6 announcement manager.
Client-side approach
-
Extend NostrClientTransportConfig to have the required fields.
-
Add a small internal CEP-17 discovery module.
-
Use CEP-17 before transport connect when no explicit relay URLs are supplied.
Suggested deliverables
| Deliverable |
Outcome |
| Server relay-list publisher |
Announced servers can publish kind 10002 metadata |
| Client relay-list resolver |
Clients can discover operational relays without hardcoded relay config |
| Config surface for discovery relays and fallback relays |
Users can tune discovery behavior without invasive changes |
| Tests for publish/fetch/select flows |
Relay discovery behavior becomes predictable and stable |
CEP-19 Status: Ephemeral Gift Wraps
What exists now
Rust already has significant CEP-19 groundwork.
Current Rust anchors:
- [src/core/constants.rs]:16
EPHEMERAL_GIFT_WRAP_KIND = 21059
- [src/transport/base.rs]:70 subscription filter includes kind
21059
- [src/transport/client.rs]:277 accepts kind
21059
- [src/transport/server.rs]:603 accepts kind
21059
- [src/encryption/mod.rs]:61
gift_wrap_single_layer() creates outbound gift wraps
So CEP-19 is already partially implemented:
- inbound recognition exists
- inbound decryption path exists
- capability tag constant exists
Level of implementation
Status: partial protocol support.
As different modes for partial, always and never giftwrapping can be done(Took inspiration from ts sdk)
Remaining Rust gaps:
| Gap |
Current Rust state |
No GiftWrapMode |
Rust only has EncryptionMode |
| No peer capability-driven selection |
Client does not learn and use server ephemeral support to choose outbound kind |
| No strict persistent/ephemeral policy surface |
Transport cannot be configured to force one gift-wrap kind |
| Tag advertisement is ahead of real behavior |
announce() emits support_encryption_ephemeral whenever encryption is enabled |
Why it matters
Without outbound CEP-19 support:
- Rust can consume ephemeral gift wraps but cannot fully participate in the mode
- capability tags may overstate actual transport behavior
- future interoperability bugs become likely when peers rely on ephemeral support tags
Basic implementation approach
This work should be handled as a transport policy enhancement rather than a one-off patch.
-
Add GiftWrapMode to Rust core types.
-
Extend transport configuration by adding the mode to client and server configs
-
Generalize outbound gift-wrap creation.This can be possibly done by changing gift_wrap_single_layer() to accept the desired outer kind
-
Track peer support.
- client should learn server ephemeral support from announcement/init tags
- server should preserve enough per-session context to mirror or enforce selected policy
-
Fix tag advertisement.
- only advertise
support_encryption_ephemeral when the transport can actually send and receive ephemeral wraps under the configured policy
Suggested deliverables
| Deliverable |
Outcome |
GiftWrapMode enum in Rust |
Clear transport-level policy model |
| Outbound kind selection |
Rust can emit 21059 when appropriate |
| Peer capability tracking |
Optional mode becomes interoperable rather than static |
| Correct advertisement semantics |
Capability tags match implementation reality |
| Interop tests |
Persistent and ephemeral peers can communicate predictably |
CEP-8 Status: Capability Pricing And Payments
What exists now
Rust sdk does not currently implement CEP-8 as a payment system.
The nearest existing pieces are:
- generic
cap tag constant in [src/core/constants.rs]:47
- request/response correlation and server notification sending in [src/transport/server.rs]:340
- client pending request tracking in [src/transport/client.rs]:60
These are only supporting primitives. They are not a CEP-8 implementation.
Level of implementation
Status: missing as a feature, with some usable prerequisites.
Remaining Rust gaps:
| Gap |
Current Rust state |
| Payment types and API surface |
Missing |
cap tag generation from priced capabilities |
Missing |
pmi tag support |
Missing |
payment_required notification flow |
Missing |
payment_accepted notification flow |
Missing |
payment_rejected notification flow |
Missing |
| Client payment handler abstraction |
Missing |
| Server payment processor abstraction |
Missing |
| Middleware to gate requests pending payment |
Missing |
| Correlated payment notifications |
Missing |
| Dynamic pricing quote/reject/waive behavior |
Missing |
| Client-side synthetic progress while payment is pending |
Missing |
| Public announcement/tag integration |
Missing |
Why it matters
CEP-8 is not just an add-on module. It needs transport seams:
- correlated notifications tied to an original request
- tag publication for discovery
- server-side request gating
- client-side request lifetime extension while payment settles
Basic implementation approach
Finalizing it further
Suggested deliverables
| Deliverable |
Outcome |
New payments module |
Rust exposes CEP-8 concepts as a first-class API |
| Server middleware support |
Paid methods can be gated before reaching application logic |
| Client payment handler support |
Clients can react to payment_required and continue the original request flow |
| Tag builders |
CEP-8 discovery data can be published consistently |
| Tests with fake handlers/processors |
Core CEP-8 flow is verified before adding real payment rails |
Completed tasks:
- CEP 19 implementation completed
- CEP 6 issue planning completed, implementation in progress
Executive Summary
The Rust SDK currently has a usable client/server transport, public announcement helpers, discovery helpers, NIP-44 encryption, and partial support for CEP-19 inbound envelopes.
Current Status:
Current limitation pattern:
CEP-6 Status: Public Server Announcements
What exists now
Cuurent SDK already implements the core public announcement event and the public list events.
Current Rust anchors:
announce()publish_tools()publish_resources()publish_prompts()publish_resource_templates()discover_servers()The existing
announce()function does the important CEP-6 job:11316server_infoname,about,website,pictureCurrent Status:
What is still missing
The main gaps revolve around lifecycle management. Ideally the lifecycle and startup of transport layer for server should handle publishing automatically. Here is the matrix for gaps found:
Remaining Rust gaps:
announce()and each list-publish helperdelete_announcements()publishes kind5with aktag instead of deleting exact event idsWhy it matters
The current approach is manual and if not called properly can lead to:
Basic implementation approach
Proposed CEP-6 work should be a refactor-plus-enhancement, not a rewrite.
Suggested implementation direction:
Add an internal
announcementmodule.Keep current helpers as low-level building blocks.
Introduce a transport-managed publication flow.
Introduce a reusable tag model.
Improve deletion semantics.
Expected behaviour finally:
CEP-17 Status: Relay-List Metadata And Discovery
What exists now
Rust already has some foundation pieces for CEP-17:
RELAY_LIST_METADATA_KIND = 10002Level of implementation
Status: foundational only.
The actual relay-list publication and client relay resolution flow are not yet integrated.
Remaining Rust gaps:
10002rtagsWhy it matters
Without CEP-17 transport integration:
Basic implementation approach
This work should be split into server-side and client-side halves.
Server-side approach
Extend
NostrServerTransportConfig. Adding fields required for the implementationAdd a relay-list publisher.
Separate operational relays from discoverability publication relays.
Integrate this with the proposed CEP-6 announcement manager.
Client-side approach
Extend
NostrClientTransportConfigto have the required fields.Add a small internal CEP-17 discovery module.
Use CEP-17 before transport connect when no explicit relay URLs are supplied.
Suggested deliverables
10002metadataCEP-19 Status: Ephemeral Gift Wraps
What exists now
Rust already has significant CEP-19 groundwork.
Current Rust anchors:
EPHEMERAL_GIFT_WRAP_KIND = 21059210592105921059gift_wrap_single_layer()creates outbound gift wrapsSo CEP-19 is already partially implemented:
Level of implementation
Status: partial protocol support.
As different modes for partial, always and never giftwrapping can be done(Took inspiration from ts sdk)
Remaining Rust gaps:
GiftWrapModeEncryptionModeannounce()emitssupport_encryption_ephemeralwhenever encryption is enabledWhy it matters
Without outbound CEP-19 support:
Basic implementation approach
This work should be handled as a transport policy enhancement rather than a one-off patch.
Add
GiftWrapModeto Rust core types.Extend transport configuration by adding the mode to client and server configs
Generalize outbound gift-wrap creation.This can be possibly done by changing
gift_wrap_single_layer()to accept the desired outer kindTrack peer support.
Fix tag advertisement.
support_encryption_ephemeralwhen the transport can actually send and receive ephemeral wraps under the configured policySuggested deliverables
GiftWrapModeenum in Rust21059when appropriateOptionalmode becomes interoperable rather than staticCEP-8 Status: Capability Pricing And Payments
What exists now
Rust sdk does not currently implement CEP-8 as a payment system.
The nearest existing pieces are:
captag constant in [src/core/constants.rs]:47These are only supporting primitives. They are not a CEP-8 implementation.
Level of implementation
Status: missing as a feature, with some usable prerequisites.
Remaining Rust gaps:
captag generation from priced capabilitiespmitag supportpayment_requirednotification flowpayment_acceptednotification flowpayment_rejectednotification flowWhy it matters
CEP-8 is not just an add-on module. It needs transport seams:
Basic implementation approach
Finalizing it further
Suggested deliverables
paymentsmodulepayment_requiredand continue the original request flowCompleted tasks: