fix(cli): derive --help tool list from the MCP registry - #1370
Conversation
The top-level --help listed 14 hand-maintained tool names and omitted check_index_coverage; MCP tools/list correctly advertised all 15. The help string was a separate copy of the registry, so it drifted silently when the tool was added. Render the Tools block from the TOOLS registry itself (new cbm_mcp_tools_help_list, plus cbm_mcp_tool_count/cbm_mcp_tool_name accessors) so the two lists share one source of truth and cannot diverge again. A unit test pins the render against the registry: every advertised tool appears, cardinality matches, and lines stay 80-column safe. Fixes #1361 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…return CodeQL flagged two high-severity alerts in the previous commit: the help-list builder accumulated snprintf's return value, which is the length it WOULD have written rather than what it did. Once len passes cap, the next `cap - len` underflows to a huge size_t and the following write lands outside the buffer. That is the same class the Cypher UNWIND list builder was just fixed for in #1173, where blen advanced past a 2KB buffer the same way. The capacity computed here is in fact sufficient for the current registry, so nothing overflows today -- which makes this the more dangerous shape, not the safer one. The code was correct only by an argument made ten lines away in the cap loop, so renaming a tool or changing the wrap rule would have turned it into an out-of-bounds write with nothing in the function to notice. help_append() returns the bytes ACTUALLY written, clamped to the space left, so `len <= cap - 1` becomes a local invariant that holds no matter what the registry or the wrap column later become. Also adds the <stdarg.h> the variadic helper needs. Verified: builds clean under -Werror; --help still renders all 15 tools in registry order with the same wrapping; mcp + cli suites 437 passed, 0 failed; make -f Makefile.cbm lint-ci clean. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
CodeQL found two high-severity alerts in the first commit, and it was right — pushed 644c8fd to fix them. The help-list builder accumulated Worth noting what makes this uncomfortable: it is the same class as #1173, which merged an hour before this — there The capacity computed here happens to be sufficient for the current registry, so nothing actually overflowed. That makes it the more dangerous shape rather than the safer one: correctness depended on an argument made ten lines away in the cap loop, so renaming a tool or changing the wrap column would have converted it into an out-of-bounds write with nothing in the function to notice. Verified before pushing: builds clean under |
Problem
codebase-memory-mcp --helplisted 14 tools and omittedcheck_index_coverage— the headline feature of v0.9.1. MCPtools/listcorrectly returned all 15, and the tool itself worked (cli check_index_coverageand its--helpwere fine); only the top-level help was wrong.Root cause: the
Tools:block inprint_help()was a hand-maintained copy of the tool registry. Whencheck_index_coveragewas added toTOOLS[]insrc/mcp/mcp.c, nothing forced the help string to follow, so it drifted silently.Fix
Derive the help line from the registry instead of testing a second copy — a list that cannot drift beats a test that catches drift:
cbm_mcp_tools_help_list()renders theTools:block directly from the sameTOOLS[]array that answerstools/list, wrapped for 80-column terminals in the existing style (registry order preserved).print_help()now prints that render; the hard-coded list is gone.cbm_mcp_tool_count()/cbm_mcp_tool_name()expose the registry, following the existingcbm_mcp_tool_input_schema()precedent.mcp_tools_help_list_matches_registrypins the render against the registry: every advertised tool appears, comma cardinality equals registry count (catches truncation/duplication from a formatter bug), and lines stay under 80 columns. A future 16th tool is covered automatically — no test update needed.Verification
./build/c/codebase-memory-mcp --help | grep -c check_index_coverage→1(was 0); the help block now lists all 15 registry tools in registry order.mcpsuite green (180 passed); bind proven by temporarily re-introducing the omission in the formatter → test fails withstrstr(help, name) is NULL, restored → green.make -f Makefile.cbm lint-ciclean.Fixes #1361