From 41bce9029bb0e1639db3534b1b1bccf8e02f094d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20Carvalho?= Date: Sun, 8 Mar 2026 17:42:35 -0300 Subject: [PATCH] remove unused sheesh-mcp crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The crate was never referenced by the main sheesh-rs binary or any workspace member — no imports, no Cargo.toml dependency. Deleted to reduce dead code and repo clutter. Co-Authored-By: Claude Sonnet 4.6 --- crates/sheesh-mcp/Cargo.lock | 114 ---------------- crates/sheesh-mcp/Cargo.toml | 9 -- crates/sheesh-mcp/src/context.rs | 69 ---------- crates/sheesh-mcp/src/lib.rs | 11 -- crates/sheesh-mcp/src/registry.rs | 67 ---------- crates/sheesh-mcp/src/tool.rs | 34 ----- crates/sheesh-mcp/src/tools/mod.rs | 3 - crates/sheesh-mcp/src/tools/run_command.rs | 55 -------- crates/sheesh-mcp/src/types.rs | 146 --------------------- 9 files changed, 508 deletions(-) delete mode 100644 crates/sheesh-mcp/Cargo.lock delete mode 100644 crates/sheesh-mcp/Cargo.toml delete mode 100644 crates/sheesh-mcp/src/context.rs delete mode 100644 crates/sheesh-mcp/src/lib.rs delete mode 100644 crates/sheesh-mcp/src/registry.rs delete mode 100644 crates/sheesh-mcp/src/tool.rs delete mode 100644 crates/sheesh-mcp/src/tools/mod.rs delete mode 100644 crates/sheesh-mcp/src/tools/run_command.rs delete mode 100644 crates/sheesh-mcp/src/types.rs diff --git a/crates/sheesh-mcp/Cargo.lock b/crates/sheesh-mcp/Cargo.lock deleted file mode 100644 index ee67e40..0000000 --- a/crates/sheesh-mcp/Cargo.lock +++ /dev/null @@ -1,114 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "itoa" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "sheesh-mcp" -version = "0.1.0" -dependencies = [ - "anyhow", - "serde", - "serde_json", -] - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/crates/sheesh-mcp/Cargo.toml b/crates/sheesh-mcp/Cargo.toml deleted file mode 100644 index 1af89bf..0000000 --- a/crates/sheesh-mcp/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "sheesh-mcp" -version = "0.1.0" -edition = "2024" - -[dependencies] -anyhow = "1" -serde = { version = "1", features = ["derive"] } -serde_json = "1" diff --git a/crates/sheesh-mcp/src/context.rs b/crates/sheesh-mcp/src/context.rs deleted file mode 100644 index c7f8568..0000000 --- a/crates/sheesh-mcp/src/context.rs +++ /dev/null @@ -1,69 +0,0 @@ -/// Output of a command executed on the remote host. -#[derive(Debug, Clone)] -pub struct CommandOutput { - pub stdout: String, - pub stderr: String, - pub exit_code: i32, -} - -impl CommandOutput { - /// Combined stdout + stderr, useful for sending to the LLM. - pub fn combined(&self) -> String { - let mut out = self.stdout.clone(); - if !self.stderr.is_empty() { - if !out.is_empty() { - out.push('\n'); - } - out.push_str(&self.stderr); - } - out - } - - pub fn succeeded(&self) -> bool { - self.exit_code == 0 - } -} - -/// The interface that tools use to interact with the remote SSH session. -/// -/// The main app will implement this trait on top of `TerminalTab` (PTY) or -/// a dedicated SSH exec channel — tools don't care which. -pub trait SshContext: Send + Sync { - /// Execute a shell command and return its output. - fn execute(&self, command: &str) -> anyhow::Result; - - /// Read a remote file's full contents as UTF-8. - fn read_file(&self, path: &str) -> anyhow::Result; - - /// Write `content` to `path` on the remote host (create or overwrite). - fn write_file(&self, path: &str, content: &str) -> anyhow::Result<()>; - - /// Append `content` to `path` on the remote host. - fn append_file(&self, path: &str, content: &str) -> anyhow::Result<()>; - - /// List entries in a remote directory. - fn list_dir(&self, path: &str) -> anyhow::Result>; - - /// Return `true` if the remote path exists. - fn path_exists(&self, path: &str) -> anyhow::Result; - - /// Return the current working directory of the remote session. - fn working_dir(&self) -> anyhow::Result; -} - -/// A single entry returned by `SshContext::list_dir`. -#[derive(Debug, Clone)] -pub struct DirEntry { - pub name: String, - pub kind: EntryKind, - /// Size in bytes (None if unknown). - pub size: Option, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum EntryKind { - File, - Directory, - Symlink, - Other, -} diff --git a/crates/sheesh-mcp/src/lib.rs b/crates/sheesh-mcp/src/lib.rs deleted file mode 100644 index 254183a..0000000 --- a/crates/sheesh-mcp/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod context; -pub mod registry; -pub mod tool; -pub mod tools; -pub mod types; - -// Convenience re-exports so users only need `use sheesh_mcp::*` or individual items. -pub use context::{CommandOutput, DirEntry, EntryKind, SshContext}; -pub use registry::ToolRegistry; -pub use tool::Tool; -pub use types::{ParamType, ToolCall, ToolContent, ToolDef, ToolParam, ToolResult}; diff --git a/crates/sheesh-mcp/src/registry.rs b/crates/sheesh-mcp/src/registry.rs deleted file mode 100644 index 0ae92ba..0000000 --- a/crates/sheesh-mcp/src/registry.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::collections::HashMap; - -use crate::{ - context::SshContext, - tool::Tool, - types::{ToolCall, ToolDef, ToolResult}, -}; - -/// Holds all registered tools and dispatches calls to the right one. -#[derive(Default)] -pub struct ToolRegistry { - tools: HashMap>, -} - -impl ToolRegistry { - pub fn new() -> Self { - Self::default() - } - - /// Register a tool. If a tool with the same name already exists it is replaced. - pub fn register(&mut self, tool: impl Tool + 'static) { - let name = tool.def().name.clone(); - self.tools.insert(name, Box::new(tool)); - } - - /// Retrieve a tool by name. - pub fn get(&self, name: &str) -> Option<&dyn Tool> { - self.tools.get(name).map(|b| b.as_ref()) - } - - /// All tool definitions — pass this to the LLM's `tools` parameter. - pub fn defs(&self) -> Vec { - self.tools.values().map(|t| t.def()).collect() - } - - /// Names of all registered tools. - pub fn names(&self) -> Vec<&str> { - self.tools.keys().map(|s| s.as_str()).collect() - } - - /// Dispatch a `ToolCall` to the matching tool. - /// - /// Returns `ToolResult::error` if no tool with that name is registered, - /// or if the tool itself returns an `Err`. - pub fn dispatch(&self, call: &ToolCall, ctx: &dyn SshContext) -> ToolResult { - let Some(tool) = self.get(&call.name) else { - return ToolResult::error( - &call.id, - format!("unknown tool: {}", call.name), - ); - }; - - match tool.call(call, ctx) { - Ok(result) => result, - Err(e) => ToolResult::error(&call.id, e.to_string()), - } - } - - /// Dispatch a batch of calls, returning results in the same order. - pub fn dispatch_all( - &self, - calls: &[ToolCall], - ctx: &dyn SshContext, - ) -> Vec { - calls.iter().map(|c| self.dispatch(c, ctx)).collect() - } -} diff --git a/crates/sheesh-mcp/src/tool.rs b/crates/sheesh-mcp/src/tool.rs deleted file mode 100644 index f5cf245..0000000 --- a/crates/sheesh-mcp/src/tool.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::{ - context::SshContext, - types::{ToolCall, ToolDef, ToolResult}, -}; - -/// A tool that can be registered with the MCP registry and called by the LLM. -/// -/// # Example -/// ```rust -/// struct EchoTool; -/// -/// impl Tool for EchoTool { -/// fn def(&self) -> ToolDef { -/// ToolDef { -/// name: "echo".into(), -/// description: "Return the input unchanged.".into(), -/// params: vec![ToolParam { name: "text".into(), ... }], -/// } -/// } -/// -/// fn call(&self, call: &ToolCall, _ctx: &dyn SshContext) -> anyhow::Result { -/// let text = call.arg_str("text").unwrap_or(""); -/// Ok(ToolResult::ok(&call.id, text)) -/// } -/// } -/// ``` -pub trait Tool: Send + Sync { - /// Static metadata: name, description, parameter schema. - fn def(&self) -> ToolDef; - - /// Invoke the tool. Receives the full call (including id and raw arguments) - /// and a reference to the active SSH session. - fn call(&self, call: &ToolCall, ctx: &dyn SshContext) -> anyhow::Result; -} diff --git a/crates/sheesh-mcp/src/tools/mod.rs b/crates/sheesh-mcp/src/tools/mod.rs deleted file mode 100644 index 7b176b4..0000000 --- a/crates/sheesh-mcp/src/tools/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod run_command; - -pub use run_command::RunCommandTool; diff --git a/crates/sheesh-mcp/src/tools/run_command.rs b/crates/sheesh-mcp/src/tools/run_command.rs deleted file mode 100644 index 139c986..0000000 --- a/crates/sheesh-mcp/src/tools/run_command.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::{ - context::SshContext, - tool::Tool, - types::{ParamType, ToolCall, ToolDef, ToolParam, ToolResult}, -}; - -/// MCP tool: execute a shell command on the remote SSH session. -/// -/// The host app is responsible for showing a confirmation dialog before -/// calling `Tool::call` — this struct only contains the pure execution logic. -pub struct RunCommandTool; - -impl Tool for RunCommandTool { - fn def(&self) -> ToolDef { - ToolDef { - name: "run_command".into(), - description: "Execute a shell command on the remote SSH session and return its output." - .into(), - params: vec![ - ToolParam { - name: "command".into(), - description: "The shell command to execute.".into(), - ty: ParamType::String, - required: true, - }, - ToolParam { - name: "description".into(), - description: "One-sentence explanation of what this command does (shown to the user in the confirmation dialog).".into(), - ty: ParamType::String, - required: false, - }, - ], - } - } - - fn call(&self, call: &ToolCall, ctx: &dyn SshContext) -> anyhow::Result { - let command = call - .arg_str("command") - .ok_or_else(|| anyhow::anyhow!("missing required argument: command"))?; - - let output = ctx.execute(command)?; - - let text = if output.combined().is_empty() { - format!("exit code {}", output.exit_code) - } else { - format!("exit code {}\n{}", output.exit_code, output.combined()) - }; - - if output.succeeded() { - Ok(ToolResult::ok(&call.id, text)) - } else { - Ok(ToolResult::error(&call.id, text)) - } - } -} diff --git a/crates/sheesh-mcp/src/types.rs b/crates/sheesh-mcp/src/types.rs deleted file mode 100644 index 2e1fe96..0000000 --- a/crates/sheesh-mcp/src/types.rs +++ /dev/null @@ -1,146 +0,0 @@ -use serde::{Deserialize, Serialize}; - -// ── Parameter schema ────────────────────────────────────────────────────────── - -/// Primitive types a tool parameter can have. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum ParamType { - String, - Integer, - Boolean, - Array, - Object, -} - -/// A single parameter in a tool's input schema. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolParam { - pub name: String, - pub description: String, - #[serde(rename = "type")] - pub ty: ParamType, - pub required: bool, -} - -// ── Tool definition ─────────────────────────────────────────────────────────── - -/// Static metadata that describes a tool to the LLM. -/// Maps to the `tools` array in the Anthropic / OpenAI API. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolDef { - pub name: String, - pub description: String, - pub params: Vec, -} - -impl ToolDef { - /// Render the parameter list as a JSON Schema `properties` object, - /// which is the format expected by most LLM APIs. - pub fn input_schema(&self) -> serde_json::Value { - let properties: serde_json::Map = self - .params - .iter() - .map(|p| { - let schema = serde_json::json!({ - "type": p.ty, - "description": p.description, - }); - (p.name.clone(), schema) - }) - .collect(); - - let required: Vec<&str> = self - .params - .iter() - .filter(|p| p.required) - .map(|p| p.name.as_str()) - .collect(); - - serde_json::json!({ - "type": "object", - "properties": properties, - "required": required, - }) - } -} - -// ── Tool call (LLM → app) ───────────────────────────────────────────────────── - -/// A request from the LLM to invoke a specific tool. -/// Matches the `tool_use` block in Anthropic responses. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolCall { - /// Opaque ID from the LLM (echoed back in the result). - pub id: String, - pub name: String, - /// Arbitrary JSON arguments as specified by the tool's input schema. - pub arguments: serde_json::Value, -} - -impl ToolCall { - pub fn new(id: impl Into, name: impl Into, arguments: serde_json::Value) -> Self { - Self { - id: id.into(), - name: name.into(), - arguments, - } - } - - /// Convenience: get a string argument by key. - pub fn arg_str(&self, key: &str) -> Option<&str> { - self.arguments.get(key)?.as_str() - } - - /// Convenience: get a bool argument by key. - pub fn arg_bool(&self, key: &str) -> Option { - self.arguments.get(key)?.as_bool() - } - - /// Convenience: get an i64 argument by key. - pub fn arg_int(&self, key: &str) -> Option { - self.arguments.get(key)?.as_i64() - } -} - -// ── Tool result (app → LLM) ─────────────────────────────────────────────────── - -/// A content block inside a tool result. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type", rename_all = "snake_case")] -pub enum ToolContent { - Text { text: String }, -} - -impl ToolContent { - pub fn text(s: impl Into) -> Self { - Self::Text { text: s.into() } - } -} - -/// The result of invoking a tool, sent back to the LLM. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolResult { - /// Echoes the `id` from the originating `ToolCall`. - pub tool_call_id: String, - pub content: Vec, - pub is_error: bool, -} - -impl ToolResult { - pub fn ok(tool_call_id: impl Into, text: impl Into) -> Self { - Self { - tool_call_id: tool_call_id.into(), - content: vec![ToolContent::text(text)], - is_error: false, - } - } - - pub fn error(tool_call_id: impl Into, message: impl Into) -> Self { - Self { - tool_call_id: tool_call_id.into(), - content: vec![ToolContent::text(message)], - is_error: true, - } - } -}