pub mod analysis;
pub mod files;
pub mod search;
use rmcp::model::{ErrorCode, Tool};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::sync::Arc;
pub fn invalid_params(msg: impl Into<String>) -> rmcp::ErrorData {
rmcp::ErrorData::new(ErrorCode::INVALID_PARAMS, msg.into(), None)
}
pub fn parse_params<T: serde::de::DeserializeOwned>(
args: Option<&serde_json::Map<String, Value>>,
) -> Result<T, rmcp::ErrorData> {
let args = args.ok_or_else(|| invalid_params("Missing required parameters"))?;
serde_json::from_value(Value::Object(args.clone())).map_err(|e| invalid_params(e.to_string()))
}
fn schema_for<T: JsonSchema>() -> Arc<serde_json::Map<String, serde_json::Value>> {
let schema = schemars::schema_for!(T);
let value = serde_json::to_value(schema).unwrap_or_default();
if let serde_json::Value::Object(obj) = value {
Arc::new(obj)
} else {
Arc::new(serde_json::Map::new())
}
}
pub fn get_all_tools() -> Vec<Tool> {
vec![
search::search_symbols_tool(),
search::get_definition_tool(),
search::find_references_tool(),
files::get_file_tool(),
files::get_file_tree_tool(),
analysis::get_callers_tool(),
analysis::get_callees_tool(),
analysis::smart_context_tool(),
]
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct SearchParams {
pub query: String,
#[serde(default = "default_limit")]
pub limit: Option<i32>,
pub kind: Option<String>,
pub file: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct DefinitionParams {
pub symbol: String,
pub file: Option<String>,
pub kind: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ReferencesParams {
pub symbol: String,
pub file: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct GetFileParams {
pub path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct FileTreeParams {
pub path: Option<String>,
pub pattern: Option<String>,
pub depth: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct CallGraphParams {
pub function: String,
pub file: Option<String>,
#[serde(default = "default_depth")]
pub depth: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct SmartContextParams {
pub task: String,
#[serde(default = "default_max_tokens")]
pub max_tokens: Option<usize>,
#[serde(default = "default_depth")]
pub depth: Option<i32>,
#[serde(default = "default_top")]
pub top: Option<usize>,
#[serde(default)]
pub provider: Option<String>,
#[serde(default)]
pub use_openai: Option<bool>,
}
fn default_limit() -> Option<i32> {
Some(20)
}
fn default_depth() -> Option<i32> {
Some(3)
}
fn default_max_tokens() -> Option<usize> {
Some(8000)
}
fn default_top() -> Option<usize> {
Some(10)
}