Skip to main content
Glama

LeadAce

Status: Public Beta License Listed on mcpservers.org

Autonomous outbound sales agent in your browser. Builds prospect lists, writes and sends one email per company from your own mailbox, and changes who it contacts and what it says from the replies, noes and bounces that come back.

Website: https://leadace.ai

Two ways to run it. Use the hosted service at app.leadace.ai (Free tier — 50 prospects, paid plans from $49/mo), or self-host the backend on your own Cloudflare + Supabase. The web app and the optional Claude plugin work the same on either.

For Users

Get started

  1. Sign in with Google at app.leadace.ai (Free tier — no card). Signing in shares only your name and email.

  2. Paste your website in the chat. Ace proposes who to target and how to approach them. Change anything, then approve.

  3. Read the first drafts. Nothing is sent until you approve. To send, connect Gmail: LeadAce asks to send from it and to read your inbox, so it can catch the replies.

Email runs entirely in the web app: research, writing, sending and reply collection run on the server. Schedule the daily cycle from the chat or project settings. Further Google accounts and SMTP mailboxes are added in Account settings.

Claude plugin (optional)

The plugin, for Claude Cowork or Claude Code, runs the same work from a Claude session and adds a browser: it sends the contact-form messages and SNS DMs that the web app leaves for you to send by hand. It works on the same projects as the web app.

Prerequisites

  • Claude Cowork (in the Claude Desktop app) or Claude Code, on an Anthropic Pro or Max plan — verified on macOS

  • A LeadAce account at https://app.leadace.ai (Free tier — no card)

  • A connected Gmail account — for sending email (connected from the "Connect Gmail" banner or Account settings in the web app)

  • Gmail MCP (claude.ai built-in) — for checking email replies

  • A browser, only for browser channels — contact forms run on Cowork's built-in browser or any browser-automation MCP you configure (e.g. Playwright); SNS DMs and SNS reply checking require Claude in Chrome. A scheduled run reaches the browser only while Claude Desktop is open, with its default browser chosen beforehand

Installation

In Claude Desktop: Customize → Plugins → Add from a repository → aitit-inc/leadace → Install → Connectors → Connect, then Customize → Connectors → LeadAce → Connect and sign in with Google.

Or one line in your terminal (Claude Code):

claude plugin marketplace add aitit-inc/leadace && claude plugin install leadace@leadace

Or, from inside a running Claude Code session:

/plugin marketplace add aitit-inc/leadace
/plugin install leadace@leadace

To update later:

/plugin marketplace update
/plugin update leadace@leadace

Sign in to LeadAce

The first time the plugin calls a LeadAce tool, your browser opens for Google sign-in (the same Google account as the web app). The token is cached locally for subsequent runs. See plugin/README.md for details and troubleshooting.

Usage

