Files
kebab/crates/kebab-mcp/tests/tools_list.rs
th-kim0823 6ab0d782ef feat(mcp): kebab__bulk_search tool (fb-42)
Exposes bulk multi-query search via MCP `bulk_search` tool:
- Input: { queries: [SearchInput shapes...] }, capped at 100
- Output: bulk_search_response.v1 with per-query results + summary
- Sequential execution reuses App instance for cache amortization
- Per-query errors embed error.v1 JSON; never aborts bulk call

Updates tool count from 7 to 8 in lib.rs comment + tools_list test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:31:20 +09:00

73 lines
2.6 KiB
Rust

//! Integration: `build_tools_vec` returns 8 tools with correct names and
//! inputSchema. Uses the extracted `pub fn build_tools_vec()` helper — no
//! transport or RequestContext needed.
use kebab_mcp::build_tools_vec;
#[test]
fn tools_list_returns_eight_tools() {
let tools = build_tools_vec();
assert_eq!(tools.len(), 8, "expected exactly 8 tools, got {}", tools.len());
let names: Vec<&str> = tools.iter().map(|t| t.name.as_ref()).collect();
assert!(names.contains(&"schema"), "missing 'schema' tool");
assert!(names.contains(&"doctor"), "missing 'doctor' tool");
assert!(names.contains(&"search"), "missing 'search' tool");
assert!(names.contains(&"ask"), "missing 'ask' tool");
assert!(names.contains(&"ingest_file"), "missing 'ingest_file' tool");
assert!(names.contains(&"ingest_stdin"), "missing 'ingest_stdin' tool");
assert!(names.contains(&"fetch"), "missing 'fetch' tool");
assert!(names.contains(&"bulk_search"), "missing 'bulk_search' tool");
}
#[test]
fn search_tool_input_schema_has_required_query() {
let tools = build_tools_vec();
let search = tools
.iter()
.find(|t| t.name.as_ref() == "search")
.expect("search tool must be present");
// input_schema is Arc<JsonObject> (serde_json::Map<String, Value>).
let schema_val = serde_json::Value::Object(search.input_schema.as_ref().clone());
let required = schema_val
.get("required")
.and_then(|v| v.as_array())
.expect("search inputSchema must have a 'required' array");
assert!(
required.iter().any(|v| v.as_str() == Some("query")),
"search inputSchema 'required' must contain 'query', got: {required:?}"
);
}
#[test]
fn schema_and_doctor_tools_accept_empty_input() {
let tools = build_tools_vec();
for name in &["schema", "doctor"] {
let tool = tools
.iter()
.find(|t| t.name.as_ref() == *name)
.unwrap_or_else(|| panic!("{name} tool must be present"));
let schema_val = serde_json::Value::Object(tool.input_schema.as_ref().clone());
// An empty-input schema has type "object" and no required fields
// (or no 'required' key at all).
let ty = schema_val.get("type").and_then(|v| v.as_str());
assert_eq!(
ty,
Some("object"),
"{name} inputSchema 'type' must be 'object', got {ty:?}"
);
if let Some(required) = schema_val.get("required").and_then(|v| v.as_array()) {
assert!(
required.is_empty(),
"{name} inputSchema 'required' must be empty, got: {required:?}"
);
}
}
}