selfhog-mcp
Provides tools to interact with a self-hosted PostHog instance, enabling analytics queries, feature flag management, and product insights.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@selfhog-mcp@selfhog-mcp what were the top 5 events yesterday?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
selfhog-mcp
Run PostHog's MCP server against a self-hosted PostHog instance.
Unofficial. Not affiliated with PostHog Inc. The server itself is PostHog's, from
services/mcp, used unmodified under the MIT license — see NOTICE. This project adds a container entrypoint and an installer, nothing more.Not to be confused with
@posthog/mcpon npm, which is a tracking SDK rather than a server.
PostHog's hosted MCP server at mcp.posthog.com routes only to PostHog Cloud,
so self-hosted instances cannot use it.
Install
npx @ownego/selfhog-mcp init \
--host https://posthog.example.com \
--key phx_your_personal_api_keyThat checks the instance and the key, pulls the image, starts a container that
survives reboots, waits for it to be ready, and registers it with Claude Code
at user scope — once, for every directory, not just the one you ran npx
from. Restart Claude Code afterwards.
Before doing anything else, init calls the instance's current-user API with
the key you gave it. A container's /readyz only checks its own embedded
Redis, not whether --host actually points at a reachable PostHog instance —
without this check, a typo'd host or a stale key would only surface later, as
an opaque 500 on your first tool call. A bad host or key now fails init
immediately, before anything is pulled or registered, with a message that says
which it was.
Create the key at https://<your-instance>/settings/user-api-keys?preset=mcp_server.
Requires Docker.
Flags
Flag | Effect |
| Skip |
| Skip the instance/key check. For setting up before the instance is reachable. |
| Take over a name another MCP server already holds. Without it, |
| Register under a different name. Accepted by |
Upgrading
Re-run the same init. It always re-pulls the image (unless --no-pull is
given), and recreates the container if anything it depends on has moved: a
different --host, a different SELFHOG_PORT, a different
SELFHOG_IMAGE, or a newer build of the tag it is already on. An
up-to-date container is left running untouched, so re-running init is cheap
and safe.
If the pull itself fails but the image is already present locally — offline,
or a locally built image that was never pushed — init warns that it is
proceeding with the local copy (which may be stale) instead of failing
outright. It only fails the pull outright when no usable image exists locally
either.
Related MCP server: posthog-mcp
What it runs
One long-lived container holding the PostHog MCP server and a small Redis that
the server requires. Clients talk to it over HTTP on localhost:8787, so there
is no extra process per editor session.
Your API key is not stored in the container. It lives in your MCP client's config and travels per request, so one container can serve several people, each with their own key.
Commands
Command | Effect |
| Verify, pull, start, and register. Safe to re-run. |
| Show whether the container is running, its port, and which instance it points at. |
| Remove the container. |
| Remove the container and the user-scope client registration. |
Environment variables
Variable | Effect |
| Fallback for |
| Fallback for |
| Host port to publish on (default |
| Image to run (default |
| Container name (default |
Re-running init under a name it already owns re-registers rather than skipping.
That is what makes a rotated API key take effect: the stored header is rewritten
with the current key. It works by removing the entry and adding it back, because
claude mcp add refuses a name that is already taken.
That removal is also why init checks who holds the name before it starts. Left
unchecked, re-registering would delete a server this tool never created. So if
the name belongs to something else, init stops before pulling anything, tells
you where that server points, and leaves it alone. Pass --replace to take the
name over, or --server-name to register under a different one.
Other MCP clients
init only knows how to drive Claude Code's CLI. If claude mcp add is not
available, or you use a different client, init prints a JSON block to paste
instead. It is an ordinary HTTP MCP server entry:
{
"mcpServers": {
"posthog": {
"type": "http",
"url": "http://localhost:8787/mcp",
"headers": { "Authorization": "Bearer phx_your_personal_api_key" }
}
}
}Merge it into your client's user-wide config: ~/.claude.json for Claude Code
(the same scope claude mcp add --scope user writes to), ~/.cursor/mcp.json
for Cursor, claude_desktop_config.json for Claude Desktop. The container
itself is already running by that point — only the client registration is
manual.
Memory
One container, measured on the published image:
Constraint | Behaviour |
unconstrained | ~780 MiB for its first minute, settling near 220 MiB once V8 collects |
| comfortable — 323 MiB used |
| runs, but at 253/256 MiB with no headroom |
The first-minute figure is not a requirement. Node sizes its heap to the memory it is given, so the container adapts to a cap rather than needing the peak. If you are placing it somewhere with a limit, 512 MB is a sensible floor.
Known rough edges
Some tools will fail on smaller instances. The tool catalogue is generated
from all of PostHog's products, and a self-hosted deployment does not implement
every endpoint behind them. Narrow the catalogue with the upstream query
parameters, for example ?features=flags,sql,insights or
?tools=execute-sql,dashboard-get appended to the MCP URL.
There is no version to pin to. PostHog's Docker Hub release tags have not
moved since 2023-05-17 and hobby deploys track master, so images here are
tagged sha-<posthog-commit> with a rolling latest. If you need to match your
instance exactly, pin the SHA.
Advanced
MCP_MODE=stdio runs the image as a stdio MCP server instead, for clients that
spawn the process themselves:
claude mcp add --scope user posthog -- docker run -i --rm \
-e MCP_MODE=stdio \
-e POSTHOG_API_BASE_URL=https://posthog.example.com \
-e POSTHOG_AUTH_HEADER="Bearer phx_..." \
ghcr.io/ownego/selfhog-mcp-e MCP_MODE=stdio is required: the image defaults to MCP_MODE=http, and
without the flag this command starts the HTTP daemon, never speaks JSON-RPC,
and hangs until the client gives up.
This costs a container per editor session and puts the key in the container's
environment, so init is the better default.
Releasing
Tag a version and publish a GitHub release; publish-npm.yml does the rest.
It runs the tests, checks the release tag matches package.json, installs the
packed tarball and runs the binary, then publishes.
Publishing uses npm trusted publishing over OIDC — there is no npm token in
this repository. The package's trusted publisher on npmjs.com names this
repository and publish-npm.yml; a release from anywhere else cannot publish
it. Provenance is attested to the commit the release was built from.
License
MIT — see LICENSE. NOTICE carries the bundled PostHog server's own MIT grant and attribution.
This server cannot be deployed
Maintenance
Related MCP Connectors
- SupabaseOAuthcom.supabase
MCP server for interacting with the Supabase platform
Read-only MCP access to sessions, funnels, campaigns, errors, live visitors, and anomalies.
MCP server for Statsig API - interact with Statsig's feature flags, experiments, and analytics
Query metrics, targets, entities, and team data in your Steep workspace via MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Posthog through a standardized MCP interface, providing access to Posthog's tools and services for analytics and product management.MIT
- AlicenseBqualityDmaintenanceEnables interaction with PostHog analytics platform, allowing users to list projects, create annotations, and search insights through natural language in Claude Desktop.5MIT
- AlicenseBqualityCmaintenanceEnables to manage Plane CE projects, issues, pages, modules, cycles, and more via MCP.56MIT
- AlicenseNot gradedqualityCmaintenanceEnables interaction with PostHog's product analytics platform through natural language, allowing users to manage feature flags, view errors, and access other platform features.1MIT