use crate::commands::mcp::capability::CapabilitySet;
use crate::commands::mcp::error::McpError;
use crate::commands::mcp::registry::ToolContext;
use arcature_build::uag::SCHEMA_VERSION;
use serde::Serialize;
use serde_json::Value;
#[derive(Serialize)]
struct ConfigSchemaResult {
schema_version: u32,
describes: &'static str,
uag_fields: &'static [&'static str],
route_fields: &'static [&'static str],
module_fields: &'static [&'static str],
service_fields: &'static [&'static str],
not_covered: &'static [&'static str],
}
const UAG_FIELDS: &[&str] = &[
"schema_version",
"application",
"framework_version",
"modules",
"routes",
"services",
"pages",
];
const ROUTE_FIELDS: &[&str] = &[
"method",
"path",
"name",
"handler",
"pages",
"action_fields",
"action_type",
"query_fields",
"query_type",
"query_array",
"query_string_fields",
"query_string_type",
];
const MODULE_FIELDS: &[&str] = &[
"name",
"imports",
"exports",
"controllers",
"services",
"policies",
"routes",
"listeners",
"jobs",
"commands",
"schedules",
];
const SERVICE_FIELDS: &[&str] = &["name", "deps"];
const NOT_COVERED: &[&str] = &[
"Application configuration schema (arcature.toml, environment, #[model] config) — deferred to AP2.1-6.",
"Model/database-schema/migrations entries — deferred to AP2.1-6.",
"System-check / log / trace sinks — deferred to AP2.1-7.",
];
pub(crate) fn call(
_arguments: &Value,
_capabilities: &CapabilitySet,
_context: &ToolContext,
) -> Result<Value, McpError> {
let result = ConfigSchemaResult {
schema_version: SCHEMA_VERSION,
describes: "Unified Application Graph (UAG) schema",
uag_fields: UAG_FIELDS,
route_fields: ROUTE_FIELDS,
module_fields: MODULE_FIELDS,
service_fields: SERVICE_FIELDS,
not_covered: NOT_COVERED,
};
serde_json::to_value(result).map_err(McpError::from)
}
#[cfg(test)]
mod tests {
use super::*;
use arcature_build::uag::Uag;
use std::collections::BTreeMap;
fn ctx() -> ToolContext {
ToolContext {
uag: Uag {
schema_version: 1,
application: String::new(),
framework_version: String::new(),
modules: BTreeMap::new(),
routes: vec![],
services: vec![],
pages: vec![],
},
}
}
#[test]
fn returns_schema_version_and_field_lists() {
let value = call(
&Value::Null,
&CapabilitySet::from_options(&crate::cli::McpOptions::default()),
&ctx(),
)
.expect("ok");
assert_eq!(value["schema_version"], SCHEMA_VERSION);
assert_eq!(value["describes"], "Unified Application Graph (UAG) schema");
let uag_fields = value["uag_fields"].as_array().expect("array");
assert!(uag_fields.iter().any(|f| f == "routes"));
assert!(uag_fields.iter().any(|f| f == "pages"));
}
#[test]
fn honestly_lists_deferred_coverage() {
let value = call(
&Value::Null,
&CapabilitySet::from_options(&crate::cli::McpOptions::default()),
&ctx(),
)
.expect("ok");
let not_covered = value["not_covered"].as_array().expect("array");
let joined = serde_json::to_string(not_covered).expect("serialize");
assert!(joined.contains("AP2.1-6"), "{joined}");
assert!(joined.contains("AP2.1-7"), "{joined}");
}
}