use std::sync::Arc;
use pforge_runtime::HandlerRegistry;
use tokio::sync::RwLock;
use super::adapter::VerbToolAdapter;
use super::handlers::*;
use super::handlers_drift::DriftHandler;
use super::handlers_ops::*;
pub fn export_schema() -> serde_json::Value {
let tools: Vec<serde_json::Value> = crate::verb::verbs()
.iter()
.map(|v| {
serde_json::json!({
"name": v.mcp_name(),
"description": v.description,
"input_schema": (v.input_schema)(),
"output_schema": (v.output_schema)(),
"annotations": { "readOnlyHint": v.effects.read_only() },
})
})
.collect();
serde_json::json!({
"schema_version": "1.0",
"server": "forjar-mcp",
"version": env!("CARGO_PKG_VERSION"),
"tool_count": tools.len(),
"tools": tools,
})
}
fn register_all(reg: &mut HandlerRegistry) {
reg.register("forjar_validate", ValidateHandler);
reg.register("forjar_plan", PlanHandler);
reg.register("forjar_drift", DriftHandler);
reg.register("forjar_lint", LintHandler);
reg.register("forjar_graph", GraphHandler);
reg.register("forjar_show", ShowHandler);
reg.register("forjar_status", StatusHandler);
reg.register("forjar_trace", TraceHandler);
reg.register("forjar_anomaly", AnomalyHandler);
reg.register("forjar_remediate", RemediateHandler);
reg.register("forjar_audit", AuditHandler);
reg.register("forjar_workspace", WorkspaceHandler);
}
pub fn build_registry() -> HandlerRegistry {
let mut registry = HandlerRegistry::new();
register_all(&mut registry);
registry
}
fn build_server(registry: Arc<RwLock<HandlerRegistry>>) -> Result<pmcp::Server, String> {
let mut builder = pmcp::Server::builder()
.name("forjar-mcp")
.version(env!("CARGO_PKG_VERSION"));
for v in crate::verb::verbs() {
builder = builder.tool(
v.mcp_name(),
VerbToolAdapter {
registry: registry.clone(),
name: v.mcp_name(),
description: v.description.to_string(),
read_only: v.effects.read_only(),
input_schema: (v.input_schema)(),
},
);
}
builder
.build()
.map_err(|e| format!("cannot build MCP server: {e}"))
}
pub async fn serve() -> Result<(), String> {
let registry = Arc::new(RwLock::new(HandlerRegistry::new()));
register_all(&mut *registry.write().await);
build_server(registry)?
.run_stdio()
.await
.map_err(|e| format!("MCP server error: {e}"))
}