Agent Skill

Connect an AI agent to Sending over MCP

Connect to Sending's MCP server and get the right permissions. Use this before anything else, and whenever a tool answers forbidden while the connection looks fine.

Skill connect-mcp · the same bytes agents read at /.well-known/agent-skills/connect-mcp/SKILL.md

Connect to Sending over MCP

Endpoint: https://sending.dev/api/mcp (Streamable HTTP). The server is remote: there is no Sending npm package to install, and we publish no SSE endpoint.

Two credentials, two uses

API key (server to server, one fixed workspace):

Authorization: Bearer sk_...

You create it in the dashboard under Settings › API Keys. The plaintext value is shown only once, at creation. Scopes are chosen at that moment.

OAuth 2.1 (on behalf of a user): dynamic client registration at https://sending.dev/api/auth/mcp/register (RFC 7591), then authorization_code with PKCE S256. Metadata lives at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource.

An agent cannot create an account on its own: a human has to open the workspace.

How the user adds you to their client

If the user is reading you but has not connected you yet, these are the commands to give them. Full guide: https://sending.dev/docs/mcp/clients

Claude Code:

claude mcp add --transport http sending https://sending.dev/api/mcp \
  --header "Authorization: Bearer sk_..."

Cursor (.cursor/mcp.json), Claude Code by hand (.mcp.json, which also needs "type": "http") and generally any client that accepts headers:

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

VS Code uses the servers key instead of mcpServers, and wants "type": "http".

ChatGPT (developer mode) and claude.ai / Claude Desktop (custom connector) take the URL only: they do not accept headers, so they go through OAuth and the permissions are picked on the consent screen.

Clients that speak stdio only go through the mcp-remote bridge: npx -y mcp-remote https://sending.dev/api/mcp --header "Authorization: Bearer sk_...".

When a tool answers forbidden

This is the most common case, and reconnecting does not fix it.

MCP clients do not know our scope catalogue, so at authorize they almost always ask for the OIDC scopes alone (openid, profile, email, offline_access): those are in fact the only ones listed in scopes_supported.

The effective permissions are the ones the user picks on the consent screen, where the full catalogue is shown with the requested ones pre-selected. They stay editable afterwards, under MCP Connections, without reconnecting the client.

So: when you get forbidden, ask the user to open MCP Connections and enable the area you need. Do not retry in a loop, and do not try to request the scope in a new authorize call: nothing would change.

Assignable areas: automations, campaigns, commerce, contacts, domains, email, events, inbox, integrations, messages, utm, webhooks, in the :read, :write or :send forms depending on the area, plus * for full access.

Before you start working

Call get_usage: it returns the plan, the month's included quota, current consumption and capacity limits (contacts, domains, inboxes, seats). It saves you from building a campaign that would be refused at the end of the flow.

Codes: 401 missing or invalid credential, 403 missing scope, 402 plan quota exceeded.

Documentation

Use it

Point your agent at the file, or paste it into a system prompt. The tools it names live on our MCP server, so an agent needs to be connected first and needs the scopes for what it is about to do.

Connect over MCP · Documentation · Raw markdown

The other skills

Start with Sending

Give your agent something worth sending.

3,000 messages a month, free. No card. The MCP endpoint is on every plan, including this one.