Skip to content

fix(cli): derive --help tool list from the MCP registry - #1370

Merged
DeusData merged 2 commits into
mainfrom
fix/1361-help-missing-tool
Jul 31, 2026
Merged

fix(cli): derive --help tool list from the MCP registry#1370
DeusData merged 2 commits into
mainfrom
fix/1361-help-missing-tool

Conversation

@DeusData

Copy link
Copy Markdown
Owner

Problem

codebase-memory-mcp --help listed 14 tools and omitted check_index_coverage — the headline feature of v0.9.1. MCP tools/list correctly returned all 15, and the tool itself worked (cli check_index_coverage and its --help were fine); only the top-level help was wrong.

Root cause: the Tools: block in print_help() was a hand-maintained copy of the tool registry. When check_index_coverage was added to TOOLS[] in src/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 the Tools: block directly from the same TOOLS[] array that answers tools/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 existing cbm_mcp_tool_input_schema() precedent.
  • New test mcp_tools_help_list_matches_registry pins 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_coverage1 (was 0); the help block now lists all 15 registry tools in registry order.
  • mcp suite green (180 passed); bind proven by temporarily re-introducing the omission in the formatter → test fails with strstr(help, name) is NULL, restored → green.
  • make -f Makefile.cbm lint-ci clean.

Fixes #1361

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>
Comment thread src/mcp/mcp.c Fixed
Comment thread src/mcp/mcp.c Fixed
…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>
@DeusData

Copy link
Copy Markdown
Owner Author

CodeQL found two high-severity alerts in the first commit, and it was right — pushed 644c8fd to fix them.

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.

Worth noting what makes this uncomfortable: it is the same class as #1173, which merged an hour before this — there blen walked past a 2 KB buffer by exactly the same mechanism.

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. help_append() now returns the bytes actually written, clamped to the remaining space, so len <= cap - 1 is a local invariant that survives whatever the registry becomes.

Verified before pushing: builds clean under -Werror, --help still renders all 15 tools in registry order with identical wrapping, mcp + cli suites 437 passed / 0 failed, and lint-ci clean.

@DeusData
DeusData merged commit c6f564e into main Jul 31, 2026
32 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--help omits check_index_coverage from the Tools list (MCP tools/list correctly returns all 15)

2 participants