Skip to main content
This page describes the agentcat PyPI package, version 2.x. For the first setup, see Python setup.

Options

agentcat.track(server, project_id, options) takes an AgentCatOptions object. Every field is optional.
We recommend that you keep the defaults of enable_tool_call_context, enable_report_missing, enable_tracing, and disable_diagnostics, because each one feeds a part of the dashboard or helps us fix a broken install. With enable_tool_call_context=False, the dashboard has no intent data. With enable_report_missing=False, agents cannot report missing tools. With enable_tracing=False, AgentCat records nothing.
UserIdentity is a dataclass with three fields and no defaults: user_id (a string), user_name (a string or None), and user_data (a dict of strings or None). A project_id of None turns on telemetry-only mode: events go to your exporters and not to AgentCat. With no project ID and no exporters, the SDK sends nothing and writes a warning to the log. The SDK reads these environment variables: The SDK does not read AGENTCAT_PROJECT_ID. The setup page passes it to track() in your code.

Framework and transport details

Official mcp 2.x

  • track() accepts MCPServer from mcp.server.mcpserver and the low-level server of mcp 2.x.
  • A server that you build for each worker or tenant calls track() inside its factory. All objects share one event queue, one set of exporters, and one diagnostics client. AgentCat builds them on the first track() call, so a call for each object is cheap.
  • server.run(transport="streamable-http", stateless_http=True) serves each request with a new transport. Calls still join one session, because the session_id value travels with the agent.

Official mcp 1.x

track() accepts FastMCP from mcp.server.fastmcp and the low-level Server. FastMCP 1.x sets host, port, and stateless_http in its constructor (FastMCP("my-server", stateless_http=True)), and run() takes only the transport. A FastMCP 1.x server reports no version.

Community fastmcp

track() adds an AgentCat middleware to FastMCP 3.x and 4.x, and it needs pip install "agentcat[community]". For stateless HTTP, pass stateless_http=True to run(transport="http", ...). fastmcp 2.x is not supported: track() returns the server untracked and writes a warning that names the 2.x line.

What track() changes in your server

  • Each tool schema gets session_id and context (and agent_id with enable_agent_tracking), listed in required. AgentCat removes these values before your handler runs.
  • AgentCat removes additionalProperties: false from the input schemas that it changes.
  • On the first call of a task, the result carries a new ses_ session ID for the agent. For a tool with an output schema, the ID goes in structuredContent under mcp_session. Otherwise it is a text block.
  • If your tool already declares session_id, AgentCat leaves that parameter alone and writes a line to the log. A tool with its own session_id sends its events with no session.
  • A tool schema with oneOf, allOf, or anyOf at the top level gets no session_id or agent_id. The log names the tool.
  • Tools that you register after track() are tracked too.
  • track() returns the server and never raises.

Runtimes, delivery, and shutdown

The identify, resolve_session_id, event_tags, and event_properties hooks run in the request path, before your tool handler. A sync hook runs on a worker thread, so it does not block the event loop of your server. Each hook has 5 seconds, then AgentCat sends the event without that value. A slow hook delays the response of that call, so we recommend a cheap lookup, with your own cache when it calls a database or an API. AgentCat puts each event in a queue in the process. One background thread sends the events, with a 10-second limit for each attempt, and tries again 3 times (after 1, 2, and 4 seconds). The queue holds up to 10,000 events. When the queue is full, AgentCat drops the new event. The thread starts at the first event, so import agentcat starts nothing. At exit, AgentCat stops the sending thread and does not drain the queue. A short script can end before it sends its last events. A long-lived server is not affected. There is no handle to flush or close.

Logging and debug mode

With debug mode on, the SDK writes its log to ~/agentcat.log, and never to stdout, because stdout carries JSON-RPC on a stdio server. With debug mode off, the SDK writes no log file. Every line ends with a stamp of the agentcat, Python, mcp, and fastmcp versions, which helps when you share an excerpt. Useful log lines:
  • AgentCat setup complete | project ... | tracing=True context=True report_missing=True ...: track() worked.
  • Successfully sent event ... | mcp:tools/call | session ... | ... | <user>: an event reached AgentCat. The value after the duration is the user ID from identify.
  • Warning: Failed to track server - Unrecognized MCP server shape: the server shape is not supported. track() returns the server untracked.

Testing

When PYTEST_CURRENT_TEST or PYTEST_VERSION is set, the SDK turns off diagnostics. It still sends events when it has a project ID. If you prefer that tests send no events, you can leave AGENTCAT_PROJECT_ID unset in the test environment, or pass project_id=None. AgentCat changes your tool schemas. If your tests compare exact schemas, they see session_id and context after your own parameters.

Differences and known limits

  • identify runs on every tool call. AgentCat keeps no identity cache.
  • Each event carries the request context, with the HTTP headers. The redact_event hook can remove a header before the event leaves your server.
  • AgentCat cuts each string to 10 KB and each event to 100 KB. Objects keep at most 5 levels and 500 keys or items for each level.
  • event_properties values must be JSON-serializable, which is stricter than the TypeScript SDK.
  • publish_custom_event(server, project_id, data) sends an event with no session, unless data["session_id"] gives one. See Custom events.
  • Exporters: otlp, datadog, and sentry. The Python SDK has no PostHog exporter.
  • The old package name is mcpcat. It still works, but new features go to agentcat.