feat(mcp): implement 4-pillar auto-sync, dynamic introspection, and non-blocking validation

- Pillar 1 (Runtime Auto-Sync):
  * Add sync_agent_tool_schemas() in src/mcp.rs to atomically export live tool schemas & instructions to ~/.gemini/antigravity/mcp/opencadstudio/
  * Automatically invoke sync on MCP startup (mcp::run()) and GUI automation startup (transport::listen())
  * Add --sync-mcp-schemas CLI flag in src/cli.rs and src/main.rs

- Pillar 2 (Development Hook):
  * Strengthen export_agent_tool_schemas test in src/mcp.rs to assert all schema files and instructions.md exist and are in sync on every cargo test run

- Pillar 3 (In-Band Dynamic Introspection):
  * Add 'tools' to READ_OPS in src/mcp.rs and query match in src/app/control/mod.rs
  * Enable agents to dynamically query live tool definitions and instructions via ocs_read (op: 'tools') over MCP or raw socket

- Pillar 4 (Non-Blocking Validation):
  * Set additionalProperties: true on ocs_capture schema in src/mcp.rs to prevent rigid schema rejection of emerging options
This commit is contained in:
Karim Jerbi committed 2026-10-01 17:13:24 +01:00
1 parent 3c1c1364c6
commit 9d53502b19
5 files changed
+114 -15

No files matched your search

+12
View File
@@ -464,6 +464,7 @@ impl OpenCADStudio {
| "records"
| "record_schema"
| "capabilities"
| "tools"
| "entities"
| "layers"
| "header"
@@ -527,6 +528,17 @@ impl OpenCADStudio {
Task::none(),
);
}
if op == "tools" {
return (
json!({
"ok": true,
"status": "completed",
"tools": crate::mcp::tool_definitions(),
"instructions": crate::mcp::INSTRUCTIONS
}),
Task::none(),
);
}
if op == "commands" {
let mut names = crate::command::all_registered_command_names();
let mut names: Vec<String> = names.drain(..).map(str::to_owned).collect();
+1
View File
@@ -53,6 +53,7 @@ fn listen(sender: mpsc::Sender<Envelope>) -> std::io::Result<()> {
let mut file = options.open(&path)?;
write!(file, "{descriptor}")?;
drop(file);
let _ = crate::mcp::sync_agent_tool_schemas();
let clients = Arc::new(AtomicUsize::new(0));
for stream in listener.incoming().flatten() {
if clients.fetch_add(1, Ordering::SeqCst) >= 8 {