Install Sending in your agent

Add the Sending MCP server to Claude, ChatGPT, Cursor, VS Code and the other clients.

Sending is not installed: it is a remote MCP server. Nothing to download, no npm package, no process to keep running. Your client needs two things:

Endpointhttps://sending.dev/api/mcp
TransportStreamable HTTP
AuthAuthorization: Bearer sk_... (API key) or OAuth 2.1
Streamable HTTP is the only supported transport. We do not publish an SSE endpoint: if a client only speaks stdio or SSE, use the mcp-remote bridge.

Which credential to pick

API key if the client accepts custom headers (Claude Code, Cursor, VS Code, mcp-remote). You create it in Settings › API Keys, pick its scopes there, and see it in plaintext only once. It always points at the same workspace: the right choice for a project or a build machine.

OAuth 2.1 if the client opens a consent screen in the browser (ChatGPT, claude.ai, Claude Desktop). You paste no secret: you authorize with your account and choose the permissions on the consent screen. It is also the only route in clients that cannot send custom headers.

Neither one bypasses the sending guardrails (verified domain, suppression, idempotency, plan quota).

Claude Code

# with an API key
claude mcp add --transport http sending https://sending.dev/api/mcp \
  --header "Authorization: Bearer sk_your_api_key"

Add --scope user to get it in every project, --scope project to write it into the repo's .mcp.json (shared with the team: in that case do not put the key in plaintext). Check with claude mcp list: it must answer ✔ Connected.

By hand, in .mcp.json or ~/.claude.json:

{
  "mcpServers": {
    "sending": {
      "type": "http",
      "url": "https://sending.dev/api/mcp",
      "headers": { "Authorization": "Bearer sk_your_api_key" }
    }
  }
}
The type field is not optional: an entry with url but no type is read as an stdio server and skipped. If you set the Authorization header and the key is wrong, Claude Code reports the connection as failed and does not fall back to OAuth: remove the header to use consent.

Claude Desktop and claude.ai

These go through connectors, so OAuth.

Open connectors

Settings › Connectors, then Add custom connector.

Paste the endpoint

https://sending.dev/api/mcp, named Sending.

Authorize

The browser opens the Sending consent screen: pick the workspace and tick the permissions you want to grant the agent.

The client registers itself (RFC 7591), so there is no OAuth app to create.

ChatGPT

Custom connectors sit behind developer mode and accept only OAuth or no authentication: there is no way to pass an API key, use consent.

Enable developer mode

In ChatGPT web: Settings › Apps › Advanced settings › Developer mode.

Add the server

Create / Add custom connector, URL https://sending.dev/api/mcp, OAuth authentication.

Authorize and choose permissions

On first use, ChatGPT opens our consent screen.

From the API (Responses) the endpoint is passed as a tool, and there an API key works again:

{
  "model": "gpt-5",
  "tools": [{
    "type": "mcp",
    "server_label": "sending",
    "server_url": "https://sending.dev/api/mcp",
    "authorization": "sk_your_api_key",
    "require_approval": "always"
  }],
  "input": "How many emails do I have left this month?"
}
require_approval: "never" removes the human step in front of tools that really send. If you do it, keep the key on read-only scopes or bound sending with the plan caps.

Cursor

In .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "sending": {
      "url": "https://sending.dev/api/mcp",
      "headers": { "Authorization": "Bearer sk_your_api_key" }
    }
  }
}

Then Settings › MCP: the server must show up green with its tools listed.

VS Code (GitHub Copilot)

In .vscode/mcp.json. The key is servers, not mcpServers, and with inputs you type the key on first launch instead of committing it:

{
  "inputs": [
    { "id": "sending-key", "type": "promptString", "description": "Sending API key", "password": true }
  ],
  "servers": {
    "sending": {
      "type": "http",
      "url": "https://sending.dev/api/mcp",
      "headers": { "Authorization": "Bearer ${input:sending-key}" }
    }
  }
}

stdio-only clients (Cline, Windsurf, Gemini CLI)

Clients that do not speak remote HTTP go through mcp-remote, which bridges the two: stdio on one side, our endpoint on the other.

{
  "mcpServers": {
    "sending": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://sending.dev/api/mcp",
        "--header", "Authorization: Bearer sk_your_api_key"
      ]
    }
  }
}

Without --header the bridge starts the OAuth flow in the browser on first connection.

Any other client

If your agent is not in the list, these parameters are all it takes: URL https://sending.dev/api/mcp, streamable HTTP transport, header Authorization: Bearer <api key or access token>. A client that implements MCP fully finds everything on its own:

To hand an agent both REST and MCP in one go, there is a ready-made prompt.

Prompt pronto per il tuo agente

Tutta la conoscenza REST + MCP in un blocco, da incollare in Cursor o Claude Code. Oppure leggi /llms-full.txt.

Check that it works

Ask the agent to call get_usage: it is read-only, sends nothing, and answers with the plan, this month's quota and the capacity limits. If you get JSON back, the install is fine.

Permissions

With an API key, the permissions are the scopes you chose at creation, under API Keys.

With an OAuth connection (the client opens the consent screen) you choose the permissions at authorization time: the screen lists the full catalogue, with whatever the client asked for pre-selected. This is needed because MCP clients do not know Sending's scopes and usually ask for identity only: with nothing ticked, the tools answer forbidden: {"need":"..."}.

You can change the permissions of a live connection from MCP Connections, without revoking and reconnecting: they apply from the next call.

Creating a campaign takes campaigns:write (creation), contacts:read (to resolve the list's listId) and email:send (sending).

If something does not work

SymptomCauseFix
The server does not appear among the toolsJSON entry without type: "http"add type, restart the client
401key revoked, or header missingregenerate the key, or complete the OAuth flow
forbidden: {"need":"..."}permissions missing on the bindingMCP Connections, tick the required area; do not reconnect the client
402plan quota exceededcheck get_usage and Plans
Connection fails right after claude mcp addAuthorization header with an invalid keyfix the key, or remove it and use OAuth