diff --git a/src/mcp/mcp.c b/src/mcp/mcp.c index f6e43b317..5bd02e4e3 100644 --- a/src/mcp/mcp.c +++ b/src/mcp/mcp.c @@ -21029,7 +21029,9 @@ char *cbm_mcp_server_handle(cbm_mcp_server_t *srv, const char *line) { cbm_clock_gettime(CLOCK_MONOTONIC, &t1); long long dur_us = ((long long)(t1.tv_sec - req_t0.tv_sec) * MCP_S_TO_US) + ((long long)(t1.tv_nsec - req_t0.tv_nsec) / MCP_MS_TO_US); - cbm_log_mcp_request(req.method, NULL, true, dur_us); + /* server/discover is the modern connect probe. -32601 stays so the + * client falls back to initialize; that miss is not an error (#2433). */ + cbm_log_mcp_request(req.method, NULL, strcmp(req.method, "server/discover") != 0, dur_us); cbm_mcp_server_request_scope_end(srv); cbm_jsonrpc_request_free(&req); return err; diff --git a/tests/test_mcp.c b/tests/test_mcp.c index 1ced07c95..80a320ca5 100644 --- a/tests/test_mcp.c +++ b/tests/test_mcp.c @@ -2463,6 +2463,59 @@ TEST(server_handle_unknown_method) { PASS(); } +/* Issue #2433: a modern client probes server/discover before initialize. + * The -32601 stays so it falls back; only that probe is logged as info. */ +TEST(server_handle_discover_probe_logs_info) { + mcp_log_buf[0] = '\0'; + CBMLogLevel prev_level = cbm_log_get_level(); + cbm_log_set_level(CBM_LOG_DEBUG); + cbm_log_set_format(CBM_LOG_FORMAT_TEXT); + cbm_log_set_sink_ex(mcp_capture_log, CBM_LOG_SINK_REPLACE); + + cbm_mcp_server_t *srv = cbm_mcp_server_new(NULL); + + char *resp = + cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"server/discover\"}"); + ASSERT_NOT_NULL(resp); + ASSERT_NOT_NULL(strstr(resp, "\"code\":-32601")); + ASSERT_NOT_NULL(strstr(resp, "Method not found")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "method=server/discover")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "level=info")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "status=ok")); + ASSERT_NULL(strstr(mcp_log_buf, "level=warn")); + ASSERT_NULL(strstr(mcp_log_buf, "status=error")); + free(resp); + + mcp_log_buf[0] = '\0'; + resp = + cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"unknown/method\"}"); + ASSERT_NOT_NULL(resp); + ASSERT_NOT_NULL(strstr(resp, "-32601")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "method=unknown/method")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "level=warn")); + ASSERT_NOT_NULL(strstr(mcp_log_buf, "status=error")); + free(resp); + + resp = cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"initialize\"," + "\"params\":{\"protocolVersion\":\"2026-07-28\"}}"); + ASSERT_NOT_NULL(resp); + ASSERT_NOT_NULL(strstr(resp, "2025-11-25")); + ASSERT_NULL(strstr(resp, "2026-07-28")); + free(resp); + + resp = + cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"resources/list\"}"); + ASSERT_NOT_NULL(resp); + ASSERT_NOT_NULL(strstr(resp, "\"resources\":[]")); + ASSERT_NULL(strstr(resp, "-32601")); + free(resp); + + cbm_mcp_server_free(srv); + cbm_log_set_sink(NULL); + cbm_log_set_level(prev_level); + PASS(); +} + /* ══════════════════════════════════════════════════════════════════ * TOOL HANDLERS (via server_handle) * ══════════════════════════════════════════════════════════════════ */ @@ -25013,6 +25066,7 @@ SUITE(mcp) { RUN_TEST(server_handle_prompts_get_validates_arguments); RUN_TEST(server_handle_logs_request_without_params); RUN_TEST(server_handle_unknown_method); + RUN_TEST(server_handle_discover_probe_logs_info); /* Server handle — edge cases */ RUN_TEST(server_handle_invalid_json);