pub(crate) mod capability;
pub(crate) mod dispatch;
pub(crate) mod error;
pub(crate) mod execute;
pub(crate) mod redact;
pub(crate) mod registry;
pub(crate) mod server;
pub(crate) mod tools;
pub(crate) mod transport;
pub(crate) use execute::execute;
#[cfg(test)]
mod no_grep_tests {
use super::dispatch::DispatchOutcome;
use super::dispatch::dispatch;
use super::registry::ToolContext;
use super::transport::{JSONRPC_VERSION, Request, RequestId, validate};
use arcature_build::uag::Uag;
use arcature_build::uag::schema::{
CadenceEntry, CommandEntry, JobEntry, ListenerEntry, ModuleEntry, RouteEntry,
ScheduleEntry, ServiceEntry,
};
use serde_json::Value;
use std::collections::BTreeMap;
const APP_CANARY: &str = "NoGrepCanary";
const FW_CANARY: &str = "canary-fw-2026.1.0";
const ROUTE_NAME_CANARY: &str = "no_grep.canary";
const ROUTE_PATH_CANARY: &str = "/canary/no-grep";
const PAGE_CANARY: &str = "Canary/Page";
const SERVICE_CANARY: &str = "CanaryService";
const SERVICE_DEP_CANARY: &str = "CanaryDep";
const JOB_CANARY: &str = "canary_job";
const COMMAND_CANARY: &str = "canary:cmd";
const SCHEDULE_CANARY: &str = "canary_sched";
fn canary_context() -> ToolContext {
let route = RouteEntry {
method: "get".into(),
path: ROUTE_PATH_CANARY.into(),
name: ROUTE_NAME_CANARY.into(),
handler: "CanaryHandler::show".into(),
pages: vec![PAGE_CANARY.into()],
action_fields: vec![],
action_type: String::new(),
query_fields: vec![],
query_type: String::new(),
query_array: false,
query_string_fields: vec![],
query_string_type: String::new(),
};
let module = ModuleEntry {
name: "CanaryModule".into(),
imports: vec![],
exports: vec![],
controllers: vec!["CanaryController".into()],
services: vec![SERVICE_CANARY.into()],
policies: vec![],
routes: vec![route.clone()],
listeners: vec![ListenerEntry {
event: "CanaryEvent".into(),
listener: "on_canary".into(),
}],
jobs: vec![JobEntry {
kind: JOB_CANARY.into(),
version: 1,
handler: "handle_canary".into(),
}],
commands: vec![CommandEntry {
name: COMMAND_CANARY.into(),
function: "canary_command".into(),
}],
schedules: vec![ScheduleEntry {
job: SCHEDULE_CANARY.into(),
version: 1,
cadence: CadenceEntry::Every { seconds: 300 },
}],
};
let mut modules = BTreeMap::new();
modules.insert("CanaryModule".to_owned(), module);
ToolContext {
uag: Uag {
schema_version: 1,
application: APP_CANARY.into(),
framework_version: FW_CANARY.into(),
modules,
routes: vec![route],
services: vec![ServiceEntry {
name: SERVICE_CANARY.into(),
deps: vec![SERVICE_DEP_CANARY.into()],
}],
pages: vec![arcature_build::uag::schema::PageEntry {
name: PAGE_CANARY.into(),
}],
},
}
}
fn call_tool(name: &str, arguments: Value) -> String {
let request = Request {
jsonrpc: JSONRPC_VERSION.to_owned(),
id: Some(RequestId::Num(1)),
method: "tools/call".to_owned(),
params: serde_json::json!({ "name": name, "arguments": arguments }),
};
let parsed = validate(request).expect("valid request");
let caps =
super::capability::CapabilitySet::from_options(&crate::cli::McpOptions::default());
let outcome = dispatch(parsed, &caps, &canary_context());
match outcome {
DispatchOutcome::Respond(resp) => serde_json::to_string(&resp).expect("serialize"),
DispatchOutcome::Skip => "SKIP".to_owned(),
}
}
fn assert_canary(tool: &str, hay: &str, needle: &str) {
assert!(
hay.contains(needle),
"no-grep invariant: tool `{tool}` did not surface canary `{needle}` from the in-memory UAG (no filesystem). response: {hay}"
);
}
#[test]
fn application_info_reads_the_uag_not_the_filesystem() {
let out = call_tool("application_info", Value::Object(Default::default()));
assert_canary("application_info", &out, APP_CANARY);
assert_canary("application_info", &out, FW_CANARY);
}
#[test]
fn routes_reads_the_uag_not_the_filesystem() {
let out = call_tool("routes", Value::Object(Default::default()));
assert_canary("routes", &out, ROUTE_NAME_CANARY);
assert_canary("routes", &out, ROUTE_PATH_CANARY);
}
#[test]
fn inspect_route_reads_the_uag_not_the_filesystem() {
let out = call_tool(
"inspect_route",
serde_json::json!({ "route_name": ROUTE_NAME_CANARY }),
);
assert_canary("inspect_route", &out, ROUTE_PATH_CANARY);
}
#[test]
fn pages_reads_the_uag_not_the_filesystem() {
let out = call_tool("pages", Value::Object(Default::default()));
assert_canary("pages", &out, PAGE_CANARY);
}
#[test]
fn services_reads_the_uag_not_the_filesystem() {
let out = call_tool("services", Value::Object(Default::default()));
assert_canary("services", &out, SERVICE_CANARY);
assert_canary("services", &out, SERVICE_DEP_CANARY);
}
#[test]
fn jobs_reads_the_uag_not_the_filesystem() {
let out = call_tool("jobs", Value::Object(Default::default()));
assert_canary("jobs", &out, JOB_CANARY);
assert_canary("jobs", &out, COMMAND_CANARY);
assert_canary("jobs", &out, SCHEDULE_CANARY);
}
#[test]
fn docs_search_reads_the_uag_protocol_coordinate_not_the_filesystem() {
let out = call_tool("docs_search", Value::Object(Default::default()));
assert_canary("docs_search", &out, FW_CANARY);
}
#[test]
fn every_registered_tool_works_with_no_filesystem() {
let caps =
super::capability::CapabilitySet::from_options(&crate::cli::McpOptions::default());
let ctx = canary_context();
for tool in super::registry::all_tools() {
let arguments = if tool.name == "inspect_route" {
serde_json::json!({ "route_name": ROUTE_NAME_CANARY })
} else {
Value::Object(Default::default())
};
let request = Request {
jsonrpc: JSONRPC_VERSION.to_owned(),
id: Some(RequestId::Num(1)),
method: "tools/call".to_owned(),
params: serde_json::json!({ "name": tool.name, "arguments": arguments }),
};
let parsed = validate(request).expect("valid request");
let outcome = dispatch(parsed, &caps, &ctx);
let resp = match outcome {
DispatchOutcome::Respond(r) => r,
DispatchOutcome::Skip => panic!("tool `{}` returned Skip", tool.name),
};
assert!(
resp.error.is_none(),
"no-grep invariant: tool `{}` returned an error with no filesystem: {:?}",
tool.name,
resp.error
);
}
}
}