/mcp-servers
Install, configure, authenticate, and troubleshoot MCP (Model Context Protocol) servers for this agent. Use when the user asks to add/install/remove an MCP server, connect a tool like Linear/Sentry/Supabase/GitHub via MCP, set up mcp.json, or when MCP tools are failing or need
$ npx -y skills add posthog/posthog --skill mcp-servers --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/mcp-servers
Context preview
The summary Claude sees to decide when to auto-load this skill.
Install, configure, authenticate, and troubleshoot MCP (Model Context Protocol) servers for this agent. Use when the user asks to add/install/remove an MCP server, connect a tool like Linear/Sentry/Supabase/GitHub via MCP, set up mcp.json, or when MCP tools are failing or need
SKILL.md
mcp-servers.SKILL.mdname: mcp-servers
description: Install, configure, authenticate, and troubleshoot MCP (Model Context Protocol) servers for this agent. Use when the user asks to add/install/remove an MCP server, connect a tool like Linear/Sentry/Supabase/GitHub via MCP, set up mcp.json, or when MCP tools are failing or need OAuth login.
MCP servers
This agent has a built-in MCP client. Servers are declared in `mcp.json`; their tools appear as `mcp_<server>_<tool>` once connected. The model can also always find and call MCP tools via a single `mcp` proxy tool (`mcp({ search: "..." })` / `mcp({ tool: "...", args }`) without their schemas ever being loaded into context, and without a `lifecycle: "lazy"` server being connected until one of its tools is actually needed — see "Context window control" below.
Config files
| File | Scope | | --- | --- | | `~/.pi/agent/mcp.json` | global (all projects) | | `<project>/.pi/mcp.json` | project-local, only honored in trusted projects |
Project entries override global entries with the same server name; project `settings` keys override global ones per key. Prefer project-local config for project-specific servers, global for personal/general-purpose ones. Create the file if it doesn't exist.
**Applying changes:** config is read at session start. After editing `mcp.json`, tell the user to run `/reload` (this re-reads config, restarts servers, and refreshes tools). You cannot run `/reload` yourself.
Config format
{
"settings": {
"toolPrefix": "mcp",
"requestTimeoutMs": 30000,
"maxRetries": 3,
"searchResultLimit": 15
},
"mcpServers": {
"<server-name>": { ... }
}
}`settings` is optional. Server names: keep them short and lowercase; they become part of tool names.
Local (stdio) server — spawned as a subprocess
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
"env": { "SOME_VAR": "literal-value" }
}
}
}- `command` is required; `transport` defaults to `"stdio"`.
- `env` values are literals merged over the parent environment — there is **no**
`${VAR}` interpolation. If a server needs a secret, ask the user to provide it or reference their shell environment by launching via a wrapper script.
- Most published servers run via `npx -y <package>` (Node) or `uvx <package>` (Python).
If unsure of the package name, search the web for "<product> MCP server".
Remote (HTTP) server
{
"mcpServers": {
"internal": {
"transport": "streamable-http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer <api-key>" }
}
}
}- `transport`: `"streamable-http"` (preferred) or `"sse"` (legacy); `url` required.
- `headers` is for static API-key auth. Never invent keys — ask the user for theirs.
Remote server with OAuth (user login in browser)
{
"mcpServers": {
"linear": {
"transport": "streamable-http",
"url": "https://mcp.linear.app/mcp",
"auth": { "type": "oauth" }
}
}
}- `auth: { "type": "oauth" }` is enough for most servers (discovery + dynamic client
registration + PKCE are automatic). Optional fields: `scope`, `clientId`, `clientSecret`, `redirectUrl` (only for pre-registered clients), `clientName`.
- After `/reload`, the first connection will fail with "Authentication required" —
that is expected. Start the login yourself with the `mcp_auth` tool (opens the user's browser), or tell the user to run `/mcp:auth <server-name>`. Tokens are stored and refreshed automatically afterwards.
- OAuth is only valid for `streamable-http`/`sse`, not `stdio`.
- If dynamic client registration is rejected (e.g. a client-name policy error), set
`"clientName"` in the `auth` object and retry.
Other per-server options
- `lifecycle`: `"lazy"` (default — starts on first use of one of its tools via the `mcp`
proxy tool, or manually with `/mcp:start <name>`) or `"eager"` (starts at session start). Use eager only for a server you want connected from the very first turn.
- `requestTimeoutMs`, `healthCheckIntervalMs`: numeric overrides, rarely needed.
- `idleTimeoutMs`: `lifecycle: "lazy"` only — auto-disconnect this many ms after the
server's last tool call. Good for servers used in bursts, e.g. `600000` (10 min).
- `description`: one-line summary shown by `mcp` search before this server has ever
connected (its real tool list isn't known yet). Set this on lazy servers so the model can find them via search before the first connection.
- `directTools`: `false` (default — all tools stay searchable-only via `mcp`), `true`
(all tools load straight into context), or an array of MCP-side tool names to keep direct while the rest stay proxy-only. Set `true` (or list specific names) only for a small server used on nearly every turn, where a `search` round-trip isn't worth it.
Context window control (the `mcp` proxy tool)
A single `mcp` tool is always available, independent of `mcp.json`:
- `mcp({ search: "keywords" })` — finds relevant tools/servers by keyword, including
ones that are not currently connected (their cached or configured `description` metadata is searched instead of connecting).
- `mcp({ tool: "<name>", args: '{"key":"value"}' })` — calls a tool by its exact name
(from search), starting its server automatically if needed. Passing a bare server name instead of a tool name connects that server and lists its tools without calling anything.
You do not need to do anything for this to work — it's automatic for every configured server. Only mention `directTools`/`idleTimeoutMs`/`description` to the user if they ask about reducing context usage or about servers not starting immediately.
Workflow for "install X MCP server"
1. Find the server's package name (stdio) or MCP endpoint URL (remote). Use web search if unsure; official docs usually show an `mcpServ
Read more
name: mcp-servers description: Install, configure, authenticate, and troubleshoot MCP (Model Context Protocol) servers for this agent. Use when the user asks to add/install/remove an MCP server, connect a tool like Linear/Sentry/Supabase/GitHub via MCP, set up mcp.json, or when MCP tools are failing or need OAuth login.
MCP servers
This agent has a built-in MCP client. Servers are declared in `mcp.json`; their tools appear as `mcp_<server>_<tool>` once connected. The model can also always find and call MCP tools via a single `mcp` proxy tool (`mcp({ search: "..." })` / `mcp({ tool: "...", args }`) without their schemas ever being loaded into context, and without a `lifecycle: "lazy"` server being connected until one of its tools is actually needed — see "Context window control" below.
Config files
| File | Scope | | --- | --- | | `~/.pi/agent/mcp.json` | global (all projects) | | `<project>/.pi/mcp.json` | project-local, only honored in trusted projects |
Project entries override global entries with the same server name; project `settings` keys override global ones per key. Prefer project-local config for project-specific servers, global for personal/general-purpose ones. Create the file if it doesn't exist.
**Applying changes:** config is read at session start. After editing `mcp.json`, tell the user to run `/reload` (this re-reads config, restarts servers, and refreshes tools). You cannot run `/reload` yourself.
Config format
{
"settings": {
"toolPrefix": "mcp",
"requestTimeoutMs": 30000,
"maxRetries": 3,
"searchResultLimit": 15
},
"mcpServers": {
"<server-name>": { ... }
}
}`settings` is optional. Server names: keep them short and lowercase; they become part of tool names.
Local (stdio) server — spawned as a subprocess
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
"env": { "SOME_VAR": "literal-value" }
}
}
}- `command` is required; `transport` defaults to `"stdio"`.
- `env` values are literals merged over the parent environment — there is **no**
`${VAR}` interpolation. If a server needs a secret, ask the user to provide it or reference their shell environment by launching via a wrapper script.
- Most published servers run via `npx -y <package>` (Node) or `uvx <package>` (Python).
If unsure of the package name, search the web for "<product> MCP server".
Remote (HTTP) server
{
"mcpServers": {
"internal": {
"transport": "streamable-http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer <api-key>" }
}
}
}- `transport`: `"streamable-http"` (preferred) or `"sse"` (legacy); `url` required.
- `headers` is for static API-key auth. Never invent keys — ask the user for theirs.
Remote server with OAuth (user login in browser)
{
"mcpServers": {
"linear": {
"transport": "streamable-http",
"url": "https://mcp.linear.app/mcp",
"auth": { "type": "oauth" }
}
}
}- `auth: { "type": "oauth" }` is enough for most servers (discovery + dynamic client
registration + PKCE are automatic). Optional fields: `scope`, `clientId`, `clientSecret`, `redirectUrl` (only for pre-registered clients), `clientName`.
- After `/reload`, the first connection will fail with "Authentication required" —
that is expected. Start the login yourself with the `mcp_auth` tool (opens the user's browser), or tell the user to run `/mcp:auth <server-name>`. Tokens are stored and refreshed automatically afterwards.
- OAuth is only valid for `streamable-http`/`sse`, not `stdio`.
- If dynamic client registration is rejected (e.g. a client-name policy error), set
`"clientName"` in the `auth` object and retry.
Other per-server options
- `lifecycle`: `"lazy"` (default — starts on first use of one of its tools via the `mcp`
proxy tool, or manually with `/mcp:start <name>`) or `"eager"` (starts at session start). Use eager only for a server you want connected from the very first turn.
- `requestTimeoutMs`, `healthCheckIntervalMs`: numeric overrides, rarely needed.
- `idleTimeoutMs`: `lifecycle: "lazy"` only — auto-disconnect this many ms after the
server's last tool call. Good for servers used in bursts, e.g. `600000` (10 min).
- `description`: one-line summary shown by `mcp` search before this server has ever
connected (its real tool list isn't known yet). Set this on lazy servers so the model can find them via search before the first connection.
- `directTools`: `false` (default — all tools stay searchable-only via `mcp`), `true`
(all tools load straight into context), or an array of MCP-side tool names to keep direct while the rest stay proxy-only. Set `true` (or list specific names) only for a small server used on nearly every turn, where a `search` round-trip isn't worth it.
Context window control (the `mcp` proxy tool)
A single `mcp` tool is always available, independent of `mcp.json`:
- `mcp({ search: "keywords" })` — finds relevant tools/servers by keyword, including
ones that are not currently connected (their cached or configured `description` metadata is searched instead of connecting).
- `mcp({ tool: "<name>", args: '{"key":"value"}' })` — calls a tool by its exact name
(from search), starting its server automatically if needed. Passing a bare server name instead of a tool name connects that server and lists its tools without calling anything.
You do not need to do anything for this to work — it's automatic for every configured server. Only mention `directTools`/`idleTimeoutMs`/`description` to the user if they ask about reducing context usage or about servers not starting immediately.
Workflow for "install X MCP server"
1. Find the server's package name (stdio) or MCP endpoint URL (remote). Use web search if unsure; official docs usually show an `mcpServ
:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.
Repo: posthog/posthog
Other skills on posthog.
- /analyzing-expensive-users
Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top spenders, expensive users, per-user LLM cost, user-level cost drivers, or patterns behind high AI observability spend.
Open skill - /creating-online-evaluations
Author continuously-running online evaluations in PostHog AI observability, grounded in real failure modes you've identified. Use when the user wants evaluations that automatically score new generations or whole traces going forward — "create an eval to catch X", "continuously
Open skill - /exploring-ai-failures
Find where an AI/LLM application is failing in production and surface the failure patterns, working from real traces. Use when someone wants to understand what's going wrong with an AI feature, find and categorize failure modes, triage errors, or investigate quality issues
Open skill - /exploring-llm-clusters
Investigate AI observability clusters — understand usage patterns in AI/LLM traffic, compare cluster behavior, compute cost/latency metrics, and drill into individual traces within clusters.
Open skill - /exploring-llm-costs
Investigate LLM spend in PostHog — total cost over time, cost by model, provider, user, trace, or custom dimension, token and cache-hit economics, and cost regressions. Use when the user asks "how much are we spending on LLMs?", "which model / user / feature is most expensive?",
Open skill - /exploring-llm-evaluations
Investigate AI observability evaluations — `hog` (deterministic code-based), `llm_judge` (LLM-prompt-based), and `sentiment` (user-message sentiment). Find existing evaluations, inspect their configuration, run them against specific generations, query individual results, and
Open skill

