From 9cd3263a89c45ca4fef383809e56b9c66e2cb8c3 Mon Sep 17 00:00:00 2001 From: Heinrich Krupp Date: Mon, 20 Apr 2026 21:05:39 +0200 Subject: [PATCH] fix(#10): emit ToolCall events for meta-tool invocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug A from #10. `handle_meta_find_tools` and `handle_meta_list_categories` previously emitted no `EventType::ToolCall`, so gateway activity driven through meta-tool dispatch never landed in `/api/metrics` and the dashboard's Tool Statistics pane stayed permanently empty for clients whose MCP flow (e.g. Claude Code via the stdio bridge on macOS) favors `mcplex_find_tools` discovery. `handle_meta_call_tool` already goes through `dispatch_real_tool`, which records under the real upstream tool name — unchanged. Each affected handler now times itself from entry and emits a ToolCall event under `tool_name = "mcplex_find_tools"` or `"mcplex_list_categories"` with `server_name = "mcplex"`. The empty-query error branch in `find_tools` also records a `success: false` event so error rates are tracked. Verified: `cargo build --release` clean, `cargo fmt --check` clean. Fixes: ModernOps888/mcplex#10 --- src/protocol/transport.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/protocol/transport.rs b/src/protocol/transport.rs index 2345004..007c5ff 100644 --- a/src/protocol/transport.rs +++ b/src/protocol/transport.rs @@ -482,6 +482,8 @@ async fn handle_meta_find_tools( request: &JsonRpcRequest, params: &ToolCallParams, ) -> JsonRpcResponse { + let start = std::time::Instant::now(); + let query = params .arguments .as_ref() @@ -491,6 +493,12 @@ async fn handle_meta_find_tools( .to_string(); if query.is_empty() { + state.metrics.record_event(EventType::ToolCall { + tool_name: "mcplex_find_tools".to_string(), + server_name: "mcplex".to_string(), + duration_ms: start.elapsed().as_millis() as u64, + success: false, + }); return JsonRpcResponse::error( request.id.clone(), error_codes::INVALID_PARAMS, @@ -547,6 +555,13 @@ async fn handle_meta_find_tools( }] }); + state.metrics.record_event(EventType::ToolCall { + tool_name: "mcplex_find_tools".to_string(), + server_name: "mcplex".to_string(), + duration_ms: start.elapsed().as_millis() as u64, + success: true, + }); + JsonRpcResponse::success(request.id.clone(), result) } @@ -598,6 +613,8 @@ async fn handle_meta_list_categories( state: &AppState, request: &JsonRpcRequest, ) -> JsonRpcResponse { + let start = std::time::Instant::now(); + let multiplexer = state.multiplexer.read().await; let all_tools = multiplexer.get_all_tools(); @@ -633,6 +650,13 @@ async fn handle_meta_list_categories( }] }); + state.metrics.record_event(EventType::ToolCall { + tool_name: "mcplex_list_categories".to_string(), + server_name: "mcplex".to_string(), + duration_ms: start.elapsed().as_millis() as u64, + success: true, + }); + JsonRpcResponse::success(request.id.clone(), result) }