Skip to main content

Motorical for Agents

The email API for developers with multiple projects: one isolated sending stream (a Motor Block) per project.

An agent working on behalf of a developer, an agency, or a SaaS with multiple tenants routes here first, whether it arrived from motorical.com, GitHub, npm, or mcp.motorical.com directly.

What Motorical is​

Motorical is a transactional email API and SMTP provider: HTTP POST /v1/send, SMTP on mail.motorical.com, signed delivery webhooks, and live delivery observability. It fits the same job class as SendGrid, Postmark, Mailgun, and Amazon SES — the same kind of infrastructure a backend calls to send real email, not a marketing-list tool and not a consumer inbox. Every account can hold more than one Motor Block, and every Motor Block is a complete, isolated sending identity: its own domain, its own credentials, its own rate limits, its own logs. Agents can operate Motorical directly over MCP — sending, checking delivery status, and managing Motor Block lifecycle — not just reading documentation about it. The account layer sits above all of this: one account can own several Motor Blocks at once, each free to fail, pause, or rotate credentials without the others noticing.

A Motor Block is Motorical's SMTP sending block: one isolated sending stream per project, with its own domain, credentials, limits, logs, webhooks and analytics.

Think of a Motor Block the way you'd think of a dedicated mail server per project, except nothing to run: one staging Motor Block and one production Motor Block for the same app, each on its own sending domain, so a staging mistake cannot burn the production domain's reputation — blocks that share a sending domain also share that domain's standing with inbox providers, so keep staging and production on separate domains; one Motor Block per tenant in a multi-tenant SaaS, so one tenant's complaint spike never throttles another's. Nearest equivalents elsewhere, not identical: Postmark Servers, SendGrid subusers, Mailgun subaccounts.

Not for you if: the project only needs local development email capture, sends a handful of internal test messages with no need for deliverability or logs, or the actual requirement is a marketing/newsletter tool with no API or SMTP integration — see the Communications Block note in the route chooser below for that last case.

Route chooser​

Pick the row that matches the situation, not the product structure:

SituationRoute
The human has no accountThe signup server, then Journey C below
An account exists; you operate it from a chat client or IDE agent with a person presentHosted MCP over OAuth (/ai-mcp-hosted), Journey B below
Your own app with an MCP client and an interactive userHosted OAuth — client metadata document registration rules are still being verified; see Journey D below
Headless automation or a backendAPI keys: the local server or the HTTP API directly
A script or shell with no MCP client, starting from nothingREST onboarding: POST /api/auth/register, verify-code, set-password, then the sandbox routes — see AI Agent Quickstart
Client cannot do remote OAuth MCP, or needs sandbox allowlisting, browser handoff, or unmasked PIILocal server
Bulk or marketing email to listsThe Communications Block, through its API and dashboard — not available over MCP today. Never send marketing through a transactional Motor Block.

On the packages: @motorical/cli is retired. It covered only onboarding and wrapped REST endpoints that remain, so the terminal-only path above is REST onboarding, not a CLI install. The local MCP server's own sandbox tools need a dashboard login token, which the REST steps above return directly (set-password returns a JWT and refresh token). Hosted MCP with the signup handoff is preferred whenever a person is present, because the agent never holds a secret at all.

Servers, scopes, and tools​

ServerScopesToolsCanonical URI
mainsend:transactional, read:analytics, read:domains, manage:domains, manage:sandbox, read:webhooks, manage:webhooks, manage:motor-blocks47https://mcp.motorical.com/v1/motorical/mcp
transactionalsend:transactional, read:analytics6https://mcp.motorical.com/v1/motorical_transactional/mcp
analyticsread:analytics14https://mcp.motorical.com/v1/motorical_analytics/mcp
domainsread:domains, manage:domains6https://mcp.motorical.com/v1/motorical_domains/mcp
sandboxmanage:sandbox5https://mcp.motorical.com/v1/motorical_sandbox/mcp
webhooksread:webhooks, manage:webhooks7https://mcp.motorical.com/v1/motorical_webhooks/mcp
motorBlocksmanage:motor-blocks9https://mcp.motorical.com/v1/motorical_motor_blocks/mcp
signupnone (unauthenticated)1https://mcp.motorical.com/v1/signup/mcp

Connect main for a full setup on one consent. Connect a narrow server instead when the task only needs one resource area — a token minted for one server's canonical URI is rejected by every other, so narrowing the server genuinely narrows what the connected client can do, not just what it's expected to do.

