highseat/mcp records each call as an mcp_tool_call event: which tool, which assistant, whether it worked, how long it took and how many items it returned. It works with servers built on the MCP TypeScript SDK v2.
Record every call
SetHIGHSEAT_SITE and HIGHSEAT_SECRET from your site’s Installation settings on the server. Then call trackToolCalls() once, after creating the server and before registering any tool. It throws when the server already has tools, since those would go unrecorded.
waitUntil to trackToolCalls(), such as after from next/server, so each event is sent before the function stops.
What a call records
A client on the 2026-07-28 MCP protocol names itself on every request. An older client names itself only when it connects, which a stateless server never sees again, so its User-Agent stands in.
What it never records
The tool’s arguments, its result, the caller’s IP address and its user agent never leave your server, and neither do ChatGPT’s user and conversation ids. Anthropic’s and OpenAI’s directory policies forbid collecting conversation data, so a server listed there stays within them. A call comes from the assistant’s servers, not from a person, so it counts as an event on your plan and never as a visitor. Highseat acceptsmcp_tool_call only from a server holding the site secret.
Tag the links your tools return
mcpLink(url, context) adds utm_source, set to the assistant’s client, and utm_medium=mcp to a link. Highseat reads utm_medium=mcp as the AI channel, so the visit, the goals and the revenue that follow a link read as that assistant. A link that already names a utm_source is left as it is.
A link through a redirect of your own, such as /go/<slug>, carries the tags to the redirect. When the redirect records the click with track() from highseat/server, pass its url: request.url, so the event takes the tags from the URL.