> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentcat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Go reference

> Options, transports, delivery, logging, and limits of the AgentCat Go SDK.

This page describes the AgentCat Go SDK, version 2.x (`go.agentcat.com/sdk/mcpgo/v2` and `go.agentcat.com/sdk/officialsdk/v2`). For the first setup, see [Go setup](https://docs.agentcat.com/languages/go.md).

## Options

`agentcat.Track(server, projectID, options)` takes an `*agentcat.Options`. Passing `nil` uses the defaults. Every field is optional, and both modules have the same fields, except where the table says otherwise. The names that start with `Disable` turn a feature off, so the zero value keeps it on.

| Option | Default | What it does |
| - | - | - |
| `Identify` | none | Runs on every tool call and names the user of that call. The mcp-go signature is `func(ctx context.Context, request any) *UserIdentity`, and the official signature is `func(ctx context.Context, request mcp.Request) *UserIdentity`. Both get a `*mcp.CallToolRequest`. A `nil` result, or an empty `UserID`, skips identity for that call. See [Identifying users](https://docs.agentcat.com/languages/go.md#identifying-users). |
| `DisableToolCallContext` | `false` | Stops AgentCat from adding the `context` parameter to each tool. The agent explains in that parameter why it calls the tool. This is the source of intent data. |
| `CustomContextDescription` | built-in text | Replaces the description of the `context` parameter, for example with domain-specific guidance. Works only while `DisableToolCallContext` is `false`. |
| `DisableReportMissing` | `false` | Stops AgentCat from adding the `get_more_tools` tool, which lets agents report the tools that they looked for and did not find. |
| `DisableTracing` | `false` | Stops AgentCat from publishing events and from adding the `session_id` parameter. |
| `EnableAgentTracking` | `false` | Adds an `agent_id` parameter, in the `required` list of each tool schema. Each agent makes its own ID and sends it on every call. AgentCat puts it on the event as the `agentcat_agent_id` tag. A call without `agent_id` still works, and the event has no agent identity. A strict client can refuse to send such a call, so this option is off by default. |
| `ResolveSessionID` | none | Gives your own task ID for each request. AgentCat then adds no `session_id` parameter, and combines your value with the project ID into one fixed `ses_` ID. An empty string or an error makes a new session that the agent never learns. The mcp-go signature takes a `mcp.CallToolRequest`, and the official signature takes an `mcp.Request`. |
| `RedactSensitiveInformation` | none | `func(text string) string`. Changes every text value before the event leaves your server. |
| `RedactEvent` | none | `func(event *Event) (*Event, error)`. Gets the full event before `RedactSensitiveInformation`. The hook returns a changed event, or `nil` to drop it. If the hook returns an error or panics, AgentCat drops the event. |
| `EventTags` | none | Same arguments as `Identify`, returns `map[string]string`. Adds tags that you can filter on. Keys: 32 characters or fewer, from `[a-zA-Z0-9$_.:\- ]`. Values: 200 characters or fewer, with no newlines. At most 50 tags. AgentCat drops invalid entries and logs a warning. |
| `EventProperties` | none | Same arguments as `Identify`, returns `map[string]any`. Adds JSON data to each event. |
| `Exporters` | none | `map[string]ExporterConfig`. Sends events to `otlp`, `datadog`, `sentry`, or `posthog` too. See [Integrations](https://docs.agentcat.com/integrations.md). |
| `Debug` | `false` | Writes the SDK log to `~/agentcat.log`. |
| `APIBaseURL` | `https://api.agentcat.com` | The address that receives events. If empty, the SDK reads `AGENTCAT_API_URL`, then `MCPCAT_API_URL`. |
| `DisableDiagnostics` | `false` | Stops the anonymous error reports that the SDK sends to AgentCat. These reports never contain tool calls, responses, or user data. |

> [!NOTE]
>
> We recommend that you keep the defaults of `DisableToolCallContext`, `DisableReportMissing`, `DisableTracing`, and `DisableDiagnostics`, because each one feeds a part of the dashboard or helps us fix a broken install. With `DisableToolCallContext: true`, the dashboard has no intent data. With `DisableReportMissing: true`, agents cannot report missing tools. With `DisableTracing: true`, AgentCat publishes no events.

`UserIdentity` has three fields: `UserID` (a string), `UserName` (optional), and `UserData` (an optional `map[string]any`).

An empty `projectID` is valid only with at least one exporter. That is telemetry-only mode: events go to your `Exporters` and not to AgentCat. With no project ID and no exporters, `Track()` returns `agentcat.ErrEmptyProjectID`.

The SDK reads these environment variables:

| Variable | What it does |
| - | - |
| `AGENTCAT_API_URL` | The address that receives events, when `APIBaseURL` is empty. `MCPCAT_API_URL` is the old name. |
| `DISABLE_DIAGNOSTICS` | Stops the anonymous error reports, the same as `DisableDiagnostics`. |
| `DIAGNOSTICS_ENDPOINT`, `DIAGNOSTICS_TOKEN` | The address and token for a self-hosted diagnostics collector. |

The SDK does not read `AGENTCAT_PROJECT_ID`. The example programs in the SDK repository read `MCPCAT_PROJECT_ID`, which is only a convention of those examples.

## Framework and transport details

### mark3labs/mcp-go

* `Track()` takes a `*server.MCPServer`. It installs a tool-call middleware through `MCPServer.Use`, and composes with your own hooks through `GetHooks()`.
* `server.NewStreamableHTTPServer(s)` and `server.ServeStdio(s)` both work. `server.WithStateLess(true)` also works, and it still uses one `MCPServer`, so one `Track()` call is enough. `ServeStdio` stops on `SIGINT` and `SIGTERM`, and then returns, so a deferred `shutdown` runs.
* On HTTP, the request headers are in `req.Header`. On stdio, `req.Header` is empty.
* AgentCat also declares its parameters on the registered schemas of your tools, as optional properties, so `WithInputSchemaValidation` and `WithOutputSchemaValidation` accept the calls and results. Your `required` list does not change. After that, `MCPServer.ListTools()` returns `RawInputSchema` for the tool and not the structured fields.

### Official go-sdk

* `Track()` takes a `*mcp.Server` and installs receiving middleware.
* `mcp.NewStreamableHTTPHandler(factory, &mcp.StreamableHTTPOptions{Stateless: true})` calls the factory for each request, so `Track()` goes inside it. The go-sdk accepts requests at protocol version 2026-07-28 only with `Stateless: true`. Per-server state is released when the garbage collector frees the server, so a factory does not leak memory.
* A server that you create once runs with `server.Run(ctx, &mcp.StdioTransport{})`, or behind a handler that returns the same server. It needs one `Track()` call.
* On HTTP, the headers are in `req.Extra.Header`, and the checked bearer token is in `req.Extra.TokenInfo`. Both are empty on stdio.
* AgentCat reads the server name and version from a private field of `mcp.Server`. If a go-sdk release changes that field, events carry no server name until AgentCat ships an update.

### What `Track()` changes in your server

* Each tool schema gets `session_id` and `context` (and `agent_id` with `EnableAgentTracking`). AgentCat removes these values before your handler runs.
* On the first call of a task, the result starts with a text block that gives the agent its new `session_id`. For a tool with an output schema, AgentCat also puts the ID in `structuredContent`.
* If your tool already declares `session_id`, `agent_id`, or `context`, 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 with a `oneOf`, `allOf`, or `anyOf` input schema gets no parameters.
* A `session_id` that AgentCat did not issue does not join a session. The event is published without one.
* Tools that you register after `Track()` are tracked too.
* A second `Track()` on the same server does nothing, and the first configuration stands.

## Runtimes, delivery, and shutdown

`Identify`, `ResolveSessionID`, `EventTags`, and `EventProperties` run inline, on the goroutine of the tool call, so a slow hook adds time to that call. We recommend that they read the request and make no network calls. The `ctx` is the live request context, so it is already done when the client cancelled the call. A lookup that uses this `ctx` then fails, and the event goes out without that value.

AgentCat puts each event in a queue in the process and sends it in the background. Five workers send at the same time. Each attempt times out after 10 seconds, and a failed send is tried 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 and writes a warning to the log.

The SDK does not listen for signals. The queue goes out at exit when your code calls the `shutdown` function from `Track()`, or `agentcat.Shutdown(ctx)`, which is the same for the whole process. Both wait up to 5 seconds when `ctx` has no deadline. The setup page shows the pattern: the HTTP server stops first, then the queue goes out. When you give the queue its own deadline, a slow client cannot use up the time for sending. `shutdown` is safe to call more than once, but it stops the process-wide publisher, so we recommend one call at exit. `log.Fatal` and `os.Exit` skip deferred calls.

## Logging and debug mode

The log is off until you set `Debug: true`. Then the SDK writes to `~/agentcat.log`, and never to stdout, because stdout carries JSON-RPC on a stdio server. The log is shared by every AgentCat SDK on the machine, and each Go line starts with `[AgentCat]` and ends with the SDK, Go, and MCP library versions. If the process has no home directory, the SDK writes no log.

Useful log lines:

* `AgentCat setup complete | project ... | context=true report_missing=true exporters=0`: `Track()` worked.
* `Event evt_... enqueued for publishing`, then `Worker N successfully published event evt_...`: an event reached AgentCat.
* `AgentCat setup failed | ...`: `Track()` returned an error, for example for an empty project ID.
* `inject: tool "..." already declares a "session_id" parameter`: that tool is published without a session.

## Testing

The SDK has no test mode. It sends events whenever it has a project ID. If you prefer that tests send no events, you can leave `AGENTCAT_PROJECT_ID` empty in the test environment, and `Track()` then returns an error that your test setup can ignore. Another choice is to point `APIBaseURL` at a local test server.

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, and there is no separate identify event.
* The SDK publishes `mcp:tools/call` and custom events. It does not publish `initialize` or `tools/list` events.
* The `agentcat_mrtr` tag, which marks multi-round tool calls, needs go-sdk v1.7.0 or later. mcp-go has no multi-round support, so the tag never appears there.
* Integers above 2^53 keep their exact value in events only on mcp-go v0.56.0 or later.
* AgentCat cuts each string to 32 KB, each event to 100 KB, and the intent text to 2,048 characters. Objects keep at most 10 levels and 100 keys or items for each level.
* `PublishCustomEvent(server, projectID, data)` sends an event with no session, unless `data.SessionID` gives one. See [Custom events](https://docs.agentcat.com/sdk/custom-events.md).
* The old module is `github.com/mcpcat/mcpcat-go-sdk`. It keeps working, but new features go to `go.agentcat.com/sdk`. The [migration guide](https://github.com/agentcathq/agentcat-go-sdk/blob/main/MIGRATION.md) shows the steps.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.