---
title: "MCP server"
description: "Connect Grok, Cursor, or Claude Code to the Mailfully MCP server to send email and check email status and domains with an API key."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://mailfully.com/docs/llms.txt). Append `.md` to any page URL for its markdown version.

Mailfully runs an MCP server, so an AI agent tool can send email and look up what happened to it. The agent uses your API key and gets the same results the API would give you.

## Connect

| Setting | Value |
|---|---|
| URL | `https://api.mailfully.com/mcp` |
| Header | `Authorization: Bearer <key>` |

The server works with test keys (`mf_test_`) and live keys (`mf_live_`). Your tool can list the tools without a key, but every tool call needs one.

## Grok

Tell Grok in chat:

```
Add a custom MCP server named mailfully at https://api.mailfully.com/mcp
with the header Authorization: Bearer mf_test_xxxxxxxxxxxx
```

Replace the example key with your own.

## Cursor

Add this to `.cursor/mcp.json` in your project:

```json
{
  "mcpServers": {
    "mailfully": {
      "url": "https://api.mailfully.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:MAILFULLY_API_KEY}"
      }
    }
  }
}
```

Cursor reads the key from the `MAILFULLY_API_KEY` environment variable, so the key stays out of the file and out of your repository.

## Claude Code

Run this in your terminal:

```bash
claude mcp add --transport http mailfully https://api.mailfully.com/mcp \
  --header "Authorization: Bearer $MAILFULLY_API_KEY"
```

## Tools

| Tool | What it does |
|---|---|
| `send_email` | Sends one email and returns its id |
| `get_email` | Gets one email by id, with its latest status |
| `list_emails` | Lists recent emails, newest first, with filters for status and recipient |
| `list_domains` | Lists your sending domains and whether each is verified |
| `get_domain` | Gets one domain with the DNS records to add at your DNS provider |

The tools never return what an email says: not its body (`html` or `text`) and not its subject. They return its id, status, recipients, and dates. Password-reset links and one-time codes often sit in those fields, and an agent can be tricked into passing on what it reads.

When an agent retries a send, it should pass the same `idempotency_key` it used the first time. The email is then sent only once. See [Idempotency](https://mailfully.com/docs/concepts/idempotency).

## Test and live keys

A test key sends to a simulator and never reaches a real inbox. Start with one while you try things out. See [Test mode](https://mailfully.com/docs/guides/test-mode).

A live key sends real mail. It needs a [verified domain](https://mailfully.com/docs/guides/verify-a-domain), and every account limit applies, the same as when you call the API directly.

## Use a separate key

Give each agent tool its own key, so you can see what it sent and revoke it without touching your other keys.

- Start with a test key.
- When you move to a live key, limit it to one sending domain.
- When you stop using the tool, revoke its key in the [dashboard](https://dashboard.mailfully.com) under **API keys**.

See [API key security](https://mailfully.com/docs/concepts/api-key-security) for scopes and where to store a key.

## Troubleshooting

- **401**: the key is missing or wrong. Check the `Authorization` header and that the key was copied in full.
- **403 `invalid_api_key`**: the key was revoked. Create a new one in the dashboard.
- **403 `insufficient_scope`**: the key cannot send. Create a key with the `send` scope.
- **Other refusals** come from the API unchanged, with the same type and message. Look them up in [Errors](https://mailfully.com/docs/concepts/errors).
