ThreadCamp
Start free
MCP server

ThreadCamp as agent tools

The ThreadCamp MCP server exposes the whole email platform as callable tools for any MCP-compatible agent - Claude, Cursor, OpenAI Agents and others. It is a thin wrapper over the /v1 REST API, so tools behave exactly like the endpoints they call.

Connect

Over stdio, run npx -y @threadcamp/mcp. It reads two environment variables: THREADCAMP_API_KEY (required - a sk_live_ or sk_test_ key; try the public sandbox key sk_test_sandbox_threadcamp_public_demo) and THREADCAMP_BASE_URL (optional, defaults to https://www.threadcamp.com).

{
  "mcpServers": {
    "threadcamp": {
      "command": "npx",
      "args": ["-y", "@threadcamp/mcp"],
      "env": {
        "THREADCAMP_API_KEY": "sk_live_..."
      }
    }
  }
}

Running several products? Point THREADCAMP_ACCOUNT_SOURCESat each one's .env.local. Every key stays in the project that owns it, and every tool then takes an account argument. Call list_accounts first to see what is configured.

{
  "mcpServers": {
    "threadcamp": {
      "command": "npx",
      "args": ["-y", "@threadcamp/mcp"],
      "env": {
        "THREADCAMP_ACCOUNT_SOURCES": "/path/to/duebay/.env.local,/path/to/job13/.env.local"
      }
    }
  }
}

Or connect by URL, with nothing to install. The hosted server speaks Streamable HTTP at https://www.threadcamp.com/api/mcp and authenticates with the same Bearer key. Because that key already names one account, the hosted server omits the account-selection tools and create_account - the latter is an unauthenticated operation and has no business behind an authenticated endpoint. Everything else is identical: both shapes are built from one tool definition, so they cannot drift apart.

{
  "mcpServers": {
    "threadcamp": {
      "url": "https://www.threadcamp.com/api/mcp",
      "headers": { "Authorization": "Bearer sk_live_..." }
    }
  }
}

Tools

The server advertises typed tools for every operation ThreadCamp’s public API actually supports. Your client lists them automatically once connected.

whoami(account?)

Account, plan, usage, verified domains, default inbox - and the calling key's MODE. Call it before a production run to prove you are on a live key and the right product's account.

list_accounts((none))

List ready and unavailable account sources without exposing API keys. stdio only.

create_account(email?, password?, key_name?, key_mode?)

Create an account and receive its initial API key once; it cannot be recovered. Omit BOTH email and password for a machine account keyed only by its API key. stdio only.

get_account / update_account / delete_account(account?, email or confirm_email)

Read, update or delete only the selected authenticated account. Deletion revokes its keys but leaves provider-hosted mail intact. stdio only.

list_api_keys / create_api_key / get_api_key / update_api_key / delete_api_key(account?, api_key_id, name?, mode?)

Full self-owned API-key CRUD. Secrets are returned only when a key is created; reads expose safe metadata only.

create_inbox / list_inboxes / get_inbox / update_inbox / delete_inbox(account?, inbox_id, display_name?, domain?, autonomy?, callback_url?, forward_to?)

Full CRUD for an account's inboxes. forward_to sends replies on to a human; set it to null on update to stop.

send_email / send_email_batch(from, to[], subject, markdown? | text? | html?, button?, cc?, bcc?, scheduled_at?, client_id?)

Send an email. Prefer markdown: it renders into both a styled HTML part and a matching plain-text part, so links stay clickable in one and readable in the other. button adds a call to action. From an approve-first inbox the send is held and returns pending_approval. A test-mode key validates in full, delivers nothing, and returns the rendered html and text.

list_messages / list_inbox_messages / get_message / search_messages(account?, inbox_id?, message_id, query, status?, limit?)

Read real mailbox data for the selected, isolated account.

list_threads / get_thread(account?, thread_id, inbox_id?, limit?)

Conversations, with their messages embedded oldest-first. The call to make before replying.

wait_for_message(account?, inbox_id, timeout_seconds?)

Poll an inbox for a new inbound message (an OTP email, say) up to timeout_seconds, returning the newest inbound message once one arrives.

list_attachments / get_attachment(account?, message_id | thread_id, attachment_id)

Attachment metadata, and a five-minute signed download URL. Fetch it; do not store it.

add_domain / list_domains / get_domain / delete_domain(account?, name, inbound_host?, domain_id)

Manage custom domains and read the DNS records to publish. Inbound defaults to mail.<name>, so ThreadCamp's MX cannot take over mailboxes on your root domain.

check_domain(account?, domain_id)

Run a real verification check. DKIM is polled and every record is resolved live, so the result says WHICH record is missing, wrong or in conflict. Read each record's status and found, not just the overall status.

create_route / list_routes / update_route / delete_route(account?, match, destination, inbox_id?, route_id, enabled)

Full CRUD for SRS forwarding routes in a selected account.

list_suppressions / add_suppression / remove_suppression(account?, address)

Addresses ThreadCamp will not send to. Bounces, complaints and unsubscribes land here automatically; remove one only when you know why it was suppressed.

list_approvals / resolve_approval(account?, approval_id, action)

The human-in-the-loop queue. Approving a held message sends it.

list_events(account?, limit?)

The account's activity log, derived from real message records.

Worked example: retrieve an OTP

The canonical agent email job: create an inbox, use its address to sign up somewhere, then call wait_for_message to pull the verification code out of the inbound email.

// Agent task: sign up for a service and retrieve the OTP.

// 1. Give the agent an inbox
create_inbox({ display_name: "Signup Agent" })
// -> { "id": "inbox_...", "address": "signup-agent@relay.threadcamp.com" }

// 2. (agent uses that address to sign up on the target site)

// 3. Wait for the verification email to land
wait_for_message({ inbox_id: "inbox_...", timeout_seconds: 60 })
// -> { "id": "msg_...", "direction": "inbound",
//      "subject": "Your code is 481920",
//      "text": "Your one-time code is 481920." }

// The agent parses the code from the message and continues the flow.

MCP questions

What is MCP?

The Model Context Protocol is an open standard for exposing tools and data to AI agents. An MCP server advertises a set of callable tools; an MCP-compatible client (Claude, Cursor, OpenAI Agents and others) discovers them and calls them during a task. ThreadCamp's MCP server wraps the /v1 REST API as tools so an agent can send and receive email without writing HTTP code.

How do agents discover ThreadCamp?

Two ways. Over stdio, run `npx -y @threadcamp/mcp` with either one THREADCAMP_API_KEY or a multi-account source. Or connect by URL to the hosted server at https://www.threadcamp.com/api/mcp, passing the same Bearer key - no install. Either way the client lists the tools automatically. For non-MCP discovery, ThreadCamp also publishes llms.txt, an OpenAPI spec at /openapi.json and machine-readable pricing at /pricing.json.

Can I try it without signing up?

Yes. Use the public sandbox key sk_test_sandbox_threadcamp_public_demo as THREADCAMP_API_KEY. It authenticates against the API in test mode so an agent can create an inbox and exercise the tools before you sign up for a live key.

Wire ThreadCamp into your agent.

Start with the sandbox key, then sign up for a live key when you ship.

Start freeRead the docs