senderkit_
so they don’t collide with other servers in a multi-server setup.
No MCP prompts or resources are exposed — tools only.
Structured results
Every tool on the hosted server (https://mcp.senderkit.com) declares an
MCP outputSchema — a JSON Schema for its result, visible in tools/list —
and returns its result as structuredContent conforming to that schema. The
same object is also serialized as JSON in the text content, so clients that
predate structured results see exactly the same data. The advertised schemas
set additionalProperties: false, so a result never carries fields beyond
what its schema lists.
The result shapes mirror the corresponding REST responses, minus internal
identifiers: senderkit_messages_list / senderkit_messages_get return the
public publicId (msg_…) — the id every other message tool takes — but
not the database row id, the workspace id, or the provider-connection id
that GET /v1/messages still includes, and inbound-domain DNS records carry
type/name/value/priority/purpose only. The schemas are published
as Zod shapes in @senderkit/sdk/mcp (contextOutput, sendOutput,
messagesListOutput, …, one per tool) alongside the input shapes.
The local stdio server bundled with the CLI returns the SDK client’s shapes
(unwrapped arrays for the list tools) and does not declare output schemas
yet.
Workspace
senderkit_context
Report the connected workspace and the active send mode. No parameters.
Call this before sending when you need to confirm which workspace subsequent
calls will affect, or whether messages will really be delivered (live) or
only recorded in test mode (test). The mode is fixed per connection —
derived from the API key prefix for API-key connections (sk_live_ /
sk_test_), or from the workspace/mode you chose on the consent screen for
OAuth connections.
Returns { workspace: { id, slug, name }, mode: "live" | "test" } — the
only identifier here is the workspace’s own id.
Sending
senderkit_send
Send a templated message to a recipient. Dispatches a real message; live vs
test mode is fixed per connection (call senderkit_context
to confirm before sending). The result includes a mode field alongside the
message ID and status.
The most common tool — an agent uses this when you ask it to “send the welcome
template” or “email a notice to user@example.com”. Mirrors the
POST /v1/send endpoint.
string
required
Recipient address — email address, E.164 phone number, push device token, or
JSON-encoded web-push
PushSubscription."email" | "sms" | "push" | "web-push"
Force a channel. Defaults to the template’s primary channel.
object
Free-form metadata as a JSON object of scalar values. Indexed for filtering
in
senderkit_messages_list.string
ISO 8601 timestamp for scheduled delivery.
Must be in the future, within 30 days.
string
Idempotency key. Repeat values return the
original send instead of duplicating.
string[]
Email-only. Cc recipients as a JSON array of addresses (max 50).
string[]
Email-only. Bcc recipients as a JSON array of addresses (max 50).
string
Email-only. Reply-To address.
Attachment[]
Email-only. Up to 10 MB total across all attachments. Each
Attachment is
{ filename, contentType, content (base64), inline?, contentId? }.string
Email-only. From address override (bare address). Must match a verified custom sending domain when using the managed email sender.
string
Email-only. From display name override, rendered as
Name <address>. Max 128 characters; no control characters or angle brackets. Always applies, regardless of sending domain.senderkit_send_raw
Send inline content without a registered template. Dispatches a real message;
live vs test mode is fixed per connection (call senderkit_context
to confirm). The result includes a mode field.
Useful for one-off sends an agent constructs in the moment — e.g. “draft and
send a status update to this list.” See
Template sends and raw sends.
"email" | "sms" | "push" | "web-push"
required
The channel to send on.
string
required
Recipient address — email address, E.164 phone number for
channel: "sms",
push device token for channel: "push", or the JSON-encoded browser
PushSubscription (endpoint + p256dh/auth keys) for channel: "web-push".
Non-E.164 SMS recipients are rejected.string
Email subject. Required for
channel: "email".string
Email preheader (the snippet preview some clients show).
string
Email HTML body. Required for
channel: "email".string
Email plain-text body.
string
Email from-address override. Must match a verified custom sending domain when using the managed email sender.
string
Email-only. From display name override, rendered as
Name <address>. Max 128 characters; no control characters or angle brackets. Always applies, regardless of sending domain.string
Message body. Required for
channel: "sms", channel: "push", and
channel: "web-push".string
Notification title. Required for
channel: "push" and channel: "web-push".integer
Badge count. Push and web-push.
string
Notification sound name. Push only.
string
Icon URL shown in the notification. Web-push only.
string
URL opened when the user clicks the notification. Web-push only.
object
Data payload as a JSON object of string values. Push and web-push.
object
Variables for interpolation. Only applied when
interpolate: true.boolean
Run server-side variable substitution over the inline content. Defaults to
false (content delivered verbatim).object
Free-form metadata.
string
ISO 8601 timestamp for scheduled delivery. Must be in the future, within 30 days.
string
Idempotency key.
string[]
Email-only. Cc recipients as a JSON array of addresses (max 50).
string[]
Email-only. Bcc recipients as a JSON array of addresses (max 50).
string
Email-only. Reply-To address.
Attachment[]
Email-only. Same shape as
senderkit_send.Templates
senderkit_templates_list
List available templates. No parameters.
Use when the agent needs to discover what’s available before sending — e.g.
asking “which templates exist?” — or to confirm a slug before referencing it.
Mirrors GET /v1/templates. See Templates.
senderkit_templates_get
Fetch a single template by slug.
Use to inspect a template’s current state — its channel, status, and currently
published version (excluding the raw content blob). Mirrors
GET /v1/templates/{slug}.
string
required
Template slug, e.g.
"welcome". Slugs are always lowercase.senderkit_templates_create
Generate a new template from a plain-language brief and save it as a draft.
The tool composes channel-native content server-side and returns a deep link to
review the draft in the editor. Nothing is sent until the user reviews and
publishes the draft. Template creation counts toward the workspace’s template
cap; the tool returns 409 template_limit_reached if the cap is hit before the
AI call runs.
This is a non-destructive write — creating a draft doesn’t modify or remove
anything that already exists.
"email" | "sms" | "push" | "web-push"
required
The channel for the new template.
string
required
Plain-language description of the message to generate (max 4,000 characters).
string
Lowercase URL-safe identifier (digits,
a-z, _, -). Converted to
lowercase automatically. Auto-derived from the brief if omitted; a numeric
suffix is appended on collision.string
Optional internal note (max 280 characters).
senderkit_templates_regenerate
Regenerate an existing draft template from a new brief.
This fully replaces the draft’s content and discards any manual edits made in
the editor — warn the user before calling. Only draft templates can be
regenerated; published templates are left untouched.
string
required
Slug of the draft template to regenerate.
string
required
New brief that fully replaces the draft’s content (max 4,000 characters).
Messages
senderkit_messages_list
List messages, optionally filtered.
The agent’s window into message history. Use it to answer
“did the welcome email to user@example.com go through?” or “show me recent
failures.” Mirrors GET /v1/messages.
integer
Max messages to return, 1-200 (default 50).
string
Pagination cursor from a previous response.
"scheduled" | "queued" | "rendered" | "dispatched" | "sent" | "delivered" | "failed" | "opted_out" | "blocked" | "canceled"
Filter by message status.
"email" | "sms" | "push" | "web-push"
Filter by channel.
string
Filter by template slug.
object
Filter by metadata; every key/value must match (jsonb containment).
senderkit_messages_get
Fetch a single message by ID.
Use to inspect the full record for one send — its current status, the
provider’s response, and the timeline of events. Mirrors
GET /v1/messages/{id}, minus the internal identifiers (see
Structured results); the message is keyed by its
public publicId.
string
required
Public message id, e.g.
"msg_…".senderkit_cancel_message
Cancel a still-pending (scheduled or queued) message by ID.
Use to abort a scheduled send before its
fire time, or pull back a message that hasn’t yet been handed to a provider.
Only scheduled and queued messages are cancelable — anything later returns
a 409, since delivery once started isn’t reversible. Mirrors
DELETE /v1/messages/{id}.
string
required
Public message id, e.g.
"msg_…".Inbound
Requires an API key or connection scoped for inbound email (theinbound scope).
senderkit_inbound_addresses_list
List the workspace’s programmatic inbound email addresses. No parameters.
Use to check which addresses already exist before creating another one, or to
find an address’s id. Mirrors GET /v1/inbound/addresses.
senderkit_inbound_addresses_create
Create a new inbound email address that receives mail for the workspace — on
the shared receiving domain or a verified custom domain
— and, optionally, forwards it and/or fires a webhook on receipt. Mirrors
POST /v1/inbound/addresses. This is a non-destructive write — it only adds
a new address.
string
Local part before the
@, e.g. "invoices" for
invoices@{slug}.in.senderkit.email — 1-64 chars of a-z, 0-9, ., _,
-, starting and ending alphanumeric (lowercased; some names are
reserved). Pass "*" for a catch-all that receives mail for every local
part no exact address claims. Omit to mint an unguessable random one.string
Optional internal note describing what this address is for. Max 200 characters.
string
Email address to forward received mail to. Must be a plausible address and
can’t be another inbound address (would create a mail loop).
string
This workspace’s webhook endpoint id to fire
message.received events to on
receipt — a bound endpoint receives them even if not subscribed, but must be
active and match this address’s livemode (test-mode addresses bind
test-mode endpoints). When unset, events fan out to every active endpoint
subscribed to message.received in the address’s mode.string
A verified custom inbound domain id
(from
senderkit_inbound_domains_list) to mint the address on. Omit for the
workspace’s shared receiving domain.boolean
Defaults to
true. Test-mode addresses receive real mail but fan out only
to test-mode webhook endpoints, and their forwards are recorded as test
sends without real delivery. Every address, test or live, counts toward the
plan’s inbound-address limit.senderkit_inbound_addresses_delete
Delete an inbound address by id. It immediately stops receiving new mail;
already-received messages are unaffected. Mirrors
DELETE /v1/inbound/addresses/{id}.
string
required
Inbound address id, e.g.
"inb_…".senderkit_inbound_messages_list
List received inbound messages for the workspace, newest first. Mirrors
GET /v1/inbound/messages.
string
Inbound address id (e.g.
"inb_…") to filter by.integer
Max messages to return, 1-100 (default 50).
string
ISO 8601 cursor — only return messages received strictly before this instant.
A non-ISO-8601 value is rejected with
invalid_request rather than silently
ignored.senderkit_inbound_messages_get
Fetch a single received inbound message by id — envelope, headers, subject,
body, attachments, and spam/auth verdicts. Mirrors
GET /v1/inbound/messages/{id}.
string
required
Inbound message id, e.g.
"rcv_…"./v1/inbound/* API links, not signed/presigned URLs — fetch them with an
Authorization: Bearer header carrying a key with the inbound scope. See
Inbound Email for the full reference.
senderkit_inbound_domains_list
List the workspace’s inbound domains — the shared receiving domain and any
custom domains — with their verification status and, for a pending custom
domain, the DNS records still required to verify it. No parameters. Mirrors
GET /v1/inbound/domains.
senderkit_inbound_domains_create
Claim a custom domain for receiving mail, e.g. "inbound.acme.com". Mirrors
POST /v1/inbound/domains. Returns the DNS records (an MX, plus a DKIM TXT
proving ownership — skipped if the domain already has a verified custom
sending domain, which reuses its identity) — surface these to the user
exactly as returned. Nothing is received until the records are live and a
background sweep verifies the domain.
string
required
Domain to claim for receiving, e.g.
"inbound.acme.com". Must not already
be claimed and must not be a senderkit.com/senderkit.email suffix.boolean
Only pass
true after the user has explicitly confirmed they want to
redirect this domain’s mail to SenderKit. Omit on the first attempt — if the
domain already has live MX records pointing elsewhere, the call fails with a
409 (existing_mx) naming the current mail host(s), so you can confirm
before retrying with this set.senderkit_inbound_domains_delete
Delete a custom inbound domain by id. Its addresses stop receiving mail
immediately. The workspace’s shared receiving domain can’t be deleted.
Mirrors DELETE /v1/inbound/domains/{id}.
string
required
Inbound domain id (UUID) to delete.
Errors
Tool failures come back as MCP errors with a single text message. The shape:- Validation —
invalid_request: <field> <message>. A missing required field, wrong type, or invalid ISO timestamp. Validation errors name the specific offending field rather than a generic message. - Domain —
<code>: <message>from the underlying API. e.g.template_not_found: No template "welcom",rate_limited: Too many requests. - Auth —
unauthorizedon a missing or invalid API key. - Permission —
insufficient_scopewhen the key is valid but doesn’t hold the scope required by the called tool. See Authentication → Scopes.
code /
message pair, so anything in the API troubleshooting guide applies here too.
Sending
How a send becomes a delivered message.
Messages
The lifecycle behind every tool response.
Inbound Email
Provision addresses and receive mail as a
message.received webhook.API Reference
The REST surface backing these tools.
Installation
Connect a client and start calling tools.