From 62a7f903f252edd936337381c5c1de00671f3faa Mon Sep 17 00:00:00 2001 From: Mateusz Sych <151755914+SychPL@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:38:54 +0200 Subject: [PATCH] fix: MCP instructions name body_topology, not a list_edges tool (#729) The MCP server instructions now point to `body_topology` for finding edge points (there is no `list_edges` tool), with a test that every tool the instructions name exists. --- crates/mcp/src/server.rs | 2 +- crates/mcp/src/tests.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/mcp/src/server.rs b/crates/mcp/src/server.rs index de49f34d..3d205457 100644 --- a/crates/mcp/src/server.rs +++ b/crates/mcp/src/server.rs @@ -29,7 +29,7 @@ and degrees in expressions (internally radians), Z is up. Model like in Fusion: and dimension (`sketch.dimension {entities, value}`; values may name parameters), `sketch.finish`, then features \ (`solid.extrude {distance, operation?: new|join|cut|intersect}`, `solid.revolve`, `solid.fillet {edges: [[x,y,z] point on \ edge], radius}`, `solid.chamfer`, patterns, mirror, primitives). Use `batch` for several steps at once, \ -`list_commands` for ids and parameter docs, `inspect_design` / `measure` to verify, `list_edges` to find edge points, \ +`list_commands` for ids and parameter docs, `inspect_design` / `measure` to verify, `body_topology` to find edge points, \ `set_parameter` to drive the design and `screenshot` to look at it."; pub struct Server { diff --git a/crates/mcp/src/tests.rs b/crates/mcp/src/tests.rs index fb6bdd46..d78bf5b0 100644 --- a/crates/mcp/src/tests.rs +++ b/crates/mcp/src/tests.rs @@ -621,3 +621,18 @@ fn compact_execute_uses_one_backend_call_and_keeps_removed_bodies() { assert_eq!(b.calls, 1); assert_eq!(v, json!({"feature": 7, "name": "Combine1", "created_bodies": [], "changed_bodies": ["Base"], "removed_bodies": ["Tool"]})); } + +/// Every tool the server instructions name (a bare `snake_case` word in backticks) is a real tool. +#[test] +fn instructions_name_only_real_tools() { + let mut s = server(); + let init = call(&mut s, 1, "initialize", json!({"protocolVersion": PROTOCOL_VERSION, "capabilities": {}})); + let text = init["result"]["instructions"].as_str().unwrap().to_owned(); + let tools: Vec = tool_definitions().iter().map(|t| t["name"].as_str().unwrap().to_owned()).collect(); + let named: Vec<&str> = + text.split('`').skip(1).step_by(2).filter(|w| !w.is_empty() && w.chars().all(|c| c.is_ascii_lowercase() || c == '_')).collect(); + assert!(named.contains(&"body_topology"), "{named:?}"); + for name in named { + assert!(tools.iter().any(|t| t == name), "the instructions name `{name}`, which is not a tool"); + } +}