scripts/smoke-invariants.sh asserts that the server advertises every expected tool. Its list omits two tools the server does register:
EXPECTED_TOOLS="index_repository search_graph query_graph trace_path get_code_snippet \
get_graph_schema get_architecture search_code list_projects delete_project index_status \
detect_changes manage_adr ingest_traces"
EXPECTED_TOOL_COUNT=14
check_index_coverage and compare_graphs are missing. Both are registered in src/mcp/mcp.c (the tool table, and the analysis profile allowlist). Found while working on #1941; not fixed there.
Why the check does not catch it
inv_tools_list walks the expected list and reports the names it did not find in the server's tools/list response. It never walks the other direction. A tool the server advertises but the list does not name is simply invisible, so the invariant passes while covering 14 of 16 tools and prints all 14 tools present — a number that reads like full coverage.
That is the same failure the parse-coverage work in #1941 was about: a check that reports success without having looked at everything.
Suggested fix
Add the two names and set the count to 16, then make the check symmetric — report any advertised tool the list does not name, so the next tool added cannot go unnoticed the same way. EXPECTED_TOOL_COUNT should be derived from EXPECTED_TOOLS rather than written twice.
Note that smoke-invariants.sh runs from smoke.yml, whose triggers are workflow_dispatch and pushes to qa/smoke-**, and which is documented non-gating. So this is a gap in a check that never runs on a PR.
Related: #963, #1941.
scripts/smoke-invariants.shasserts that the server advertises every expected tool. Its list omits two tools the server does register:check_index_coverageandcompare_graphsare missing. Both are registered insrc/mcp/mcp.c(the tool table, and theanalysisprofile allowlist). Found while working on #1941; not fixed there.Why the check does not catch it
inv_tools_listwalks the expected list and reports the names it did not find in the server'stools/listresponse. It never walks the other direction. A tool the server advertises but the list does not name is simply invisible, so the invariant passes while covering 14 of 16 tools and printsall 14 tools present— a number that reads like full coverage.That is the same failure the parse-coverage work in #1941 was about: a check that reports success without having looked at everything.
Suggested fix
Add the two names and set the count to 16, then make the check symmetric — report any advertised tool the list does not name, so the next tool added cannot go unnoticed the same way.
EXPECTED_TOOL_COUNTshould be derived fromEXPECTED_TOOLSrather than written twice.Note that
smoke-invariants.shruns fromsmoke.yml, whose triggers areworkflow_dispatchand pushes toqa/smoke-**, and which is documented non-gating. So this is a gap in a check that never runs on a PR.Related: #963, #1941.