fix(mcp): avoid default tools/list truncation

Signed-off-by: Dustin Persek <dustin.persek@protonmail.com>
This commit is contained in:
Dustin Persek
2026-07-09 11:09:53 -04:00
parent 20b115357d
commit dff70f5eb0
2 changed files with 27 additions and 7 deletions
+13 -3
View File
@@ -621,7 +621,10 @@ const char *cbm_mcp_tool_input_schema(const char *tool_name) {
return NULL;
}
static int mcp_tools_cursor_offset(const char *params_json) {
static int mcp_tools_cursor_offset(const char *params_json, bool *has_cursor_out) {
if (has_cursor_out) {
*has_cursor_out = false;
}
if (!params_json) {
return 0;
}
@@ -635,6 +638,9 @@ static int mcp_tools_cursor_offset(const char *params_json) {
yyjson_val *root = yyjson_doc_get_root(doc);
yyjson_val *cursor = root ? yyjson_obj_get(root, "cursor") : NULL;
if (cursor) {
if (has_cursor_out) {
*has_cursor_out = true;
}
offset = TOOL_COUNT;
if (yyjson_is_str(cursor)) {
const char *cursor_str = yyjson_get_str(cursor);
@@ -654,8 +660,12 @@ static int mcp_tools_cursor_offset(const char *params_json) {
}
static char *cbm_mcp_tools_list_page(const char *params_json) {
return cbm_mcp_tools_list_range(mcp_tools_cursor_offset(params_json), MCP_TOOLS_PAGE_SIZE,
true);
bool has_cursor = false;
int offset = mcp_tools_cursor_offset(params_json, &has_cursor);
if (!has_cursor) {
return cbm_mcp_tools_list();
}
return cbm_mcp_tools_list_range(offset, MCP_TOOLS_PAGE_SIZE, true);
}
/* Supported protocol versions, newest first. The server picks the newest
+14 -4
View File
@@ -586,16 +586,26 @@ TEST(server_handle_tools_list) {
PASS();
}
TEST(server_handle_tools_list_paginates) {
TEST(server_handle_tools_list_defaults_to_all_tools_and_accepts_cursor) {
cbm_mcp_server_t *srv = cbm_mcp_server_new(NULL);
char *resp =
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":200,\"method\":\"tools/list\"}");
ASSERT_NOT_NULL(resp);
ASSERT_NOT_NULL(strstr(resp, "\"id\":200"));
ASSERT_NOT_NULL(strstr(resp, "\"nextCursor\":\"8\""));
ASSERT_NULL(strstr(resp, "\"nextCursor\""));
ASSERT_NOT_NULL(strstr(resp, "index_repository"));
ASSERT_NULL(strstr(resp, "manage_adr"));
ASSERT_NOT_NULL(strstr(resp, "manage_adr"));
ASSERT_NOT_NULL(strstr(resp, "ingest_traces"));
free(resp);
resp = cbm_mcp_server_handle(
srv, "{\"jsonrpc\":\"2.0\",\"id\":202,\"method\":\"tools/list\",\"params\":{}}");
ASSERT_NOT_NULL(resp);
ASSERT_NOT_NULL(strstr(resp, "\"id\":202"));
ASSERT_NULL(strstr(resp, "\"nextCursor\""));
ASSERT_NOT_NULL(strstr(resp, "manage_adr"));
ASSERT_NOT_NULL(strstr(resp, "ingest_traces"));
free(resp);
resp = cbm_mcp_server_handle(
@@ -5026,7 +5036,7 @@ SUITE(mcp) {
RUN_TEST(server_handle_initialize);
RUN_TEST(server_handle_initialized_notification);
RUN_TEST(server_handle_tools_list);
RUN_TEST(server_handle_tools_list_paginates);
RUN_TEST(server_handle_tools_list_defaults_to_all_tools_and_accepts_cursor);
RUN_TEST(server_handle_logs_request_without_params);
RUN_TEST(server_handle_unknown_method);