@posthog/mcp weekly downloads statistics
By posthog (5 listings) · npm · MCP servers
PostHog SDK for Model Context Protocol (MCP) servers — tracks tool usage, intent, and identity
@posthog/mcp has 179,129 recorded weekly downloads on npm, a decrease of 12.7% over the past 30 days.
It ranks #383 of 2,256 tracked npm listings by weekly downloads.
Over 90 days, weekly downloads changed by +993%.
PluginStats has 543 daily observations since Apr 23, 2025; the latest is from Oct 17, 2026.
About @posthog/mcp
PostHog MCP package
Please see the main PostHog docs.
SDK usage examples and code snippets live in the official documentation so they stay up to date.
Documentation
• MCP analytics docs
Stateless & multi-pod servers
On stateless deployments the SDK mints the Mcp-Session-Id response header at initialize as a token carrying the session id and client name/version. Clients replay the header on every request, so any pod keeps $session_id and $mcp_client_name/$mcp_client_version stable with no server-side store.
A standalone $identify event fires at most once per session — at initialize (or, on a long-lived server, when the identity first appears or materially changes). Tool calls on other pods reuse the identity to stamp distinct_id/$set on every event without re-publishing $identify, so person properties are never lost. (Edge case: if identity isn't resolvable until _after_ initialize, the first $identify is suppressed too, so pre-identify anonymous events aren't aliased onto the user — see docs/ARCHITECTURE.md §4.) To drop $identify entirely, return null from beforeSend when event === '$identify'.
Streamable HTTP: set enableJsonResponse: true
The token is minted onto the Mcp-Session-Id response header from inside the initialize handler, so it only reaches the client when the transport builds the response after the handler runs — i.e. JSON mode. In SSE (streaming) mode StreamableHTTPServerTransport flushes the response headers before the handler runs, so the minted header never lands and behavior silently falls back to a session-per-request. This is a property of the transport, so it applies to every Streamable-HTTP host — set enableJsonResponse: true (and use a fresh transport per request):
If you must stream (SSE)
Set the header yourself at the HTTP layer with the exported encodeSessionId (read clientInfo from the initialize body) — the SDK decodes it either way:
Details: docs/ARCHITECTURE.md §4.
MCP TypeScript SDK v2
instrument() works on both SDK majors — @modelcontextprotocol/sdk v1 and @modelcontextprotocol/{core,server,client} v2 — and on both the high-level McpServer and the low-level Server. Shapes are detected at runtime, so neither major is a dependency here.
Sessions and client identity on a v2 server
Protocol revision is a property of each request, not of the server: a v2 server serves both 2025-11-25 and 2026-07-28 traffic, and the SDK is instrumented once for both.
• On 2026-07-28 there is no initialize and no session header — the revision removed protocol-level sessions, and this SDK will not mint one. Session correlation therefore comes from enableConversationId, which is on by default. Without it every request is its own $session_id. The get_more_tools and send_feedback virtual tools also use this handle, including calls handled by a fresh server instance. • On 2025-11-25, the session id and the client's name and version are exchanged once at initialize. If your server builds a fresh McpServer per HTTP request — which createMcpHandler does by default — the instance serving a later tools/call never saw that handshake. The SDK bridges it by minting the Mcp-Session-Id token described above, which the client replays on every request.
**That token only reaches the client if the transport builds response headers _after_ the handler runs.** @rekog/mcp-nest with enableJsonResponse: true does; createMcpHandler's legacy leg does not, and there is no setting we can reach from inside the server. On that leg, expect $mcp_client_name and $mcp_client_version to be absent for 2025-11-25 traffic — the protocol version still arrives, because clients send it on the MCP-Protocol-Version header of every request.
Reading request headers in a callback
If your identify, intentFallback, eventProperties or beforeSend reads HTTP headers, it has to change. The two majors put the request in different places and in different shapes: v1 attaches a plain object at extra.requestInfo.headers, v2 attaches the WHATWG Request at extra.http.req, whose headers only answers to .get(). A v1-shaped read returns undefined on v2 — an identify() written that way returns null and every event goes anonymous.
The SDK hands your callback whatever the MCP SDK handed it, unchanged; it does not fake a v1 shape on v2, because a partially synthesised requestInfo is a more convincing lie than an absent one. Read headers through the exported helper instead, which handles both majors, lowercases keys, and duck-types Headers so it also works on edge runtimes:
What $mcp_intent records, and how to turn it off
context defaults to on: the SDK adds a context parameter to every tool it advertises, asks the agent to say why it is calling, and records the answer as $mcp_intent. It is stripped before your tool runs wherever the SDK can confirm the parameter is its own.
On a server that builds a fresh instance per HTTP request — createMcpHandler, or @rekog/mcp-nest in its stateless mode — that confirmation is not available: ownership is learned while serving tools/list, and the instance handling a tools/call never served one. There the SDK records the argument but does not strip it, because deleting an argument your tool declared would cost you the call, while an extra key usually costs nothing.
What matters is instance lifetime, not statelessness. A server that is stateless at the transport (sessionIdGenerator: undefined) but keeps one long-lived server object learns ownership from the first tools/list and keeps it, so none of the above applies to it.…
Description from the npm listing.
- posthog
- mcp
- model-context-protocol
- analytics
- llm
Charts
Images: 30d · 1y · all time · 1600×900 dark
Adoption over time
7/30/90-day growth
Listing placement
Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.
Each band is one page of 20. Weekly downloads on a log scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.
Recent observations
Full history (543)Similar npm MCP servers plugins
All 20 @posthog/mcp alternativesData source
Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.
Listing: https://www.npmjs.com/package/@posthog/mcp. First seen Oct 16, 2026; last successful collection Oct 19, 2026. See the methodology.