Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.YS-projectcalc/agent-cold-email

REMOTE · AGENT-COLD-EMAIL-API.YAAKOVSCHER.WORKERS.DEV · 2 COMPONENTS · SCANNED SEP 20

Coldrig — cold-email infra run by your agent: 28 MCP tools, live sending, free sandbox. $99/mo.

0 this week 81 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →

Endpoint Security71
Transport & Reachability100
Schema Quality & AI Usability65
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 7428 tokens (~265/item across 28 items; 28 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage80
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 39% of tool parameters carry a description.Partial
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 28 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the io.github.YS-projectcalc/agent-cold-email MCP server?

io.github.YS-projectcalc/agent-cold-email is a hosted endpoint at https://agent-cold-email-api.yaakovscher.workers.dev/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

remote · agent-cold-email-api.yaakovscher.workers.dev

# add to Claude Code
claude mcp add --transport http ys-projectcalc-agent-cold-email 'https://agent-cold-email-api.yaakovscher.workers.dev/mcp'
// .cursor/mcp.json
{
  "mcpServers": {
    "ys-projectcalc-agent-cold-email": {
      "url": "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "ys-projectcalc-agent-cold-email": {
      "type": "http",
      "url": "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.ys-projectcalc-agent-cold-email]
url = "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ys-projectcalc-agent-cold-email": {
      "type": "remote",
      "url": "https://agent-cold-email-api.yaakovscher.workers.dev/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add ys-projectcalc-agent-cold-email --url 'https://agent-cold-email-api.yaakovscher.workers.dev/mcp' --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  ys-projectcalc-agent-cold-email:
    url: "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "ys-projectcalc-agent-cold-email": {
      "Transport": "http",
      "Url": "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
    }
  }
}
# add to Vellum
assistant mcp add ys-projectcalc-agent-cold-email -t streamable-http -u 'https://agent-cold-email-api.yaakovscher.workers.dev/mcp'
// mcp.json
{
  "mcpServers": {
    "ys-projectcalc-agent-cold-email": {
      "type": "http",
      "url": "https://agent-cold-email-api.yaakovscher.workers.dev/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 26 Aug 26 +2
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 25 Aug 26 0
    • Stability: 0.97 → pass security
  • 24 Aug 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 93 to 97. That category is still filling its 30-day observation window: 28 days of observed history at the previous scan, 29 at this one. The score rises as the window fills, whether or not the server changes.

  • 21 Aug 26 0
    • Tool “remove_mailboxes” rewrote its description, which is the text the model reads security
    • Tool “infrastructure_status” rewrote its description, which is the text the model reads security
    • Tool “contact_operator” rewrote its description, which is the text the model reads security
    • Tool “configure_webhook” rewrote its description, which is the text the model reads security
    • Tool “setup_infrastructure” rewrote its description, which is the text the model reads security
    • Tool “reply” rewrote its description, which is the text the model reads security
    • Schema quality: unverified → excellent functional
    • “configure_webhook” reworded the description of “eventTypes” cosmetic
  • 20 Aug 26 0
    • Tool “infrastructure_status” rewrote its description, which is the text the model reads security
    • Tool “setup_infrastructure” rewrote its description, which is the text the model reads security
    • Schema quality: 218 → 248 functional
    • Schema quality: excellent → unverified functional
    • “setup_infrastructure” added an optional parameter “distribution” cosmetic
    • “setup_infrastructure” made “inboxesEach” optional cosmetic
  • 19 Aug 26 0
    • Tool “infrastructure_status” rewrote its description, which is the text the model reads security
    • Tool “setup_infrastructure” rewrote its description, which is the text the model reads security
    • Tool “remove_mailboxes” rewrote its description, which is the text the model reads security
    • Tool “list_messages” rewrote its description, which is the text the model reads security
    • Tool “ack_message” rewrote its description, which is the text the model reads security
    • Schema quality: 193 → 218 functional
  • 12 Aug 26 0
    • New tool “contact_operator” functional
  • 11 Aug 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Probed https://agent-cold-email-api.yaakovscher.workers.dev/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=yaakovscher.workers.dev CN=WE1,O=Google Trust Services,C=US 12 Aug 2026 10 Nov 2026 ECDSA 256 ECDSA-SHA256 6f125888bafcff1313b2e68505955a7c
SANs: yaakovscher.workers.dev, *.yaakovscher.workers.dev
CN=WE1,O=Google Trust Services,C=US (CA) CN=GTS Root R4,O=Google Trust Services LLC,C=US 13 Dec 2023 20 Feb 2029 ECDSA 256 ECDSA-SHA384 7ff31977972c224a76155d13b6d685e3
CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE 15 Nov 2023 28 Jan 2028 ECDSA 384 SHA256-RSA 7fe530bf331343bedd821610493d8a1b

Background: What to check on a remote MCP endpoint →

DNSSEC insecure

Validation of agent-cold-email-api.yaakovscher.workers.dev. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
dev. present 60074 8 Verified
workers.dev. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication Challenged, unverified

The endpoint asked for a token, but we could not retrieve and validate the RFC 9728 metadata that tells a client how to obtain one.

Result Challenged, unverified
Enforced On tool calls
HTTP status 200

Protected resource metadata

Retrieved No
Problem no_resource_metadata

Background: How OAuth 2.1 works in the 2026 MCP spec →

Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://agent-cold-email-api.yaakovscher.workers.dev/mcp Verified 200
http (plaintext) http://agent-cold-email-api.yaakovscher.workers.dev/mcp Served over HTTP 200
MCP tools · 28 exposed · ~7,428 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
account ~204

Account overview: brand, plan, status, billingState, activationState, resource counts, usageCents, quota, deliverability (loop state: paused/throttled mailboxes, burning domains, auto-replacements, recentActions[]), and teardown (reclaim summary once canceled, else null). Billing is per-provisioned-mailbox: $49 platform + $10 x live provisioned mailboxes, minimum 5 ($99); the billed quantity tracks the real provisioned count (deprovision lowers it). activationState is the HONEST send state — trust it over 'sent' counts: 'active' = real sending live; 'pending_provisioning' = paid but infrastructure still being armed, sends shown are sandbox previews that DON'T leave; 'capacity_pending' = provisioning held at a spend/plan-slot limit; 'screening_hold' = account under review; 'sandbox' = demo/free. Use metrics for counts, infrastructure_status for per-mailbox health.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ack_message ~124

Acknowledge a message by id (from list_messages or infrastructure_status's messages[]) — sets it read so it stops surfacing as unacked. THIS IS THE ONLY THING THAT SETS readAt: reading or listing messages never marks them, so a message stays unacked until you call this explicitly. Idempotent: acking an already-acked id returns success with no second effect, never an error. 404 if the id doesn't exist for this tenant.

NameTypeReqDescription
messageIdstringyesThe message id, from list_messages or infrastructure_status's messages[].

No output schema declared.

No examples provided.

activity ~108

Unified activity feed: campaign events (sent/reply/bounce/...) merged with deliverability loop actions (pause/throttle/replace-domain). Cursor-paginated → { items[], nextCursor }; each item { id, kind:'event'|'deliverability', label, ts, target, detail }. Filters: kind, limit (default 50, max 200). Use inbox for replies only.

NameTypeReqDescription
cursorstring
kindstring
limitinteger

No output schema declared.

No examples provided.

campaign_results ~95

Outcome counts for ONE campaign. Input: campaignId (from launch_campaign). Returns { campaignId, sent, reply, bounce, complaint, unsubscribe, failed, soft_bounce } — bounce = HARD only, soft_bounce separate, opens not tracked. 404 if unknown. Use metrics for account-wide totals, list_campaigns for every campaign at once.

NameTypeReqDescription
campaignIdstringyesThe campaign id returned by launch_campaign.

No output schema declared.

No examples provided.

configure_byo_domain ~563

Register or advance a BYO domain/mailbox intake (SPEC.md §20). action = register (needs domain + domainRelationship: fresh_standalone|subdomain_of_primary|is_primary — runs the pre-flight live-infra scan + abuse gate + reputation ladder, returns the starting byoStatus) | poll_dns (needs id — re-checks DNS delegation/records, advances pending_dns → active, or → abandoned after 7 idle days) | acknowledge_consent (needs id + acknowledged:true — REQUIRED before a primary domain can proceed past pending_consent; this does not remove your business's exposure, it documents informed consent) | request_managed_mailboxes (needs id + count — platform-provisioned mailboxes on an ALREADY-ACTIVE domain, the primary shape; every response carries a `billing` projection { provisionedAfter, projectedMonthlyCents, formula } — quoteOnly:true previews it without provisioning) | connect_mailbox (needs id + email + transport — declares an EXISTING OAuth/SMTP+IMAP connection you already have, bypassing provisioning; transport is { kind:'smtp', host, port, secure, user, pass } | { kind:'gmail_api', clientId, clientSecret, refreshToken } | { kind:'ms_graph', mode, tenantId, clientId, clientSecret, refreshToken? }).

NameTypeReqDescription
acknowledgedbooleanRequired (must be true) for acknowledge_consent — SPEC.md §20.4's separate, unbundled risk acknowledgment.
actionstringyes
countintegerRequired for request_managed_mailboxes — how many platform-provisioned mailboxes to attach.
domainstringRequired for register.
domainRelationshipstringRequired for register: fresh_standalone | subdomain_of_primary | is_primary.
emailstringRequired for connect_mailbox — the existing mailbox address.
idstringRequired for poll_dns/acknowledge_consent/request_managed_mailboxes/connect_mailbox — the domainId from register.
personaSlugstringOptional for request_managed_mailboxes — defaults to a slug of the domain.
quoteOnlybooleanOptional for request_managed_mailboxes — true previews the new mailbox count + projected monthly price WITHOUT provisioning (SPEC §18 quote-before-add).
transportRequired for connect_mailbox — { kind: 'smtp', host, port, secure, user, pass } | { kind: 'gmail_api', clientId, clientSecret, refreshToken } | { kind: 'ms_graph', mode: 'delegated'|'app_only', tenan…

No output schema declared.

No examples provided.

configure_dashboard ~205

Write a saved dashboard view. action = create (needs name+layout) | update (needs id+rev+layout; optional name renames) | promote (id → default) | delete (id). update is rev-CAS: a stale rev returns { currentRev, currentLayout } to rebase and retry. Optional note. Read the current rev+layout via get_dashboard first.

NameTypeReqDescription
actionstringyes
idstringRequired for update/promote/delete.
layoutobjectRequired for create/update.
namestringRequired for create. Optional for update — pass it to rename the view; omit to leave the name unchanged.
notestringOptional human-readable note recorded alongside this edit (edited_by_note).
revintegerRequired for update — the rev this edit is based on; stale vs. the view's CURRENT rev returns a structured conflict with currentRev/currentLayout to rebase onto.

No output schema declared.

No examples provided.

configure_webhook ~272

Manage an outbound webhook subscription. action = create (needs url + eventTypes: reply|bounce|soft_bounce|complaint|unsubscribe; optional secret/active) | update (needs id + one changed field; active:true re-enables an auto-disabled one, active:false pauses; secret rotates) | delete (needs id). create/rotate return the HMAC signing secret ONCE. URLs must be https to a public host (private/metadata IPs rejected). Deliveries are signed X-Coldrig-Signature: sha256=HMAC-SHA256(secret, raw body).

NameTypeReqDescription
actionstringyes
activebooleanOptional. On update, active:true re-enables an auto-disabled subscription; active:false pauses delivery.
eventTypesarrayRequired for create: which events to push (reply | bounce | soft_bounce | complaint | unsubscribe).
idstringRequired for update/delete.
notestringIgnored placeholder for symmetry; webhooks record no provenance note.
secretstringOptional signing secret (>=16 chars). Omit on create to have one generated; pass on update to rotate.
urlstringRequired for create. HTTPS endpoint; private/link-local/metadata IPs are rejected.

No output schema declared.

No examples provided.

contact_operator ~380

Reach a human operator — for anything list_messages/infrastructure_status can't answer (a stuck vendor issue, a billing question, an account-level ask). Inputs: body (1-2000 chars), urgency ('normal' | 'needs_human', default 'normal'). Files a support ticket and notifies the operator; returns { ticketId, note, deduplicated }. Works in every account state a tenant token still authenticates in, including dunning-suspended, canceling and canceled — this is exactly the channel for 'why is my account suspended?'. The ONE exception is an admin-TERMINATED (abuse) account, whose token is rejected at auth with 401 before this tool runs. The operator's reply arrives as a message on THIS account (poll list_messages / infrastructure_status.messages[] — there is no separate reply-fetch call). Sending the IDENTICAL body AND urgency again within an hour returns the SAME ticketId and does not file a second ticket or send a second alert (`deduplicated: true` on that response; `false` when a new ticket was actually filed) — no separate idempotency key is needed to retry a dropped response. This is a TEXT match, not an intent match: the platform cannot tell a deliberate retry from a coincidentally-identical NEW message, so a genuinely new ask with the same wording collapses into the earlier ticket just as silently — vary the wording (or raise urgency, which is always treated as an escalation and files a new ticket) if you have something new to say. 'needs_human' also bypasses the ~10-minute ops-email throttle so an urgent message is pushed immediately. Rate-limited to 5 calls/hour per tenant — a 429 names retryAfter (seconds) when hit.

NameTypeReqDescription
bodystringyes
urgencystring

No output schema declared.

No examples provided.

get_byo_domains ~157

List your BYO (bring-your-own) domains, or (with id) one domain's full intake detail. No id → [{ domainId, domain, isPrimary, dnsMode, byoStatus, breakerTier, reputationBranch, mailboxCount }]. With id → adds the pre-flight scan result, abuse-gate verdict, and consent-acknowledgment status. byoStatus progresses pending_kyc|pending_consent|pending_dns → active (or rejected/abandoned). Use configure_byo_domain to register a new one or advance it.

NameTypeReqDescription
idstringOmit to list every BYO domain; pass an id for that domain's full intake detail (scan result, abuse verdict, consent status).

No output schema declared.

No examples provided.

get_dashboard ~99

Read saved dashboard views. No id → list all: [{ id, name, isDefault, rev, editedBy }]. With id → that view's full layout + rev (pass this rev as the CAS base to configure_dashboard update). Views are both agent- and human-editable; write them with configure_dashboard.

NameTypeReqDescription
idstringOmit to list every saved view (summary); pass a view id for its full layout + rev.

No output schema declared.

No examples provided.

get_webhooks ~109

List your outbound webhook subscriptions, or (with id) one subscription plus its recent delivery + attempt log. No id → [{ id, url, eventTypes, active, status, disabledReason, consecutiveFailures }]. With id → { subscription, recentDeliveries[], recentAttempts[] }. Secrets are never returned on reads — they are shown once at create/rotate.

NameTypeReqDescription
idstringOmit to list every subscription; pass an id for that subscription plus its recent delivery + attempt log.

No output schema declared.

No examples provided.

inbox ~148

Unified reply inbox across mailboxes. Cursor-paginated → { threads[], nextCursor }; each row: threadId, campaignName, leadEmail, subject, mailboxEmail, label, lastEventType, markStatus. Filters: mailbox, campaign, label, read, includeNonreply (bounces/OOO, default true), archived (exclude|include|only). Use thread for one thread's history.

NameTypeReqDescription
archivedstring
campaignstring
cursorstring
includeNonreplyboolean
labelstring
limitinteger
mailboxstring
readboolean

No output schema declared.

No examples provided.

infrastructure_status ~717

Warmup + provisioning progress per mailbox. New mailboxes are ramp-limited server-side: 5 sends/day week 1 rising to 40/day after 4 weeks; current dailyCap for each mailbox is in the response below — ramp caps permit CAPPED sending from day 1, never zero until fully warmed. Returns { domains, mailboxes, sendReady, mailboxHealth[], messages[], nextSteps }; each mailbox: warmupDay, dailyCap, sentToday, sendReady, delivStatus (healthy/throttled/paused), complaint/bounce/softBounce rates (first-party measured), vendorReputationScore + vendorPlacementRate (VENDOR-REPORTED, not first-party measurements — the control loop uses local signals only; BOTH ARE null whenever the provider does not report them, which is the normal case today, so treat null as 'not measured' and never as zero), lastPolledAt. Per-mailbox `sendReady` is a FULLY-RAMPED flag, NOT a send gate — a mailbox below full ramp still sends, capped at its own `dailyCap`; `sendReady` only says warmup has finished, so read `dailyCap`/`sentToday` for actual send capacity, never `sendReady` alone. The top-level `sendReady` is the AND across ALL mailboxes (true only once every one has finished ramping) — for whether THIS mailbox can send right now, the per-mailbox flag next to it is the one that matters, not the top-level one. Vendor-pool warmup (the underlying reputation-building the provider runs) is FEED-INVISIBLE by design: nothing in this response surfaces the vendor's own warmup internals — dailyCap/warmupDay/sendReady here are this platform's own ramp schedule, computed independently of whatever the vendor is doing in its pool, so do not expect a vendor-side warmup event to show up here. `messages[]` surfaces system notices this account should act on (e.g. a setup step that needs a retry, a mailbox credential that just went live) — each has kind, severity ('info' = resolves on its own | 'action_required' = nothing progresses until you act, and acting works | 'operator_pending' = the platform has stopped and n…

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

label_thread ~102

Set or clear a triage LABEL on an inbox thread — the same chip the dashboard shows. Inputs: threadId, label (string; pass label:null to clear). Distinct from mark (read/unread/archived state): a label is a free-form category, not a read flag. Filterable via inbox's label param.

NameTypeReqDescription
label
threadIdstringyesThe thread id, e.g. from inbox() or campaign events.

No output schema declared.

No examples provided.

launch_campaign ~266

Create and activate a campaign on a lead list. You supply name, offer, leads[], sequence[] (per step: subject, body, delayDays), sendWindow, timezone, stopOnReply — the platform does not write copy. Steps schedule up front; suppressed leads are skipped. Returns { campaignId }. Campaigns send real mail, so a launch identical to one this account made in the last 60 seconds is REFUSED with 409 { code:'duplicate_campaign', existingCampaignId } rather than contacting the same prospects twice — check that campaign instead of relaunching. Resend the same idempotencyKey to retry a call whose response you lost: that replays the original result instead of being refused. Campaigns that differ in any field, and deliberate relaunches after the window, are never blocked.

NameTypeReqDescription
idempotencyKeystringOptional idempotency key: resend the SAME key when retrying this call so a dropped-response retry is not applied twice (no duplicate campaign/provision/send).
leadsarrayyes
namestringyes
offerstringyes
sendWindowobject
sequencearrayyes
stopOnReplyboolean
timezonestring

No output schema declared.

No examples provided.

list_campaigns ~69

List every campaign at once: [{ campaignId, name, status, counts{sent,reply,bounce,complaint,unsubscribe,failed,soft_bounce} }], newest first — no per-campaign lookup needed. Use campaign_results for one campaign's counts, metrics for account-wide totals.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_leads ~165

List/export leads with their contact-level disposition, cursor-paginated. Returns { leads[], nextCursor }; each row: leadId, email, firstName, company, campaignId, campaignName, globalStatus, interestStatus, notes, tags, suppressed, lastEventType, lastEventTs, createdAt. Filters: campaign, interestStatus, suppressed, replied. This IS the export surface — paginate to dump the full book of business as JSON (no separate CSV endpoint). Use update_lead to write disposition, suppress_lead to opt an address out.

NameTypeReqDescription
campaignstring
cursorstring
interestStatusstring
limitinteger
repliedboolean
suppressedboolean

No output schema declared.

No examples provided.

list_messages ~307

List this tenant's system + operator messages (a retryable setup step, a credential going live, an operator notice), cursor-paginated. Unacked messages sort first (newest first within that group), then acked ones (also newest first). Returns { messages[], nextCursor }; each message: id, kind, severity ('info'|'action_required'|'operator_pending'|'terminal' — 'operator_pending' means the platform has stopped, nothing you change restarts it, and an operator clearing the blocker makes the SAME retry work, so keep the same inputs and idempotency key; 'terminal' means the platform has stopped and only a human can move it, so do NOT retry), body, actionHint (structured — e.g. which tool + idempotencyKey to retry with), source ('system'|'operator'), createdAt, readAt. `readAt` is set ONLY by an explicit ack_message call — LISTING messages never marks them, here or anywhere else, so calling this tool leaves every readAt exactly as it was. A null readAt therefore means 'not acked', which is NOT evidence the message was never seen: it may have been read and simply not acknowledged. Use ack_message to acknowledge one by id so it stops resurfacing. infrastructure_status also inlines the newest 5 unacked messages for a quick glance — this is the full paginated surface.

NameTypeReqDescription
cursorstring
limitinteger

No output schema declared.

No examples provided.

mark ~121

Set a thread's READ-STATE for inbox triage. Inputs: threadId, status = 'read' | 'unread' | 'archived' (archived hides it from the default inbox; refetch with inbox archived='include'/'only'). Returns { marked: true }. 404 if unknown. This is the read/archive flag ONLY — use label_thread for a triage label chip, reply to respond.

NameTypeReqDescription
statusstringyes
threadIdstringyesThe thread id, e.g. from inbox() or campaign events.

No output schema declared.

No examples provided.

metrics ~73

Account-wide outcome totals across ALL campaigns: { sent, reply, bounce, complaint, unsubscribe, failed, soft_bounce } — same shape as campaign_results but summed tenant-wide (bounce = hard only, opens not tracked). Use campaign_results for one campaign, list_campaigns per-campaign, or account for billing/quota.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

pause ~81

Pause ONE campaign: its status → 'paused', so the tick schedules no further steps (already-sent mail is unaffected; there is no resume tool). Input: campaignId. Returns { paused: true }. 404 if not found. Use pause_all to pause every active campaign at once.

NameTypeReqDescription
campaignIdstringyesThe campaign id returned by launch_campaign.

No output schema declared.

No examples provided.

pause_all ~53

Pause EVERY active campaign for the tenant at once (each active status → 'paused'; the tick then schedules no further sends). No inputs. Returns { pausedAll: true }. Use pause to pause a single campaign by id.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

remove_mailboxes ~558

Downgrade: release your N NEWEST live mailboxes now and lower the billed quantity. Inputs: count, acknowledged (must be true — this is a quoted, irreversible-this-cycle consent: the release is immediate for provisioning but there is NO mid-cycle credit; the lower price takes effect next renewal, minimum 5 mailboxes / $99). Returns { releasedCount, failedCount, unreleased, billing, deduplicated } where billing is the new projected monthly. `releasedCount` is what COMPLETED and can be less than the `count` you asked for; `failedCount` is how many the provider refused, which are STILL LIVE and still billed, and `unreleased` names those addresses — read them before concluding a downgrade landed. `deduplicated: true` means this call did NOT re-perform the downgrade — every count above describes an EARLIER call's already-recorded outcome under the same idempotencyKey, not new work done just now. This can be true even after the 30-day idempotency window itself has expired: the underlying release record persists independently, so a reused key still reports no re-release rather than silently starting a fresh one. `count` is RELATIVE — it releases that many MORE mailboxes, it does not set your fleet to that size — and release cannot be undone through this API, so ALWAYS pass an idempotencyKey: the FIRST call under a key resolves WHICH mailboxes to release and records that exact set, so every later call carrying the SAME key can only ever finish that same set. A same-key retry re-attempts the stragglers and can never release a mailbox outside them, whatever `count` you send with it (the recorded set wins over a changed count); a retry WITHOUT a key always releases another `count`. A genuine SECOND downgrade is therefore a NEW key — reusing an old one can only ever finish what that key already asked for. A call that came back with failedCount above zero did NOT finish, so its key is not frozen: resend the identical request with the same key until failedCount is 0 — from then o…

NameTypeReqDescription
acknowledgedbooleanyes
countintegeryes
idempotencyKeystringOptional idempotency key: resend the SAME key when retrying this call so a dropped-response retry is not applied twice (no duplicate campaign/provision/send).

No output schema declared.

No examples provided.

reply ~448

Send a reply on an existing thread, from the mailbox that sent it. Inputs: threadId, body. Returns { messageId, deduplicated }. A reply is real sending volume and is governed exactly like campaign sends: it counts against that mailbox's daily cap (sentToday +1, visible in infrastructure_status), and it is REFUSED — never silently dropped — when the recipient is suppressed, the mailbox is deliverability-paused, or the cap is used up. A refusal returns { error, code:'send_blocked', reason:'suppressed'|'mailbox_paused'|'daily_cap_reached', retryable }: retryable (cap) clears at the next daily rollover, non-retryable does not, so stop retrying and don't loop replies to manufacture volume. Idempotent: identical retries collapse to one send — pass a stable idempotencyKey (else a body hash is used) so a dropped-response retry can't double-send. `deduplicated: true` means NO new email was sent — `messageId` is from an earlier send this call matched. `deduplicated: false` means this platform sent the call onward as a NEW send, which is normally a new email — but it is not a guarantee one left the building: with NO idempotencyKey the body hash is only matched here for 10 minutes, while the sending provider keeps its own record of an identical body on the same thread for longer, and can collapse a much later repeat into the original send. So on a long-delayed identical repeat you may get `deduplicated: false` with the ORIGINAL send's messageId and no new email. PASS AN IDEMPOTENCYKEY, or vary the body, if you need a repeat to genuinely go out. 404 if no sending mailbox is on record for the thread.

NameTypeReqDescription
bodystringyes
idempotencyKeystringOptional idempotency key: resend the SAME key when retrying this call so a dropped-response retry is not applied twice (no duplicate campaign/provision/send).
threadIdstringyesThe thread id, e.g. from inbox() or campaign events.

No output schema declared.

No examples provided.

setup_infrastructure ~1,568

Provision sending infrastructure: buy branded lookalike domains, create mailboxes, start warmup. New mailboxes are ramp-limited server-side — 5 sends/day in week 1, rising to 40/day after 4 weeks — and your own calls cannot exceed that cap; poll infrastructure_status for the current dailyCap. Inputs: brand, primaryDomain, domains + inboxesEach counts, persona, physicalAddress, senderIdentity. Billing is per-provisioned-mailbox ($10/mailbox + $49 platform, min 5) and the billed quantity follows what you provision here — pass quoteOnly:true first to preview the new count + projected monthly price before committing (no silent capacity addition). Every response carries a `billing` projection { provisionedAfter (the live count AFTER this call — reality, not the ask), projectedMonthlyCents, formula }: on quoteOnly it's the preview, on an actual provision it's the real post-provision bill (a capacity-limited partial reflects only what landed). Returns { jobId, billing } — `jobId` is a correlation id only, not a trackable job handle: there is no job store and no endpoint that accepts it, so do not poll for it or treat its presence as meaningful; it exists to correlate this response with logs. A `provisioning` field is present ONLY when the call returned still OWING work, and names which state: 'pending' (a domain's DNS registration is still completing — `pendingDomain` names one of them) or 'capacity_pending' (held at a spend/plan-slot limit, so polling will NOT progress until an operator raises it — call contact_operator instead of waiting). Its ABSENCE is what says the provision finished; the only way to find out is to re-call setup_infrastructure or read infrastructure_status's `nextSteps`. An outcome carrying `provisioning`, and a quoteOnly preview, are deliberately NOT recorded against your idempotencyKey — retrying with the same key re-runs the call and finishes the job rather than replaying the unfinished answer. `domains` and `inboxesEach` are the infrastructure yo…

NameTypeReqDescription
brandstringyes
distributionarray
domainsintegeryes
idempotencyKeystringOptional idempotency key: resend the SAME key when retrying this call so a dropped-response retry is not applied twice (no duplicate campaign/provision/send).
inboxesEachinteger
personastringyes
physicalAddressstringyes
primaryDomainstringyes
quoteOnlyboolean
registerDomainsboolean
registrantobject
senderIdentitystringyes

No output schema declared.

No examples provided.

suppress_lead ~154

Permanently suppress an email address tenant-wide (every current and future campaign) — the manual/free-text 'stop emailing me' path for opt-outs the strict typed-unsubscribe matcher misses. Inputs: email, reason (fixed 'manual' — the only value this tool honestly claims; bounce/complaint/unsubscribe are recorded automatically elsewhere), note (accepted, not persisted). Cancels every pending send + marks every campaign-lead row 'suppressed'. Last-write-wins: re-suppressing a bounce/complaint/unsubscribe row relabels its reason to 'manual'. There is no un-suppress tool.

NameTypeReqDescription
emailstringyes
notestring
reasonstring

No output schema declared.

No examples provided.

thread ~113

Full message history for ONE thread. Input: threadId (from inbox). Returns { threadId, campaignId, leadId, leadEmail, mailboxEmail (null before first send), messages[] }, each message { type (sent/reply/bounce/...), ts, messageId, metadata }, oldest first. 404 if unknown. Use inbox to LIST threads; reply to respond; mark/label_thread to triage.

NameTypeReqDescription
threadIdstringyesThe thread id, e.g. from inbox() or campaign events.

No output schema declared.

No examples provided.

update_lead ~169

Record what you learned about a contact (their reply, your triage) as a durable, contact-level disposition — keyed by email, visible across every campaign that lists them. Inputs: email, interestStatus (none|interested|meeting_booked|not_now|not_interested|bad_fit|out_of_office|wrong_person — a server-enforced enum; 'do not contact' is NOT a member, use suppress_lead instead), notes, tags (free-form). A PARTIAL patch — only the fields you pass are changed; at least one of interestStatus/notes/tags is required. Filterable via list_leads.

NameTypeReqDescription
emailstringyes
interestStatusstring
notesstring
tagsarray

No output schema declared.

No examples provided.

Common questions

What is the io.github.YS-projectcalc/agent-cold-email MCP server?

io.github.YS-projectcalc/agent-cold-email is an MCP server listed in the public MCP registry as io.github.YS-projectcalc/agent-cold-email. Coldrig, cold-email infra run by your agent: 28 MCP tools, live sending, free sandbox. $99/mo. This page covers its hosted endpoint (https://agent-cold-email-api.yaakovscher.workers.dev/mcp).

Is the io.github.YS-projectcalc/agent-cold-email MCP server safe to use?

io.github.YS-projectcalc/agent-cold-email scores 81 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.YS-projectcalc/agent-cold-email MCP server expose?

io.github.YS-projectcalc/agent-cold-email exposes 28 tools: setup_infrastructure, infrastructure_status, launch_campaign, campaign_results, metrics, and 23 more. Their descriptions and schemas cost roughly 7,428 tokens of context every time the server is loaded.

Does the io.github.YS-projectcalc/agent-cold-email MCP server require authentication?

Yes. io.github.YS-projectcalc/agent-cold-email asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.

Is the io.github.YS-projectcalc/agent-cold-email MCP server still maintained?

io.github.YS-projectcalc/agent-cold-email is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.