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
- MCP overview: https://sending.dev/docs/mcp/overview
- Credentials and scopes: https://sending.dev/auth.md
- REST reference: https://sending.dev/docs/api/rest

