# MCP server

> Connect Claude Code, Claude Desktop, Cursor, VS Code or any MCP client to your Emelia account. 26 tools for campaigns, lists, contacts, enrichment and deliverability.

Source: https://docs.emelia.io/docs/ai/mcp

The Emelia MCP server lets an AI assistant work in your Emelia account in plain language: "add these three prospects to my SaaS founders list", "what is the reply rate of my Q4 campaign this week?", "which of my mailboxes are disconnected?".

|                |                                                                                                         |
| -------------- | ------------------------------------------------------------------------------------------------------- |
| URL            | `https://mcp.emelia.io/mcp`                                                                             |
| Transport      | Streamable HTTP, stateless (`POST` only)                                                                |
| Authentication | Your Emelia API key in the `Authorization` header (raw or `Bearer <key>`), or in `X-Api-Key`. No OAuth. |
| Health check   | `https://mcp.emelia.io/mcp/health` answers `{"ok":true}`                                                |

You need an API key first:

[Get your API key](https://v3.emelia.io/settings/api)

Whatever the client, name the server `emelia`: the tools then show up as `mcp__emelia__<tool>`, the names the [Claude Code plugin](https://docs.emelia.io/docs/ai/claude-code-plugin.md) expects.

## Install

**Claude Code**

For yourself, in every project:

```bash
claude mcp add --transport http --scope user emelia https://mcp.emelia.io/mcp \
  --header "Authorization: YOUR_EMELIA_API_KEY"
```

For a shared project, commit a `.mcp.json` at the root. It references the variable, not the key: each person keeps the key in their environment (`export EMELIA_API_KEY=YOUR_EMELIA_API_KEY`).

```json title=".mcp.json"
{
  "mcpServers": {
    "emelia": {
      "type": "http",
      "url": "https://mcp.emelia.io/mcp",
      "headers": {
        "Authorization": "${EMELIA_API_KEY}"
      }
    }
  }
}
```

Run `/mcp`: `emelia` should show as connected. That does not prove the key is right (the server checks it at the first tool call): ask "list my campaigns" to test it. If `/mcp` shows "needs authentication", the header does not reach the server.

**Claude Desktop**

**Custom connector**, nothing to install: **Customize, Connectors, Add, Add custom connector** (Pro and Max plans; on Team and Enterprise an owner adds it in the organization settings).

* URL: `https://mcp.emelia.io/mcp`
* Authentication: no OAuth sign in.
* Request headers: name `Authorization`, value `YOUR_EMELIA_API_KEY`.

The calls then come from Anthropic's cloud, not from your computer. On Team and Enterprise, the header is set once for the whole organization: every member acts on the same Emelia account.

**Or the configuration file** (`claude_desktop_config.json`, opened from **Settings, Developer, Edit Config**; quit and restart the app after saving). This file only starts local servers, so it uses the `mcp-remote` bridge, which needs Node 18 or later:

```json title="claude_desktop_config.json"
{
  "mcpServers": {
    "emelia": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://mcp.emelia.io/mcp",
        "--header",
        "Authorization:${EMELIA_API_KEY}"
      ],
      "env": {
        "EMELIA_API_KEY": "YOUR_EMELIA_API_KEY"
      }
    }
  }
}
```

**Cursor**

[Install in Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=emelia&config=eyJ1cmwiOiJodHRwczovL21jcC5lbWVsaWEuaW8vbWNwIiwiaGVhZGVycyI6eyJBdXRob3JpemF0aW9uIjoiWU9VUl9FTUVMSUFfQVBJX0tFWSJ9fQ%3D%3D)

The button opens Cursor with the server ready to add. Then replace `YOUR_EMELIA_API_KEY` with your key in the MCP configuration of Cursor.

Or add it by hand to `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project):

```json title="~/.cursor/mcp.json"
{
  "mcpServers": {
    "emelia": {
      "url": "https://mcp.emelia.io/mcp",
      "headers": {
        "Authorization": "YOUR_EMELIA_API_KEY"
      }
    }
  }
}
```

To keep the key out of the file, write `"Authorization": "${env:EMELIA_API_KEY}"`.

**VS Code**

[Install in VS Code](https://insiders.vscode.dev/redirect/mcp/install?name=emelia&config=%7B%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.emelia.io%2Fmcp%22%2C%22headers%22%3A%7B%22Authorization%22%3A%22YOUR_EMELIA_API_KEY%22%7D%7D)

The button opens VS Code with the server ready to install. Then replace `YOUR_EMELIA_API_KEY` with your key in the configuration it creates.

To keep the key out of the file, configure it in `.vscode/mcp.json` (or with the command **MCP: Open User Configuration**): VS Code asks for the key the first time the server starts and stores it securely.

```json title=".vscode/mcp.json"
{
  "inputs": [
    {
      "type": "promptString",
      "id": "emelia-api-key",
      "description": "Emelia API key",
      "password": true
    }
  ],
  "servers": {
    "emelia": {
      "type": "http",
      "url": "https://mcp.emelia.io/mcp",
      "headers": {
        "Authorization": "${input:emelia-api-key}"
      }
    }
  }
}
```

**ChatGPT**

> **Not available.** ChatGPT connectors sign in with OAuth or without authentication, and the Emelia MCP server needs your API key in a header. ChatGPT cannot connect to it today. Use Claude, Cursor or VS Code.

**Other clients**

Any client that supports remote MCP servers over Streamable HTTP with a custom header works:

* URL: `https://mcp.emelia.io/mcp`
* Header: `Authorization: <your API key>`, or `X-Api-Key: <your API key>` if your client reserves `Authorization`.

Every request must accept both `application/json` and `text/event-stream`. To check the server and your key by hand:

```bash
curl -s https://mcp.emelia.io/mcp \
  -H "Authorization: $EMELIA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Clients that can only sign in to remote servers with OAuth cannot connect.

## Tools

The server relays each tool to the [REST API](https://docs.emelia.io/docs/all-endpoints.md) with your key. Tools marked **credits** spend Emelia credits ([prices](https://docs.emelia.io/docs/credits.md)). Tools marked **destructive** delete data for good.

### Campaigns

| Tool                      | What it does                                                                                                       |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `list_campaigns`          | All campaigns of the current app (not the legacy ones), with id, name and status. Archived campaigns are left out. |
| `get_campaign`            | Full configuration: status, schedule, steps, attached and excluded lists.                                          |
| `create_campaign`         | Creates a draft campaign from a name, with the default settings.                                                   |
| `get_campaign_stats`      | Sent, opens, clicks, replies, bounces, globally and per step, optionally between two dates.                        |
| `get_campaign_activities` | The 30 most recent activities, replies included, filtered by type, contact or version.                             |
| `list_manual_tasks`       | Pending manual tasks of a campaign.                                                                                |
| `complete_manual_task`    | Marks a manual task `ok` or `ko`.                                                                                  |

### Lists and contacts

| Tool                        | What it does                                                                    |
| --------------------------- | ------------------------------------------------------------------------------- |
| `create_list`               | Creates an empty list.                                                          |
| `list_lists`                | Your lists, paginated, with name search and filters.                            |
| `get_list`                  | One list and its counters.                                                      |
| `rename_list`               | Renames a list.                                                                 |
| `delete_list`               | **Destructive.** Deletes a list and all its contacts.                           |
| `get_list_contacts`         | Contacts of a list, or an exact lookup by email or LinkedIn URL.                |
| `get_contact`               | One contact of a list.                                                          |
| `add_contact_to_list`       | Adds one contact; it enters the campaigns of the list. Duplicates are detected. |
| `add_contacts_to_list_bulk` | Adds up to 100 contacts in one call.                                            |
| `update_contact`            | Updates the fields of a contact.                                                |
| `delete_contact`            | **Destructive.** Deletes a contact, and removes it from campaigns.              |
| `find_contact`              | Looks a contact up across all your lists, by email or LinkedIn URL.             |

### Enrichment

| Tool                    | What it does                                                                       |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `find_email`            | **Credits.** Finds a professional email from a full name, a company and a country. |
| `find_phone`            | **Credits.** Finds a phone number from a LinkedIn profile URL.                     |
| `verify_email`          | **Credits.** Verifies an email address.                                            |
| `get_enrichment_result` | Reads a job that was still running.                                                |

The three enrichment tools wait up to 90 seconds for the result. A longer job comes back with its `jobId` and `status: "running"`: ask the assistant to check it later with `get_enrichment_result`.

### Deliverability

| Tool                   | What it does                                                                   |
| ---------------------- | ------------------------------------------------------------------------------ |
| `list_email_providers` | Your sending mailboxes, passwords masked. Can list only the disconnected ones. |
| `get_warmup_status`    | Warmup of each mailbox: running or not, score, sent, received, spam.           |
| `set_warmup`           | Turns the warmup of a mailbox on.                                              |

### Known quirks

* **`find_email` needs `country`.** The tool marks it optional, but the API refuses a search without it. Always give the country of the company.
* **`set_warmup` with `enabled: false` fails** with "Warmup not found": the tool sends the id of the mailbox where the API expects the id of the warmup. Turn the warmup off in the Emelia app.
* **`get_warmup_status` returns every mailbox at once**, whatever the `page` you pass.
* **`get_campaign_stats` on an unknown campaign** shows "Invalid or disabled Emelia API key", because the statistics route answers `401`. Check the campaign id before your key. Its `end` date is an exact bound: a date without time excludes that day.

## Limits

The server has no quota of its own: it uses the one of your account. The tools that read or change campaigns, mailboxes and warmup count in your [per minute quota](https://docs.emelia.io/docs/rate-limits.md) (30 to 1,000 requests per minute depending on your plan). The enrichment tools and the list and contact tools are not counted. Over the quota, a tool fails with "Emelia API error (500)": wait a minute.

Requests to the server are limited to 4 MB, and each tool returns the whole API response, without truncation: ask for small pages on big lists.

## Troubleshooting

| Symptom                                                      | Cause                                                                                                                                                      |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Missing Emelia API key` (JSON-RPC error `-32001`, HTTP 401) | The header did not reach the server. Check the client configuration.                                                                                       |
| "Invalid or disabled Emelia API key"                         | The key is wrong, disabled or deleted, or the campaign of `get_campaign_stats` does not exist. Create a new key in **Settings, API & Webhooks** if needed. |
| "Emelia API error (500)"                                     | Usually the per minute quota. Wait a minute.                                                                                                               |
| "Emelia API error (400): ..." with a JSON body               | The API refused the request; the message says why, for example `"country" is required`.                                                                    |
| `405` on `/mcp`                                              | The server only answers `POST`. A `GET` in the browser is expected to fail.                                                                                |
| `406` or `415`                                               | The client does not send `Accept: application/json, text/event-stream` or `Content-Type: application/json`.                                                |
| A tool is missing                                            | The server covers the 26 tools above. Everything else is in the [REST API](https://docs.emelia.io/docs/all-endpoints.md).                                                           |

## Prompts to try

* "List my campaigns and tell me which ones are running."
* "Add Claire Fontaine, CTO at Nexora, [claire.fontaine@nexora.io](mailto:claire.fontaine@nexora.io), to my **Q4 SaaS founders** list." She enters the campaigns of that list.
* "What is the reply rate of my **Q4 SaaS founders** campaign since Monday, step by step?"
* "Find and verify the email of Hugo Martin at Brightlane, in France, then add him to my **Warm leads** list."
* "Which of my mailboxes are disconnected, and which have a low warmup score?"

> **Your assistant acts with your key.** The assistant can change your campaigns and spend your credits. Keep the confirmations of your client on for tools that delete data or use credits.