Most commands take your project name as the first argument (chosen during /leadace onboarding); /leadace itself takes a free-form question or homepage URL. Run them in a Cowork session (the Cowork tab, not Chat — /daily-cycle runs sub-agents, which Chat can't start) or in Claude Code.

Command

Purpose

Setup

/leadace

Entry point — onboarding, environment setup / re-check, strategy authoring, overview, and routing

Add prospects (pick one)

/build-list <name>

Web search for new prospects

/import-prospects <name>

Load CSV / Excel / SQLite

/match-prospects <name>

Reuse prospects already in your tenant

Sales loop

/outbound <name>

Send via email, contact forms, SNS DMs

/check-responses <name>

Collect Gmail + SNS replies → DB

/evaluate <name>

PDCA — analyse, auto-improve strategy, and surface tactical rejection signals (recontact queue, decision-maker referrals, targeting hints)

Reflection

/check-feedback <name>

Surface PMF signals from rejection feedback (feature gaps, competitor presence) — ad-hoc product reflection

Automation

/daily-cycle <name> [count]

One-shot bundle: check-responses → evaluate → outbound + build-list

/setup-cron <name>

Set up a daily run (a server-side schedule that needs no machine, a Cowork scheduled task, a Claude Code Desktop task, or an OS scheduler)

Maintenance

/delete-project <name>

Permanently delete a project and all its data

Projects, prospects, outreach logs, and strategy documents live in the cloud — there are no local files to manage. Review everything in the web app at https://app.leadace.ai.

Flow

flowchart TD
  LA["/leadace<br/>onboard · setup · strategy"] --> P{add prospects}

  P -- web search --> BL["/build-list"]
  P -- CSV / Excel --> IP["/import-prospects"]
  P -- reuse tenant --> MP["/match-prospects"]

  BL --> OB["/outbound"]
  IP --> OB
  MP --> OB

  OB --> CR["/check-responses"]
  CR --> EV["/evaluate"]
  EV -- next round --> P

  CR -. PMF signals .-> CF["/check-feedback"]
  CF -. revisit strategy .-> LA

  DC["/daily-cycle<br/>check + outbound + build, one shot"]
  SC["/setup-cron<br/>daily schedule"] --> DC
  DC -. replaces manual loop .-> P

  DEL["/delete-project"]

Solid arrows = the main loop. Dashed = optional / occasional / wrapper. /evaluate also consumes the tactical slice of rejection feedback (recontact requests, decision-maker referrals, not_relevant industry clusters) recorded by /check-responses — no separate user step.


Related MCP server: TAPAC MCP

License

LeadAce is released under the LeadAce Open Source License — a modified Apache 2.0 with two additional conditions:

  • No multi-tenant SaaS for third parties without a commercial license from SurpassOne Inc. Self-hosting for your own organization is fine.

  • Frontend logo and copyright must be preserved in any deployment exposing the LeadAce console.

Hosted service (cloud)

  • Free tier: 50 prospects (lifetime), 60 chat messages (lifetime), 1 project, 1 mailbox, 500 stored prospects.

  • Paid plans start at $49/month for 100 prospects and 150 chat messages a month. A prospect counts once, when the first message to it goes out; follow-ups are free. Manage your subscription from the web app.

Self-host

See docs/self-host.md. The self-hosted edition runs on the unlimited tier — no Stripe, no caps. For commercial-license inquiries, contact leo.uno@surpassone.com.


For Developers

Repository layout

plugin/                          # Claude Code plugin
├── .claude-plugin/plugin.json   # Manifest
├── .mcp.json                    # MCP server config
├── skills/                      # Slash commands (each directory has SKILL.md)
├── scripts/fetch_url.py         # Local web fetch helper
└── references/                  # Shared reference docs
backend/                         # API + MCP servers (Cloudflare Workers, Hono, Drizzle)
frontend/                        # Web app (SvelteKit, Cloudflare Worker + static assets)
docs/                            # Project-wide docs (deploy runbook, self-host, architecture)
docker-compose.yml               # Bare Postgres for non-Supabase local dev

Quick start (local dev)

One-time setup — copy the env templates:

cp backend/.dev.vars.example backend/.dev.vars
cp frontend/.env.example frontend/.env

Fill in the Supabase keys from supabase status — it prints them once the local stack is running, so run make dev once first (it starts Supabase), then paste the keys in.

For Google sign-in to your local stack, also create a Google OAuth client and export SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID / _SECRET in your shell (via .envrc) before the first make dev — it boots Supabase, which reads them from the shell at start time. See docs/self-host.md → Local development. (These shell vars gate sign-in; the GOOGLE_CLIENT_ID / _SECRET in backend/.dev.vars are separate — they power Gmail send.)

Then start the whole stack with one command — Supabase, migrations, the master seed, the API/MCP Workers, and the frontend, all together. Ctrl-C tears the dev servers down (Supabase stays up for a fast restart; make stop halts it):

make dev          # or: ./scripts/dev.sh

To run on different ports (e.g. one is taken by another dev server), copy dev.ports.env.example to dev.ports.env and set the ports there — dev.sh rewires every dependent URL (and Google sign-in keeps working). Defaults are unchanged when the file is absent.

npx supabase start                      # Auth + Postgres on ports 54321/54322
cd backend
npm install
npm run db:migrate
npx tsx scripts/seed-master-documents.ts

npm run dev:api                         # API → http://localhost:8787
npm run dev:mcp                         # MCP → http://localhost:8788  (separate terminal)

cd ../frontend
npm install
npm run dev                             # → http://localhost:5273

Pre-release checks:

cd backend && npm run typecheck
cd frontend && npm run check

Updating dependencies (lockfile gotcha)

npm install with node_modules already present can prune other-platform optional deps (@emnapi/*, @img/sharp-*, esbuild binaries) from package-lock.json (npm/cli#7961, npm 10.3+–11.x). CI then runs npm ci against that pruned lockfile and fails with Missing: … from lock file. This bites both backend/ and frontend/, and is what makes Dependabot's npm PRs go red.

When you change a package.json / package-lock.json (or repair a Dependabot PR), regenerate the lockfile under the repo's pinned toolchain — not in Docker:

nvm use                 # node 24 (repo .nvmrc) — matches CI
cd backend              # or cd frontend
rm -rf node_modules     # removing this first is what avoids the prune
npm install --no-audit --no-fund

Then commit the regenerated package-lock.json. Code-only changes don't need this — CI consumes the committed lockfile as-is.

Available Tools

55 tools
add_prospectsB

Batch-register prospects; server-side dedup is authoritative. Returns inserted, skipped, and skippedDetails [{name, reason, detail?}]. Rows whose industry is not in the tpl_industries vocabulary are skipped (reason unknown_industry), and rows whose discoveryStrategy is not registered on the project are skipped (reason unknown_strategy) — fix and re-register.

Inputs: prospects (required), projectId.

check_prospect_dedupA

Read-only duplicate pre-check. Returns decisions[] in input order, each {kind: 'fresh' | 'skip', reason?}; reasons are the dedup subset of add_prospects (no plan_limit).

Inputs: candidates (required), projectId.

create_organizationA

Register an organization by domain alone — e.g. to flag a company do_not_contact before any prospect exists. Omitted name/websiteUrl default from the domain; CONFLICT if the domain already exists (use update_organization).

Inputs: domain (required), name, websiteUrl, doNotContact.

delete_organizationsA

Permanently delete organizations by id (max 200); organizations that still have prospects are skipped with a reason. Preview with list_organizations.

Inputs: organizationIds (required).

delete_projectA

Delete a project and its project-scoped data (project-prospect links, outreach logs, responses, inquiry sessions, learned send-optimization state, documents, settings, message variants). Prospects are tenant assets and are NOT deleted.

Inputs: projectId (required).

delete_prospectsA

Permanently delete prospects by id (max 200), workspace-wide. Do-not-contact prospects, prospects with outreach history, and prospects on 2+ projects are skipped with a reason; reports organizations left with no prospects. Preview with list_project_prospects.

Inputs: prospectIds (required).

discard_draftsA

Batch-delete pending_review drafts by ids, or by projectId to wipe every pending_review draft in the project. Only pending_review rows are deleted; any other status silently excluded. Returns the deleted count and any skipped ids. Preview with list_drafts.

Inputs: ids, projectId.

get_compliance_statusA

Pre-flight compliance check for outbound. Reports ready or incomplete, with the unset fields. Incomplete means at least one of legalName / physicalAddress / defaultSenderCountry is missing, and send_email_and_record / record_outreach_with_inquiry then refuse with 412.

Inputs: no named parameters.

get_documentA

Get the latest version of a project document by slug.

Inputs: slug (required), projectId (required).

get_eval_dataA

Evaluation statistics for a project: response rates, channel performance, sentiment breakdown, discoveryStrategyResponseRate (per discovery strategy; reply metrics count mature sends only while its bounce metrics span all sends — the early source-quality read; the null bucket is prospects without recorded provenance), targeting observation axes (industryResponseRate by coarse bucket / sizeResponseRate by employee band / countryResponseRate — these also count mature sends only, older than the reply-maturity window), freshSignalResponseRate, inquiry-landing outcome counts, respondedMessages, and a data-sufficiency check. Reply rates exclude bounces/auto-replies; per-bucket bounces + bounceRate are a threaded-only lower bound.

Inputs: projectId (required).

get_gmail_statusA

Whether the current user's Google account is connected (gmail.send scope), the address it is connected as, and whether Google has revoked the stored access.

Inputs: no named parameters.

get_lever_decisionsA

Read-only history of the project's daily lever-tick decisions, newest first. Each entry is one UTC day: message-variant draw weights, variants archived that day (reason "stagnation" marks a rotation, absent = dominated), per-variant sample counts, channel affinity per coarse-industry bucket, targetingLifts, the discovery-strategy decision (weights / archived / samples / the prior UTC day's per-strategy registration counts), vitals — the project futility check over recent mature email sends (sends / replies / pDead / verdict), and configUsed — the effective lever config the tick ran under (the latter four null on pre-upgrade entries). Empty until the tick has run at least once.

Inputs: projectId (required), days.

get_lever_stateA

Read-only snapshot of the project's outbound optimizer: message-variant draw weights (null until the first tick → uniform), channel affinity per coarse-industry bucket ({} until measured → policy order), targetingLifts (null until a tick has computed them → neutral ordering), updatedAt, per-active-variant mature-sample progress, the discovery block (the strategy registry — each entry's slug, approach, and archived state; the active set is what /build-list runs, while add_prospects accepts any registered slug — plus the tick's strategy draw weights, a batchPlan apportioning a registration batch of batchSize across the active strategies by those weights, and a needsReplenishment flag that asks /evaluate to register fresh strategies), today's tick decision if it ran, and the variant-pool needsReplenishment (also true while a stagnation-rotation slot awaits its fresh angle).

Inputs: projectId (required), batchSize.

get_mailbox_healthA

Warmup and daily-cap state of the mailbox this project sends from (assigned custom mailbox, else connected Gmail). This per-mailbox email cap is separate from the plan/billing outreach quota — email sends only, resets at UTC midnight. Returns the mailbox email, warmup ramp (week X of N) or fixed cap override, today's cap/used/remaining, any pause, and a trailing 30-day bounceRate (threaded-only lower bound). Returns a no-mailbox state when the project has no assigned mailbox and no linked Gmail.

Inputs: projectId (required).

get_master_documentA

Get a shared master document by slug.

Inputs: slug (required).

get_outbound_targetsA

Prospects due for outreach (new + follow-up/recycle touches), ordered by the measured targeting score (x priority multiplier; a share of each batch is random exploration slots); server-filters by enabled channels and deliverable country (unknown country passes unless the project sets targetCountries). Reports the reachable total and its email / formOnly / snsOnly / platformOnly split, the outbound mode (send|draft), remaining outreach quota, and the mailbox email cap; then the prospects as JSON, each carrying country, discoveryStrategy, and cycle {kind, touchNumber}.

Inputs: projectId (required), limit.

get_project_settingsA

Get user-editable project settings as JSON (outboundMode, sender identity, unsubscribeEnabled, footerOverride, inquiry-landing config, follow-up/recycle windows, outboundChannels, targetCountries, targetLanguage). Fields the user never set carry their column defaults; 404 when the project does not exist.

Inputs: projectId (required).

get_recent_outreachA

Recent outreach logs for a project. Confirmed events only (sent / failed / skipped) — pending_review drafts and pre_send rows are excluded; use list_drafts for those. Each log carries recipient identifiers (prospectName, contactName, prospectEmail, organizationDomain) and inquiry-landing aggregates (inquirySessionCount, inquiryOutcome, inquiryMeetingSource, inquiryLastVisitAt).

Inputs: projectId (required), limit.

get_rejection_feedback_summaryA

Aggregate rejection_feedback for a project. Returns primaryReasonDistribution, the tactical fields recontactWindows / decisionMakerPointers / notRelevantNotes / budgetNotes (budget free-text), and the pmf field feature_gap free-text notes. Read-only view — any deferral or prospect creation these rows imply happened at record_response time, not on read.

Inputs: projectId (required), scope, windowDays.

get_server_versionA

Returns { serverVersion, minPluginVersion } for the LeadAce backend MCP server.

Inputs: no named parameters.

get_tenant_settingsA

Returns the workspace identity/compliance fields (legalName, physicalAddress, defaultSenderCountry) plus a readiness status line; all three gate outbound: send tools refuse (412) until each is set.

Inputs: no named parameters.

import_prospects_from_csvA

Import prospects from a canonical CSV string. Returns inserted, overwritten, skipped, errors, skippedDetails [{row, name, reason}], and errorDetails. dedupPolicy 'overwrite' refreshes prospects matched by email, contactFormUrl, or platformUrl and re-links them, but domain-only matches skip as already_in_project and do_not_contact rows are always skipped; doNotContact is a one-way ratchet on overwrite (true sets it, false/absent never clears). Max 1000 data rows.

Inputs: csvText (required), projectId, dedupPolicy.

list_country_codesA

Lists the ISO 3166-1 alpha-2 country codes LeadAce recognizes for a prospect/organization country. Returns { countries: [{ code, name, sendAllowed }], sendAllowed, note }; sendAllowed marks codes outreach can currently deliver to, others store but are blocked at send time.

Inputs: no named parameters.

list_documentsB

List all documents for a project with their last updated timestamps.

Inputs: projectId (required).

list_draftsA

List pending_review drafts for a project, newest first. Returns total and rows with a truncated bodyPreview; doNotContact marks drafts whose recipient became DNC after drafting — discard those, sending is blocked.

Inputs: projectId (required), limit, offset.

list_master_documentsB

List all available master documents (templates, guidelines, frameworks).

Inputs: no named parameters.

list_message_variantsA

List the project's message-angle variants. Reports the active / archived counts, then the variants as JSON — [{ variantId, subjectPattern, bodyApproach, label, archivedAt, … }] ordered by createdAt asc.

Inputs: projectId (required).

list_organizationsA

List tenant organizations with employee-size band and per-org prospect and project counts; do-not-contact organizations are marked [DNC].

Inputs: q, limit, offset.

list_project_prospectsA

List a project's prospects with per-project status, priority, and matchReason. Unlike get_outbound_targets (reachable rows only), lists prospects in any status. Sorted by priority ascending, newest first within a rank.

Inputs: projectId (required), q, limit, offset, +2 more.

list_projectsA

List all projects for the current user.

Inputs: no named parameters.

list_suggestionsA

List persisted suggestions for a project: id, kind, dedupeKey, title, body, command, status (open/dismissed/done), timestamps. Optional status filter.

Inputs: projectId (required), status.

list_tenant_prospectsA

List existing prospects across the entire tenant, excluding do-not-contact prospects. No pagination — results beyond limit are truncated.

Inputs: q, limit, industry, excludeProjectId.

pick_message_variantA

Pick an active message-angle variant for the project via a server-side weighted draw. Returns the drawn variant id, its subject pattern, its body approach (line absent when the variant has none), and label; NOT_FOUND when the project has no active variants.

Inputs: projectId (required), variantId.

record_outreachA

Record an outreach log entry. status="sent" flips the prospect to "contacted" and stamps next_outreach_after = sentAt + noResponseRecycleDays so it recycles back into get_outbound_targets only after that window; status="failed" stamps the same window without marking the prospect contacted so it drops out of get_outbound_targets for it; status="pending_review" leaves the prospect unchanged but excludes it from get_outbound_targets while the draft is open. For form / SNS DM submissions, prefer record_outreach_with_inquiry.

Inputs: body (required), channel (required), projectId (required), prospectId (required), +4 more.

record_outreach_with_inquiryA

Reserve an outreach log row for a form / SNS DM / platform channel before submission. Returns outreachLogId, status ("pre_send" in send mode, "pending_review" in draft mode), inquiryUrl, and finalBody — the body with the compliance footer (legal identity + opt-out line, plus an inquiry-landing URL line when inquiryLandingEnabled) appended; channel "platform" gets no footer (solicited in-platform message). The "pre_send" row must be resolved by update_outreach_status ("sent" / "failed"); a "pending_review" row needs no follow-up call. For email use send_email_and_record instead.

Inputs: body (required), channel (required), projectId (required), prospectId (required), +2 more.

record_responseA

Record a response (email reply, SNS DM, etc.) to an outreach; updates prospect status and marks do-not-contact. do_not_contact is forced on responseType=bounce, on rejectionFeedback opt-out reasons, and when the per-project rejection cycle cap (maxReapproachCycles) is reached — the cap also drops the recontact window so a would-be deferred becomes rejected. rejectionFeedback with wrong_timing/budget plus a recontact window sets status=deferred (next_outreach_after); a decision_maker_pointer auto-creates or updates a prospect, reported back as derived prospects.

Inputs: channel (required), content (required), sentiment (required), responseType (required), +4 more.

record_suggestionA

Persist an actionable suggestion for the user (surfaced in the Web UI dashboard). Reserve for actions only the user can perform. Upserts by kind + dedupeKey: refreshes an open suggestion, never resurrects a dismissed/done one — the confirmation reports id, status, and whether it was written or left untouched.

Inputs: body (required), kind (required), title (required), command (required), +2 more.

report_bugA

File a bug, feedback, or idea about LeadAce. Daily-capped per tenant; over-cap returns an error.

Inputs: body (required), title (required), category (required), context.

run_lever_tickC

Run the project's daily outbound-optimization tick: recompute the message-variant draw weights pick_message_variant reads (Thompson sampling over graded reward; archives variants whose P(best) stays below the threshold at maturity, never below two active), the discovery-strategy draw weights over the active registry (same Thompson math; archives dominated strategies, never below two active), the per-industry channel affinity get_outbound_targets surfaces, and the measured targeting lifts (industry / size / country / discovery strategy / fresh signal) that re-score the get_outbound_targets ordering. After a sustained flat streak (every arm mature yet none likely best) it rotates out the weakest variant to free a slot for a fresh angle. Idempotent per UTC day — a repeat call returns that day's recorded decision without re-applying. Returns variant weights and archived variants (a stagnation rotation is marked as such), strategy weights and archived strategies, channelAffinity by industry bucket, targeting lifts, the futility vitals verdict (ok / insufficient / futile over recent mature email sends — futile means outreach is statistically drawing no replies and belongs in the cycle report; it clears on its own once recent sends draw replies again), and the live needsReplenishment / needsStrategyReplenishment flags (recomputed each call, not the frozen recorded value).

Inputs: projectId (required).

save_documentA

Save a project document by slug as a new immutable version; prior versions preserved.

Inputs: slug (required), content (required), projectId (required).

send_emailA

Sends an email via the connected Gmail account without recording an outreach log; returns Gmail messageId/threadId. For prospect outreach use send_email_and_record instead.

Inputs: to (required), body (required), subject (required), cc, +2 more.

send_email_and_recordA

Sends a prospect email to the address stored on the prospect and records the outreach log in one call; project outboundMode decides send vs a pending_review draft. Reports whether it sent or drafted, the outreach id, and on a send the From address the project's sending mailbox used.

Inputs: body (required), subject (required), projectId (required), prospectId (required), +1 more.

set_prospect_do_not_contactA

Set the do_not_contact flag on a tenant prospect. DNC prospects are excluded from re-discovery and outbound targeting.

Inputs: prospectId (required), doNotContact (required).

set_prospect_priorityA

Set one prospect's outreach priority (1=highest) within a project. Per-prospect operator override applied regardless of the prospect's status; measured targeting outranks priority in the outbound ordering once data accrues. Read the current value via list_project_prospects or get_outbound_targets.

Inputs: priority (required), projectId (required), prospectId (required).

setup_projectA

Create a new LeadAce project; returns the auto-generated project id. Errors if the plan project limit is reached.

Inputs: name (required).

skip_prospectA

Record a deliberate skip of a prospect on this outbound run — no send is attempted. Writes a "skipped" audit row and stamps next_outreach_after = sentAt + noResponseRecycleDays so the prospect drops out of get_outbound_targets for that window; no quota is consumed and the prospect is NOT marked contacted. Not for unsupported-country prospects — get_outbound_targets already filters those server-side.

Inputs: reason (required), channel (required), projectId (required), prospectId (required), +1 more.

update_organizationA

Partial-update an organization's name, website URL, employeeBand, or doNotContact; domain is immutable. organizationId is the PK returned in the organizationId field of list_tenant_prospects / list_project_prospects / get_outbound_targets, not a domain.

Inputs: patch (required), organizationId (required).

update_outreach_statusA

Resolve the "pre_send" outreach log row from record_outreach_with_inquiry. Both terminal transitions stamp next_outreach_after = sentAt + noResponseRecycleDays, dropping the prospect from get_outbound_targets for that window: status="sent" also flips the prospect to "contacted", confirms quota consumption, and advances the follow-up sequence; status="failed" refunds the in-flight quota reservation. Only the "pre_send" → terminal transition is accepted.

Inputs: status (required), outreachLogId (required), errorMessage.

update_project_settingsA

Update user-editable project settings. Any omitted field keeps its current value. Pass null to clear nullable fields.

Inputs: projectId (required), outboundMode, inquiryCtaUrl, inquiryPdfUrl, +21 more.

update_prospectA

Partial-update a tenant prospect's fields. UNPROCESSABLE if the patch would leave no contact channel (email, contactFormUrl, an snsAccounts entry, or platformUrl); CONFLICT if email, contactFormUrl, or platformUrl already belongs to another prospect in the workspace. Changing email resets its deliverability verdict and queues a background re-check. Per-project status via update_prospect_status, priority via set_prospect_priority, DNC via set_prospect_do_not_contact.

Inputs: patch (required), prospectId (required).

update_prospect_statusA

Update a prospect's status within a project. Setting 'new' is rejected while the prospect has sent outreach in that project.

Inputs: status (required), projectId (required), prospectId (required).

update_tenant_settingsA

Updates workspace identity/compliance fields; only the keys passed are written (merge, not replace). legalName, physicalAddress, defaultSenderCountry gate outbound: send tools refuse (412) until all are set. defaultSenderCountry is the sender's own country, separate from recipient targeting and message language.

Inputs: name, legalName, physicalAddress, defaultSenderCountry.

upsert_discovery_strategyA

Register or update a discovery strategy — the named prospect-search arm /build-list executes and add_prospects stamps for per-strategy reply attribution. Idempotent by slug: re-calling updates the approach, and any call without archived=true lands the strategy active (re-registering an archived slug revives it). archived=true retires it from registration while keeping historic attribution. Refused (400) when it would push the active count past the project's cap.

Inputs: slug (required), approach (required), projectId (required), archived.

upsert_message_variantA

Register or update a message-angle variant (subject pattern + optional body approach) on a project. Idempotent by variantId — re-calling updates that variant's fields / archived state. archived=true retires it from rotation but keeps it analysable for historic outreach rows. Refused (400) when it would push the active count past the project's cap.

Inputs: projectId (required), variantId (required), subjectPattern (required), label, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 55 tools

    Disambiguation4/5

    Most tools map to distinct resource-action pairs (projects, prospects, organizations, settings, documents, outreach). The main ambiguity is between the outreach-recording tools (record_outreach, record_outreach_with_inquiry, send_email_and_record) and the two prospect-registration paths (add_prospects, import_prospects_from_csv), but the descriptions cross-reference one another well enough that an agent can usually pick correctly.

    Naming Consistency4/5

    Names overwhelmingly follow a verb_noun snake_case pattern (list_*, get_*, update_*, delete_*, send_*, record_*). Minor inconsistencies exist, such as setup_project instead of create_project and a mix of update_/set_ for prospect mutations, but the overall convention is predictable.

    Tool Count1/5

    At 55 tools, this is an extreme surface for a single MCP server. Even though the tools are grouped into coherent subdomains, the sheer number burdens an agent's navigation and makes selection harder than it should be.

    Completeness4/5

    The core outreach lifecycle is well covered: project setup, prospect and organization management, outreach recording, draft handling, compliance settings, document storage, and optimization levers. Minor gaps exist, such as no standalone discovery-strategy listing and no direct suggestion dismissal, but most can be worked around through existing tools like get_lever_state.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      A free MCP server that runs a full B2B outbound pipeline inside a Claude conversation, enabling lead scraping, Google Sheets integration, and Instantly campaign creation.
      -
    • A
      license
      A
      quality
      A
      maintenance
      A native MCP server for real-time B2B contact finding and SMTP email validation, scraping company websites, Discord, and Telegram to deliver live, verified contacts that AI agents like Claude and Cursor can query directly.
      2
      3
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      LinkedIn prospect intelligence inside Claude. It automates the research behind outreach, not the sending: scrapes posts, profiles and comment threads into a local SQLite database, classifies what a person or company actually posts about, mines comment threads for people already describing your problem, and surfaces uncommon commonalities worth opening with.
      18
      34
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      This MCP server lets coding agents research and score leads, draft cold emails, run every message through CAN-SPAM and deliverability gates, and hold them for human approval while logging why each lead was contacted. It enforces caps, warmup ramps, and a Tuesday/Wednesday send window, and by default never sends anything.
      7 npm
      MIT