MOLTED EMAIL

MCP Server

Connect any MCP-compatible agent runtime to the Molted Email API with the @molted/mcp server package.

The @molted/mcp package exposes the Molted Email API as discoverable tools for any runtime that supports the Model Context Protocol. Claude Desktop, Cursor, VS Code Copilot, Windsurf, and any other MCP client can use it to send email, manage threads, classify inbound messages, and more.

Installation

npx -y @molted/mcp

Or install globally:

npm install -g @molted/mcp

Environment variables

VariableRequiredDefaultDescription
MOLTED_API_KEYYes-Your Molted API key (mm_live_* or mm_test_*)
MOLTED_API_URLNohttps://api.molted.emailAPI base URL

Setup

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "molted": {
      "command": "npx",
      "args": ["-y", "@molted/mcp"],
      "env": {
        "MOLTED_API_KEY": "mm_live_..."
      }
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project:

{
  "mcpServers": {
    "molted": {
      "command": "npx",
      "args": ["-y", "@molted/mcp"],
      "env": {
        "MOLTED_API_KEY": "mm_live_..."
      }
    }
  }
}

VS Code Copilot

Add to .vscode/mcp.json in your project:

{
  "servers": {
    "molted": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@molted/mcp"],
      "env": {
        "MOLTED_API_KEY": "mm_live_..."
      }
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "molted": {
      "command": "npx",
      "args": ["-y", "@molted/mcp"],
      "env": {
        "MOLTED_API_KEY": "mm_live_..."
      }
    }
  }
}

HTTP transport

For cloud agents or server-side use, run in HTTP mode:

MOLTED_API_KEY=mm_live_... molted-mcp --transport http --port 3100

The HTTP transport is stateless -- each request creates a fresh MCP session. This works well for serverless deployments and load-balanced environments.

Tools

The MCP server exposes 25 tools across five groups, plus 8 resources and 5 prompts.

Budget

check_budget

Check remaining send capacity including daily/hourly limits and bounce/complaint budget. Call this before planning a campaign or batch send to verify you have capacity.

Parameters: None

Returns: { daily: { used, remaining }, hourly: { used, remaining }, negativeBudget: { bounces, complaints } }


Inbox and threads

read_inbox

List threads in a mailbox with optional filtering.

ParameterTypeRequiredDescription
mailbox_idstringNoFilter by mailbox UUID
statusstringNoFilter by status: open, waiting, resolved, escalated
limitnumberNoMax results (1-50, default 25)

Returns: { items: [{ id, contactEmail, subject, status, messageCount, lastMessageAt }], total }

get_thread

Get a full thread with all messages, intent classification, and SLA status.

ParameterTypeRequiredDescription
thread_idstringYesThread UUID

Returns: { thread: { id, status, contactEmail, ... }, envelopedMessages: [...] }

reply

Reply to a thread. Supports two modes:

  • Shorthand: Provide body (plain text) or html -- uses the _default template with an auto-generated dedupe key.
  • Template: Provide template_id, payload, and dedupe_key for custom templates.
ParameterTypeRequiredDescription
thread_idstringYesThread UUID to reply to
bodystringNoPlain text reply body (shorthand mode)
htmlstringNoHTML reply body (shorthand mode)
subjectstringNoOverride reply subject
template_idstringNoTemplate ID (template mode)
payloadobjectNoTemplate payload (template mode)
dedupe_keystringNoDeduplication key
send_reasonstringNoReason for sending (audit trail)

Returns: { status: "queued" | "sent", requestId }

archive

Archive a resolved thread, moving it out of the active inbox.

ParameterTypeRequiredDescription
thread_idstringYesThread UUID

Returns: { archived: 1 }

update_thread

Update a thread's status, metadata, or assignment.

ParameterTypeRequiredDescription
thread_idstringYesThread UUID
statusstringNoNew status: open, waiting, resolved, escalated
metadataobjectNoMetadata to set
assigned_agent_idstringNoAgent to assign to

Returns: The updated thread object.

approve

Approve a pending send in the approval queue (human-in-the-loop).

ParameterTypeRequiredDescription
thread_idstringYesThread UUID with pending approval
reasonstringYesReason for approving (audit trail)

Returns: Approval confirmation.


Sending

send_email

Send a policy-checked email. Supports shorthand (body/html) and template modes.

ParameterTypeRequiredDescription
tostringYesRecipient email
bodystringNoPlain text body (shorthand)
htmlstringNoHTML body (shorthand)
subjectstringNoSubject line (shorthand)
template_idstringNoTemplate ID
payloadobjectNoTemplate payload
dedupe_keystringNoDeduplication key
send_reasonstringNoReason for sending
mailbox_idstringNoMailbox to send from
idempotency_keystringNoIdempotency key for safe retries

Returns: { status: "queued" | "blocked" | "pending_approval", requestId }

Policy blocks are returned as successful results with the block reason so your agent can reason about alternatives.

draft_email

Draft an email with AI-assisted composition and policy pre-check.

ParameterTypeRequiredDescription
tostringYesRecipient email
contextobjectNoBackground context for draft generation

Returns: { draftCandidates: [...], policyPreCheck: { allowed, reason }, contactContext }

dry_run

Simulate a send without dispatching. Preview the policy decision.

ParameterTypeRequiredDescription
tostringYesRecipient email
template_idstringYesTemplate to simulate
dedupe_keystringNoDeduplication key
payloadobjectNoTemplate payload
mailbox_idstringNoMailbox to simulate from

Returns: { wouldAllow: boolean, reason?, cooldownExpiresAt?, simulation: true }

batch_send

Send to multiple recipients with per-recipient policy evaluation. Max 500 recipients per batch.

ParameterTypeRequiredDescription
template_idstringYesTemplate for all recipients
sendsarrayYesArray of { to, dedupe_key, payload?, send_reason? }
mailbox_idstringNoMailbox to send from

Returns: { batchId, total, queued, blocked, results: [{ recipientEmail, requestId, status, reason? }] }

schedule_followup

Schedule a delayed follow-up email that auto-cancels if the recipient replies.

ParameterTypeRequiredDescription
contact_emailstringYesContact to follow up with
thread_request_idstringYesRequest ID from the initial send
delay_minutesnumberYesDelay before sending (1-43200)
cancel_on_replybooleanNoAuto-cancel on reply
trigger_conditionsobjectNoCustom trigger conditions

Returns: { followupId, status, scheduledAt }


Intelligence

classify_inbound

Classify an inbound email's intent.

ParameterTypeRequiredDescription
subjectstringYesEmail subject line
body_textstringYesPlain text body

Returns: { intent, confidence, suggestedAction, flags?, safetyVerdict? }

Intent categories: interested, objection, not_now, support, billing, legal, security, out_of_office.

next_best_action

Get a recommendation for what to do next with a contact based on timeline, fatigue, and intent signals.

ParameterTypeRequiredDescription
contact_emailstringYesContact email address

Returns: { recommendation, reasoning, contactSummary: { email, lastSendAt, isSuppressed } }

Recommendations: reply, wait, nudge, stop, escalate.

get_context

Get full contact timeline including sends, replies, journeys, engagement history, and suppression status.

ParameterTypeRequiredDescription
contact_emailstringYesContact email address

Returns: { timeline: { sends, journeyRuns, inboundMessages }, suppressionStatus, activeIncidents, lastClassification }

batch_classify

Classify multiple inbound emails in one call.

ParameterTypeRequiredDescription
messagesarrayYesArray of { subject, body_text }

Returns: { results: [{ intent, confidence, suggestedAction }] } in the same order as inputs.

batch_next_action

Get next-best-action recommendations for multiple contacts.

ParameterTypeRequiredDescription
contact_emailsarrayYesArray of email addresses

Returns: { results: [{ contactEmail, recommendation, reasoning }] }


Governance and outcomes

add_suppression

Suppress a contact or domain so no further emails are sent to them. Provide either recipient_email (email-level) or domain (domain-level).

ParameterTypeRequiredDescription
recipient_emailstringNoEmail address to suppress
domainstringNoDomain to suppress (e.g. example.com)
scopestringNoScope: global, tenant, or campaign
reason_codestringNoReason code: complaint, hard_bounce, manual_dnc, legal_request, role_account, domain_suppressed, no_engagement
sourcestringNoSource of the suppression

Returns: The created suppression record.

check_suppression

Check if an email address or domain is currently suppressed. Call this before sending to verify the recipient is not on a suppression list.

ParameterTypeRequiredDescription
recipient_emailstringNoEmail to check
domainstringNoDomain to check

Returns: Suppression records if found, empty array if not suppressed.

remove_suppression

Remove a suppression so the contact or domain can receive emails again.

ParameterTypeRequiredDescription
suppression_idstringNoUUID of the email suppression to remove
domainstringNoDomain suppression to remove

Returns: { deleted: true }

Check consent status for a contact (GDPR/CCPA compliance).

ParameterTypeRequiredDescription
recipient_emailstringYesEmail address to check

Returns: { hasConsent: boolean, basis: string }

Record consent for GDPR/CCPA compliance.

ParameterTypeRequiredDescription
recipient_emailstringYesEmail address
basisstringYesLegal basis: explicit_opt_in, legitimate_interest, contractual, legal_obligation
sourcestringNoWhere consent was given (e.g. signup_form)
jurisdictionstringNoLegal jurisdiction (e.g. GDPR, CCPA)
granted_atstringNoISO 8601 timestamp when consent was granted
revoked_atstringNoISO 8601 timestamp when consent was revoked

Returns: The consent record.

record_outcome

Record a business outcome (conversion, revenue, engagement) linked to email touches. Molted automatically attributes the outcome to recent email interactions.

ParameterTypeRequiredDescription
contact_emailstringYesContact email
event_typestringYesactivation, trial_conversion, meeting_booked, deal_closed, upsell, or custom
event_namestringYesEvent name (e.g. purchase, demo_booked)
revenuenumberNoRevenue amount in cents
metadataobjectNoAdditional metadata
occurred_atstringNoISO 8601 timestamp (defaults to now)

Returns: The ingested outcome record with attribution data.

outcome_dashboard

Get a revenue attribution summary showing how email campaigns contributed to business outcomes.

Parameters: None

Returns: { totalRevenue, conversions, topCampaigns }

journey_impact

Analyze which journeys had the most impact on business outcomes.

ParameterTypeRequiredDescription
modelstringNoAttribution model: first_touch, last_touch, or linear (default last_touch)

Returns: Journeys ranked by outcome contribution.


Resources

Resources provide read-only context that agents can pull into their working memory without calling tools. Access them via resources/list and resources/read in any MCP client.

URIDescription
molted://mailboxesAll mailboxes with address, reputation, autonomy, and send limits
molted://mailboxes/{id}/configFull mailbox configuration: rules, SLA, alerts, autonomy level
molted://templatesAvailable email templates with variable schemas
molted://templates/{id}Specific template with version history
molted://segmentsAudience segments with filter definitions
molted://journeysActive email journeys with step definitions
molted://policy-rulesCurrent policy rules and thresholds
molted://domainsVerified sending domains with DNS and warmup status

Resources return JSON data from the Molted API. Template URIs ({id} parameters) auto-populate from the list callback, so MCP clients that support resource templates will show available mailboxes and templates as completions.

Prompts

Prompts are pre-built multi-step workflows that agents can invoke. Each prompt returns a message sequence that guides the agent through chaining multiple tools together.

draft-followup

Given a thread, draft an appropriate follow-up email. Reads the thread, checks budget, and composes a reply matching the conversation tone.

ArgumentTypeRequiredDescription
thread_idstringYesThread UUID to follow up on
mailbox_idstringNoMailbox UUID to send from

triage-inbox

Process unread threads: classify intent, recommend action, and auto-archive resolved/spam/OOO threads.

ArgumentTypeRequiredDescription
mailbox_idstringNoMailbox UUID to triage (omit for all)
max_threadsstringNoMaximum threads to process (default 20)

pre-send-check

Before sending an email, verify it is safe: check suppression status, consent, and remaining budget. Returns a GO / NO-GO recommendation.

ArgumentTypeRequiredDescription
to_emailstringYesRecipient email to validate
mailbox_idstringNoMailbox UUID to send from

investigate-bounce

Investigate why an email bounced and recommend corrective action. Automatically suppresses hard bounces.

ArgumentTypeRequiredDescription
thread_idstringYesThread UUID of the bounced email
mailbox_idstringNoMailbox UUID

campaign-readiness

Check if conditions are right to send a campaign to a segment: budget capacity, template readiness, domain health, and negative-signal budget.

ArgumentTypeRequiredDescription
segment_idstringYesSegment UUID
mailbox_idstringNoMailbox UUID
template_idstringNoTemplate UUID

Error handling

The MCP server maps API responses to structured tool results:

HTTP StatusBehavior
2xxSuccess with parsed JSON data
429Rate limited -- includes retry timing
403Insufficient scope -- key lacks required permissions
401Authentication error -- invalid or expired key
404Resource not found
5xxServer error

Policy blocks (e.g., suppressed contact, rate limit exceeded) are returned as successful results with the block reason. This lets your agent reason about why the send was blocked and decide on alternatives rather than treating it as an error.

Scoped keys

API keys can be scoped to specific mailboxes. When using a scoped key, all tools automatically operate within that mailbox's context. This is useful for multi-tenant setups where each agent should only access its own mailbox. See Authentication for details on key scoping.