How do I trace my agent’s calls to MCP servers?
Rius traces your agent’s outgoing MCP tool calls automatically after you call init in Python or TypeScript, with one span for each call. Python needs nothing extra. TypeScript needs the @modelcontextprotocol/sdk package, which any agent that calls MCP tools already has. Each span records the tool name, the arguments, the result and any failure.
How it works
The MCP instrumentation ships inside the Rius SDK. It turns itself on when the MCP client library can be found: the mcp package in Python, @modelcontextprotocol/sdk in TypeScript. There is no extra to install, and Python has no mcp extra because MCP tracing is built in.
Each tool call becomes a span named execute_tool followed by the tool name. In Python the call goes through mcp.ClientSession.call_tool(). In TypeScript it goes through the MCP SDK’s Client.callTool(). Each span carries:
gen_ai.tool.name: the tool being called.input.value: the tool arguments.output.value: the tool result. In Python it prefers structured content and falls back to text blocks.mcp.method.name, set totools/call.mcp.protocol.version, the negotiated protocol version, when the session exposes it. In TypeScript this covers stdio, SSE and Streamable HTTP for a client that connects afterinit().gen_ai.agent.name, the agent that made the call: the innermost enclosing agent span you opened withobserveor the scoped span helper, otherwise your configured agent name.
The span’s OpenTelemetry kind is CLIENT. A call is marked ERROR when it raises (Python) or rejects (TypeScript), and also when the MCP result itself is flagged as an error. Rius reads is_error and isError, so both major versions of the MCP libraries work. A flagged result sets error.type to tool_error and keeps its output, because the error content is what you need to see.
When a tool call comes back asking for more input, that round records no output, since an input request carries conversation content. Its span still has mcp.method.name set to tools/call, so the round counts as an MCP tool call. The final round of the same call records its output as usual.
Argument and result values are content attributes, so the same privacy controls apply to them as to prompts. For example, RIUS_CAPTURE_CONTENT set to false strips them at export.
Set it up
-
Make sure the MCP client library is installed. In Python, the
mcppackage is already there if your agent calls MCP tools, so there is nothing to add. In TypeScript,@modelcontextprotocol/sdkmust be resolvable. If it is not in your project yet, install it:npm install @modelcontextprotocol/sdk -
Call
init()once, before you make tool calls, and keep using your MCP client as before. In Python:import rius rius.init(api_key="ri_...", service_name="my-agent") # use mcp.ClientSession exactly as beforeIn TypeScript:
import { init } from '@glassflow-ai/rius' init({ apiKey: 'ri_...', serviceName: 'my-agent' }) // use the MCP SDK's Client exactly as before -
In TypeScript,
init()patches the MCP SDK’sClientclass itself, so every client you construct afterwards is traced. In a CommonJS application, require the MCP SDK beforeinit(). The SDK patches the copies ofClientalready in your process, and a copy first required later stays untraced. -
Run the agent and open the trace. Each MCP call shows as an
execute_toolspan. The MCP integration page has the full reference, and Integrations lists the other libraries and frameworks Rius traces.
What you get
- A span for every outgoing MCP tool call, with the tool name, arguments and result, in both Python and TypeScript.
- Failures that stand out. Raised or rejected calls and error-flagged results all get ERROR status, and the error content stays visible.
- The calling agent’s name on each call, so you can see which agent used which tool.
- One waterfall across your agent and the MCP server, in Python on
mcp2.x. Trace context propagates through the call, so the server’s spans appear under your agent’sexecute_toolspan. This needs two things. The server must be instrumented, with the Rius SDK or any OpenTelemetry SDK. It must also export its traces to Rius with an API key for the same workspace as your agent. - Separate but queryable traces in the other cases. On
mcp1.x, and in TypeScript, an instrumented server’s spans still arrive, but as their own traces. The timestamps line up, but there is no single waterfall across the call.
When something else fits
This integration traces your agent calling MCP servers. If you want AI clients such as Claude Code or Codex to query your Rius telemetry, that is the separate Rius MCP server, and it works independently of this integration. If you need nested server spans in TypeScript, the SDK does not propagate context there, so you compare the two traces side by side.