Skip to content

Commit d032259

Browse files
committed
feat(mcp): Implement dynamic MCP tool discovery
**MAJOR IMPROVEMENT:** Replace hardcoded tool list with runtime discovery Before: - 34 hardcoded MCP tools in ovsm_handler.rs - Tools would get out of sync with server capabilities - Required code changes to add new tools After: - Dynamically discovers ALL tools from configured MCP servers - Automatically registers tools at runtime via list_tools() API - Tested: ✅ 75 tools discovered from osvm-mcp server - Graceful degradation if server initialization fails Implementation: - Iterate through all configured MCP servers - Call initialize_server() + list_tools() for each - Register McpBridgeTool for every discovered tool - Debug output shows discovered tool count per server Additional fixes: - Add getBlockHeight to RPC bridge registry - Fix getBalance example to use direct parameters - Handle async context properly with .await (not block_on) Testing: ✅ getSlot, getBlockHeight, getVersion working ✅ 75 MCP tools auto-discovered ✅ Graceful error handling for unavailable servers This resolves the hardcoded tool list antipattern and makes OSVM truly dynamic with MCP server capabilities.
1 parent 5451c6f commit d032259

File tree

3 files changed

+52
-39
lines changed

3 files changed

+52
-39
lines changed

examples/ovsm_scripts/mcp_basic_rpc.ovsm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
;; 4. Get balance for a known wallet
2525
(log :message "\n4. Checking wallet balance...")
2626
(define wallet "GBBbhHigLDyfxV71A24vGM2JLFukdChaNDTXGED1mF5r")
27-
(define balance (getBalance :address wallet))
27+
(define balance-result (getBalance wallet))
28+
(define balance (. balance-result value))
2829
(log :message "Balance (lamports):" :value balance)
2930
(log :message "Balance (SOL):" :value (/ balance 1000000000.0))
3031

src/commands/ovsm_handler.rs

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,47 +19,58 @@ pub async fn handle_ovsm_command(
1919
use crate::utils::rpc_bridge::create_rpc_registry;
2020

2121
let mut registry = create_rpc_registry();
22-
// Register MCP tools for OVSM script execution
22+
23+
// Dynamically register MCP tools from configured servers
2324
let mut mcp_service = McpService::new_with_debug(debug);
2425
let _ = mcp_service.load_config();
2526
let mcp_arc = Arc::new(tokio::sync::Mutex::new(mcp_service));
26-
let mcp_tools = vec![
27-
"get_account_transactions",
28-
"get_transaction",
29-
"batch_transactions",
30-
"analyze_transaction",
31-
"explain_transaction",
32-
"get_account_stats",
33-
"get_account_portfolio",
34-
"get_solana_balance",
35-
"get_account_token_stats",
36-
"check_account_type",
37-
"search_accounts",
38-
"get_balance",
39-
"get_block",
40-
"get_recent_blocks",
41-
"get_block_stats",
42-
"get_token_info",
43-
"get_token_metadata",
44-
"get_nft_collections",
45-
"get_trending_nfts",
46-
"get_defi_overview",
47-
"get_dex_analytics",
48-
"get_defi_health",
49-
"get_validator_analytics",
50-
"universal_search",
51-
"verify_wallet_signature",
52-
"get_user_history",
53-
"get_usage_stats",
54-
"manage_api_keys",
55-
"get_api_metrics",
56-
"report_error",
57-
"get_program_registry",
58-
"get_program_info",
59-
"solana_rpc_call",
60-
];
61-
for tool in mcp_tools {
62-
registry.register(McpBridgeTool::new(tool, Arc::clone(&mcp_arc)));
27+
28+
// Discover and register tools from all configured MCP servers
29+
{
30+
let mut svc = mcp_arc.lock().await;
31+
let mut total_tools = 0;
32+
33+
// Get all configured servers
34+
let servers: Vec<String> = svc.list_servers()
35+
.iter()
36+
.map(|(id, _)| (*id).clone())
37+
.collect();
38+
39+
for server_id in servers {
40+
// Initialize server
41+
if let Err(e) = svc.initialize_server(&server_id).await {
42+
if debug {
43+
eprintln!("⚠️ Failed to initialize MCP server '{}': {}", server_id, e);
44+
}
45+
continue;
46+
}
47+
48+
// List tools from this server
49+
match svc.list_tools(&server_id).await {
50+
Ok(tools) => {
51+
if debug {
52+
println!("📦 Discovered {} tools from MCP server '{}'", tools.len(), server_id);
53+
}
54+
total_tools += tools.len();
55+
56+
// Register each tool
57+
drop(svc); // Release lock before registering
58+
for tool in tools {
59+
registry.register(McpBridgeTool::new(&tool.name, Arc::clone(&mcp_arc)));
60+
}
61+
svc = mcp_arc.lock().await; // Re-acquire lock
62+
}
63+
Err(e) => {
64+
if debug {
65+
eprintln!("⚠️ Failed to list tools from '{}': {}", server_id, e);
66+
}
67+
}
68+
}
69+
}
70+
71+
if debug && total_tools > 0 {
72+
println!("✅ Registered {} MCP tools total\n", total_tools);
73+
}
6374
}
6475
let mut service = OvsmService::with_registry(registry, verbose, debug);
6576

src/utils/rpc_bridge.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ pub fn create_rpc_registry() -> ToolRegistry {
273273
"getParsedTransaction",
274274
"getSlot",
275275
"getBlock",
276+
"getBlockHeight",
276277
"getTransaction",
277278
"getAccountInfo",
278279
"getBalance",

0 commit comments

Comments
 (0)