omk 0.5.0

A Rust runtime for Kimi CLI. Turns prompts into proof-backed engineering runs with gates, worktrees, and replay.
Documentation
use anyhow::{Context, Result};
use serde::Deserialize;
use serde_json::Value;
use tracing::debug;

use super::types::McpClient;
use crate::mcp::client::transport_trait::McpTransport;
use crate::mcp::client::types::{CallToolResult, Resource, ResourceContent, Tool};

impl<T: McpTransport> McpClient<T> {
    pub async fn list_tools(&mut self) -> Result<Vec<Tool>> {
        #[derive(Debug, Deserialize)]
        struct ListToolsResult {
            tools: Vec<Tool>,
        }
        let result: ListToolsResult = self.request("tools/list", None::<Value>).await?;
        debug!(server = %self.server_name, count = result.tools.len(), "MCP tools listed");
        Ok(result.tools)
    }

    pub async fn call_tool(&mut self, name: &str, arguments: Value) -> Result<CallToolResult> {
        let params = serde_json::json!({"name": name, "arguments": arguments});
        let result: CallToolResult = self
            .request("tools/call", Some(params))
            .await
            .with_context(|| format!("MCP tool call failed: {name} on {}", self.server_name))?;
        Ok(result)
    }

    pub async fn list_resources(&mut self) -> Result<Vec<Resource>> {
        #[derive(Debug, Deserialize)]
        struct ListResourcesResult {
            resources: Vec<Resource>,
        }
        let result: ListResourcesResult = self.request("resources/list", None::<Value>).await?;
        debug!(server = %self.server_name, count = result.resources.len(), "MCP resources listed");
        Ok(result.resources)
    }

    pub async fn read_resource(&mut self, uri: &str) -> Result<Vec<ResourceContent>> {
        #[derive(Debug, Deserialize)]
        struct ReadResourceResult {
            contents: Vec<ResourceContent>,
        }
        let params = serde_json::json!({"uri": uri});
        let result: ReadResourceResult = self
            .request("resources/read", Some(params))
            .await
            .with_context(|| {
                format!("MCP read_resource failed for {uri} on {}", self.server_name)
            })?;
        Ok(result.contents)
    }

    pub async fn shutdown(mut self) -> Result<()> {
        self.transport.close().await
    }

    pub fn server_name(&self) -> &str {
        &self.server_name
    }

    pub fn into_transport(self) -> T {
        self.transport
    }
}