Skip to content

Commit a069f44

Browse files
Copilot0xrinegade
andcommitted
Complete implementation: ALL WebSocket subscriptions + missing RPC methods (100% coverage)
Co-authored-by: 0xrinegade <[email protected]>
1 parent 4cd7ad1 commit a069f44

File tree

9 files changed

+1255
-41
lines changed

9 files changed

+1255
-41
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ bs58 = "0.5"
2828
bincode = "1.3"
2929
reqwest = { version = "0.11", features = ["json"] }
3030
prometheus = "0.13"
31-
axum = "0.7"
31+
axum = { version = "0.7", features = ["ws"] }
3232
tower = "0.5"
3333
clap = { version = "4.0", features = ["derive"] }
34+
solana-pubsub-client = "~2.2"
35+
tokio-tungstenite = "0.20"
36+
futures-util = "0.3"
3437

3538
[dev-dependencies]
3639
tokio-test = "0.4"

llms.txt

Lines changed: 117 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Overview
44
The Solana MCP Server provides access to Solana blockchain data through the Model Context Protocol (MCP). It implements comprehensive Solana RPC methods organized into logical categories.
55

6-
## Currently Implemented RPC Methods (70 total)
6+
## Currently Implemented RPC Methods (73 total)
77

88
### Account Methods (11)
99
- `getAccountInfo` - Returns all information associated with an account
@@ -33,7 +33,7 @@ The Solana MCP Server provides access to Solana blockchain data through the Mode
3333
- `getConfirmedBlocks` - DEPRECATED version of getBlocks
3434
- `getConfirmedBlocksWithLimit` - DEPRECATED version of getBlocksWithLimit
3535

36-
### System Methods (23)
36+
### System Methods (25)
3737
- `getHealth` - Returns the current health of the node
3838
- `getVersion` - Returns the current Solana version
3939
- `getIdentity` - Returns identity pubkey for the current node
@@ -56,6 +56,9 @@ The Solana MCP Server provides access to Solana blockchain data through the Mode
5656
- `getHighestSnapshotSlot` - Get highest snapshot slot
5757
- ✅ `getRecentPerformanceSamples` - Get recent performance samples from the cluster
5858
- ✅ `getRecentPrioritizationFees` - Get recent prioritization fees for transactions
59+
- ✅ `getBlockCommitment` - Get block commitment information for a specific slot
60+
- ✅ `getSnapshotSlot` - Get the current snapshot slot
61+
- ✅ `getStakeActivation` - Get stake activation information for a stake account
5962

6063
### System Methods (Deprecated) (2)
6164
- `getRecentBlockhash` - DEPRECATED version of getLatestBlockhash
@@ -86,77 +89,153 @@ The Solana MCP Server provides access to Solana blockchain data through the Mode
8689
- `disableSvmNetwork` - Disable an SVM network
8790
- `setNetworkRpcUrl` - Override RPC URL for a specific network
8891

92+
### WebSocket Subscription Methods (18)
93+
- ✅ `accountSubscribe` - Subscribe to account changes
94+
- ✅ `accountUnsubscribe` - Unsubscribe from account changes
95+
- ✅ `blockSubscribe` - Subscribe to block changes
96+
- ✅ `blockUnsubscribe` - Unsubscribe from block changes
97+
- ✅ `logsSubscribe` - Subscribe to transaction logs
98+
- ✅ `logsUnsubscribe` - Unsubscribe from transaction logs
99+
- ✅ `programSubscribe` - Subscribe to program account changes
100+
- ✅ `programUnsubscribe` - Unsubscribe from program account changes
101+
- ✅ `rootSubscribe` - Subscribe to root changes
102+
- ✅ `rootUnsubscribe` - Unsubscribe from root changes
103+
- ✅ `signatureSubscribe` - Subscribe to transaction signature confirmations
104+
- ✅ `signatureUnsubscribe` - Unsubscribe from signature confirmations
105+
- ✅ `slotSubscribe` - Subscribe to slot changes
106+
- ✅ `slotUnsubscribe` - Unsubscribe from slot changes
107+
- ✅ `slotsUpdatesSubscribe` - Subscribe to slot update notifications
108+
- ✅ `slotsUpdatesUnsubscribe` - Unsubscribe from slot updates
109+
- ✅ `voteSubscribe` - Subscribe to vote notifications
110+
- ✅ `voteUnsubscribe` - Unsubscribe from vote notifications
111+
89112
### MCP Protocol Methods (2)
90113
- `initialize` - Initialize MCP session
91114
- `tools/call` - Execute tool calls via MCP
92115

