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

# MoEngage MCP Server and Connector

> Connect AI assistants like Claude and ChatGPT to your MoEngage workspace to build campaigns, manage segments and flows, and analyze performance through natural language.

MoEngage offers a hosted [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) server that lets AI assistants work with your workspace directly. Your assistant can **build campaign drafts, create and count segments, read and analyze flows, browse dashboards, and analyze performance** — all through natural-language conversation.

The MoEngage MCP server is available as a **custom connector** for any MCP-compatible client. It is also published in Anthropic's Claude connector directory, so you can add it directly from Claude (web, mobile, Claude API, Claude Code, and Claude Desktop) without entering the server URL yourself. We are actively working to list it on the ChatGPT marketplace as well.

<Note>
  The MCP server connects external AI assistants, such as Claude or ChatGPT, to your MoEngage workspace. To build and run AI agents inside the MoEngage dashboard itself, refer to [Custom Agents](/docs/user-guide/ai-and-intelligence/merlin-ai/custom-agents/custom-agents-overview).
</Note>

<Info>
  The MoEngage AI Connector (MCP server) is available in **DC01, DC02, DC03, and DC04**.
</Info>

## MCP Server URL

Use this URL wherever a client asks for a remote MCP server or custom connector:

```text theme={null}
https://mcp.moengage.com
```

<Info>
  For the MoEngage **docs** MCP (search the documentation site), use `https://www.moengage.com/docs/mcp`.
</Info>

<Note>
  The connector runs from the AI provider's cloud (for example, Anthropic's cloud for Claude), not from your local device, so the server must be reachable over the public internet. `https://mcp.moengage.com` is publicly reachable, so no firewall or allowlist changes are needed.
</Note>

## Setup

There are two ways to make the connector available:

* **Organization-wide setup** — an admin adds MoEngage once for the whole organization, so every member only has to click **Connect**. Recommended for teams.
* **Personal setup** — an individual adds the connector to their own account.

In both cases, each user still authenticates individually with their own MoEngage account, so the assistant only ever sees data and tools that user already has access to.

### Organization-Wide Setup (Admin, One-Time)

Set this up once so anyone in your organization can connect without pasting the URL themselves.

<Tabs>
  <Tab title="Claude (Team / Enterprise)">
    <Info>
      Only a **Primary Owner** or **Owner** of a Claude Team or Enterprise organization can add an organization connector.
    </Info>

    1. Go to **Settings** → **Connectors** (organization settings).
    2. Click **Add**.
    3. Enter the MCP server URL: `https://mcp.moengage.com`.
    4. Leave **Advanced settings** (OAuth Client ID and Client Secret) blank — MoEngage handles OAuth automatically.
    5. Click **Add**.

    The connector now appears in every member's **Connectors** list. Each member clicks **Connect** once to authenticate with their own MoEngage account.
  </Tab>

  <Tab title="ChatGPT (Business / Enterprise)">
    <Info>
      A **workspace admin** (Business, Enterprise, or Edu plan) manages connectors for the workspace.
    </Info>

    1. Open **Settings** → **Connectors** (workspace admin settings).
    2. Choose to add a **custom** or **third-party MCP connector**.
    3. Enter the MCP server URL: `https://mcp.moengage.com`.
    4. Save. The connector becomes available to members, who then authenticate individually with their MoEngage accounts.
  </Tab>
</Tabs>

### Personal Setup (Per User)

Use this if you are connecting your own account, or if the connector has not been added organization-wide.

