Conversation IDs

Contents

A PostHog $session_id normally follows the MCP protocol session. The handshake-free 2026-07-28 revision has no protocol session, so each request gets a new session unless you add another correlation signal.

$mcp_conversation_id groups those calls by conversation. The SDK also derives $session_id from an accepted conversation handle, so PostHog session queries group the same calls.

Enabled by default

Conversation IDs are enabled by default. Calls stay correlated when the agent echoes the handle returned in tool results.

Enabling

No extra configuration is needed in either SDK:

instrument(server, posthog)

The SDK does three things:

  1. Injects an optional conversation_id argument into compatible tool schemas, with a description telling the agent to reuse the value the server returns.
  2. Creates a handle when needed and returns it on eligible tool responses as a {"conversation_id":"…"} text block.
  3. Captures the handle as $mcp_conversation_id. When the agent echoes a valid handle, the SDK derives a stable $session_id from it. Until then, existing protocol sessions remain in use.

The SDK reuses an echoed UUIDv7 that matches the handles it creates. It replaces missing or arbitrary values with a new handle to avoid merging unrelated conversations.

Event properties

{
event: "$mcp_tool_call",
properties: {
"$session_id": "ses_2a3f…", // derived from the conversation handle
"$mcp_conversation_id": "0198f2d6-…", // echoed UUIDv7 conversation handle
"$mcp_tool_name": "search_events",
...
}
}

A new request or connection made by the same agent reusing the same conversation_id shares both $mcp_conversation_id and $session_id. You can group by the conversation property in HogQL:

SQL
SELECT
properties.$mcp_conversation_id AS conversation,
arrayDistinct(groupArray(properties.$mcp_tool_name)) AS tools_called,
count() AS tool_calls
FROM events
WHERE event = '$mcp_tool_call'
AND properties.$mcp_conversation_id IS NOT NULL
AND timestamp > now() - INTERVAL 7 DAY
GROUP BY conversation
ORDER BY tool_calls DESC
LIMIT 50

Caveats

Some tools can't take the injection

The SDK cannot add conversation_id to schemas that use oneOf, allOf, anyOf, or $ref. It also skips tools without an input schema. It logs a warning and returns no handle for these tools. Use identify to group their calls by user.

A client with a stale cached tool listing does not know about the new parameter. The ttlMs setting on tools/list can extend this period.

The handle is visible in tool output

The SDK returns the handle as a {"conversation_id":"…"} text block. Clients that display raw tool results also display this JSON. The block contains data rather than an instruction because hardened clients can treat instructions in tool results as prompt injection.

The SDK preserves structured output and result metadata. Clients that only consume structured output may never see the text block, so they may not echo the handle.

Agent-controlled values

The SDK only reuses UUIDv7 values that match the shape of handles it can create. It replaces other values with a new handle. A client can still reuse a valid-looking handle across users, so don't use $mcp_conversation_id as a security boundary.

It also anchors the PostHog session

PostHog's session-level joins use $session_id. When conversation IDs are enabled, the SDK hashes the accepted conversation_id into a deterministic $session_id. Separate server instances derive the same value without shared storage.

When to skip this

If your MCP server runs over a long-lived 2025-11-25 connection that already matches your conversation boundaries, you can disable conversation IDs. Set enableConversationId: false in TypeScript or MCPAnalyticsOptions(enable_conversation_id=False) in Python to omit the injected argument and response block.

Keep it enabled when:

  • The same logical conversation crosses connections (HTTP/SSE clients that reconnect).
  • Your server handles the 2026-07-28 revision and you want more than one request in each PostHog session.

Still have questions?

Was this page useful?