MCP server
SpacePost speaks the Model Context Protocol, so AI assistants can send email and manage domains, API keys, webhooks, audiences, contacts, broadcasts, suppressions and tenants on your behalf.
Every endpoint in the API reference is an MCP tool. The tools are generated from the same OpenAPI document as the reference, so when the API gains a feature, the MCP server offers it automatically: there is no separate list to maintain or wait for.
You can connect in two ways:
- Hosted (recommended):
https://api.spacepost.dev/mcp, Streamable HTTP, authenticated with your API key. Nothing to install. - Local:
npx -y @spacepost/mcp, a stdio server that calls the API from your machine. The tool definitions ship inside the package, so it starts offline.
Connect to the hosted server
Section titled “Connect to the hosted server”Send your API key as a bearer token: Authorization: Bearer sp_live_....
claude mcp add --transport http spacepost https://api.spacepost.dev/mcp \ --header "Authorization: Bearer sp_live_YOUR_API_KEY"Use claude mcp list to confirm.
Claude Desktop starts local (stdio) servers from claude_desktop_config.json, so bridge the hosted endpoint with mcp-remote
(Settings, Developer, Edit Config):
{ "mcpServers": { "spacepost": { "command": "npx", "args": [ "-y", "mcp-remote", "https://api.spacepost.dev/mcp", "--header", "Authorization:${SPACEPOST_AUTH}" ], "env": { "SPACEPOST_AUTH": "Bearer sp_live_YOUR_API_KEY" } } }}Restart Claude Desktop. Or use the local server instead.
Add to .cursor/mcp.json in your project, or ~/.cursor/mcp.json globally:
{ "mcpServers": { "spacepost": { "url": "https://api.spacepost.dev/mcp", "headers": { "Authorization": "Bearer sp_live_YOUR_API_KEY" } } }}Add to .vscode/mcp.json:
{ "inputs": [ { "id": "spacepost-key", "type": "promptString", "description": "SpacePost API key", "password": true } ], "servers": { "spacepost": { "type": "http", "url": "https://api.spacepost.dev/mcp", "headers": { "Authorization": "Bearer ${input:spacepost-key}" } } }}VS Code asks for the key the first time and keeps it out of the file.
Narrow the tool list with query parameters on the URL, for example https://api.spacepost.dev/mcp?read_only=true&toolsets=emails,domains.
The hosted server is stateless: each request is independent, so GET and DELETE on /mcp answer 405 and there is no session to resume.
Run the server locally
Section titled “Run the server locally”| Variable | Required | Description |
|---|---|---|
SPACEPOST_API_KEY |
Yes | Your API key |
SPACEPOST_BASE_URL |
No | Alternate API URL, default https://api.spacepost.dev |
SPACEPOST_DEFAULT_FROM |
No | Sender used when the assistant calls send_email without from, for example Acme <hello@acme.com> |
SPACEPOST_READ_ONLY |
No | true is the same as --read-only |
SPACEPOST_TOOLSETS |
No | Same as --toolsets, for example emails,domains |
SPACEPOST_PERMISSION |
No | Same as --permission; set sending_access when the key is send-only |
claude mcp add spacepost -e SPACEPOST_API_KEY=sp_live_YOUR_API_KEY -- npx -y @spacepost/mcpAdd -e SPACEPOST_DEFAULT_FROM="Acme <hello@acme.com>" to set a default sender, or flags after the package name, such as npx -y @spacepost/mcp --read-only.
{ "mcpServers": { "spacepost": { "command": "npx", "args": ["-y", "@spacepost/mcp"], "env": { "SPACEPOST_API_KEY": "sp_live_YOUR_API_KEY", "SPACEPOST_DEFAULT_FROM": "Acme <hello@acme.com>" } } }}{ "mcpServers": { "spacepost": { "command": "npx", "args": ["-y", "@spacepost/mcp", "--toolsets", "emails,domains"], "env": { "SPACEPOST_API_KEY": "sp_live_YOUR_API_KEY" } } }}{ "inputs": [ { "id": "spacepost-key", "type": "promptString", "description": "SpacePost API key", "password": true } ], "servers": { "spacepost": { "type": "stdio", "command": "npx", "args": ["-y", "@spacepost/mcp"], "env": { "SPACEPOST_API_KEY": "${input:spacepost-key}" } } }}npx -y @spacepost/mcp --help lists the options, and --list-tools prints the tools a configuration exposes.
Options
Section titled “Options”| Local flag | Hosted query | Effect |
|---|---|---|
--read-only |
read_only=true |
Only tools for GET endpoints (list_*, get_*, get_broadcast_readiness) |
--permission sending_access |
automatic, from your key | Only the tools a sending_access key can use |
--toolsets emails,domains |
toolsets=emails,domains |
Only tools of these API areas: emails, domains, apikeys, webhooks, audiences, contacts, broadcasts, suppressions, tenants (the reference’s sections; case, spaces and dashes are ignored, so api-keys works too) |
Both can be combined.
How tools map to the API
Section titled “How tools map to the API”- One tool per endpoint, named after the endpoint’s
operationIdin snake_case:sendEmailbecomessend_email,getBroadcastReadinessbecomesget_broadcast_readiness,pauseTenantbecomespause_tenant. The API reference documents every field. - Arguments are one flat object: path parameters (in snake_case, e.g.
id,audience_id,ref), query parameters (limit,after,before) and the fields of the JSON body (from,to,subject, …). If a body field has the same name as a parameter, it is calledbody_<field>. A body that is not an object, such as the array forsend_batch_emails, is passed asbody. idempotency_keyonsend_emailandsend_batch_emailssets theIdempotency-Keyheader, so retries never send twice.- Results are the API’s JSON response, also as structured content. Errors come back with
isError: trueand the same{ "statusCode", "name", "message" }body as the REST API, plus a hint on what to do next. - Annotations tell the client what a tool does: read tools are
readOnlyHint, deletes,cancel_emailandpause_tenantaredestructiveHint, and the tools that send email (send_email,send_batch_emails,send_broadcast) areopenWorldHint. Clients use them to decide when to ask you before running a tool.
Example prompts
Section titled “Example prompts”- “Send a test email from onboarding@test.spacepost.dev to delivered@test.spacepost.dev saying hello.”
- “Add the domain acme.com and tell me which DNS records to create.”
- “Did the email I sent to ada@example.com yesterday get delivered?”
- “Cancel the scheduled email to the beta list.”
- “Create a webhook to https://acme.com/hooks for bounces and complaints.”
- “Draft a broadcast to my Newsletter audience, check it for deliverability problems, but don’t send it yet.”
- “Which of my tenants are paused, and why?”