Skip to main content

ctx/mcp/tools/
mod.rs

1//! MCP tool implementations for ctx.
2
3pub mod analysis;
4pub mod files;
5pub mod search;
6
7use rmcp::model::{ErrorCode, Tool};
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11use std::sync::Arc;
12
13/// Helper to create an invalid params error.
14pub fn invalid_params(msg: impl Into<String>) -> rmcp::ErrorData {
15    rmcp::ErrorData::new(ErrorCode::INVALID_PARAMS, msg.into(), None)
16}
17
18/// Parse tool parameters from JSON.
19pub fn parse_params<T: serde::de::DeserializeOwned>(
20    args: Option<&serde_json::Map<String, Value>>,
21) -> Result<T, rmcp::ErrorData> {
22    let args = args.ok_or_else(|| invalid_params("Missing required parameters"))?;
23
24    serde_json::from_value(Value::Object(args.clone())).map_err(|e| invalid_params(e.to_string()))
25}
26
27/// Helper to create a JSON schema object from a type.
28fn schema_for<T: JsonSchema>() -> Arc<serde_json::Map<String, serde_json::Value>> {
29    let schema = schemars::schema_for!(T);
30    let value = serde_json::to_value(schema).unwrap_or_default();
31    if let serde_json::Value::Object(obj) = value {
32        Arc::new(obj)
33    } else {
34        Arc::new(serde_json::Map::new())
35    }
36}
37
38/// Get all available tools.
39pub fn get_all_tools() -> Vec<Tool> {
40    vec![
41        // Search tools
42        search::search_symbols_tool(),
43        search::get_definition_tool(),
44        search::find_references_tool(),
45        // File tools
46        files::get_file_tool(),
47        files::get_file_tree_tool(),
48        // Analysis tools
49        analysis::get_callers_tool(),
50        analysis::get_callees_tool(),
51        analysis::smart_context_tool(),
52    ]
53}
54
55// Common parameter types used across tools
56
57/// Parameters for searching symbols.
58#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
59pub struct SearchParams {
60    /// The search query (symbol name or pattern).
61    pub query: String,
62    /// Maximum number of results to return (default: 20).
63    #[serde(default = "default_limit")]
64    pub limit: Option<i32>,
65    /// Filter by symbol kind (function, struct, enum, trait, etc.).
66    pub kind: Option<String>,
67    /// Filter by file path pattern (glob syntax).
68    pub file: Option<String>,
69}
70
71/// Parameters for getting a symbol definition.
72#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
73pub struct DefinitionParams {
74    /// The symbol name to get the definition for.
75    pub symbol: String,
76    /// Filter by file path pattern (glob syntax).
77    pub file: Option<String>,
78    /// Filter by symbol kind.
79    pub kind: Option<String>,
80}
81
82/// Parameters for finding references.
83#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
84pub struct ReferencesParams {
85    /// The symbol name to find references to.
86    pub symbol: String,
87    /// Filter by file path pattern (glob syntax).
88    pub file: Option<String>,
89}
90
91/// Parameters for getting a file's contents.
92#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
93pub struct GetFileParams {
94    /// The file path relative to the project root.
95    pub path: String,
96}
97
98/// Parameters for listing files.
99#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
100pub struct FileTreeParams {
101    /// Optional directory path to list (defaults to project root).
102    pub path: Option<String>,
103    /// File pattern to match (glob syntax, e.g., "*.rs").
104    pub pattern: Option<String>,
105    /// Maximum depth to traverse (default: unlimited).
106    pub depth: Option<u32>,
107}
108
109/// Parameters for getting callers/callees.
110#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
111pub struct CallGraphParams {
112    /// The function name to analyze.
113    pub function: String,
114    /// Filter by file path pattern (glob syntax).
115    pub file: Option<String>,
116    /// Maximum depth to traverse (default: 3).
117    #[serde(default = "default_depth")]
118    pub depth: Option<i32>,
119}
120
121/// Parameters for smart context selection.
122#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
123pub struct SmartContextParams {
124    /// Natural language description of the task.
125    pub task: String,
126    /// Maximum tokens in output (default: 8000).
127    #[serde(default = "default_max_tokens")]
128    pub max_tokens: Option<usize>,
129    /// Call graph expansion depth (default: 2).
130    #[serde(default = "default_depth")]
131    pub depth: Option<i32>,
132    /// Number of initial semantic matches (default: 10).
133    #[serde(default = "default_top")]
134    pub top: Option<usize>,
135    /// Embedding backend: "local" (default), "openai", or "ollama".
136    #[serde(default)]
137    pub provider: Option<String>,
138    /// Deprecated: use `provider: "openai"`. Kept for backward compatibility.
139    #[serde(default)]
140    pub use_openai: Option<bool>,
141}
142
143fn default_limit() -> Option<i32> {
144    Some(20)
145}
146
147fn default_depth() -> Option<i32> {
148    Some(3)
149}
150
151fn default_max_tokens() -> Option<usize> {
152    Some(8000)
153}
154
155fn default_top() -> Option<usize> {
156    Some(10)
157}