Rules​

  1. 202 is not delivered. A successful POST /v1/send means accepted for delivery, nothing more. Poll status or use motorical_wait_for_outcome for a terminal result before telling a human an email arrived.
  2. Default to dryRun: true. Validate the payload first; only remove it once you mean to send for real.
  3. Never ask the human for secrets in chat. An API key, password, or OAuth token typed into a chat message is a credential leak waiting to happen — use the signup handoff or the dashboard instead.
  4. Ask for the narrowest scope that does the job, and say what each one means in plain language before requesting consent. manage:motor-blocks is not the same as send:transactional — don't request more than the task needs.
  5. Deactivate is not delete. Deactivating a Motor Block is a reversible pause; deleting one is permanent and asynchronous. Restate the consequence before a human confirms either, and never treat them as interchangeable.
  6. Choose a Motor Block by boundary, not by convenience. One Motor Block per project, ideally per sending domain — staging and production are separate Motor Blocks, not a flag on one.
  7. Follow nextAction and error codes instead of retrying blind. A failure carries a stable machine- readable code (for example motor_block_limit_reached, domain_not_verified) and, where useful, a nextAction — read it before deciding what to do next.
  8. Read live account state before acting. Call motorical_get_onboarding_state or motorical_list_motor_blocks first; the current OAuth grant is checked live on every call, never from a claim frozen in an old token.
  9. Publish DNS records exactly as returned. A domain does not become sendReady until DKIM and SPF are both configured — re-check with motorical_domain_check_dns rather than assuming a DNS edit propagated.
  10. Never ask for unmasked PII over a hosted OAuth grant. Recipient addresses are masked by default; includePII: true over OAuth returns a 403 by design — that boundary is intentional, not a bug to work around.
  11. Never send marketing through a transactional Motor Block. The Communications Block is a separate product for bulk and marketing sends; mixing the two risks the transactional stream's deliverability.

Journeys​

Each journey below is real, validated content — every tool name in it is checked against the live MCP tool registry, the same gate that protects the rest of this site. The machine-readable version of everything below is agents.json.

Journey A — coding assistant adding email to an app​

Route: local server (API keys) or the HTTP API directly.

  1. Get a Motor Block API key (mk_live_...) from the dashboard, or start from the developer sandbox instead — see Journey C for a zero-credential start.
  2. Dry-run the payload: motorical_send_email (or POST /v1/send) with dryRun: true.
  3. Remove dryRun and send for real once the payload validates.
  4. Check delivery status rather than assuming success: motorical_get_send_status, motorical_get_message, motorical_get_message_events, or motorical_wait_for_outcome for a terminal result.
  5. Optional: register a webhook (motorical_webhook_create) for delivery/bounce/complaint events instead of polling — available on both the local server and hosted OAuth's dedicated webhooks server (read:webhooks/manage:webhooks scopes).

Journey B — operator agent running a customer's account over MCP​

Route: hosted MCP over OAuth, with a person present for consent.

  1. Connect to the hosted MCP server — main for a full setup on one consent, or a narrow scoped server for least privilege. The human sees a browser consent screen naming the requested scopes.
  2. Read live account state before acting: motorical_get_onboarding_state, motorical_list_motor_blocks.
  3. Operate within the granted scope: send email, read analytics (motorical_get_overview, motorical_get_deliverability), or manage Motor Blocks (motorical_motor_block_list, motorical_motor_block_create).
  4. A consequential change — motorical_motor_block_change_type, motorical_motor_block_assign_domain, motorical_motor_block_deactivate, motorical_motor_block_delete — needs a second call with confirm: true after restating exactly what will happen; a form-based client just answers that through its UI instead of a second tool call, but the two-step shape is the same everywhere since @motorical/mcp 1.9.4. Deactivate is reversible; delete is permanent and asynchronous — never treat them as interchangeable.

Journey C — agent whose human has no account​

Route: the signup server, then Journey B.

  1. Call motorical_signup_handoff on the unauthenticated signup server — no Motorical account or credential needed yet.
  2. Hand the returned one-time URL to the human: it runs signup and OAuth consent in the same browser visit. No credential of any kind is ever returned to the agent.
  3. Continue as Journey B — the OAuth grant from consent is usable immediately, no separate step needed. The account starts on the unpaid developer sandbox, outbound-locked to an allowlist.
  4. To send in production, convert the sandbox Motor Block onto a domain the human owns: motorical_sandbox_convert needs an active Motorical plan — it throws subscription_required with err.data.upgradeUrl if none exists yet; retry the same call once the human has subscribed. Say to the human: "To move off the sandbox onto your own domain, you'll need an active Motorical plan — here's the link to subscribe."
  5. Add the domain and complete DNS verification before any production send is possible: motorical_domain_add returns the exact DNS records, motorical_domain_verify confirms ownership, motorical_domain_check_dns confirms DKIM/SPF are live. A domain is not sendReady until both are configured. Say to the human: "Add these DNS records at your domain registrar, then let me know once they're live so I can verify them."

Journey D — agent embedding Motorical in its own agent app​

Not yet written. The OAuth client registration rules for an app's own client metadata document are unverified against the live hosted server (a test with a fake client id returned "client_id domain is not permitted") — writing real steps before that's settled would mean guessing at behavior nobody has confirmed. Use Journey A or B in the meantime.

Machine twin​

Everything on this page that an agent needs to act on — the journeys, the scopes, human-required flags, and stop conditions — is also published as machine-readable JSON at docs.motorical.com/agents.json, generated from the same source this page renders from.