From c9a32194ca0a5b614b9cdadceb0eeee71b6c200e Mon Sep 17 00:00:00 2001 From: Alex Vazquez Date: Fri, 24 Jul 2026 09:02:53 +0200 Subject: [PATCH] fix(telemetry): namespace tool_call span under :anubis_mcp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tools/call telemetry span passed Telemetry.event_server_tool_call() directly to :telemetry.span/3, bypassing Anubis.Telemetry.execute/3 — the one place that prepends the :anubis_mcp prefix every other server event gets. Consumers attaching to [:anubis_mcp, :server, :tool_call, ...] per the library's own documented convention silently never received it. Fixes #243. --- lib/anubis/server/session.ex | 2 +- .../server/session_async_dispatch_test.exs | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/anubis/server/session.ex b/lib/anubis/server/session.ex index 47bf8ab0..a75869cf 100644 --- a/lib/anubis/server/session.ex +++ b/lib/anubis/server/session.ex @@ -800,7 +800,7 @@ defmodule Anubis.Server.Session do tool_name = get_in(request, ["params", "name"]) :telemetry.span( - Telemetry.event_server_tool_call(), + [:anubis_mcp | Telemetry.event_server_tool_call()], %{tool: tool_name}, fn -> {module.handle_request(request, frame), %{tool: tool_name}} end ) diff --git a/test/anubis/server/session_async_dispatch_test.exs b/test/anubis/server/session_async_dispatch_test.exs index 33389b0e..2028936d 100644 --- a/test/anubis/server/session_async_dispatch_test.exs +++ b/test/anubis/server/session_async_dispatch_test.exs @@ -217,6 +217,31 @@ defmodule Anubis.Server.SessionAsyncDispatchTest do end end + describe "tool_call telemetry" do + test "stop event fires under the :anubis_mcp namespace", %{session: session} do + handler_id = "test-tool-call-telemetry-#{System.unique_integer([:positive])}" + test_pid = self() + + :telemetry.attach( + handler_id, + [:anubis_mcp, :server, :tool_call, :stop], + fn _event, measurements, metadata, _config -> + send(test_pid, {:tool_call_stop, measurements, metadata}) + end, + nil + ) + + on_exit(fn -> :telemetry.detach(handler_id) end) + + ctx = with_test_pid() + req = tool_call_request("echo", %{"value" => "telemetry"}, "tel-1") + assert {:ok, _encoded} = GenServer.call(session, {:mcp_request, req, ctx}, 5_000) + + assert_receive {:tool_call_stop, %{duration: duration}, %{tool: "echo"}}, 1_000 + assert is_integer(duration) and duration >= 0 + end + end + defp start_async_session(_ctx) do session_id = "async-#{System.unique_integer([:positive])}" transport_name = Registry.transport_name(AsyncDispatchTestServer, StubTransport)