Skip to main content

oxios_kernel/kernel_handle/
mcp_api.rs

1use crate::mcp::{self, McpBridge, McpServer, McpToolCallResult};
2use crate::tools::tool_types::ToolDef;
3use std::collections::HashMap;
4use std::sync::Arc;
5
6/// MCP system calls.
7pub struct McpApi {
8    pub(crate) mcp_bridge: Arc<McpBridge>,
9}
10
11impl McpApi {
12    /// Create a new McpApi.
13    pub fn new(mcp_bridge: Arc<McpBridge>) -> Self {
14        Self { mcp_bridge }
15    }
16    /// List registered MCP servers.
17    pub fn list_servers(&self) -> Vec<String> {
18        self.mcp_bridge.servers()
19    }
20
21    /// Get MCP server info.
22    pub fn get_server(&self, name: &str) -> Option<McpServer> {
23        self.mcp_bridge.get_server(name)
24    }
25
26    /// Register an MCP server.
27    pub fn register_server(&self, server: McpServer) {
28        self.mcp_bridge.register_server(server);
29    }
30    /// Overwrite a registered MCP server's configuration in place. The `name`
31    /// is the key and cannot be changed. The old client is stopped before
32    /// the config is mutated; callers (the route handler) are responsible
33    /// for re-initializing the server afterwards so they can roll back on
34    /// failure — same pattern as the register path.
35    pub async fn update_server(
36        &self,
37        name: &str,
38        command: String,
39        args: Vec<String>,
40        env: HashMap<String, String>,
41        enabled: bool,
42    ) -> anyhow::Result<McpServer> {
43        self.mcp_bridge
44            .update_server(name, command, args, env, enabled)
45            .await
46    }
47
48    /// Initialize a specific MCP server.
49    pub async fn init_server(&self, name: &str) -> anyhow::Result<()> {
50        self.mcp_bridge.initialize_server(name).await
51    }
52
53    /// Get MCP client status.
54    pub async fn client_status(&self, name: &str) -> Option<bool> {
55        if let Some(client) = self.mcp_bridge.client(name).await {
56            Some(client.is_initialized().await)
57        } else {
58            None
59        }
60    }
61
62    /// List all MCP tools as ToolDefs.
63    pub async fn list_tools(&self) -> anyhow::Result<Vec<ToolDef>> {
64        mcp::list_tool_defs(&self.mcp_bridge).await
65    }
66
67    /// Get cached tools for a server as ToolDefs.
68    pub async fn cached_tools(&self, server_name: &str) -> Option<Vec<ToolDef>> {
69        mcp::cached_tool_defs(&self.mcp_bridge, server_name).await
70    }
71
72    /// Call an MCP tool.
73    pub async fn call_tool(
74        &self,
75        server: &str,
76        tool: &str,
77        arguments: serde_json::Value,
78    ) -> anyhow::Result<McpToolCallResult> {
79        self.mcp_bridge.call_tool(server, tool, arguments).await
80    }
81
82    /// MCP bridge reference.
83    pub fn bridge(&self) -> &Arc<McpBridge> {
84        &self.mcp_bridge
85    }
86
87    /// Number of configured MCP servers.
88    pub fn server_count(&self) -> usize {
89        self.mcp_bridge.servers().len()
90    }
91
92    /// Remove (disconnect and delete) an MCP server.
93    pub async fn remove_server(&self, name: &str) -> anyhow::Result<()> {
94        self.mcp_bridge.remove_server(name).await
95    }
96
97    /// Toggle MCP server enabled/disabled. Returns the new enabled state.
98    pub async fn toggle_server(&self, name: &str) -> anyhow::Result<bool> {
99        self.mcp_bridge.toggle_server(name).await
100    }
101
102    /// Shutdown all MCP servers.
103    pub async fn shutdown_all(&self) -> anyhow::Result<()> {
104        self.mcp_bridge.shutdown_all().await
105    }
106}