<Tabs>
  <Tab title="Connect with Claude">
    1. Open **Claude Desktop** or go to [claude.ai](https://claude.ai/login).
    2. In the sidebar, click **Settings**.
    3. Click **Connectors**.
    4. Click **Add custom connector**.
    5. Enter the MCP server URL: `https://mcp.moengage.com`.
    6. Click **Add**, then **Connect**. You are redirected to authenticate with your MoEngage account.
    7. After authentication, the MoEngage tools appear under **Connectors** in **Settings**.
    8. Configure **Tool permissions** (*Automatic*, *Ask first*, or *Disabled*) per tool. See [Enable the Tools You Need](#enable-the-tools-you-need).
  </Tab>

  <Tab title="Connect with ChatGPT">
    1. Open [ChatGPT](https://chatgpt.com/).
    2. In the sidebar, click **Settings**.
    3. Select **Connectors** (or **Connected apps**, depending on your plan).
    4. Click **Add**, then choose **Custom MCP Connector**.
    5. Enter the MCP server URL: `https://mcp.moengage.com`.
    6. Click **Connect** and authenticate with your MoEngage account.
    7. After authentication, the MoEngage tools are available in your conversations.
  </Tab>

  <Tab title="Connect with GitHub Copilot (VS Code)">
    <Info>
      Requires **VS Code 1.101 or later** (remote MCP + OAuth support), and Copilot **agent mode**.
    </Info>

    1. In VS Code, open the Command Palette and run **MCP: Add Server** (or edit `.vscode/mcp.json` directly).
    2. Choose **HTTP (remote server)** and enter the URL: `https://mcp.moengage.com`.
    3. Save. On the server entry in `mcp.json`, click **Auth** (CodeLens) — a browser window opens to authenticate with your MoEngage account.
    4. Open **Copilot Chat**, switch to **Agent** mode, and the MoEngage tools appear in the tools picker.

    <Note>
      Other Copilot IDEs (Visual Studio, JetBrains, Xcode, Eclipse) currently connect MCP servers with a personal access token only; OAuth support is rolling out. Because this server is OAuth-based, **VS Code is the supported Copilot client today.**
    </Note>
  </Tab>
</Tabs>

### Use It in a Conversation

After connecting, turn the MoEngage tools on for a chat:

1. In a new conversation, open the tools or connectors menu (in Claude, the **+** icon → **Connectors**).
2. Toggle **MoEngage** on.
3. Ask for what you want in plain language (see [Example Prompts](#example-prompts)).

## Authentication

The MoEngage MCP server uses OAuth-based authentication tied to your MoEngage account. Unlike the dashboard, an MCP connection defaults to a workspace list rather than your last-used workspace, since MCP clients switch workspaces more frequently. If you are already signed in, you go directly to the authorization prompt described in the final step below; otherwise, the full flow is:

<Steps>
  <Step title="Initiate a connection">
    In your MCP client, initiate a new MoEngage connection. MoEngage redirects you to the global login page.
  </Step>

  <Step title="Enter your email">
    In the **Work email** box, type your email address and click **Continue**. MoEngage redirects you to the login page for your last-used workspace's data center.
  </Step>

  <Step title="Verify your identity">
    On the **User authentication** page, open your authenticator app, find the 6-digit code for MoEngage, and type it in the verification box. Click **Continue**.
  </Step>

  <Step title="Select a workspace">
    On the **Login to a different workspace** page, choose the workspace and environment you want to connect to. The environment options are **Live** and **Test**.
  </Step>

  <Step title="Complete workspace authentication">
    Complete authentication using the workspace's configured login method (password, Google, or SSO). You then see an authorization prompt. The screen shows:

    * **Account** — your MoEngage email
    * **Workspace** — the workspace you are currently signed into
    * **Role** — your role in that workspace (for example, Manager, Admin)
    * **Data Center** — your data center environment

    Click **Accept** to grant access.

    <div style={{ maxWidth:"440px" }}>
      <Frame>
        <img src="https://mintcdn.com/moengage/e5VzzqYs1CiiuLiR/images/MCP-request-access.png?fit=max&auto=format&n=e5VzzqYs1CiiuLiR&q=85&s=570b3103686b0aea19e51b3648145fb6" alt="MoEngage MCP OAuth authorization screen showing account, workspace, role, and data center" width="1461" height="1337" data-path="images/MCP-request-access.png" />
      </Frame>
    </div>
  </Step>
</Steps>

### Key Authentication Behaviors

* The connection uses the **environment**, **workspace**, and **role** you selected when you authorized it — not your current dashboard session.
* Authentication tokens are issued by the MCP authorization flow and are scoped to that workspace and environment.
* To use a different workspace or environment, **re-authenticate** the connection from your MCP client and select it there. If the connection is interrupted, re-initiate it the same way.
* All actions respect your existing MoEngage role-based permissions — including which tools your role can use. Reading data requires read access; building or editing requires the matching create/manage permission.
* **Session duration**: 30 days, with a 7-day idle timeout.
* **Independent from the dashboard**: the MCP session is separate from your dashboard session. Logging in or out of one does not affect the other, and signing in to a different workspace on the dashboard does not switch the workspace your MCP connection uses.

## Built for Agents

The server is designed so that *any* AI assistant — not just one vendor's — can act correctly on the first try. Two capabilities make that possible:

* **`discover_schema`** returns the exact, current request shape for whatever you're building (required fields, allowed values, a working example) — so the assistant doesn't guess.
* **`get_content_guide`** serves validated, on-demand guidance for writing content (Jinja personalization, email HTML) — so the content is correct, not trial-and-error.

<Note>
  The MCP builds and validates **drafts**. Publishing a campaign and starting (publishing) a flow remain human actions in the MoEngage dashboard; pausing, resuming, and stopping an existing flow are available through `update_flow_status`.
</Note>

## What You Can Do

<CardGroup cols={2}>
  <Card title="Build campaigns" icon="pen-to-square">
    Draft push and email campaigns — including A/B variants, multi-locale, scheduling, segmentation, and content blocks.
  </Card>

  <Card title="Author content" icon="wand-magic-sparkles">
    Get validated patterns for Jinja personalization and email HTML, and preview how content renders for sample users.
  </Card>

  <Card title="Manage segments" icon="users">
    Create custom segments, browse existing ones, and get live user counts with channel reachability.
  </Card>

  <Card title="Work with flows" icon="diagram-project">
    Search flows, read their configuration and versions, analyze flow and per-channel performance, and pause or resume them.
  </Card>

  <Card title="Search & review" icon="magnifying-glass">
    Find campaigns across the supported channels; read a campaign's full configuration and content.
  </Card>

  <Card title="Analyze performance" icon="chart-line">
    Pull campaign performance, delivery funnels, click breakdowns, device analytics, and dashboard charts.
  </Card>

  <Card title="Analyze product data" icon="chart-mixed">
    Run behavior, funnel, retention, user, and session and source analyses, and discover the events and attributes to use.
  </Card>
</CardGroup>

## Available Tools

Create, edit, and test-send are supported for **Push and Email**. Campaigns on every other channel, including SMS, Webhook, and WhatsApp, are read-only: you can search and read them, but not create or edit them. The `channel` filter on `search_campaigns` is narrower still — see [Other limitations](#other-limitations).

Which tools you can use depends on your MoEngage role. If a tool you expect is missing, [refresh the tools list](#refresh-the-tools-list).

### Build a Campaign

| Tool | Description |
| - | - |
| `discover_schema` | Returns the exact request shape for a campaign type, component, template, or modifier — required/forbidden fields, a proven minimum example, and the rules for that type. **Call this before building any payload.** |
| `create_campaign_draft` | Create a campaign draft in one call. |
| `patch_campaign_components` | Update one or more components of an existing draft. |
| `validate_campaign_draft` | Dry-run the full publish validation against a draft without changing it; returns field-level errors if anything is missing. |
| `create_personalization_preview` | Render personalization for sample users to spot-check content before creating. |
| `test_campaign_inline` / `test_campaign_by_draft_id` | Send a test message to verify a draft. |
| `update_campaign_status` | STOP, PAUSE, or RESUME an already-running campaign (not drafts). |

### Author Content

| Tool | Description |
| - | - |
| `get_content_guide` | Validated authoring guidance for content — how to write Jinja personalization and email HTML well. Request a `topic` (`jinja`, `email_html`, `email_deliverability`) and an optional `section` to get just the part you need. This is authoring *quality* guidance, distinct from `discover_schema` (which gives the request *shape*). |

### Content Blocks

| Tool | Description |
| - | - |
| `create_content_block` / `edit_content_block` | Create or update a reusable content block (for example, a shared email footer). |
| `search_content_blocks` / `get_content_blocks_by_ids` | Find content blocks by label, or fetch them by ID. |

### Segments

| Tool | Description |
| - | - |
| `create_custom_segment` | Creates a filter-based (ELASTIC\_SEARCH) custom segment from `included_filters` / `excluded_filters`. The segment `name` must be unique, at most 200 characters, and contain no HTML (`All Users` is reserved). Names inside filters are only partially validated at create time: a user-attribute display name, or a wrongly-cased internal name, is rejected up front when the catalog is reachable, but event names and event-attribute names are never checked — a wrong one is accepted, and the segment count fails later with no error reason. |
| `list_segments` | Browse existing segments, paginated (`page`, `page_size`, optional `name` filter). Returns Filter and File type segments only, as metadata (`id`, `name`, `type`, `source`, timestamps); Warehouse, Analytics, and Composite are excluded. |
| `get_segment` | Read a single segment's full filter definition by ID, in the same format `create_custom_segment` accepts. File-based and cohort-import segments return metadata only, with no filter tree. |
| `start_segment_count` / `poll_segment_count` | Kick off an async user count for a segment (with an optional `callback_url` webhook), then poll for the result — includes channel-level reachability, with per-channel and per-platform breakdowns available. Results are cached for 15 minutes; jobs typically finish in under 30 seconds. |
| `get_value_suggestions` | Gets up to 5,000 distinct stored values (`string`, `double`, or array/object variants) for a user or event attribute, useful for checking real values before writing an equality filter. For `array_object` attributes, `node_attribute_name` / `node_data_type` resolve values for a child field. |
| `describe_segment_filters` | Turns a filter set into a plain-English sentence to confirm intent before creating a segment or query. Its `filter_operator` also accepts `difference`, unlike `create_custom_segment`. |
| `deep_validate_segment_filters` | Semantically validates a filter set (attribute existence, data types, operators) against the workspace's live catalog. **Always returns HTTP 200** — check the `is_valid` field in the response, not the status code; on failure, `errors` gives the dot-notation path of each problem. |
| `create_recent_query` / `get_recent_query` / `get_recent_query_filters` | Count an audience **without creating a segment**: run an ad-hoc audience query (optionally restricted to specific `platforms`, or linked to an existing segment via `cs_id`), poll its result, and read back its filters. `status` is `received`, `running`, or `retry_wait` while the query is in flight, then `success` (with `user_count`) or `failure` — on failure, `failure_reason` carries the reason. Pass `reachability` to choose which of push, email, SMS, and WhatsApp to count: a channel you omit is skipped, and only the requested channels appear in `reachability_count`. |
| `is_user_in_segment` | Check in real time whether a specific user is in up to 10 segments. `segment_eligibility: false` means the segment type doesn't support real-time evaluation (batch-only) — it is not a "no". |

<Info>
  * Segment filters must use the exact **internal** (platform) names of events and attributes, not the dashboard display name (for example, `moe_city`, not "City"). A display name used as an **event** or **event-attribute** name is accepted at create time, and a user-attribute display name gets through too whenever the catalog check cannot resolve it — in both cases the count later fails with **no error reason**. Resolve names first with `find_events`, `find_user_attributes`, and `find_event_attributes` (see [Catalog Discovery](#catalog-discovery)), and always use the returned `name` field.
  * Equality depends on the attribute's data type. `equals` is never a valid operator. For `string`, `double`, `array_string`, and `array_double` attributes, equality is `"operator": "in"` with a **list** value (for example, `"value": ["Mumbai"]`). For the scalar types, "is not" is the same operator with `"negate": true`. To negate an **array** attribute, remove the filter's `array_filter_type` key — keeping it alongside `negate` invalidates the filter. `is` is the equality operator for `bool` attributes and for date parts on `datetime` attributes — on a `string` attribute it is reserved for the is-empty check (`"value": ""`), so don't use it for text equality. `geopoint` attributes take no operator at all. Get the exact set for a data type from `discover_schema(kind="component", id="segment_filters")`.
  * To target users who did **not** perform an event, set `executed: false` on the `actions` filter and pair it with `"execution": {"type": "exactly", "count": 0}` — that combination is required, and `aggregation_attributes` must be omitted. Alternatively, place a positive `actions` filter in `excluded_filters`, which excludes matching users outright.
  * Common create-time errors: `409` (name already taken), `400` (malformed filter, or an operator the API does not accept), `413` (filter too large or too deeply nested). The `400` names no field, so re-check the filter shape rather than retrying variations — or pre-flight with `deep_validate_segment_filters`, which answers `200` with `is_valid: false` and the path of each problem.
</Info>

<Info>
  * PII-marked attributes are not exposed through the MCP.
  * **Email (Standard)** and **Mobile Number (Standard)** are masked even when they are not marked as PII.

  This applies to `get_user_events`, `get_recent_query`, `get_recent_query_users`, and `get_value_suggestions`.
</Info>

### Flows

| Tool | Description |
| - | - |
| `search_flows` | Find flows by name, status, or other criteria. |
| `get_flow` / `get_flow_version` | Read a flow's configuration, or a specific version of it. |
| `get_flow_analytics` | The flow-level health view — how the flow is performing overall. Flow Analytics is in beta. |
| `get_flow_channel_analytics` | Channel-scoped analytics for a flow — how Email, Push, SMS, and other channels performed within it. Flow Analytics is in beta. |
| `update_flow_status` | Pause, resume, stop, retire, archive, or unarchive a flow. Stop and retire are irreversible. |

### Dashboards

| Tool | Description |
| - | - |
| `list_dashboards` | List the analytics dashboards available in the workspace. |
| `get_dashboard` | Return the full metadata for a single dashboard by ID. |
| `get_chart_data` | Fetch the analytical data for a specific chart within a dashboard. |

### Search & Read

| Tool | Description |
| - | - |
| `search_campaigns` | Search campaigns by name, status, ID, channel, delivery type, or date range. Include `DRAFT` in the status filter to see drafts. The `channel` filter accepts Push, Email, SMS, and MMS only; search without it to include WhatsApp and Webhook campaigns. |
| `get_campaign` / `get_campaign_meta` | Fetch a single campaign's full configuration and content, or just its metadata. |

**Supported status filters:** `ACTIVE`, `DRAFT`, `EXPIRED`, `NOT_SENT`, `PAUSED`, `SCHEDULED`, `SENDING`, `SENT`, `STOPPED`, `UNDER_REVIEW`, `REJECTED`.

### Campaign Analytics

<Info>
  Campaign analytics tools enforce a maximum date range of **30 days** per query. Flow analytics tools allow up to **90 days**. The analyze tools each use their own window, which varies by analysis type and granularity — `run_user_analysis` is more restricted than the rest, and retention caps hourly analyses at 24 hours.
</Info>

| Tool | Description |
| - | - |
| `get_campaign_stats` | Aggregate performance — delivery rate, opens, clicks, CTR, and channel-specific metrics. Up to 50 campaigns per call. |
| `get_detailed_campaign_stats` | Breakdowns by conversion goal, device/platform, locale, and A/B variation. |
| `get_delivery_stats` | The delivery funnel — reachable users, frequency-cap removals, send/delivery failures, and per-platform device stats. |
| `get_click_performance` | Per-URL click breakdown, with total and unique counts. |
| `get_device_analytics` | Performance by device dimensions — OEM, app version, or dormancy, with multi-dimensional splits. |

### Analyze

| Tool | Description |
| - | - |
| `discover_analyze_schema` | Returns the request shape for an analysis — call this before running one. |
| `run_behavior_analysis` | Analyze how users perform a chosen event over time. |
| `run_funnel_analysis` | Measure conversion across an ordered sequence of events. |
| `run_retention_analysis` | Measure how users return over time after a starting event. |
| `run_user_analysis` | Analyze your user base by user properties — for example, how users break down by location, device type, or language. |
| `run_session_source_analysis` | Analyze sessions by source properties — session count, average session duration, conversions, and bounce rate by source, medium, or campaign. |

<Info>
  * PII-marked attributes are not exposed through the MCP.
  * **Email (Standard)** and **Mobile Number (Standard)** are masked even when they are not marked as PII.

  In all five analyze tools, these attributes cannot be used to group by user property or to split by.
</Info>

### Catalog Discovery

Use these to find the right events and attributes before building a segment or running a behavior analysis. All three return top-ranked matches with confidence scores, never the full catalog; event and attribute names vary per workspace, so the assistant should never guess them.

| Tool | Description |
| - | - |
| `find_events` | Discover trackable events matching a natural-language term (for example, "purchase"). Takes `query` and an optional `limit` (1–50, default 10); returns the internal `name` to use as `action_name` in filters. Events inactive for more than 60 days are excluded. |
| `find_event_attributes` | Discover the attributes of a specific event. Takes `event_name` (the exact name from `find_events`), `query`, and an optional `limit`. |
| `find_user_attributes` | Discover user attributes matching a natural-language term (for example, "city"). Takes `query` and an optional `limit`; returns the internal `name` and `data_type`, which determines valid filter operators. |

### Feedback

| Tool | Description |
| - | - |
| `submit_feedback` | Lets the assistant report tool-quality issues back to MoEngage to help improve the tools. |

## Building a Campaign, Step by Step

<Steps>
  <Step title="Discover the Shape">
    The assistant calls `discover_schema` for your channel and delivery type to get the exact payload structure.
  </Step>

  <Step title="Find the Audience">
    Use `find_events` / `find_user_attributes` and `create_custom_segment` (with `start_segment_count` to confirm reach) to target the right users.
  </Step>

  <Step title="Author the Content">
    For email HTML or Jinja personalization, it calls `get_content_guide` for validated patterns.
  </Step>

  <Step title="Create the Draft">
    `create_campaign_draft` (or `patch_campaign_components` to refine an existing draft).
  </Step>

  <Step title="Preview Personalization">
    `create_personalization_preview` confirms the content renders correctly for sample users.
  </Step>

  <Step title="Validate">
    `validate_campaign_draft` runs the full publish check and reports any field-level issues.
  </Step>

  <Step title="Publish">
    Review and publish the draft from the **MoEngage dashboard**.
  </Step>
</Steps>

## Example Prompts

| What you want to do | Example prompt |
| - | - |
| Build a campaign | *"Draft a one-time push to all users for tomorrow 10am IST titled 'Weekend sale'."* |
| Personalize content | *"Write the email greeting with a first-name fallback and mention the user's city."* |
| Create a segment | *"Create a segment of users who opened an email in the last 7 days but didn't purchase."* |
| Check segment reach | *"How many reachable users are in my 'Cart abandoners' segment?"* |
| Review a flow | *"Show me the steps and current status of the onboarding flow."* |
| Analyze a flow | *"How is the win-back flow performing by channel over the last 2 weeks?"* |
| Check performance | *"What's the CTR for my email campaigns over the last 2 weeks?"* |
| Read a dashboard | *"Pull the numbers from the 'Weekly engagement' dashboard."* |
| Analyze behavior | *"Run a 7-day retention analysis for users who completed onboarding."* |
| Analyze traffic sources | *"Which sources drove the most sessions last month, and what was the bounce rate?"* |
| Diagnose delivery | *"Why did my last push campaign have a low delivery rate?"* |
| Device insights | *"How does Android vs iOS performance compare for my push campaigns?"* |
| Explore the catalog | *"What purchase-related events do we track, and what attributes do they have?"* |
| Sanity-check a filter | *"Before creating it, explain in plain English what this segment's filters mean."* |
| Create a segment via MCP | *"Create a segment of users in Mumbai who purchased at least 3 times in the last 30 days."* |
| Count a segment | *"How many reachable users are in my 'Cart abandoners' segment, split by channel?"* |
| Count without creating | *"How many users opened an email in the last 7 days but didn't purchase? Just the count, don't create a segment."* |
| Check membership | *"Is user 12345 currently in the 'Churn risk' segment?"* |

## Known Behaviors and Limitations

We document known quirks so you and your assistant can work around them instead of hitting them unexpectedly.

### Enable the Tools You Need

Write tools (for example, creating campaigns, editing content blocks, creating segments) may be off by default in your client. If the assistant says it lacks access to do something, enable that tool in your client's connector settings — in Claude, under **Settings** → **Connectors** → **MoEngage** → **Tool permissions**. Which tools you can enable is still bounded by your MoEngage role.

### Refresh the Tools List

New tools are added to the connector over time. If a newly shipped tool doesn't appear, refresh the connector's tools list in your client. If the refresh option isn't available, disconnect and reconnect (re-authenticate) the MoEngage connector to pick up the latest tools.

### Segmentation Behaviors

| Behavior | Details |
| - | - |
| Internal names only | `create_custom_segment` has a partial safety-net catalog check that covers `user_attributes` filters only, and it fails open when the catalog is unavailable. Event names and event-attribute names are never checked, so an unresolved bad name can still surface later as a count job that fails with no error reason. Always resolve names via `find_events` / `find_user_attributes` / `find_event_attributes` first, and validate with `deep_validate_segment_filters`. |
| Stale events are hidden | `find_events` excludes events inactive for more than 60 days. |
| Equality depends on the attribute's data type | `equals` is not a valid operator and is rejected with a flat `400` (Bad Request) that names no field. For `string`, `double`, `array_string`, and `array_double` attributes, equality is `"operator": "in"` with a **list** value (for example, `"value": ["Mumbai"]`). For the scalar types, "is not" is the same operator with `"negate": true` — there is no `notEquals`. To negate an **array** attribute, remove the filter's `array_filter_type` key; keeping it alongside `negate` invalidates the filter. `is` is the equality operator for `bool` attributes and for date parts on `datetime` attributes; on a `string` attribute `is` is reserved for the is-empty check (`"value": ""`), so don't use it for text equality. `geopoint` attributes take no operator at all — only `value` (latitude), `value1` (longitude), and `radius`. Get the exact set for an attribute's data type from `discover_schema(kind="component", id="segment_filters")`, and confirm the filter with `deep_validate_segment_filters` before creating. |
| Negative event conditions need `executed: false` plus `exactly 0` | To express "did not do the event", set `executed: false` on the `actions` filter and pair it with `"execution": {"type": "exactly", "count": 0}`; `aggregation_attributes` must be omitted. Alternatively, place a positive `actions` filter in `excluded_filters`. |
| Segment types vary in MCP support | `create_custom_segment` only creates filter-based (ELASTIC\_SEARCH) segments. `list_segments` returns Filter and File segments, but excludes Warehouse, Analytics, and Composite. `get_segment` returns a full filter tree only for Filter segments; File and cohort-import segments return metadata only. `is_user_in_segment` evaluates Filter segments in real time; file-based, funnel, retention, and predictive segments are batch-only. See [Types of Segments](/docs/user-guide/segment/getting-started/types-of-segments) for what each type means. |
| Counts are cached for 15 minutes | `start_segment_count` returns the cached result (`served_from_cache: true`) when a successful count already exists within the window. |
| Validation returns HTTP 200 either way | For `deep_validate_segment_filters`, check `is_valid` in the response body. |
| Value suggestions are capped | 5,000 distinct values per attribute. |
| PII and contact attributes are restricted | Attributes marked as PII are not exposed through the MCP and are not available in `get_user_events`, `get_recent_query`, `get_recent_query_users`, or `get_value_suggestions`. **Email (Standard)** and **Mobile Number (Standard)** are masked in these tools even when they are not marked as PII. |
| Role-based permissions apply | Creating segments and queries requires the matching create/manage permission on your MoEngage role; read tools require read access. See [Security and Permissions](#security-and-permissions). |

### Segmentation Limits

The segmentation tools do not enforce rate limits of their own; the limits below come from the MoEngage APIs they call. There is no published quota on how many segments or queries you can create in a period, no enforced minimum interval between polls, and no documented cap on concurrent count jobs.

| Limit | Value |
| - | - |
| Segments evaluated per `is_user_in_segment` call | 10 |
| Values returned by `get_value_suggestions` | 5,000 distinct values |
| Segments returned per `list_segments` page | 1 to 100 (default 10) |
| Segment count result cache | 15 minutes |
| Filter payload size | Oversized or overly deep filters are rejected with a `413` (Payload Too Large) error |
| Filter nesting depth | One level of `nested_filters` |

Rate limiting can still occur at the platform level.

<Note>
  Some segmentation APIs, including the real-time membership check, can return a `429` (Too Many Requests) error under heavy traffic. There is no published request quota; when a `429` occurs, retry after about 60 seconds. All tool calls also pass through the MoEngage API gateway, which can apply its own traffic controls.
</Note>

### Other Limitations

* **Publishing** a campaign is not available through the MCP — drafts are published from the MoEngage dashboard.
* **Campaign creation is Push and Email only.** SMS, Webhook, and WhatsApp campaigns are searchable and analyzable, but must be created and edited in the MoEngage dashboard.
* **The campaign `channel` filter accepts Push, Email, SMS, and MMS only.** WhatsApp and Webhook campaigns cannot be filtered by channel — omit the filter to include them in results. WhatsApp is supported elsewhere: flow analytics covers WhatsApp, and WhatsApp appears in segment reachability counts.
* **Date range** for campaign analytics is limited to **30 days** per query; flow analytics allows up to **90 days**.
* **Batch size**: `get_campaign_stats` accepts up to **50 campaign IDs** per request.
* **Content size**: email HTML can be large (10–50 KB); fetch full content deliberately.
* **Campaign-name date format**: campaign names often encode dates as **DDMMYY** (for example, `230326` = 23 March 2026). If analytics return all zeros, check your date range first.
* **PII and contact attributes are not available to the analyze tools.** In `run_behavior_analysis`, `run_funnel_analysis`, `run_retention_analysis`, `run_session_source_analysis`, and `run_user_analysis`, these attributes cannot be used to group by user property or to split by:
  * PII-marked attributes are not exposed through the MCP.
  * **Email (Standard)** and **Mobile Number (Standard)** are masked even when they are not marked as PII.
* **Analytics response shape**: stats are returned as a single cross-channel structure — metrics that don't apply to a campaign's channel come back as `0`, not absent. Don't infer a campaign's channel from which fields are non-zero.

## Security and Permissions

* The MCP server can **build and validate drafts**, **create segments**, and **read and analyze** campaigns, flows, and dashboards. It does **not** publish campaigns — publishing is a human action in the dashboard.
* Every action is scoped to the **workspace and role** of the authenticated user. Tools your role lacks permission for are not available to you.
* Data shared with AI assistants is subject to the respective AI provider's data-handling policies. MoEngage lists its AI [sub-processors](https://www.moengage.com/moengage-list-of-sub-processors/) (including Anthropic and OpenAI) on its website.
* Review MoEngage's [Privacy Policy](https://www.moengage.com/privacy-policy/) and [Terms of Use](https://www.moengage.com/terms-of-use/) for more information.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Cannot access the MCP server or your data">
    The connection is bound to the workspace and environment you chose when you authorized it, independently of your dashboard session.

    1. Verify the connection was authorized against the workspace you expect. Changing workspaces on the dashboard does not change it.
    2. To point the connection at a different workspace, re-authenticate it from your MCP client and select that workspace.
  </Accordion>

  <Accordion title="A tool you expected isn't available">
    First, make sure the tool is **enabled** in your client's connector settings — see [Enable the Tools You Need](#enable-the-tools-you-need). Then confirm your MoEngage role has the matching permission (for example, campaign create/manage for build tools). If it's a newly announced tool, [refresh the tools list](#refresh-the-tools-list).
  </Accordion>

  <Accordion title="A newly announced tool doesn't show up">
    Refresh the connector's tools list, or disconnect and reconnect the MoEngage connector to re-authenticate. See [Refresh the Tools List](#refresh-the-tools-list).
  </Accordion>

  <Accordion title="Re-authentication fails when switching workspace or data center">
    Switching the workspace or database on an active connection can briefly error. Wait a short while and re-authenticate — the connection typically succeeds on retry.
  </Accordion>

  <Accordion title="A segment count fails with no error reason">
    This almost always means a filter uses a display name instead of an internal name. Resolve names with [Catalog Discovery](#catalog-discovery) and re-validate with `deep_validate_segment_filters` before creating the segment again.
  </Accordion>

  <Accordion title="A segment or query is not created">
    Check the response for a specific error code: `409` means the name is already taken, `400` means the filter structure or one of its operators is invalid, and `413` means the filter is too large or deeply nested. The `400` carries no field-level detail. A `400` on a filter that otherwise appears correct is usually the operator, and the right one depends on the attribute's data type: for a text (`string`) attribute, equality is `"operator": "in"` with a list value — not `equals`, and not `is` (`is` is for `bool` attributes and for the is-empty check). Run `deep_validate_segment_filters` first: it answers `200` with `is_valid: false` and the path of each problem, instead of a flat `400`. See the common-errors note under [Segments](#segments).
  </Accordion>

  <Accordion title="is_user_in_segment returned segment_eligibility: false">
    This is not a "no": it means the segment type does not support real-time evaluation (file-based, funnel, retention, and predictive segments are batch-only). Check the segment's type, or fall back to a saved count with `start_segment_count`.
  </Accordion>

  <Accordion title="A segmentation tool is not available to the assistant">
    Tool availability depends on your MoEngage role and your client's connector settings. See [Security and Permissions](#security-and-permissions) and [Enable the Tools You Need](#enable-the-tools-you-need).
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.