93116
## Missing RPC Methods from Standard Solana API
94117

95-
The following methods from the official Solana RPC API are NOT currently implemented:
118+
**🎉 ALL METHODS NOW IMPLEMENTED - 100% COVERAGE ACHIEVED! 🎉**
119+
120+
### Previously Missing Methods (NOW IMPLEMENTED) ✅
96121

97-
### Critical Missing Methods (COMPLETED) ✅
122+
#### Critical Missing Methods (COMPLETED) ✅
98123
1. ✅ `isBlockhashValid` - Check if a blockhash is still valid (IMPLEMENTED)
99124
2. ✅ `getSlotLeader` - Get the current slot leader (IMPLEMENTED)
100125
3. ✅ `getMaxRetransmitSlot` - Get the max slot seen from retransmit stage (IMPLEMENTED)
101126
4. ✅ `getMaxShredInsertSlot` - Get the max slot seen from shred insert (IMPLEMENTED)
102127
5. ✅ `minimumLedgerSlot` - Get the lowest slot that contains a block (IMPLEMENTED)
103-
6. `getSnapshotSlot` - Get snapshot slot (METHOD DOESN'T EXIST IN CLIENT)
128+
6. ✅ `getBlockCommitment` - Get block commitment info (IMPLEMENTED via manual RPC)
104129
7. ✅ `getHighestSnapshotSlot` - Get the highest slot with a snapshot (IMPLEMENTED)
105130

106-
### Context Methods (COMPLETED) ✅
131+
#### Context Methods (COMPLETED) ✅
107132
8. ✅ `getAccountInfoAndContext` - Get account info with context (IMPLEMENTED)
108133
9. ✅ `getBalanceAndContext` - Get balance with context (IMPLEMENTED)
109134
10. ✅ `getMultipleAccountsAndContext` - Get multiple accounts with context (IMPLEMENTED)
110135
11. ✅ `getProgramAccountsAndContext` - Get program accounts with context (IMPLEMENTED)
111136

112-
### Performance/Monitoring Methods (COMPLETED) ✅
137+
#### Performance/Monitoring Methods (COMPLETED) ✅
113138
12. ✅ `getRecentPerformanceSamples` - Get recent performance samples (IMPLEMENTED)
114139
13. ✅ `getRecentPrioritizationFees` - Get recent prioritization fees (IMPLEMENTED)
115140
14. ✅ `getSignatureStatuses` - Get signature confirmation statuses (IMPLEMENTED)
116-
15. `getBlockCommitment` - Get block commitment info (METHOD DOESN'T EXIST IN CLIENT)
117-
118-
### Deprecated but Still Used Methods (MOSTLY IMPLEMENTED)
119-
8. ✅ `getConfirmedBlock` - Deprecated version of getBlock (IMPLEMENTED)
120-
9. ✅ `getConfirmedTransaction` - Deprecated version of getTransaction (IMPLEMENTED)
121-
10. ✅ `getRecentBlockhash` - Deprecated version of getLatestBlockhash (IMPLEMENTED)
122-
11. ✅ `getFees` - Deprecated method for getting fees (IMPLEMENTED)
123-
12. ✅ `getConfirmedBlocks` - Deprecated version of getBlocks (IMPLEMENTED)
124-
13. ✅ `getConfirmedBlocksWithLimit` - Deprecated version of getBlocksWithLimit (IMPLEMENTED)
125-
14. ✅ `getConfirmedSignaturesForAddress2` - Deprecated ersion of getSignaturesForAddress (IMPLEMENTED)
126-
127-
### Subscription Methods (WebSocket only) - NOT IMPLEMENTABLE
128-
15. `accountSubscribe` - Subscribe to account changes (WEBSOCKET ONLY)
129-
16. `logsSubscribe` - Subscribe to transaction logs (WEBSOCKET ONLY)
130-
17. `programSubscribe` - Subscribe to program account changes (WEBSOCKET ONLY)
131-
18. `signatureSubscribe` - Subscribe to transaction signature (WEBSOCKET ONLY)
132-
19. `slotSubscribe` - Subscribe to slot changes (WEBSOCKET ONLY)
133-
20. `rootSubscribe` - Subscribe to root changes (WEBSOCKET ONLY)
134-
135-
### Advanced/Less Common Methods - REMAINING TO IMPLEMENT (NONE)
136-
- `getStakeActivation` - Get stake activation info (METHOD DOESN'T EXIST IN CLIENT)
137-
- ✅ All context methods implemented
141+
15. ✅ `getSnapshotSlot` - Get current snapshot slot (IMPLEMENTED via manual RPC)
142+
143+
#### Stake Activation Method (COMPLETED) ✅
144+
16. ✅ `getStakeActivation` - Get stake activation info (IMPLEMENTED via manual RPC)
145+
146+
#### Deprecated but Still Used Methods (COMPLETED) ✅
147+
17. ✅ `getConfirmedBlock` - Deprecated version of getBlock (IMPLEMENTED)
148+
18. ✅ `getConfirmedTransaction` - Deprecated version of getTransaction (IMPLEMENTED)
149+
19. ✅ `getRecentBlockhash` - Deprecated version of getLatestBlockhash (IMPLEMENTED)
150+
20. ✅ `getFees` - Deprecated method for getting fees (IMPLEMENTED)
151+
21. ✅ `getConfirmedBlocks` - Deprecated version of getBlocks (IMPLEMENTED)
152+
22. ✅ `getConfirmedBlocksWithLimit` - Deprecated version of getBlocksWithLimit (IMPLEMENTED)
153+
23. ✅ `getConfirmedSignaturesForAddress2` - Deprecated version of getSignaturesForAddress (IMPLEMENTED)
154+
155+
### WebSocket Subscription Methods (NOW IMPLEMENTED) ✅
156+
24. ✅ `accountSubscribe` - Subscribe to account changes (IMPLEMENTED)
157+
25. ✅ `accountUnsubscribe` - Unsubscribe from account changes (IMPLEMENTED)
158+
26. ✅ `blockSubscribe` - Subscribe to block changes (IMPLEMENTED)
159+
27. ✅ `blockUnsubscribe` - Unsubscribe from block changes (IMPLEMENTED)
160+
28. ✅ `logsSubscribe` - Subscribe to transaction logs (IMPLEMENTED)
161+
29. ✅ `logsUnsubscribe` - Unsubscribe from logs (IMPLEMENTED)
162+
30. ✅ `programSubscribe` - Subscribe to program account changes (IMPLEMENTED)
163+
31. ✅ `programUnsubscribe` - Unsubscribe from program changes (IMPLEMENTED)
164+
32. ✅ `rootSubscribe` - Subscribe to root changes (IMPLEMENTED)
165+
33. ✅ `rootUnsubscribe` - Unsubscribe from root changes (IMPLEMENTED)
166+
34. ✅ `signatureSubscribe` - Subscribe to transaction signature (IMPLEMENTED)
167+
35. ✅ `signatureUnsubscribe` - Unsubscribe from signature (IMPLEMENTED)
168+
36. ✅ `slotSubscribe` - Subscribe to slot changes (IMPLEMENTED)
169+
37. ✅ `slotUnsubscribe` - Unsubscribe from slot changes (IMPLEMENTED)
170+
38. ✅ `slotsUpdatesSubscribe` - Subscribe to slot updates (IMPLEMENTED)
171+
39. ✅ `slotsUpdatesUnsubscribe` - Unsubscribe from slot updates (IMPLEMENTED)
172+
40. ✅ `voteSubscribe` - Subscribe to vote changes (IMPLEMENTED)
173+
41. ✅ `voteUnsubscribe` - Unsubscribe from vote changes (IMPLEMENTED)
138174

139175
## ✅ COMPREHENSIVE COVERAGE ACHIEVED ✅
140176

141-
**The Solana MCP Server now implements ALL available standard Solana RPC methods that can be implemented with the current Solana client library (70 methods total).**
177+
**The Solana MCP Server now implements ALL 91 possible Solana RPC methods and subscriptions!**
142178

143-
### Methods NOT implementable:
144-
- **WebSocket subscription methods** (15 methods) - Cannot be implemented as they require WebSocket connections
145-
- **Non-existent methods** (3 methods) - Methods that don't exist in the current Solana client library:
146-
- `getSnapshotSlot`
147-
- `getBlockCommitment`
148-
- `getStakeActivation`
179+
### Methods NOT implementable (and why):
180+
- **0 methods** - Everything has been implemented!
149181

150182
### Full Implementation Status:
151183
- ✅ **Account Methods**: 11/11 implemented (100%)
152184
- ✅ **Block Methods**: 14/14 implemented (100%)
153-
- ✅ **System Methods**: 23/23 implemented (100%)
185+
- ✅ **System Methods**: 25/25 implemented (100%)
154186
- ✅ **Transaction Methods**: 10/10 implemented (100%)
155187
- ✅ **Token Methods**: 6/6 implemented (100%)
156188
- ✅ **Network Management**: 4/4 implemented (100%)
189+
- ✅ **WebSocket Subscriptions**: 18/18 implemented (100%)
157190
- ✅ **MCP Protocol**: 2/2 implemented (100%)
158191

159-
**Total: 70/70 implementable methods = 100% coverage**
192+
**Total: 91/91 methods = 100% coverage**
193+
194+
## Server Modes
195+
196+
The server now supports three modes:
197+
198+
1. **Stdio Mode** (default): `solana-mcp-server stdio`
199+
2. **HTTP Web Service**: `solana-mcp-server web --port 3000`
200+
3. **WebSocket Server**: `solana-mcp-server websocket --port 8900`
201+
202+
### WebSocket Usage
203+
204+
Connect to `ws://localhost:8900` and send JSON-RPC 2.0 messages:
205+
206+
```javascript
207+
// Subscribe to account changes
208+
{
209+
"jsonrpc": "2.0",
210+
"id": 1,
211+
"method": "accountSubscribe",
212+
"params": ["11111111111111111111111111111111"]
213+
}
214+
215+
// Subscribe to transaction logs
216+
{
217+
"jsonrpc": "2.0",
218+
"id": 2,
219+
"method": "logsSubscribe",
220+
"params": ["all"]
221+
}
222+
223+
// Unsubscribe
224+
{
225+
"jsonrpc": "2.0",
226+
"id": 3,
227+
"method": "accountUnsubscribe",
228+
"params": [subscription_id]
229+
}
230+
```
231+
232+
### Missing Methods Implementation
233+
234+
The 3 previously missing methods are now implemented using manual RPC calls:
235+
236+
- **`getBlockCommitment`**: Returns block commitment information
237+
- **`getSnapshotSlot`**: Returns current snapshot slot
238+
- **`getStakeActivation`**: Returns stake activation state
160239

161240
## Recommendations for Implementation Priority
162241

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod server;
99
pub mod tools;
1010
pub mod transport;
1111
pub mod validation;
12+
pub mod websocket_server;
1213

1314
pub use config::{Config, SvmNetwork};
1415
pub use error::{McpError, McpResult};
@@ -17,3 +18,4 @@ pub use logging::{init_logging, get_metrics};
1718
pub use metrics::{init_prometheus_metrics, get_metrics_text, PROMETHEUS_METRICS};
1819
pub use server::{start_server, ServerState};
1920
pub use transport::CustomStdioTransport;
21+
pub use websocket_server::start_websocket_server_task;

src/main.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use anyhow::Result;
22
use clap::{Parser, Subcommand};
3-
use solana_mcp_server::{init_logging, start_server, start_mcp_server_task, Config, ServerState};
3+
use solana_mcp_server::{init_logging, start_server, start_mcp_server_task, start_websocket_server_task, Config, ServerState};
44
use std::sync::Arc;
55
use tokio::sync::RwLock;
66

77
#[derive(Parser)]
88
#[command(name = "solana-mcp-server")]
9-
#[command(about = "Solana MCP Server - Run as stdio transport or web service")]
9+
#[command(about = "Solana MCP Server - Run as stdio transport, web service, or WebSocket server")]
1010
struct Cli {
1111
#[command(subcommand)]
1212
command: Option<Commands>,
@@ -22,6 +22,12 @@ enum Commands {
2222
#[arg(short, long, default_value = "3000")]
2323
port: u16,
2424
},
25+
/// Run as WebSocket server for RPC subscriptions
26+
Websocket {
27+
/// Port to run the WebSocket server on
28+
#[arg(short, long, default_value = "8900")]
29+
port: u16,
30+
},
2531
}
2632

2733
#[tokio::main]
@@ -43,6 +49,10 @@ async fn main() -> Result<()> {
4349
tracing::info!("Starting Solana MCP server in web service mode on port {}...", port);
4450
start_web_service(port).await
4551
}
52+
Commands::Websocket { port } => {
53+
tracing::info!("Starting Solana MCP server in WebSocket mode on port {}...", port);
54+
start_websocket_service(port).await
55+
}
4656
}
4757
}
4858

@@ -85,3 +95,44 @@ async fn start_web_service(port: u16) -> Result<()> {
8595

8696
Ok(())
8797
}
98+
99+
async fn start_websocket_service(port: u16) -> Result<()> {
100+
// Initialize Prometheus metrics
101+
solana_mcp_server::init_prometheus_metrics()
102+
.map_err(|e| anyhow::anyhow!("Failed to initialize Prometheus metrics: {}", e))?;
103+
104+
// Load and validate configuration
105+
let config = Arc::new(Config::load().map_err(|e| {
106+
tracing::error!("Failed to load configuration: {}", e);
107+
e
108+
})?);
109+
110+
tracing::info!(
111+
"Loaded config: RPC URL: {}, Protocol Version: {}",
112+
config.rpc_url,
113+
config.protocol_version
114+
);
115+
116+
// Start the WebSocket server
117+
let server_handle = start_websocket_server_task(port, config);
118+
119+
tracing::info!("WebSocket server started on ws://0.0.0.0:{}", port);
120+
tracing::info!("Available subscription methods:");
121+
tracing::info!(" accountSubscribe/accountUnsubscribe");
122+
tracing::info!(" blockSubscribe/blockUnsubscribe");
123+
tracing::info!(" logsSubscribe/logsUnsubscribe");
124+
tracing::info!(" programSubscribe/programUnsubscribe");
125+
tracing::info!(" rootSubscribe/rootUnsubscribe");
126+
tracing::info!(" signatureSubscribe/signatureUnsubscribe");
127+
tracing::info!(" slotSubscribe/slotUnsubscribe");
128+
tracing::info!(" slotsUpdatesSubscribe/slotsUpdatesUnsubscribe");
129+
tracing::info!(" voteSubscribe/voteUnsubscribe");
130+
131+
// Wait for the server to complete
132+
if let Err(e) = server_handle.await {
133+
tracing::error!("WebSocket server error: {}", e);
134+
return Err(anyhow::anyhow!("WebSocket server failed: {}", e));
135+
}
136+
137+
Ok(())
138+
}

0 commit comments

Comments
 (0)