Get-Projects
If you have not yet called Get-Business-Context this conversation, call it
FIRST — it may resolve project nicknames, acronyms, or org-specific terms in
the user's request and tell you which project to pick without listing them.
Get projects that are accessible to current user.
Returns the project's id, name, workspaces and context.
Use this and prompt the user to select a project from the available projects.
Get-Events
Get events for a Mixpanel project.
Two lookup modes (mutually exclusive):
- event_names: Look up specific events by exact name. Lightweight server-side filter.
- query: Search/discover events by substring match (case-insensitive). Fetches all events.
include_details: When True, return full event metadata (tags, description, display_name, verified, hidden, dropped) for each event.
Set to false if no details are needed, to keep the response compact.
tag: Filter to events that have this tag name.
verified/hidden/dropped: Filter by metadata status (True or False).
Results are ordered verified-first. Prefer verified events (verified=True)
when choosing events that match the user's request; fall back to unverified
events only when no verified event fits. Unverified events are still returned
and may be used. Each event's verified status is included in the response
(set include_details=True for full metadata).
Edit-Event
Use contact_emails or team_contact_names for ownership. Set verified=True to
verify/approve events, hidden=True to hide from UI, dropped=True to deprecate.
Bulk-Edit-Events
Edit multiple events at once. Supports two modes:
1. Uniform fields (applied to ALL events): hidden, verified, dropped,
tags, contact_emails, team_contact_names.
2. Per-event fields (on individual events in the events list):
description, display_name.
Both modes can be combined in a single call.
Maximum 50 events per call.
List-Properties
List properties for a Mixpanel project. Returns name and type by default.
Two lookup modes (mutually exclusive):
- names: Look up specific properties by exact name (max 100).
- query: Search/discover properties by substring match (case-insensitive).
resource_type: 'Event' for event properties, 'User' for user properties, or omit for both.
events: Scope to one or more events' properties (only valid with resource_type='Event' or omitted).
attributes: Extra attributes to include in the response. Valid values:
description, display_name, hidden, dropped, sensitive, example_value, merged, tags, events.
The 'events' attribute is only allowed when 'names' is provided —
it requires a specific set of properties to look up event associations for.
It is also expensive for large projects, so only request it when needed.
tag: Filter to properties that have this tag name.
hidden/dropped/sensitive: Filter by metadata status (True or False).
Get-Property-Values
Get values for one or more properties, returned as a table.
properties: one or more property names. With a single property the
result is a one-column table of its distinct values. With multiple
Event properties the result has one column per property so you can
see which values co-occur on the same events. Prefer this over the
deprecated single-string 'property' alias.
property: DEPRECATED alias for a single-element 'properties'. Use
'properties' instead. Passing both 'property' and 'properties' with
conflicting values is an error.
result_mode (Event properties only):
- 'grouped' (default): deduped combinations of the property values
with a 'count' column, sorted by count descending.
- 'expanded': one row per event occurrence, with a 'time' column,
sorted by time. Use this to inspect raw, high-cardinality values
(e.g. free-text) alongside their co-occurring properties.
limit: maximum rows to return (default 100, max 1000). When results
are truncated a trailing note row makes the cap explicit.
from_date / to_date (YYYY-MM-DD): query window for the returned
values. For the multi-property and expanded paths this defaults to
the trailing ~30 days; for the single-property distinct-values path,
omitting it falls back to the server's default trailing window.
For Event properties, the 'event' parameter is required. User
properties support only a single property in grouped mode.
Edit-Property
Set sensitive=True for PII data classification. Set example_value to populate the example shown in Lexicon.
Bulk-Edit-Properties
Edit multiple properties at once. Supports two modes:
1. Uniform fields (applied to ALL properties): hidden, dropped, sensitive, tags.
2. Per-property fields (on individual entries in the properties list):
description, display_name, example_value.
Both modes can be combined in a single call.
All properties must share the same resource_type ("Event" or "User").
Maximum 50 properties per call.
Create-Custom-Property
Create a formula-based custom property (a computed event or user
property) in a project.
Define it with a `display_formula` expression that references named
`composed_properties` variables (_A, _B, ...). Every property used in the
formula must be mapped in `composed_properties` — use List-Properties to
find the properties to compose. `resource_type` is 'events' or 'people'.
The created property appears in Lexicon and is usable in reports.
Update-Custom-Property
Update an existing formula-based custom property.
Partial update: pass only the fields you want to change (`name`,
`description`, `display_formula`, `composed_properties`); omitted fields
keep their current value. When changing `display_formula` you must also
pass the complete `composed_properties` mapping for it. `resource_type`
is immutable. Use Get-Custom-Property first to see the current definition.
Get-Custom-Property
Get a custom property by id, including its full definition (behavior or
display_formula + composed_properties).
Use this before Update-Custom-Property to see the current definition.
Custom property ids come from List-Properties (custom properties are
named '$custom_property:<id>').
Get-Lookup-Table
Read a lookup table by id or name, or list all lookup tables.
Provide `data_group_id` or `name` to get one table's schema (columns),
row count, and a capped preview of its rows. Omit both to list every
lookup table in the project (metadata only) — useful for discovering
table names/ids. The `id` returned for each table is the `data_group_id`
you pass back to this tool or to Update-Lookup-Table.
The preview is capped by `preview_limit` (default 100) and may be smaller
than `row_count` — it is a sample, not the full table. Use it to inspect
the schema and existing values; to change rows, send only the rows you
want to add/overwrite (`upsert_rows`) or remove (`delete_keys`) to
Update-Lookup-Table, which applies the delta to the full table for you.
Create-Lookup-Table
Create a lookup table from rows.
Pass `rows` as a list of {column: value} objects; one column is the
primary key (`primary_key_column`, default "Primary Key") used to join
the table to event/user data. The table appears in Lexicon and can then
be mapped to a property in the UI.
Update-Lookup-Table
Update a lookup table with a row delta and/or edit name/description.
Send only the cells you want to change — you do NOT need to read or resend
the whole table:
- `upsert_rows`: a list of {column: value} objects to add or patch. When a
row's `primary_key_column` matches an existing row, only the columns you
send are updated and the row's other columns are kept; an unmatched key
is added as a new row. Set a column to "" to blank it; to replace all of
a row's columns, `delete_keys` it and upsert it in the same call.
- `delete_keys`: a list of primary-key values whose rows to remove. Keys
not in the table are ignored (reported back under `not_found`).
The server reads the current table, applies the delta, and re-imports the
full result, so a shrink is an explicit `delete_keys` rather than an
omission. The response includes an `update_summary`
({added, updated, deleted, not_found}) so you can confirm what landed.
Pass `name`/`description` to edit metadata. Provide at least one field.
Create-Tag
Create a tag for organizing events and properties in Lexicon.
Get-Issues
Get all data quality issues for a Mixpanel project.
Returns rich context with human-readable descriptions, event/property names,
timestamps, and variance details.
Filter by event name, property name, issue type, status, date range, or search by description.
Dismiss-Issues
Dismiss data quality issues matching natural criteria - no need to look up IDs first.
Specify what to dismiss using event names, property names, dates, and issue types.
Example: dismiss issues for the 'signup' event from November 15th, or dismiss all
type drift issues for the 'user_id' property.
IMPORTANT: If multiple issues match your criteria, you must set
dismiss_all_matching=True as a safety measure. To dismiss a single issue, provide
enough criteria to uniquely identify it (event + date, or property + date).
Rename-Tag
Rename an existing tag in a Mixpanel project.
The new name must be unique within the project (max 175 characters).
This updates all events and properties currently using this tag.
Delete-Tag
Delete a tag from a Mixpanel project.
This removes the tag from all associated events and properties.
Use with caution as this operation cannot be undone.
Get-Lexicon-URL
Return a Mixpanel Lexicon transformations detail URL for an event or property.
Provide either event or property along with project_id.
If workspace_id is omitted, the tool will choose the 'All project data' workspace.
Use this when the user wants to change event/property metadata such as
display name and description.
Get-User-Replays-Data
Get session replays information. Provide either a distinct_id (with from_date
and to_date) to find all replays for a user, OR a list of specific replay_ids
(up to 20) to analyze directly.
Optionally include event_properties (up to 5) to fetch
specific property values for each event.
Get-Query-Schema
Get the full instructions and JSON schema for building a full Mixpanel query.
Call this to learn all available fields and options for the 'report' parameter in Run-Query.
report_type: 'insights', 'funnels', 'flows', or 'retention'.
Get-Report
Retrieve a saved report's metadata from a Mixpanel project. Optionally include the report results if it's a queryable report type.
Returns report metadata (id, name, type, creator info, timestamps) but NOT the query definition.
To build a similar query, call Get-Query-Schema for the report type, then Run-Query.
Run-Query
Run a single analytics query and return its results directly.
Use this whenever the user requests a chart, a report, a metric, explore a behavior or root cause, or asks to "create a report".
Returns results to chain queries iteratively.
Only use skip_results=true when building a dashboard or you won't use the results.
Report types:
- insights: Basic report, supports different chart types, trends, and metric aggregations.
- funnels: Conversion rates between sequential events within a time window. Requires at least 2 steps.
- flows: Most frequent user paths to or from events. Shows steps before/after/between events as a sankey or paths chart.
- retention: User engagement over time. Requires exactly 2 events: an initial action and a retention action.
For very simple insights queries, use this schema as the `report` parameter:
{
"name": "string",
"metrics": [
{
"eventName": "string",
"measurement": {
"type": "basic",
"math": "total | unique"
}
}
],
"chartType": "table | line | bar",
"unit": "hour | day | week | month",
"dateRange": {
"type": "relative",
"range": {
"unit": "day | week | month",
"value": "integer"
}
}
}
Breakdowns split results by a property. Each breakdown's property fields must be nested
under a `metric` object (do NOT place `type`/`propertyName` at the breakdown's top level).
For example, to split "All Events" into individual events by the "Event Name" property:
"breakdowns": [
{"metric": {"type": "property", "propertyName": "Event Name", "resource": "event"}}
]
For more elaborated queries, with multiple events, filters, breakdowns, formulas or advanced measurements you must call Get-Query-Schema(report_type: 'insights'|'funnels'|'flows'|'retention') first to see the full schema for the `report` parameter.
Keep responses compact: prefer short date ranges (7-30 days) or coarser granularity (week/month), and avoid combining many breakdowns with fine-grained time series.
Display-Query
Display the interactive chart widget for a previously-run query.
Takes a query_id returned by Run-Query and render results in the MCP App visualization widget.
Create-Dashboard
Create a Mixpanel dashboard that combines multiple reports and text into a single view.
Use when the user asks for a "dashboard," "board", or requests to save several reports grouped together.
For a single report request, prefer Run-Query.
Requires query_id(s) from prior Run-Query calls (use skip_results=true to chain multiple queries).
Max 30 rows per dashboard.
Each row can contain up to 4 items (text cards or reports).
Row schema: {'$defs': {'ReportContent': {'additionalProperties': False, 'description': 'Report content for a dashboard row.', 'properties': {'type': {'const': 'report', 'default': 'report', 'title': 'Type', 'type': 'string'}, 'query_id': {'description': 'query_id from Run-Query', 'title': 'Query Id', 'type': 'string'}, 'name': {'maxLength': 255, 'title': 'Name', 'type': 'string'}, 'description': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'title': 'Description'}}, 'required': ['query_id', 'name'], 'title': 'ReportContent', 'type': 'object'}, 'TextContent': {'additionalProperties': False, 'description': 'Text content for a dashboard cell.', 'properties': {'type': {'const': 'text', 'default': 'text', 'title': 'Type', 'type': 'string'}, 'html_content': {'description': 'HTML content for the text card. Allowed tags: a, blockquote, br, code, em, h1, h2, h3, hr, li, mark, ol, p, s, strong, u, ul. Other tags are stripped. Do not include newlines; Each html element means a new line.', 'maxLength': 2000, 'title': 'Html Content', 'type': 'string'}}, 'required': ['html_content'], 'title': 'TextContent', 'type': 'object'}}, 'description': 'A row to add to a dashboard.', 'properties': {'contents': {'items': {'discriminator': {'mapping': {'report': '#/$defs/ReportContent', 'text': '#/$defs/TextContent'}, 'propertyName': 'type'}, 'oneOf': [{'$ref': '#/$defs/TextContent'}, {'$ref': '#/$defs/ReportContent'}]}, 'maxItems': 4, 'minItems': 1, 'title': 'Contents', 'type': 'array'}}, 'required': ['contents'], 'title': 'DashboardRow', 'type': 'object'}
Time filter schema: {'$defs': {'DateRange': {'description': 'Date range specification for dashboard time filter.', 'properties': {'type': {'description': 'Type of date range', 'enum': ['since', 'between', 'in the last'], 'title': 'Type', 'type': 'string'}, 'from': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "Start date (YYYY-MM-DD) for 'since' or 'between'", 'title': 'From'}, 'to': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "End date (YYYY-MM-DD) for 'between'", 'title': 'To'}, 'window': {'anyOf': [{'$ref': '#/$defs/TimeWindow'}, {'type': 'null'}], 'default': None, 'description': "Time window for 'in the last'"}}, 'required': ['type'], 'title': 'DateRange', 'type': 'object'}, 'TimeWindow': {'description': 'Time window for relative date ranges.', 'properties': {'unit': {'description': 'Time unit', 'enum': ['day', 'week', 'month'], 'title': 'Unit', 'type': 'string'}, 'value': {'description': 'Number of units', 'minimum': 1, 'title': 'Value', 'type': 'integer'}}, 'required': ['unit', 'value'], 'title': 'TimeWindow', 'type': 'object'}}, 'description': 'Dashboard time filter.', 'properties': {'dateRange': {'$ref': '#/$defs/DateRange', 'description': 'Date range configuration'}, 'displayText': {'description': "Human-readable display text, e.g. 'Last 30 days'", 'title': 'Displaytext', 'type': 'string'}}, 'required': ['dateRange', 'displayText'], 'title': 'DashboardTimeFilter', 'type': 'object'}
List-Dashboards
Prefer Search-Entities with entity_types=['dashboard'] instead, it offers more flexibility and efficiency.
Returns a list of all the dashboards in the project.
Use query to filter by title (case-insensitive substring match).
Get-Dashboard
Set include_layout=True to get full layout with cell/row IDs (needed for Update-Dashboard).
Layout format: [[row_id, [[cell_id, type, extra], ...]], ...].
Update-Dashboard
Call Get-Dashboard with include_layout=True first to get cell/row IDs.
- To update a report cell query_id, call Run-Query first.
- To add rows or cells, use any temporary string ID (e.g. "temp-row-1").
- To add cell in a new row, use the row temp id in the cell definition.
- For updates and deletes, use real row and cell ids from Get-Dashboard.
rows: ['<row_id>', 'add'] | ['<row_id>', 'delete']
Content: {type: 'text', html_content: 'string'} | {type: 'report', query_id: 'string', name: 'string', description: 'string'}
cells: ['<cell_id>', 'create', 'text' | 'report', {row_id: 'string', ...Content}] | ['<cell_id>', 'update', 'text' | 'report', {...Content}] | ['<cell_id>', 'delete']
Duplicate-Dashboard
Create a copy of an existing dashboard with all its contents.
Optionally override the title and description of the new dashboard.
Delete-Dashboard
Delete a dashboard. Always confirm with the user before proceeding.
Use List-Dashboards or Get-Dashboard to find the dashboard ID.
List-Feature-Flags
List and search feature flags in a project.
Filter by status, key, name, creator, or creation date.
Use Get-Feature-Flag for full configuration.
Get-Feature-Flag
Get full configuration for a specific feature flag.
Returns metadata, variants, rollout rules, experiment link, and UI URL.
For listing flags, use List-Feature-Flags.
Create-Feature-Flag
Create a feature flag in the current project.
`project_id` and `workspace_id` are auto-injected from the caller's
session — pass any int and the values you supply will be replaced
before the call reaches the server. Do not ask the user for them.
For routing (Feature Gate vs Dynamic Config vs Experiment), input
gathering, naming/keying conventions, and per-flagType variant rules,
call `Get-Feature-Flag-Setup-Guidance` first.
Mechanics: flag key is auto-derived from name when omitted; flag
starts disabled (use Update-Feature-Flag to enable, or call
Get-Feature-Flag-Lifecycle-Guidance for rollout decisions);
rolloutPercentage defaults to 1.0 (100% of targeted traffic).
Configure cohort targeting in the Mixpanel UI via the URL in the
response.
Update-Feature-Flag
Update flag configuration, status, or archive state.
For rollout / kill-switch / archival decisions — including the
staged-rollout cadence, when to use status vs rolloutPercentage,
and archive-vs-restore semantics — call
`Get-Feature-Flag-Lifecycle-Guidance` first.
All fields on `flag` are optional but at least one is required. To
configure cohort targeting or advanced rollout rules, use the
Mixpanel UI via the flag's URL (returned by Get-Feature-Flag).
Get-Feature-Flag-Setup-Guidance
Returns best-practice guidance for creating and configuring a Mixpanel
feature flag.
Call this when the user is creating, configuring, or troubleshooting a
feature-flag setup — including choosing the flag type (Feature Gate vs
Dynamic Config vs Experiment-backed), naming the flag, defining
variants, or deciding on initial rollout. The response is the canonical
setup guidance document; follow it when proposing or validating
feature-flag configuration.
No input parameters. Equivalent to reading the
`guidance://feature-flags/setup` MCP resource — provided as a tool for
clients that don't read resources directly.
Get-Feature-Flag-Lifecycle-Guidance
Returns best-practice guidance for managing a Mixpanel feature flag
after creation — staged rollout, kill-switch, hygiene/cleanup,
archival, exposure tracking, and experiment linkage.
Call this when the user is rolling out, monitoring, killing,
archiving, or cleaning up an existing feature flag, or asking about
exposure tracking or flag-to-experiment links. The response is the
canonical lifecycle guidance document; follow it when reasoning about
post-creation flag operations.
No input parameters. Equivalent to reading the
`guidance://feature-flags/lifecycle` MCP resource — provided as a tool
for clients that don't read resources directly.
List-Experiments
List and search experiments in a project.
Filter by status, name (case-insensitive substring match), creator, creation date, or tags.
Use Get-Experiment for full configuration.
Get-Experiment
Get full experiment configuration and (optionally) fresh live results.
Returns metadata, variants, metrics (with IDs, type, and direction),
cached data, and UI URL. Metric IDs are included; use List-Metrics
to find saved metrics.
Set ``compute_exposures=true`` to refresh live exposure counts and
SRM analysis (``live_srm_analysis``); set ``compute_metrics=true`` to
refresh per-metric lift/CI/p-value/significance (``live_metrics``)
and the retro A/A health-check verdict (``live_retro_aa``). These
fields are the same source of truth the in-app banner reads. Either
flag persists the refreshed cache server-side and may trigger an
auto-conclude transition. Non-fatal compute errors surface in
``live_results_errors`` (``[]`` when compute was requested but
nothing failed; ``None`` when compute wasn't requested). Setting
either flag requires a workspace; the wrapper auto-resolves the
project's global workspace when ``workspace_id`` is omitted.
To turn these fields into a ship/no-ship verdict (SRM and retro A/A
thresholds, per-metric significance, and the guardrail-regression
hard gate), call ``Get-Experiment-Results-Interpretation-Guidance``.
Create-Experiment
Create an experiment (in DRAFT status) in the current project.
For setup decisions (hypothesis writing, metric selection, sample sizing,
testing model, end condition, advanced features like CUPED/Winsorization/
multiple testing correction) call Get-Experiment-Setup-Guidance first —
it is the single source of truth for what makes a sound experiment.
`project_id` and `experiment.workspaceId` are auto-injected from the
caller's session — pass any int (or omit workspaceId) and the values
you supply will be replaced before the call reaches the server. Do
not ask the user for them or call other tools to discover them.
Mechanics (NOT best-practice advice — see setup guidance for that):
- For duration-based experiments, set endCondition="days" and endAfterDays;
for sample-size-based, set endCondition="sample_size" and sampleSize.
- Metrics: pass saved metrics via primaryMetricIds/guardrailMetricIds/
secondaryMetricIds (find IDs with List-Metrics), or define inline via
the metrics array with eventName and metricType.
- Optional `variants` array — only include when the user explicitly states
variant keys/values/splits. Otherwise the system creates a default 50/50
control/treatment flag.
- The server always runs the seven deterministic pre-launch pitfall
checks before creation, deriving most inputs (arm count, sample size,
metric counts, stats toggles) from the experiment itself. Optional
`validationContext` supplies the few externals it can't derive
(baseline rate, MDE, expected exposures, cohort size, primary-metric
measurement types). Blocker pitfalls (under-half-required exposures,
cohort too small) short-circuit the create and are surfaced as an
actionable error; warnings and fyi findings ride along on the created
experiment as `validationFindings`.
After creation, use Update-Experiment with action="launch" to start the experiment.
Update-Experiment
Update experiment configuration or manage its lifecycle.
Lifecycle actions (set action param):
- "launch": DRAFT→ACTIVE. Enables linked flag.
- "conclude": ACTIVE→CONCLUDED. Disables linked flag.
- "decide": CONCLUDED→SUCCESS/FAIL. See "decide" below.
- "archive" / "restore": soft delete / undelete.
For action="decide", pick by settings.collectionMethod (call Get-Experiment
first if unknown). shipMode rolls the linked flag as part of decide; omit it
on exposure-events experiments (returns UnsupportedCollectionMethod).
feature_flag experiments:
ship variant X → shipMode="ship_variant", variant=X
keep control → shipMode="do_not_ship" (auto: success=true)
abandon flag → shipMode="abandon" (auto: success=false, variant="abandoned")
record only → success=true|false, variant=<key> (omit shipMode)
exposure_events experiments (always omit shipMode):
ship variant X → success=true, variant=X
keep control → success=true, variant=<control_key>
abandon → success=false, variant="abandoned"
keepCohortTargeting (only with shipMode=ship_variant|do_not_ship): preserve
existing cohort restrictions instead of serving the chosen variant to 100%.
Config updates (all optional): name, description, hypothesis, metrics, settings, tags.
Metrics: Use List-Metrics to find saved metric IDs, then pass them via
primaryMetricIds/guardrailMetricIds/secondaryMetricIds. Alternatively, define inline
with the metrics array using eventName and metricType.
Field edits and launches run the seven deterministic pre-launch pitfall
checks over the *resulting* configuration (the server merges this patch
onto the stored experiment and derives most inputs from it). Optional
`validationContext` supplies the externals it can't derive (baseline
rate, MDE, expected exposures, cohort size, primary-metric measurement
types). Blockers short-circuit the update (actionable error);
warnings/fyi ride along as `validationFindings` on the updated experiment.
Explain-Experiment-Health-Check
Explain why an experiment's health check is firing — or confirm it
isn't — and recommend a next action. Supports two checks:
- `health_check_kind="srm"` — Sample Ratio Mismatch (traffic split
deviates from configured allocation). Call Get-Experiment with
compute_exposures=true first, then pass:
- p_value: liveSrmAnalysis.p_value (null when SRM can't be
computed yet — pass it as-is and the tool returns a clear
"SRM unavailable" message instead of erroring)
- live_exposures: liveExposures (variant → count); webapp emits
percentages (e.g. {control: 50}), the tool accepts either
fractions or percentages
- target_allocations: experiment.settings.srm.targetAllocations
- `health_check_kind="retro_a_a"` — pre-experiment bias (per-metric
A/B z-tests on the pre-experiment window, Bonferroni-corrected).
Call Get-Experiment with compute_metrics=true first (null when
retro A/A hasn't been computed — typical right after an
experiment starts), then pass:
- retro_aa_verdict: the `liveRetroAa` block from
Get-Experiment; carries `any_failing`, `acknowledged`, and
per-metric `results`
- metric_names: map of metric_id → display name built from
`experiment.metrics`; the summary names the affected metrics
instead of surfacing raw ids
Returns a HealthCheckDiagnosis. For SRM: signed per-variant
deviation, likely causes in most-probable-first order, recommended
action (pause / investigate exposures / restart with bot filtering
/ continue). For retro A/A: list of biased metrics, retro-A/A-
specific causes (randomization bug, context mismatch, insufficient
pre-period, natural variance), recommended action (enable CUPED /
restart with longer pre-period / acknowledge / pause). The Kohavi
(SRM) or Twyman's-Law (retro A/A) trustworthiness principle is
cited in the failing case.
Get-Experiment-Setup-Guidance
Returns best-practice guidance for designing a Mixpanel experiment before launch.
Call this when the user is creating, configuring, or troubleshooting an experiment
setup — including writing a hypothesis, picking metrics, sizing the experiment,
or choosing a testing model. The response is the canonical setup guidance
document; follow it when proposing or validating experiment configuration.
No input parameters. Equivalent to reading the `guidance://experiments/setup`
MCP resource — provided as a tool for clients that don't read resources directly.
Get-Experiment-Results-Interpretation-Guidance
Returns best-practice guidance for interpreting Mixpanel experiment results
and making ship/iterate/kill decisions.
Call this when the user is analyzing, interpreting, or making a decision based
on experiment results — including reviewing a concluded experiment, asking about
p-values, lift, SRM, or whether to ship. The response is the canonical results
interpretation document; follow it when reasoning about results.
No input parameters. Equivalent to reading the
`guidance://experiments/results-interpretation` MCP resource — provided as a
tool for clients that don't read resources directly.
Run-Experiment-Pre-Launch-Checks
Cross-references a draft experiment's configuration against a
canonical list of pre-launch pitfalls and returns a structured
PitfallReport. Call this at the **config-summary-for-approval**
step before launching an experiment — once the user has chosen
their primary metrics, baseline rate, MDE, cohort, etc. and the
agent is summarizing the configuration for sign-off.
Pitfall kinds (every one of these may appear in the returned
report):
- `pre_experiment_bias_likely` — retro A/A is enabled and a
continuous-ish metric (continuous, retention, funnel) is
configured but CUPED is off.
- `high_variance_no_winsorization` — a continuous-ish metric is
configured but Winsorization is off.
- `multiple_primaries_no_bonferroni` — two or more primaries with
no Bonferroni multiple-testing correction.
- `underpowered_duration_insufficient` — expected exposures are
less than half of the per-arm sample size required for the
configured baseline rate and MDE. Severity: blocker.
- `underpowered_duration_marginal` — expected exposures are
between half and one full per-arm required sample size.
- `cohort_too_small` — configured cohort cannot supply enough
eligible users (per-arm target × `num_arms`) for every arm to
hit its target. Pass `num_arms` for non-A/B experiments;
defaults to 2. Severity: blocker.
- `missing_guardrails` — no guardrail metrics configured.
- `hypothesis_metric_mismatch` — the hypothesis mentions an
outcome (signup, conversion, retention, revenue, etc.) that
isn't represented in any configured primary metric name.
- `primary_lacks_leading_indicator` — a retention-type primary is
configured but no conversion- or funnel-type secondary metric
is configured. Retention is lagging by construction; without a
leading-indicator secondary, the agent has no earlier evidence
to reason from while the experiment runs. Pass
`secondary_metric_types` / `secondary_metric_count` so this
pitfall can evaluate; with no secondary info supplied it
silently abstains.
Each pitfall carries a `severity` (`blocker` / `warning` / `fyi`)
and an optional `fix_action` discriminated union (`extend_duration`,
`enable_cuped`, `enable_winsorization`, `enable_bonferroni`,
`add_guardrail`, `resize_cohort_or_sample`, `review_metric_alignment`)
— the renderer pre-fills a corresponding `Update-Experiment` call
from the fix_action so the user can accept a remediation with a
single confirmation.
**Blocker prevention is a form-layer concern, not Spark's.** This
tool reports blockers so the agent can surface them prominently
in the summary, but the experiment-creation form is what actually
stops a launch when a blocker is unresolved. Don't pretend to gate
the launch yourself — quote the blocker and the recommended
fix_action, then defer to the form.
Pitfalls are returned sorted by (severity, declaration order):
blockers first, then warnings, then fyi; within a severity, the
ordering above wins so data-trust risks (pre-experiment bias,
variance inflation) surface before configuration nudges.
All inputs other than `target_sample_size` are optional — the tool
silently skips any pitfall whose inputs aren't supplied, so the
agent can call it iteratively as the user fills out fields.
Search-Prior-Experiments
Search the project's experiments store for prior tests on the same
feature, metric, or hypothesis. Returns up to ``max_matches`` ranked
matches with similarity reasons.
Pass the ``metric_ids``, ``flag_key``, and ``hypothesis`` you are
considering for the experiment you're setting up; the tool checks
whether a similar experiment has already been run so you can surface
what was learned. Provide whichever of these you have — any one is
enough to get matches, and supplying more sharpens the ranking.
Three deterministic signals are combined: metric_id overlap (Jaccard),
flag-key similarity (exact / case-insensitive / substring /
shared-token), and hypothesis-token overlap. Each match carries
``similarity_reasons`` so the agent can quote *why* a prior
experiment is relevant.
Pass ``exclude_experiment_id`` when ranking against an in-progress
draft already saved in the store to prevent the draft trivially
matching itself. ``include_archived=true`` to include archived
experiments in the candidate pool.
Describe-Cohort-Schema
Return the schema for the `definition` parameter accepted by Create-Cohort
and Update-Cohort. Call this before authoring a cohort definition for the first
time in a session so you know which fields are required for the grouped vs.
selector format.
The result has three keys:
- `definition`: the CohortDefinition JSON schema (grouped/selector union).
- `grouped_filter_types`: per-type schemas + worked examples for the
grouped format's `groups[].filters[]` entries (property / behavioral /
cohort_membership), which the base schema leaves opaque.
- `notes`: gotchas worth reading before authoring a definition.
Create-Cohort
Create a new Mixpanel cohort.
A cohort is a saved group of users matching a set of criteria. Pass a `definition` dict
matching the CohortDefinition schema (grouped or selector format).
Call Describe-Cohort-Schema first to retrieve the full JSON schema, including the
required fields per format (grouped uses a `groups[]` filters grammar; selector uses
the lower-level `behaviors{}` + compound `selector` AST for cohorts that embed
funnel or retention report behaviors).
For the grouped format, each group's `event` is the anchor cohort the filters narrow
down — almost always `{"resourceType": "cohort", "value": "$all_users"}`. To anchor
on members of an existing cohort instead, pass that cohort's integer id as `value`.
`workspace_id` is required (unlike List-Cohorts, which lists project-wide when it is
omitted).
Get-Cohort
Retrieve a Mixpanel cohort by ID.
Returns the cohort's metadata (name, description, count, is_visible, creator,
updated_at) and its definition in the AI-typed format (CohortDefinition).
Only `updated_at` (last edited) is tracked — there is no creation timestamp.
If the wire-format definition contains unmodeled clause kinds, the `definition`
field will be None, `unmodeled_clause_kinds` will list the unsupported shapes,
and `definition_raw` will contain the wire-format dict so callers can still
inspect the cohort's structure.
`workspace_id` is required (unlike List-Cohorts, which lists project-wide when it is
omitted).
List-Cohorts
List all cohorts in a Mixpanel project.
Returns a lightweight list of cohort headers (id, name, description, count).
Use the optional `query` parameter to filter by name (case-insensitive substring match).
`workspace_id` is optional here: omit it to list across the whole project, or pass one
to scope to a single workspace.
Note: `count` is frequently `null` in this list. The backend suppresses cached member
counts in non-global workspaces and in projects with sensitive/classified properties
for callers without sensitive-data access. Call Get-Cohort for an authoritative count.
For full cohort definitions, call Get-Cohort on individual cohort IDs.
Update-Cohort
Update an existing Mixpanel cohort.
All fields (name, description, definition, is_visible) are optional.
Only the provided fields will be updated; omitted fields remain unchanged.
`is_visible` toggles whether the cohort is hidden in the Mixpanel UI. Note
that the `is_visible` value in the response is derived from entity
sharing/visibility (a shared webapp serialization path) and may not reflect
the value you just set — do not rely on the returned value to confirm a
hide/unhide.
To update the cohort's filter criteria, pass a new `definition` dict matching
the CohortDefinition schema (same as Create-Cohort). Call Describe-Cohort-Schema
for the full JSON schema if you don't already have it.
`workspace_id` is required (unlike List-Cohorts, which lists project-wide when it is
omitted).
Delete-Cohort
Delete a Mixpanel cohort.
WARNING: This action is destructive and cannot be undone. Always confirm with the
user before deleting a cohort.
The webapp will prevent deletion if the cohort is used in active reports or
other dependencies, returning an actionable error message.
`workspace_id` is required (unlike List-Cohorts, which lists project-wide when it is
omitted).
List-Metrics
List all saved metrics in a project.
Returns metric IDs, names, types, descriptions, and verified status. Use before creating experiments to find reusable metrics.
For full definition: Get-Metric. To use in experiment: reference by ID.
Results are ordered verified-first. Prefer verified metrics (verified=True) when
choosing a metric that matches the user's request; fall back to unverified metrics
only when no verified metric fits. Unverified metrics are still returned and may be used.
Get-Metric
Get full definition for a saved metric.
Returns complete metric structure (events, formulas, filters, aggregation).
Use to inspect, copy, or verify metric configuration.
Create-Metric
Create a saved metric (behavior or formula) for reuse across experiments.
Types:
- "metric": Single event behavior (count, unique users, DAU, etc.)
- "formula": Combines multiple metrics with mathematical expressions
Definition schema:
{
"displayOptions": {
"chartType": "line | bar"
},
"sections": {
"events": [
{
"event": "string",
"math": "unique | total | session | dau | wau | mau",
"filters": [
[
{
"type": "string",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "equals | contains | does not equal | does not contain",
"value": "string"
},
{
"type": "string",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is set | is not set"
},
{
"type": "number_array",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is between",
"value": [
"number"
]
},
{
"type": "number",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is at least | is equal to | is not equal to | is greater than | is less than | is at most",
"value": "number"
},
{
"type": "boolean",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "true | false",
"value": "boolean"
},
{
"type": "datetime",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "was on | was before | was since",
"value": "string"
},
{
"type": "list-of-objects",
"propertyName": "string",
"resource": "event | user",
"listItemFilters": [
[
{
"type": "string",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "equals | contains | does not equal | does not contain",
"value": "string"
},
{
"type": "string",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is set | is not set"
},
{
"type": "number_array",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is between",
"value": [
"number"
]
},
{
"type": "number",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "is at least | is equal to | is not equal to | is greater than | is less than | is at most",
"value": "number"
},
{
"type": "boolean",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "true | false",
"value": "boolean"
},
{
"type": "datetime",
"propertyName": "string",
"propertyType": "string | number | boolean | datetime | list",
"resource": "event | user",
"operator": "was on | was before | was since",
"value": "string"
}
]
],
"listQuantifier": "any | all",
"listInclusion": "all | matching",
"propertyObjectKey": [
"string"
]
}
]
]
}
]
}
}
Returns metric with ID for use in Create-Experiment with primaryMetricIds.
For complex definitions, use Get-Metric on existing metrics as templates.
Update-Metric
Update saved metric's name, definition, or description.
At least one field required. Warning: affects all experiments using this metric.
Consider creating new metric to preserve original. Use Get-Metric first.
Search-Entities
Search entities in a Mixpanel project: dashboards, reports,
experiments, feature flags, metric trees, playlists, and heat maps.
query: can be empty to browse by sort order.
entity_types: set to include specific entity types.
Values: insights, funnels, flows, retention, dashboard, launch-analysis, experiments, feature-flags, metric-trees, playlists, heat-maps.
- Use Get-Report to fetch full details for insights, funnels, flows, and retention types.
- Use Get-Dashboard to fetch full details for dashboards.
Get-Business-Context
Call this FIRST, before any other Mixpanel tool whenever ANY of these are true:
1. It is the first substantive turn of the conversation about this org or project.
2. The user references a name, acronym, product, team, project nickname, event,
property, or concept whose org-specific meaning you cannot verify just from
the tool list. Examples that should trigger this: "show me MCP data",
"how is ingest doing?", "the onboarding funnel", "Project Atlas".
3. You are about to guess which project_id, event name, or property to use
based on a name in the user's request.
Example:
User: "what project has sales data?"
❌ Wrong: jump to Get-Projects and pattern-match against project names.
✅ Right: call Get-Business-Context first, the org likely defines what "sales data"
refers to (a product area, an internal acronym, a specific project).
Once you have called this in the current conversation for a given
organization (and project, if applicable), do NOT call it again. The result
is stable for the session; reuse the previously returned context on every
subsequent turn — including follow-ups, drill-downs, refinements, and new
questions about the same project. Re-call ONLY if:
- The user asks about a different project_id whose context you have not
yet fetched this conversation.
- The user explicitly asks you to refresh or reload business context.
- You called Update-Business-Context this conversation and need the new
content.
What you get back:
- Specialized instructions on how to query data in this org
- How projects, events, and other entities are organized and named
- Business vocabulary and definitions (acronyms, internal product names, etc.)
Params:
- project_id (int, optional): If provided, returns context for the project AND
its organization. organization_id is not required in this case — the org is
derived from the project.
- organization_id (int, optional): Required when project_id is NOT provided.
Call List-Organizations FIRST to obtain it. If List-Organizations returns
exactly one org, use its id directly; if it returns more than one, ASK the
user which org they mean before calling this tool.
Update-Business-Context
Update the business context at the project or organization level. This is a
full replace — the new content overwrites whatever exists; there is no merge
or partial update. Other users may have authored the current context, so
ALWAYS ask the user for explicit confirmation before calling this tool.
Content should be minimal and focused: short, structured markdown notes that
capture essential domain knowledge.
Params:
- context (str, required): The new context content. Pass an empty string to clear.
- level (str, required): Either the literal string "project" or "organization". Must be passed explicitly so the level is never inferred.
- project_id (int, required when level="project"): The project to update.
- organization_id (int, required when level="organization"): The org to update.
Call List-Organizations FIRST to obtain it. If List-Organizations returns
exactly one org, use its id directly; if it returns more than one, ASK the
user which org they mean before calling this tool.
List-Organizations
Returns the organizations the current user belongs to.
Find-Duplicate-Groups
Find groups of duplicate or near-duplicate names in a Mixpanel
project — both events and event properties. Returns clusters a user
might want to merge in Lexicon (e.g. 'Add to Cart', 'add_to_cart',
'addToCart'; or 'from_date', 'from-date').
Returns a FormattedTable with Columns:
- suggested_name: the most-popular variant in the cluster — use
this as the merge target.
- entity_names: every variant in the group, in popularity order
(includes suggested_name as the first entry).
- entity_type: 'events' or 'event_properties'. Pass this value
back to Merge-Group / Dismiss-Duplicate-Group.
Groups already merged or dismissed by the user are filtered out by
the server. Empty `rows` means there is nothing actionable.
Merge-Group
Merge a group of duplicate names into one canonical entity in a
Mixpanel project's Lexicon. Works for events and event properties.
DESTRUCTIVE: source entities are remapped to the canonical entity and
their historical data is unified. Confirm with the user before
calling. However, the merge can be undone in the Mixpanel UI with a
single button click, so it's not a permanent action.
Use with Find-Duplicate-Groups: pass its suggested_name as
canonical_name, the remaining entity_names as source_names, and the
group's entity_type as entity_type. canonical_name is filtered out of
source_names automatically.
entity_type must be 'events' or 'event_properties'.
excluded: names from the suggested cluster the user does NOT want to
merge. Pass them here (not in source_names) — they are left untouched
but are still required to locate the suggestion, so include every
name the cluster originally had across canonical + source + excluded.
Server-side restrictions (rejected with an error): Mixpanel default
entities, custom entities, dropped entities, entities already merged
into another, and names that do not exist in the project.
Dismiss-Duplicate-Group
Dismiss a duplicate-group suggestion so it no longer appears in
Find-Duplicate-Groups results. Works for events and event
properties. Does not modify any entity data — only hides the
suggestion. There is no un-dismiss, so confirm with the user before
calling.
Pass the full entity_names list of the group exactly as returned by
Find-Duplicate-Groups (order does not matter; the group is keyed by
the set of names), plus the group's entity_type. entity_type must be
'events' or 'event_properties'.