Hosted MCP Resource Server (OAuth — no API keys)
For a client that supports remote MCP servers with OAuth 2.1 + PKCE (e.g. Claude Code, Claude.ai connectors), connect directly to https://mcp.motorical.com instead of running the local package — no mk_live_/ak_live_/MOTORICAL_JWT to manage. The first tool call triggers a normal OAuth consent screen in the browser.
Connect
Pick the tab that sounds like you. You need only one. The server address is the same everywhere:
https://mcp.motorical.com/v1/motorical/mcp
- I use a chat app (Claude, ChatGPT)
- I use a coding agent or editor
- I run my own local server (npm)
For you if: you talk to an assistant in an app or in the browser and you do not use a terminal. Nothing to install.
Claude app or claude.ai (tested):
- Open the connectors settings (Settings, then Connectors) and choose Add custom connector.
- Name it
Motorical, paste the address above, and click Connect. - Your browser opens: sign in, or create your account. Set up two-factor authentication (required, cannot be skipped), then press Allow.
- Back in the chat, ask: "Set up Motorical for me and send a test email to myself."
ChatGPT (tested 2026-10-14: sign-in, a real send with the outcome read back, and a second dedicated connector all work; setup from OpenAI's documentation): turn on developer mode (in Settings; the menu names change between releases, and on a work plan an admin may need to allow custom connectors), create a custom connector, paste the address above, and choose OAuth as the sign-in method. Connecting does not by itself make the assistant use the tools: in a chat, name what you want, for example "Use the Motorical connector's motorical_get_onboarding_state tool to show my account state". A vaguer request such as "show my Motorical account" may send the assistant to the website instead. ChatGPT does not ask for extra permissions by itself: for webhooks or Motor Block management, add the dedicated server as a second connector (webhook management also needs a paid plan; without one it answers 403 subscription_required).
For you if: you work in a terminal or an editor with an AI agent that supports remote MCP servers. Nothing to install either.
Claude Code (tested):
-
In a normal terminal, not inside a Claude session, run:
claude mcp add --transport http motorical https://mcp.motorical.com/v1/motorical/mcp -
Start a new Claude Code session (one that was already open may not list the new server).
-
Type
/mcp, pickmotorical, and choose Authenticate. -
Your browser opens: sign in, or create your account. Set up two-factor authentication (required, cannot be skipped), then press Allow.
-
Back in the session the Motorical tools are there. You do not run Authenticate a second time.
Codex (setup from OpenAI's documentation; not yet tested with Motorical):
codex mcp add motorical --url https://mcp.motorical.com/v1/motorical/mcp
codex mcp login motorical
Cursor (not yet tested): add {"mcpServers": {"motorical": {"url": "https://mcp.motorical.com/v1/motorical/mcp"}}} to .cursor/mcp.json.
VS Code with GitHub Copilot (accepted by the sign-in server since 2026-10-14; not yet tested end to end): add {"servers": {"motorical": {"type": "http", "url": "https://mcp.motorical.com/v1/motorical/mcp"}}} to .vscode/mcp.json, start the server from the MCP view, and finish the sign-in in the browser.
Any other agent: add the address above as a remote (streamable HTTP) MCP server with OAuth.
For you if: your client cannot use remote MCP servers, you want the server on your own machine, or you need allowlisting by 6-digit code, the browser-handoff tool, or unmasked recipient addresses. You do not need this to use Motorical from a chat app or a coding agent: the other two tabs are simpler and keep every key out of your assistant's hands.
-
Install and sign in with the local package (details, tools and Cursor configuration are on the local server page):
npx @motorical/mcp login -
Your browser opens once to approve access. The login is stored on your machine and refreshes silently.
Will my agent be able to sign in? Motorical's sign-in uses client ID metadata documents (CIMD) and does not offer dynamic client registration. Claude Code is tested end to end. VS Code (with GitHub Copilot) presents a metadata document and has been accepted since 2026-10-14. ChatGPT (it presents https://chatgpt.com/oauth/codex/client.json) signs in the same way. The Cursor domain is on the trusted list, but we have not confirmed that Cursor uses metadata documents. An agent that can only register itself dynamically cannot sign in to the hosted server yet. If yours cannot, you have two other routes that need no OAuth from your agent: agent-led onboarding over the HTTP API or the local npm server (third tab).
Want an account before you connect? Create it at https://motorical.com/register, then connect; sign-in at the consent step works the same. The npm package @motorical/mcp is the local option from the third tab, and @motorical/cli is retired.
What happens in the browser, for the first two tabs: you create your account or sign in, set up two-factor authentication, and press Allow. Consent then resumes by itself, with no second Authenticate. Your new account starts on the free developer sandbox, so you can send a first email to yourself right away.
The first consent on the main server asks only for what a trial needs: account state, domains, sandbox, recipients and sending. The tool list shows only what your connection may use, so on the first sign-in you will not see webhook or Motor Block tools at all. To use them, connect the dedicated server for that area (Webhooks or Motor Blocks below), whose consent asks only for that permission. Webhook management also needs a paid plan, and the sandbox does not offer it. You can also add it to the connection you already have: in the dashboard, Settings, API, Connected AI Agents, choose Allow next to the permission (or open https://motorical.com/settings/api-access?add=webhooks, or ?add=motor-blocks). The tools appear the next time the agent's tool list is loaded: start a new chat, or refresh the connector in your client. No reconnect is needed. An agent that is already running in the same chat may keep its old list until then.
Scoped servers
8 scoped servers, each a distinct RFC 8707 audience — a token minted for one is rejected by every other, so connecting a narrow one genuinely reduces what the client can do:
| Server | URL | Tools |
|---|---|---|
| Main (everything below) | https://mcp.motorical.com/v1/motorical/mcp | all of the below |
| Transactional | https://mcp.motorical.com/v1/motorical_transactional/mcp | motorical_get_message, motorical_get_message_events, motorical_get_send_status, motorical_integrate_send, motorical_send_email, motorical_wait_for_outcome |
| Analytics | https://mcp.motorical.com/v1/motorical_analytics/mcp | motorical_get_account_rate_limits, motorical_get_anomalies, motorical_get_daily_summary, motorical_get_deliverability, motorical_get_error_codes, motorical_get_logs, motorical_get_message_by_smtp_id, motorical_get_metrics, motorical_get_onboarding_state, motorical_get_overview, motorical_get_providers, motorical_get_rate_limits, motorical_get_reputation, motorical_list_motor_blocks |
| Domains | https://mcp.motorical.com/v1/motorical_domains/mcp | motorical_domain_add, motorical_domain_check_dns, motorical_domain_list, motorical_domain_verify, motorical_get_config, motorical_get_domain_health |
| Sandbox | https://mcp.motorical.com/v1/motorical_sandbox/mcp | motorical_sandbox_status, motorical_sandbox_provision, motorical_sandbox_convert (allowlisting by 6-digit code remains dashboard-only; recipients confirm by emailed link instead — see Free-account recipients below), motorical_free_recipient_add, motorical_free_recipient_list, motorical_free_recipient_remove |
| Motor Blocks | https://mcp.motorical.com/v1/motorical_motor_blocks/mcp | motorical_motor_block_list, motorical_motor_block_create, motorical_motor_block_rename, motorical_motor_block_change_type, motorical_motor_block_assign_domain, motorical_motor_block_deactivate, motorical_motor_block_reactivate, motorical_motor_block_delete, motorical_motor_block_delete_status — scope manage:motor-blocks |
| Webhooks | https://mcp.motorical.com/v1/motorical_webhooks/mcp | motorical_webhook_create, motorical_webhook_delete, motorical_webhook_get_deliveries, motorical_webhook_get_stats, motorical_webhook_list, motorical_webhook_test, motorical_webhook_update |
| Signup | https://mcp.motorical.com/v1/signup/mcp | motorical_signup_handoff — the one deliberate exception: unauthenticated, no OAuth grant needed. For apps that implement an OAuth client (hosts, embedded agent apps); it needs that client's OAuth values (client id, registered redirect URI, PKCE challenge, resource). A person in Claude Code, Claude Desktop or another chat client with no account should connect the Main server instead and authenticate: the browser opens the sign-in page, they create the account there, set up MFA (required, cannot be skipped), and press Allow; consent resumes by itself |
Account-wide vs. Motor-Block-scoped
Domain tools, list_motor_blocks, the motorical_free_recipient_* tools, and the Motor Block lifecycle tools motorical_motor_block_list, motorical_motor_block_create and motorical_motor_block_delete_status are account-wide: no Motor Block selection needed, works from a brand-new account before any Motor Block exists (a Motor Block is created from a verified domain, not the reverse). Every other tool is bound to whichever Motor Block(s) the OAuth grant covers; when the grant covers more than one, name the block with motorBlockId.
Tool names above are the exact names a client sees — pass them verbatim. The full catalogue, with each tool's scopes and the API route it wraps, is published as machine-readable JSON at mcp-catalogue.json.
motorical_get_config and motorical_get_domain_health sit on the Domains server rather than Analytics: they read config.read, which only the manage:domains scope grants, and a server requests the union of its tools' scopes — so putting them on Analytics would have made connecting an analytics client ask for domain-write authority.
The domain tools each call the same Public API route documented under AI Agent Quickstart: motorical_domain_list → GET /api/public/v1/domains, motorical_domain_add → POST /api/public/v1/domains, motorical_domain_verify → POST /api/public/v1/domains/{id}/verify, motorical_domain_check_dns → POST /api/public/v1/domains/{id}/check-dns.
The analytics and health tools each wrap one Public API route one-to-one, all under /api/public/v1: motorical_get_overview → GET /motor-blocks/{id}/overview, motorical_get_daily_summary → .../daily-summary, motorical_get_metrics → .../metrics, motorical_get_deliverability → .../deliverability, motorical_get_reputation → .../reputation, motorical_get_anomalies → .../anomalies, motorical_get_providers → .../providers, motorical_get_error_codes → .../error-codes, motorical_get_rate_limits → .../rate-limits, motorical_get_logs → .../logs, and motorical_get_message_by_smtp_id → GET /messages?smtpMessageId=.
The webhook tools likewise wrap one route each, all under /api/public/v1/motor-blocks/{id}/webhooks: motorical_webhook_list → GET on the collection, motorical_webhook_create → POST on the collection, motorical_webhook_update → PUT /{webhookId}, motorical_webhook_delete → DELETE /{webhookId}, motorical_webhook_test → POST /{webhookId}/test, motorical_webhook_get_deliveries → GET /{webhookId}/deliveries, and motorical_webhook_get_stats → GET /{webhookId}/stats. They sit on their own Webhooks server, which requests both read:webhooks and manage:webhooks. The three read-only tools — motorical_webhook_list, motorical_webhook_get_deliveries, motorical_webhook_get_stats — are reachable with either scope; the four write tools — motorical_webhook_create, motorical_webhook_update, motorical_webhook_delete, motorical_webhook_test — still require manage:webhooks specifically (which implies webhooks.read, so a manage-scoped grant can call every webhook tool). motorical_webhook_create returns the endpoint's signing secret exactly once; every later read masks it.
Two of these behave differently from the rest. motorical_get_account_rate_limits → GET /account/rate-limits is account-scoped: it reports the ceiling across every Motor Block and needs no motorBlockId, like the domain tools. And motorical_get_message_by_smtp_id is a lookup, not a listing — it requires an exact SMTP Message-ID and returns at most one message; use motorical_get_message when you hold the internal send UUID instead.
Recipient addresses in log and message results are masked. Unmasking requires the logs.pii scope, which is never granted to an OAuth token — passing includePII: true returns a 403 by design. Use the local server with a dashboard session if you need unmasked data.
Sandbox credentials and auth method visibility
Sandbox credentials follow the same never-over-the-wire principle as the PII masking above. Over this hosted OAuth connection, motorical_sandbox_provision never returns credentials — the response just confirms that credentials aren't included. Provisioning adds the new Motor Block to your authorization, and the backend checks your current authorization on every call, so the new block is usable immediately by naming it explicitly with motorBlockId — no token refresh or re-authorization is needed. (A call that names no block still uses the one block an older token was minted with.) After converting to a verified production domain with motorical_sandbox_convert, the response points you to a dashboard link instead of printing the credential inline — that's where you view or regenerate it. Conversion is also a one-way production identity transition: you may choose the production name and type (transactional or general_purpose), and the block's SMTP username is replaced with a production-derived one. The block keeps its id, password, API keys and auth method — only the username changes, so every SMTP client must switch to the new username (the response reports previousSmtpUsername, smtpUsername, credentialChanges and an integrationActionRequired note). The local MCP server, by contrast, runs as your own process under a dashboard session and does return credentials directly when you provision; because that's your own infrastructure, keeping that value secure from there on is on you.
Separately, a Motor Block's current authentication method — Password, API Key, OAuth 2.0, or mTLS — is visible read-only through motorical_get_config on the Domains server. Changing it is still a dashboard-only action; no MCP tool can flip it.
Two ways to start
An account with no plan and no domain starts one of two ways: with the person's own domain (on a Free account, when automatic provisioning is enabled and the domain is fully verified, a sandbox Motor Block is created on it automatically once DKIM and SPF pass; otherwise call motorical_sandbox_provision), or on a Motorical-owned .sandbox domain (instant, no DNS) from motorical_sandbox_provision. Use your own domain when the person has one whose DNS they control and want to keep; use the sandbox domain when they are only trying things, have no domain yet, or no human is at the keyboard. motorical_get_onboarding_state returns both options and this rule. The decision, both journeys and how each path is limited are in Two ways to start and the Agent Hub; this page covers only what the hosted connection adds: the manage:recipients scope, the three recipient tools below, and the re-consent note (an authorization granted before that scope existed must be re-approved to include it).
Free-account recipients
Free accounts can send test email only to their own address and to people who have allowed it. The Sandbox and Main servers carry tools for that, under the separate scope manage:recipients (an existing manage:sandbox authorization does not include it and must be re-approved to include manage:recipients). How these tools fit the two starting paths, and the limits that apply, are in Two ways to start:
| Tool | What it does |
|---|---|
motorical_free_recipient_add | Emails a person a confirmation link. They must open it and click the button themselves; this tool never confirms for them. The answer is the same whether or not the email was sent, so it cannot reveal who has stopped. |
motorical_free_recipient_list | Lists the addresses you have asked, with status, the recipient limit and usage. |
motorical_free_recipient_remove | Removes an address by its id from the list. Asks for confirmation. |
They wrap the account-scoped /api/public/v1/account/free-recipients routes.
Production Motor Block lifecycle
The Motor Blocks server (https://mcp.motorical.com/v1/motorical_motor_blocks/mcp, scope manage:motor-blocks) lets a subscribed account manage its ordinary production Motor Blocks without opening the dashboard. Only transactional and general_purpose blocks are managed; sandbox, marketing and portal blocks are refused. It wraps the account-scoped /api/public/v1/account/motor-blocks* routes.
| Tool | What it does |
|---|---|
motorical_motor_block_list | Lists production blocks covered by your current grant, including inactive ones. Shows each block's domain, activeAuthMethod (read-only) and credentialsAvailable: false. |
motorical_motor_block_create | Creates a block on a verified, non-sandbox domain you own. Requires a UUID v4 idempotencyKey; reuse it unchanged when retrying so you get the same block, never a duplicate. Subject to your plan's Motor Block limit. |
motorical_motor_block_rename | Changes the display name only. Rename never changes the SMTP username or any credential. |
motorical_motor_block_change_type | Switches between transactional and general_purpose. Asks for confirmation. |
motorical_motor_block_assign_domain | Moves a block onto another verified, non-sandbox domain. Asks for confirmation. |
motorical_motor_block_deactivate | Pauses a block — sends are refused until it is reactivated. Reversible; nothing is deleted. Asks for confirmation. |
motorical_motor_block_reactivate | Resumes a paused block. Refused if it has no verified domain or deletion is already queued. |
motorical_motor_block_delete | Permanently deletes a block. Asynchronous and irrecoverable. The block must be deactivated first, and you must state deleteHistory explicitly (true also deletes its message logs and events). Asks for confirmation and returns a jobId. |
motorical_motor_block_delete_status | Polls a deletion by jobId; still works after the block is gone. |
Things an agent should know up front:
- A newly created block is usable immediately. Creation adds the block to your current authorization in the same step, so
motorical_send_emailwith thatmotorBlockId(start withdryRun: true) works on the same connection — no token refresh. - Credentials are never returned here. Responses carry
credentialsAvailable: falseand a dashboard link; the password, API-key secrets and certificates are only ever shown in the dashboard. The auth method is readable but can only be changed in the dashboard. - Deactivate and delete are different things. Deactivate is a reversible pause; delete is permanent. Deleting one block never affects other blocks that share its domain.
- Confirmations are bound to the request. Consequential operations (type change, domain assignment, deactivate, delete) ask for confirmation, and the confirmation only applies to the exact arguments that were shown. If your client cannot answer a confirmation prompt, the reply also carries a plain
confirmation_requiredmessage: ask the person to confirm the exact action, then call the tool again withconfirm: true, which the server honors. - Errors are machine-readable. They carry a stable machine-readable
code(for examplemotor_block_limit_reached,domain_not_verified,motor_block_name_conflict,motor_block_must_be_inactive,motor_block_history_present,motor_block_not_authorized) and, where useful, anextAction. A request that names two different Motor Blocks is refused withmotor_block_id_conflict. - Communications (marketing) blocks are not part of this server.
What's not here yet
Not available over OAuth today: allowlisting by 6-digit code (to confirm a recipient over OAuth, use motorical_free_recipient_add with scope manage:recipients instead). motorical_sandbox_allowlist_request, motorical_sandbox_allowlist_confirm and motorical_web_handoff are dashboard-session-only (MOTORICAL_JWT) — no Public API route backs them. Calling them through an OAuth-connected client fails closed with an explicit error rather than a confusing 401. Use the local server for these. motorical_sandbox_status, motorical_sandbox_provision, and motorical_sandbox_convert call the account-scoped /api/public/v1/account/sandbox* routes and work over OAuth like any other account-scoped tool.
Public API surface with no MCP tool yet: exports is reachable via the Public Analytics API but has no MCP tool. Growing — this list shrinks as tools are added, check back or see openapi.json for the full route inventory.
Related
- Motorical MCP overview — which server to use
- Local MCP Server (npm package) — for the dashboard-only sandbox tools (allowlisting by 6-digit code, browser handoff)
- AI Agent Quickstart
- OpenAPI