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

# PostHog (MCP)

> Connect PostHog's hosted MCP server so OpenSRE can query analytics, feature flags, error tracking, and HogQL

## Overview

OpenSRE connects to PostHog’s hosted [Model Context Protocol (MCP)](https://posthog.com/docs/model-context-protocol) server. The agent can call PostHog products — product analytics, feature flags, error tracking, experiments, surveys, and HogQL — through MCP tools.

This is separate from the [PostHog REST integration](/docs/integrations/monitoring/posthog), which only stores project credentials for the REST API. Configure REST with `opensre integrations setup posthog`.

## Prerequisites

* A PostHog account (US or EU — the hosted server routes you automatically)
* A PostHog **personal API key** created with the **MCP Server** preset. See [PostHog personal API keys](https://posthog.com/docs/api/personal-api-keys).

<Info>
  OpenSRE defaults to **read-only** access (`x-posthog-read-only: true`) so the agent cannot mutate your PostHog project. Set `POSTHOG_MCP_READ_ONLY=false` only if you explicitly want the agent to perform writes.
</Info>

## Setup

### Option 1: Interactive CLI

```bash theme={null}
opensre integrations setup posthog_mcp
opensre integrations verify posthog_mcp
```

Or run `opensre integrations setup` and select **PostHog (MCP)**. Paste your personal API key. Setup uses the hosted Streamable HTTP transport; keep the default URL unless you have a reason to change it. For a local server, set `POSTHOG_MCP_MODE=stdio` (see below).

### Option 2: Environment variables

```bash theme={null}
POSTHOG_MCP_MODE=streamable-http
POSTHOG_MCP_URL=https://mcp.posthog.com/mcp
POSTHOG_MCP_AUTH_TOKEN=phx_your_personal_api_key
POSTHOG_MCP_PROJECT_ID=12345          # optional, scope to one project
POSTHOG_MCP_ORGANIZATION_ID=          # optional, scope to one organization
POSTHOG_MCP_FEATURES=                 # optional, comma-separated feature filter
POSTHOG_MCP_READ_ONLY=true            # optional, default true
```

| Variable                      | Default                       | Description                                                          |
| ----------------------------- | ----------------------------- | -------------------------------------------------------------------- |
| `POSTHOG_MCP_AUTH_TOKEN`      | —                             | **Required** (hosted). Personal API key with the `MCP Server` preset |
| `POSTHOG_MCP_URL`             | `https://mcp.posthog.com/mcp` | MCP server URL (use `https://mcp-eu.posthog.com/mcp` to pin EU)      |
| `POSTHOG_MCP_MODE`            | `streamable-http`             | Transport: `streamable-http`, `sse`, or `stdio`                      |
| `POSTHOG_MCP_PROJECT_ID`      | —                             | Scope tools to a specific PostHog project                            |
| `POSTHOG_MCP_ORGANIZATION_ID` | —                             | Scope tools to a specific organization                               |
| `POSTHOG_MCP_FEATURES`        | —                             | Comma-separated feature filter (e.g. `flags,error-tracking`)         |
| `POSTHOG_MCP_READ_ONLY`       | `true`                        | Send the read-only header so the agent cannot mutate PostHog         |
| `POSTHOG_MCP_COMMAND`         | —                             | Command to launch a local MCP server (`stdio` mode only)             |
| `POSTHOG_MCP_ARGS`            | —                             | Arguments for the local MCP command (`stdio` mode only)              |

Local PostHog MCP server via `stdio`:

```bash theme={null}
POSTHOG_MCP_MODE=stdio
POSTHOG_MCP_COMMAND=npx
POSTHOG_MCP_ARGS=-y @posthog/mcp-server@latest
POSTHOG_MCP_AUTH_TOKEN=phx_your_personal_api_key
```

### Option 3: Persistent store

```json theme={null}
{
  "version": 1,
  "integrations": [
    {
      "id": "posthog-mcp-prod",
      "service": "posthog_mcp",
      "status": "active",
      "credentials": {
        "url": "https://mcp.posthog.com/mcp",
        "mode": "streamable-http",
        "auth_token": "phx_your_personal_api_key",
        "project_id": "12345",
        "read_only": true
      }
    }
  ]
}
```

## Credentials

Use a PostHog **personal API key** created with the **MCP Server** preset. See [PostHog personal API keys](https://posthog.com/docs/api/personal-api-keys).

Set it as `POSTHOG_MCP_AUTH_TOKEN` (or paste it during interactive setup). Optionally scope with `POSTHOG_MCP_PROJECT_ID` and `POSTHOG_MCP_ORGANIZATION_ID`.

## Tools

| Tool                 | What it does                                                                                        |
| -------------------- | --------------------------------------------------------------------------------------------------- |
| `list_posthog_tools` | List tools the connected PostHog MCP server exposes (compact, filterable)                           |
| `call_posthog_tool`  | Call a named PostHog MCP tool (for example run a HogQL query, list feature flags, inspect an error) |

Typical flow: call `list_posthog_tools` first, then `call_posthog_tool` with the chosen name and arguments.

The hosted PostHog MCP server exposes a large vendor catalog of tools (often 240+), each with a full input schema. Returning all of them at once exceeds most model context windows, so `list_posthog_tools` returns a **compact, bounded listing** — names plus short descriptions, without schemas.

| Tip             | Detail                                                                                                                                                                          |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Narrow the list | Pass `name_filter` (space- or comma-separated terms, e.g. `"events query sql"`)                                                                                                 |
| Fetch schemas   | Pass `include_schema=true` on a narrowed list for the tool you intend to call                                                                                                   |
| Query events    | Use `call_posthog_tool` with `tool_name="execute-sql"` and a HogQL query (e.g. `SELECT event, count() FROM events WHERE ... GROUP BY event`). There is no `search_events` tool. |

## Verify

```bash theme={null}
opensre integrations verify posthog_mcp
```

A successful check connects to the MCP server and reports how many tools it discovered.

## Troubleshooting

| Symptom                             | Fix                                                                                 |
| ----------------------------------- | ----------------------------------------------------------------------------------- |
| Missing or invalid personal API key | Use a key created with the `MCP Server` preset                                      |
| Blocked outbound HTTPS              | Confirm reachability to `mcp.posthog.com` (or `mcp-eu.posthog.com` if pinned to EU) |

## Security

OpenSRE defaults to **read-only** access (`x-posthog-read-only: true`) so the agent cannot mutate your PostHog project. Set `POSTHOG_MCP_READ_ONLY=false` only if you explicitly want the agent to perform writes.
A successful check connects to the MCP server and reports how many tools it discovered. If it fails, the most common cause is a missing or invalid personal API key — confirm the key was created with the `MCP Server` preset and that outbound HTTPS to `mcp.posthog.com` is allowed.

## Metric report (scheduled)

Deliver a per-metric PostHog analytics pulse to Telegram, Slack, or Rocket.Chat, on demand or on a schedule — coworker-style digests (what moved and why it matters), not a raw dashboard dump. Slack delivery needs a bot token (a webhook alone cannot honor `--chat-id`). This uses the headless **summarizing-posthog-analytics** skill path (schema discovery, then one bounded HogQL query per metric), not generic `opensre cron` kinds. It requires the PostHog **MCP** integration above — the REST `posthog` integration alone cannot serve it.

| Command                                                                      | What it does                                         |
| ---------------------------------------------------------------------------- | ---------------------------------------------------- |
| `opensre posthog report run`                                                 | Run once and print the per-metric report to stdout   |
| `opensre posthog report run --period 30d --metrics "active users,pageviews"` | Run once for a custom window and metric focus        |
| `opensre posthog report schedule add`                                        | Schedule recurring delivery (cron + provider + chat) |
| `opensre posthog report schedule list`                                       | List PostHog report schedules                        |
| `opensre posthog report schedule run TASK_ID`                                | Run a scheduled report immediately                   |
| `opensre posthog report schedule remove TASK_ID`                             | Remove a schedule                                    |

Example — every Monday at 08:00 London time to Telegram:

```bash theme={null}
opensre posthog report schedule add \
  --cron "0 8 * * mon" \
  --tz Europe/London \
  --provider telegram \
  --chat-id "-1001234567890" \
  --period 7d
```

Example — same schedule to a Slack channel (`C…` member/channel id):

```bash theme={null}
opensre posthog report schedule add \
  --cron "0 8 * * mon" \
  --tz Europe/London \
  --provider slack \
  --chat-id C0123ABCD \
  --period 7d
```

Slack delivery needs `SLACK_BOT_TOKEN`. A `SLACK_WEBHOOK_URL` alone will not work here: a webhook always posts to the one channel it was created for, so it cannot honour `--chat-id`.

`--period` accepts a relative window (`24h`, `7d`, `30d`; default `7d`). Optional `--metrics` narrows the report to a comma-separated set instead of the default metric set.

The gateway daemon picks up scheduled reports automatically when it is running. If the LLM is unavailable, the run fails with an error (no deterministic fallback).

<Note>
  The report compares the current window against the previous comparable window per metric. Real zeros are reported as zeros; failed queries are called out as failures — never silently widened or fabricated, and never presented as zero when the query did not run.
</Note>
