#![allow(dead_code)]
use crate::base::ToolDescriptor;
use serde_json::json;
fn no_args() -> serde_json::Value {
json!({"type": "object", "properties": {}, "additionalProperties": false})
}
pub fn library_install_descriptor() -> ToolDescriptor {
ToolDescriptor::with_timeout(
"library_install",
"Install the Jumperless MCP resident library to /jumperless_mcp/ on the device. \
No-op if the current version is already installed.",
no_args(),
3_000,
)
}
pub fn library_uninstall_descriptor() -> ToolDescriptor {
ToolDescriptor::with_timeout(
"library_uninstall",
"Remove the Jumperless MCP resident library from /jumperless_mcp/ on the device.",
no_args(),
1_000,
)
}
pub fn library_check_descriptor() -> ToolDescriptor {
ToolDescriptor::with_timeout(
"library_check",
"Check whether the Jumperless MCP resident library is installed and up-to-date. \
Returns version and file presence status.",
no_args(),
1_000,
)
}
pub fn library_reinstall_descriptor() -> ToolDescriptor {
ToolDescriptor::with_timeout(
"library_reinstall",
"Force a clean reinstall of the Jumperless MCP resident library. \
Removes existing files then writes fresh copies from the embedded bundle.",
no_args(),
3_000,
)
}
pub fn descriptors() -> Vec<ToolDescriptor> {
vec![
library_install_descriptor(),
library_uninstall_descriptor(),
library_check_descriptor(),
library_reinstall_descriptor(),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn library_install_descriptor_has_correct_name_and_timeout() {
let d = library_install_descriptor();
assert_eq!(d.name, "library_install");
assert!(!d.description.is_empty());
assert_eq!(d.timeout_ms, 3_000);
}
#[test]
fn library_uninstall_descriptor_has_correct_name_and_timeout() {
let d = library_uninstall_descriptor();
assert_eq!(d.name, "library_uninstall");
assert!(!d.description.is_empty());
assert_eq!(d.timeout_ms, 1_000);
}
#[test]
fn library_check_descriptor_has_correct_name_and_timeout() {
let d = library_check_descriptor();
assert_eq!(d.name, "library_check");
assert!(!d.description.is_empty());
assert_eq!(d.timeout_ms, 1_000);
}
#[test]
fn library_reinstall_descriptor_has_correct_name_and_timeout() {
let d = library_reinstall_descriptor();
assert_eq!(d.name, "library_reinstall");
assert!(!d.description.is_empty());
assert_eq!(d.timeout_ms, 3_000);
}
#[test]
fn all_descriptors_have_object_schema() {
for d in descriptors() {
assert!(
matches!(d.input_schema, serde_json::Value::Object(_)),
"descriptor '{}' must have object input_schema",
d.name
);
}
}
#[test]
fn all_descriptors_have_additional_properties_false() {
for d in descriptors() {
let schema = &d.input_schema;
assert_eq!(
schema.get("additionalProperties"),
Some(&serde_json::Value::Bool(false)),
"descriptor '{}' input_schema must have additionalProperties=false for strict MCP validator compat",
d.name
);
}
}
#[test]
fn descriptors_returns_four_tools() {
assert_eq!(descriptors().len(), 4);
}
#[test]
fn all_tool_names_are_unique() {
let descs = descriptors();
let mut names: Vec<&str> = descs.iter().map(|d| d.name.as_str()).collect();
let original_len = names.len();
names.dedup();
assert_eq!(names.len(), original_len, "tool names must be unique");
}
#[test]
fn install_timeout_is_at_least_check_timeout() {
let install = library_install_descriptor();
let check = library_check_descriptor();
assert!(install.timeout_ms >= check.timeout_ms);
}
#[test]
fn reinstall_timeout_is_at_least_install_timeout() {
let reinstall = library_reinstall_descriptor();
let install = library_install_descriptor();
assert!(reinstall.timeout_ms >= install.timeout_ms);
}
}