
Implementing MCP Tools
FreeStreamline PostHog API endpoint exposure as MCP tools.
Free · Opens the source repo
What Implementing MCP Tools does
The Implementing MCP Tools skill is designed for developers working with PostHog who need to expose product API endpoints as MCP tools. This skill provides a comprehensive guide that walks users through the entire process, from creating new API endpoints to updating existing ones, defining MCP tools, and writing serializers with appropriate descriptions. It covers the necessary steps to ensure that the backend is correctly configured before generating YAML definitions for the tools, which is critical for the tools to function correctly.
The workflow begins with scaffolding a starter YAML file that defines the operations for the product. Users can easily configure this YAML by enabling tools, adding scopes, and providing annotations and descriptions. The skill emphasizes the importance of ensuring that the backend is properly set up, including explicit field types in serializers and correct request validation in ViewSet methods. This ensures that the generated tools have accurate schemas, which is essential for effective agent interaction.
This skill is particularly useful for developers who are responsible for integrating new API capabilities into PostHog and want to ensure that these capabilities are accessible to agents. By following the guidelines provided, users can create atomic CRUD operations that agents can utilize to perform basic actions, such as listing features or retrieving data by ID. The skill also includes best practices for naming conventions and validation rules to maintain consistency and prevent errors during the build process.
Overall, the Implementing MCP Tools skill is a valuable resource for developers looking to enhance their PostHog product with agent-accessible tools, ensuring a smooth integration process and accurate tool generation.
When to use it
Use this skill when you need to create or update API endpoints in PostHog that should be accessible to agents as MCP tools.
When not to use it
This skill is not suitable for users looking for high-level workflows or complex integrations, as it focuses on basic CRUD operations and atomic capabilities.
What you can build with it
Creating a New API Endpoint
When adding a new API endpoint to PostHog, use this skill to ensure it's agent-accessible by defining it as an MCP tool.
Updating Existing Tools
If you need to modify existing API endpoints, this skill guides you through updating the corresponding YAML definitions and regenerating tools.
Ensuring Backend Compliance
Before exposing new tools, verify that your Django backend meets the necessary requirements for accurate tool generation.
How to install Implementing MCP Tools
View source1. Install with the skills CLI
npx skills add posthog/posthog/implementing-mcp-tools --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by posthogImplementing MCP tools
Read the full guide at docs/published/handbook/engineering/ai/implementing-mcp-tools.md.
Quick workflow
# 1. Scaffold a starter YAML with all operations disabled.
# --product discovers endpoints via their x-product attribution.
# ViewSets in products/<name>/backend/ are auto-attributed via module
# path. ViewSets elsewhere need
# @extend_schema(extensions={"x-product": "<product>"}).
pnpm --filter=@posthog/mcp run scaffold-yaml -- --product your_product \
--output ../../products/your_product/mcp/tools.yaml
# 2. Configure the YAML — enable tools, add scopes, annotations, descriptions
# Place in products/<product>/mcp/*.yaml (preferred) or services/mcp/definitions/*.yaml
# 3. Add a HogQL system table in posthog/hogql/database/schema/system.py
# and a model reference in products/posthog_ai/skills/querying-posthog-data/references/
# 4. Generate handlers and schemas
hogli build:openapi
Before you scaffold: fix the backend first
The codegen pipeline can only generate correct tools if the Django backend exposes correct types. Read the type system guide for the full picture.
Before scaffolding YAML, verify:
- Serializers have explicit field types and
help_text— these flow all the way to Zod.describe()in the generated tool. Missing descriptions = agents guessing at parameters. UseListField(child=serializers.CharField())instead of bareListField(), and@extend_schema_field(PydanticModel)onJSONFieldsubclasses to get typed Zod output (seeproducts/alerts/backend/api/alert.pyfor the pattern). - Plain
ViewSetmethods have@extend_schema(request=...)— without it, drf-spectacular can't discover the request body and the generated tool getsz.object({})(zero parameters).ModelViewSetwith aserializer_classis fine; plainViewSetwith manual validation is not. - Query parameters use
@validated_requestor@extend_schemawith a query serializer — otherwise boolean and array query params may produce type mismatches in the generated code.
If a generated tool has an empty or wrong schema, the fix is almost always on the Django side,
not in the YAML config.
For a full audit checklist and before/after examples, use the improving-drf-endpoints skill.
When to add MCP tools
When a product exposes API endpoints that agents should be able to call. MCP tools are atomic capabilities (list, get, create, update, delete) — not workflows.
If you're adding a new endpoint, check whether it should be agent-accessible. If yes, add a YAML definition and generate the tool.
Tool design
Tools should be basic capabilities — atomic CRUD operations and simple actions. Agents compose these primitives into higher-level workflows.
Good: "List feature flags", "Get experiment by ID", "Create a survey". Bad: "Search for session recordings of an experiment" — bundles multiple concerns.
Tool naming constraints
Tool names and feature identifiers are validated at build time and in CI. Violations fail the build.
Tool names
- Format: lowercase kebab-case — only
[a-z0-9-], no leading/trailing hyphens - Length: 52 characters or fewer
- Convention:
domain-action, e.g.cohorts-create,dashboard-get,feature-flags-list
Feature identifiers
- Format: lowercase snake*case — only
[a-z0-9*], must start with a letter - Convention: should match the product folder name, e.g.
error_tracking,feature_flags
Why 52 characters?
MCP clients enforce different limits on tool names. The 52-char limit is the safe zone that works across all known clients:
| Client | Limit | Notes |
|---|---|---|
| MCP spec (draft) | 1–128 chars, [A-Za-z0-9_\-.] | Official recommendation, not enforced |
| Claude Code | 64 chars | Hard limit; prefixes tool names with mcp____ |
| Cursor | 60 chars combined | server_name + tool_name; tools over this are silently filtered |
| OpenAI API | ^[a-zA-Z0-9_-]+$, 64 chars | No dots allowed |
With the server name "posthog" (7 chars) plus a separator, tool names must stay at or below 52 characters to fit within Cursor's 60-char combined limit.
CI enforcement
pnpm --filter=@posthog/mcp lint-tool-names— validates length and pattern for YAML and JSON definitions- A vitest test validates all runtime
TOOL_MAPandGENERATED_TOOL_MAPentries
YAML definitions
YAML files configure which operations are exposed as MCP tools. See existing definitions for patterns:
products/<product>/mcp/*.yaml— preferred, keeps config close to the codeservices/mcp/definitions/*.yaml— fallback for functionality without a product folder
The build pipeline discovers YAML files from both paths.
Key fields
category: Human readable name
feature: snake_case_name # should match the product folder name (used for runtime filtering)
url_prefix: /path # frontend app route, used for enrich_url links
tools:
your-tool-name: # kebab-case
operation: operationId_from_openapi
enabled: true
scopes:
- your_product:read
annotations:
readOnly: true
destructive: false
idempotent: true
# Optional:
mcp_version: 1 # 2 for create/update/delete ops, 1 for read/list if available via HogQL
title: List things
description: >
Human-friendly description for the LLM.
list: true
enrich_url: '{id}'
param_overrides:
name:
description: Custom description for the LLM
response: # filter response fields (applied per-item on list endpoints)
include: [id, key, name] # keep only these fields (dot-path wildcards supported)
exclude: [filters.groups.*.properties] # remove these fields
# include and exclude are mutually exclusive
selectable: true # add optional `fields` param so the agent picks a subset of `include` per call
# (constrained to the allowlist); omit `fields` to return the full set. Requires `include`.
feature_flag: my-flag-key # gate this tool behind a PostHog feature flag
feature_flag_behavior: enable # 'enable' (default) or 'disable'
Unknown keys are rejected at build time (Zod .strict()).
Gating tools with feature flags
Add feature_flag to any tool (standard or query wrapper) to gate its exposure on a PostHog feature flag evaluated at MCP init time for the current user.
feature_flag_behavior: enable(default) — tool is shown only when the flag is on. Use for rolling out new tools.feature_flag_behavior: disable— tool is hidden when the flag is on. Use for sunsetting old tools.
Reusing the same flag key with both behaviors performs an atomic swap: flag on → new tool visible, old tool hidden; flag off → old tool visible, new tool hidden. Useful for A/B testing tool variations.
Flags are evaluated in parallel at init via evaluateFeatureFlags. If a flag can't be evaluated (service error, missing flag), enable-gated tools are excluded and disable-gated tools are included — fail-closed for new tools, fail-open for existing ones.
Syncing after endpoint changes
pnpm --filter=@posthog/mcp run scaffold-yaml -- --sync-all
Idempotent and non-destructive — adds new operations as enabled: false, removes stale ones.
Serializer descriptions
Descriptions flow through the entire pipeline:
Django serializer field → OpenAPI spec → Zod schema → MCP tool description
These descriptions are what agents read to understand tool parameters.
- Use
help_texton serializer fields — it becomes the OpenAPI description. - Use
param_overridesin YAML to override generated descriptions with imperative instructions. - Be specific about formats, constraints, and valid values.
- Avoid jargon that an LLM wouldn't understand without context.
HogQL system tables
Every list/get endpoint should have a corresponding HogQL system table
in posthog/hogql/database/schema/system.py.
This lets agents query data via SQL in v2 of the MCP.
Each system table must include a team_id column for data isolation.
Use mcp_version: 1 on read/list YAML tools when a system table covers the same data —
v2 agents use SQL instead.
When adding a system table, also add a model reference file
(models-<domain>.md) in products/posthog_ai/skills/querying-posthog-data/references/
and register it in products/posthog_ai/skills/querying-posthog-data/SKILL.md under Data Schema.
Two MCP versions
- v1 (legacy): all CRUD tools exposed, for clients without skill support.
- v2 (SQL-first): read/list tools replaced by HogQL, create/update/delete tools kept. For coding agents.
Control per-tool availability with mcp_version: 1/2 in the YAML definition.
Frequently asked questions about Implementing MCP Tools
Similar skills
WinMD API Search
Easily find and explore Windows desktop APIs.
WebMCPify
Transform any web app into an agent-ready platform.
Phoenix Tracing
Instrument LLM applications with OpenInference tracing.
Foundry Hosted Agent CopilotKit
Guidance for developing agentic web apps on Azure.
Power Automate Foundation
Connect AI agents to Power Automate seamlessly.
Power Automate Flow Builder
Efficiently build and deploy Power Automate flows programmatically.
