
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
@leadbay/mcp
Advanced tools
Model Context Protocol (MCP) server for Leadbay — AI lead discovery, qualification, and enrichment for Claude Desktop, Cursor, and Claude Code.
A Model Context Protocol server that lets Claude Desktop, Cursor, Claude Code, and any other MCP-compatible agent find, research, and prepare outreach on B2B prospects using your Leadbay account.
Upgrading? See CHANGELOG and MIGRATION.md for version-specific behavior changes. Key callout: composite write tools are ON by default since 0.3.0 — set
LEADBAY_MCP_WRITE=0to restore read-only behavior.
Leadbay MCP keeps a local, per-account agent memory at
~/.leadbay/memory/{account_id}/. It stores append-only JSONL learnings
about user taste signals such as preferred sectors, regions, deal size,
communication style, and qualification rules.
The memory tools are always exposed:
leadbay_agent_memory_recall reads the consolidated top signals.leadbay_agent_memory_capture appends a new learning after the user reveals
a material preference.leadbay_agent_memory_review lists entries and gates retractions or org
promotion through user confirmation.The main leads-touching tools (leadbay_account_status,
leadbay_pull_leads, leadbay_pull_followups,
leadbay_prepare_outreach, leadbay_research_lead_by_id) also attach
_meta.agent_memory.summary automatically. Set LEADBAY_AGENT_MEMORY=off
to suppress this ambient metadata.
On macOS and Windows, launch the guided Electron installer from the npm package:
npx -y -p @leadbay/mcp@latest installer
It downloads the npm package, opens the installer app, signs in with Leadbay OAuth in your browser, detects installed MCP clients, then installs the selected ones.
On Linux, use the terminal-only path instead (no desktop installer window):
npx -y @leadbay/mcp@latest install --oauth
On the web there's no terminal, so npx … installer doesn't apply — add
Leadbay as a custom Connector instead. Claude connects to the hosted MCP
from Anthropic's cloud and runs the OAuth sign-in in-app (no localhost
callback, no client id/secret to fill in):
Leadbay · URL: https://mcp.leadbay.app/mcpThe same hosted URL works from a terminal that has the Claude Code CLI:
claude mcp add --transport http leadbay https://mcp.leadbay.app/mcp
In Claude Cowork with a terminal, the guided installer works as usual —
it opens your browser for sign-in and configures the detected clients. If the
browser never opens, the installer no longer hangs: it exits after a short
watchdog with the Connector / claude mcp add instructions above.
From a repo checkout, run the same native installer with:
pnpm --filter @leadbay/mcp installer
pnpm --filter @leadbay/mcp installer -- --uninstall
Add --local to install your current checkout instead of pulling from npm. Useful when developing the MCP and wanting to test changes in Claude Desktop or Claude Code without publishing.
# 1. Build
pnpm --filter @leadbay/mcp build
# 2a. GUI wizard — same OAuth flow, writes node dist/bin.js into client configs
pnpm --filter @leadbay/mcp installer -- --local
# 2b. Terminal-only
node packages/mcp/dist/bin.js install --oauth --local
# 2c. Explicit path (if running from a different directory)
node packages/mcp/dist/bin.js install --oauth --local=/abs/path/to/packages/mcp/dist/bin.js
Instead of npx -y @leadbay/mcp@latest, each client config gets node /absolute/path/to/dist/bin.js. After each rebuild the next MCP session picks up your changes automatically — no reinstall needed.
For terminal-only installs (works on macOS, Windows, and Linux):
npx -y @leadbay/mcp@latest install --oauth
To uninstall with the same guided app:
npx -y -p @leadbay/mcp@latest installer --uninstall
Only shows clients that already have Leadbay MCP configured.
These commands:
--scope user so the server appears in any project, not just where you ran the command.Add --no-write to disable the composite write tools (refine_prompt, report_outreach, adjust_audience, etc. — ON by default since 0.3.0; pass --no-write for a read-only agent). Add --yes for non-interactive runs (CI / scripts). Add --target claude-code,cursor to scope to specific clients. The legacy --include-write flag is accepted but is now a no-op.
OAuth auto-detects your region through stargate. Pass --region us|fr only if you need to override it.
To rotate the local MCP credential, re-run npx -y @leadbay/mcp install --oauth.
Don't have a Leadbay account? Register here.
/plugin marketplace add leadbay/mcp
/plugin install leadbay@leadbay-mcp
Claude Code prompts for Leadbay auth/config through the plugin's userConfig. This is equivalent to the npm/CLI install above.
The plugin install gives you two surfaces in one shot:
mcpServers.leadbay block (boots @leadbay/mcp over stdio). This exposes the leadbay_* tools to the agent.skills/ — leadbay_daily_check_in, leadbay_research_a_domain, leadbay_import_file, leadbay_log_outreach, leadbay_qualify_top_n, leadbay_refine_audience. These auto-trigger on natural-language matches against each skill's description ("get me leadbay leads today", "research acme.com", etc.) and dispatch to the MCP tools above by name. Each SKILL.md is generated by @leadbay/promptforge from the same .md.tmpl source as the MCP prompt, so the two surfaces never drift.You can verify the skills installed by running /skill list after install. To uninstall everything, /plugin uninstall leadbay@leadbay-mcp removes the MCP server registration and the skills together.
The guided installer writes the local mcpServers.leadbay entry in claude_desktop_config.json with npx -y @leadbay/mcp@latest, like the Linux flow. Restart Claude Desktop after install.
The .dxt / .mcpb bundle from Releases remains available as an alternative install path.
npm install -g says "EACCES" / "permission denied"If you installed Node from the official nodejs.org .pkg, /usr/local/lib/node_modules is root-owned. Any of these works:
npx (recommended, no global install): all examples above use npx -y @leadbay/mcp@latest ... — no global install needed.sudo npm install -g @leadbay/mcp (enter your macOS password).npm install -g works without sudo.npx -y @leadbay/mcp@latest login --oauth
Default writes a 0600-mode JSON file at the platform-correct credentials path ($XDG_CONFIG_HOME/leadbay/credentials.json on Linux, ~/Library/Application Support/leadbay/credentials.json on macOS, %APPDATA%\leadbay\credentials.json on Windows). Pass --write-config /some/path.json to override the path. Pass --force to overwrite an existing file from a different account. The legacy email/password path still exists for scripts that cannot use a browser.
The hosted MCP at https://mcp.leadbay.app/mcp runs self-hosted on the Leadbay
k3s cluster (leadbay/infra). Deploys are automatic and driven off release tags
— there is nothing to run by hand:
packages/mcp/package.json in a normal PR and merge to main.
auto-tag.yml pushes the matching mcp-v<ver> tag.build-image.yml builds this repo's Dockerfile and pushes the image to
Azure Container Registry as leadbay.azurecr.io/mcp:<commit-sha> (and
:latest).leadbay/infra watches for the new SHA-tagged image
and rolls the mcp workload automatically.To confirm the live endpoint is serving the expected version:
curl https://mcp.leadbay.app/healthz
# {"ok":true,"version":"<published-version>"}
Infrastructure details (workload manifests, Argo CD app, DNS) live in
leadbay/infra — not this repo.
Prefer the installer in §1. If you need to hand-write config,
first authenticate with npx -y @leadbay/mcp@latest login --oauth, then copy the
LEADBAY_TOKEN and LEADBAY_REGION values from the credentials file it writes.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"leadbay": {
"command": "npx",
"args": ["-y", "@leadbay/mcp@latest"],
"env": {
"LEADBAY_TOKEN": "<paste-oauth-token>",
"LEADBAY_REGION": "us"
}
}
}
}
Restart Claude Desktop.
In Cursor settings, add the MCP server:
{
"mcp.servers": {
"leadbay": {
"command": "npx",
"args": ["-y", "@leadbay/mcp@latest"],
"env": { "LEADBAY_TOKEN": "<paste-oauth-token>", "LEADBAY_REGION": "us" }
}
}
}
claude mcp add leadbay --scope user \
--env LEADBAY_TOKEN=<paste-oauth-token> \
--env LEADBAY_REGION=us \
-- npx -y @leadbay/mcp@latest
--scope userregisters Leadbay globally for your account (visible from any project). Without it,claude mcp adddefaults to project-local scope and the server only appears in conversations opened from the directory where you ran the command.
To disable the composite write tools (refine_prompt, report_outreach, adjust_audience, etc.), add
--env LEADBAY_MCP_WRITE=0. They are ON by default since 0.3.0. The legacyLEADBAY_MCP_WRITE=1opt-in is now a no-op.
Before starting Claude, run:
LEADBAY_TOKEN=<paste-oauth-token> npx -y @leadbay/mcp@latest doctor
Expected output:
Leadbay connection OK.
Organization: Your Org
Billing: active
AI credits: 420 / 1000
Leadbay runs a hosted MCP server that any remote-MCP client can connect to without a local install. Pick the URL for your account's region:
https://mcp.leadbay.app/mcp # US accounts
https://mcp.leadbay.app/fr/mcp # FR accounts
On first connect the client runs the Leadbay OAuth sign-in (the server advertises OAuth 2.0 Protected Resource Metadata per RFC 9728 and challenges unauthenticated requests with 401 + WWW-Authenticate). Sign in once in the browser; the client stores the token and sends it as Authorization: Bearer <token> on every request. No token to copy-paste, no local Node install needed.
The region is encoded in the URL because OAuth discovery happens before sign-in and Leadbay tokens are region-scoped — a US account uses /mcp, a FR account uses /fr/mcp. If the sign-in prompt never appears, you're on an old build of the hosted server (pre-0.21.0); it auto-updates on release.
Updates are automatic — the hosted server is always running the latest published release. You never need to update a config file or restart anything on your side.
Find me 20 SaaS companies in Berlin that match my Ideal Buyer Profile.
Research the top prospect from that list — give me the AI summary, recent activity, and who I should reach out to.
Prepare an outreach package for Acme Corp — include the recommended contact with enriched email if we have credits.
If you're building or auditing an MCP integration, this section shows what each spec primitive looks like on the wire when calling
@leadbay/mcp. Every example is the actual JSON-RPC frame your client sends or receives — copy verbatim into a debugger.
tools/list — annotations + outputSchemaEvery tool advertises read/write/idempotent/openWorld posture and (for the top declarers) a typed return schema.
Request:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }
Response (excerpt):
{
"tools": [
{
"name": "leadbay_account_status",
"description": "Show the user's account state — admin rights, language, last-active lens, current quota …",
"inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
"annotations": {
"title": "Show Leadbay account + quota state",
"readOnlyHint": true, "destructiveHint": false,
"idempotentHint": true, "openWorldHint": true
},
"outputSchema": {
"type": "object",
"properties": {
"user": { "type": "object", "properties": { "email": {}, "name": {}, "admin": {}, "manager": {}, "language": {} } },
"organization": { "type": "object", "properties": { "id": {}, "name": {}, "ai_agent_enabled": {}, "computing_intelligence": {}, "plan": {} } },
"last_requested_lens": {},
"quota": {},
"_meta": { "type": "object", "properties": { "region": {} } }
},
"required": ["user", "organization"]
}
}
]
}
Capable clients use the annotations to decide auto-approve vs prompt; the outputSchema lets them dispatch on shape rather than re-parse the text.
tools/call with structuredContentWhen the tool declares outputSchema, the response carries a typed structuredContent block alongside text content:
Request:
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "leadbay_account_status", "arguments": {} } }
Response:
{
"content": [
{ "type": "text", "text": "{\"user\":{...},\"organization\":{...}, ...}" }
],
"structuredContent": {
"user": { "email": "you@example.com", "name": "You", "admin": true, "manager": false, "language": "en" },
"organization": { "id": "org-1", "name": "Your Co", "ai_agent_enabled": true, "computing_intelligence": false, "plan": "PRO" },
"last_requested_lens": 42,
"quota": { "plan": "PRO", "windows": [...] },
"_meta": { "region": "us" }
}
}
prompts/list and prompts/get — slash commandsRequest:
{ "jsonrpc": "2.0", "id": 3, "method": "prompts/list" }
Response (excerpt):
{
"prompts": [
{ "name": "daily-check-in", "description": "Pull fresh leads, surface auto-qualified top, deepen 1-3 promising ones.", "arguments": [] },
{ "name": "research-a-domain", "description": "Import a domain → resolve to leadId → research_lead.",
"arguments": [{ "name": "domain", "description": "Company domain (e.g., acme.com)", "required": true }] },
{ "name": "log-outreach", "description": "Gather verification → report_outreach.",
"arguments": [{ "name": "lead_id", "required": true }, { "name": "what", "required": true }] }
]
}
Then prompts/get materialises the chosen workflow as a structured messages array the agent unfurls:
{ "jsonrpc": "2.0", "id": 4, "method": "prompts/get",
"params": { "name": "research-a-domain", "arguments": { "domain": "acme.com" } } }
Clients without a prompts/list UI (Cowork is the prototypical case): the catalog still reaches the agent. The server's initialize response includes a serverInfo.instructions string that names every prompt, its trigger phrasing, and its required arguments — so the agent can match the user's natural-language ask and invoke prompts/get directly without the user clicking through a slash menu. No client action is needed beyond the standard MCP initialize handshake.
resources/list and resources/read — URI-addressable read-only dataThree URI schemes are advertised: lead://{uuid}/profile, lens://{id}/definition, org://taste-profile. Capable clients cache them across turns.
Request:
{ "jsonrpc": "2.0", "id": 5, "method": "resources/templates/list" }
Response (excerpt):
{
"resourceTemplates": [
{ "uriTemplate": "lead://{uuid}/profile", "name": "Lead profile", "description": "Lead profile by Leadbay UUID — basics + qualifications + contacts.", "mimeType": "application/json" },
{ "uriTemplate": "lens://{id}/definition", "name": "Lens definition", "description": "Filter + scoring config for a lens.", "mimeType": "application/json" }
]
}
Read a specific lead:
{ "jsonrpc": "2.0", "id": 6, "method": "resources/read",
"params": { "uri": "lead://0xabcd-…/profile" } }
Response wraps the JSON in a text content block with the URI's mime type so clients can render or cache it.
notifications/progress — streaming during long opsWhen the agent calls a long-running tool with a progressToken in _meta, the server streams progress notifications back. Long-runners that emit: bulk_qualify_leads, import_and_qualify, enrich_titles, bulk_enrich_status, qualify_status.
Request:
{ "jsonrpc": "2.0", "id": 7, "method": "tools/call",
"params": {
"name": "leadbay_bulk_qualify_leads",
"arguments": { "leadIds": ["lead-1", "lead-2", "lead-3"] },
"_meta": { "progressToken": "bq-1" }
} }
While the call runs, notifications arrive:
{ "jsonrpc": "2.0", "method": "notifications/progress",
"params": { "progressToken": "bq-1", "progress": 1, "total": 3, "message": "Qualified Acme Corp (1/3)" } }
{ "jsonrpc": "2.0", "method": "notifications/progress",
"params": { "progressToken": "bq-1", "progress": 2, "total": 3, "message": "Qualified Globex (2/3)" } }
{ "jsonrpc": "2.0", "method": "notifications/progress",
"params": { "progressToken": "bq-1", "progress": 3, "total": 3, "message": "Qualified Initech (3/3)" } }
Then the final tools/call response.
notifications/cancelled — actually cancellingSend the cancellation by id; the server's ToolContext.signal aborts the polling loop within ≤2 seconds, the bulk-store entry is marked cancelled, and the next bulk_enrich_status returns BULK_CANCELLED so the agent stops polling.
{ "jsonrpc": "2.0", "method": "notifications/cancelled",
"params": { "requestId": 7, "reason": "user clicked cancel" } }
elicitation/create — server asks the userUsed by refine_prompt (clarification flow) and report_outreach (anti-poisoning user-confirmation). The server sends an elicitation/create request to the client; the client renders a form; the user types; the response feeds back into the tool call. The agent never sees the prompt.
Server emits (mid-tools/call):
{ "jsonrpc": "2.0", "id": 99, "method": "elicitation/create",
"params": {
"message": "An AI agent wants to log outreach on lead-1: 'Called Acme'. The agent claims you confirmed this. Type your literal confirmation to proceed; cancel to reject.",
"requestedSchema": {
"type": "object",
"properties": { "confirmation": { "type": "string", "title": "Your confirmation" } },
"required": ["confirmation"]
}
} }
Client returns:
{ "jsonrpc": "2.0", "id": 99, "result": { "action": "accept", "content": { "confirmation": "yes I called Acme today" } } }
The user's literal text replaces verification.ref in the outreach record, and the response carries confirmed_via: "elicit" for the SDR audit trail.
| Problem | Cause | Fix |
|---|---|---|
LEADBAY_TOKEN environment variable is required | Local MCP credential missing from config env | Re-run npx -y @leadbay/mcp install --oauth, restart client |
Authentication token expired or invalid | Credential revoked or wrong region | Re-authenticate: npx -y @leadbay/mcp install --oauth; verify LEADBAY_REGION |
Leadbay doctor: could not reach any Leadbay region | Wrong region OR network blocked | Run doctor with LEADBAY_REGION=fr to auto-probe. Check https://api-us.leadbay.app reachable. |
No enrichment credits remaining | Out of quota | Contact Leadbay support to extend quota |
| Claude Desktop "loading forever" on first use | npx cold-start fetching the package | First run takes ~10s. Prefer npm install -g @leadbay/mcp for faster startup. |
| Claude Desktop doesn't show Leadbay tools | Server crashed at startup | Check ~/Library/Logs/Claude/mcp*.log (macOS) or %APPDATA%\Claude\logs\mcp*.log (Windows). |
| Claude Code can't find Leadbay in a new conversation | MCP server installed at project scope (default before 0.3.0) | Re-run with --scope user: claude mcp remove leadbay && claude mcp add leadbay --scope user --env LEADBAY_TOKEN=… --env LEADBAY_REGION=us -- npx -y @leadbay/mcp@latest |
Agent reports "tool not found" for refine_prompt / adjust_audience etc. | Pre-0.3.0 install with LEADBAY_MCP_WRITE unset (writes were off) | Either re-run npx @leadbay/mcp install or remove LEADBAY_MCP_WRITE=0 from your client config (writes are on by default in 0.3.0+) |
Upgrade: the guided installer pins @leadbay/mcp@latest, so each MCP session already picks up the newest published version — just restart the client. (If you hand-pinned a specific version in your config, change it to @latest or the version you want, then restart.) 0.3.0 enables composite write tools by default — see MIGRATION.md. See also the changelog.
Rotate local credential: re-run npx -y @leadbay/mcp@latest install --oauth (or login --oauth) — the new credential replaces the old one in your MCP client config.
Browser-based login is the recommended auth path:
npx -y @leadbay/mcp login --oauth
The CLI:
stargate.leadbay.app/1.0/user_info to auto-detect your region
from GeoIP (override with --region us|fr if you're behind a VPN or
travelling outside your home region).leadbay.app/oauth/authorize.http://127.0.0.1:<random-port>/callback.The CLI registers a fresh OAuth client per machine (RFC 7591 Dynamic Client
Registration), so no shared secret lives in the binary. The resulting token is
long-lived and interchangeable with the legacy bearer token. Manual MCP config
can still pass it as LEADBAY_TOKEN; the Claude Desktop bundle performs the
OAuth flow itself and persists the token without asking you to paste it.
For testing against staging before the production backend deploy lands:
npx -y @leadbay/mcp login --oauth --staging
--staging switches the backend (staging.api.leadbay.app /
api-{us,fr}-staging.leadbay.app), the consent UI (staging.leadbay.app),
and the stargate region probe (staging.stargate.leadbay.app). It also
persists LEADBAY_BASE_URL in the credentials file so subsequent runs don't
snap back to prod.
By default the server exposes the composite workflow tools — both reads (leadbay_pull_leads, leadbay_research_lead_by_id, leadbay_account_status, leadbay_recall_ordered_titles, leadbay_research_lead_by_name_fuzzy, leadbay_prepare_outreach, leadbay_qualify_status, leadbay_list_mappable_fields) and writes (leadbay_bulk_qualify_leads, leadbay_enrich_titles, leadbay_refine_prompt, leadbay_report_outreach, leadbay_adjust_audience, leadbay_answer_clarification, leadbay_import_leads, leadbay_import_and_qualify). These work well with most prompts.
To disable the write tools (run a strictly read-only agent), set LEADBAY_MCP_WRITE=0. The server's system prompt will adapt to omit references to those tools.
To unlock the granular API tools (leadbay_list_lenses, leadbay_discover_leads, leadbay_get_lead_profile, leadbay_get_contacts, leadbay_get_quota, leadbay_get_taste_profile, leadbay_get_lens_filter, leadbay_list_sectors, …), set LEADBAY_MCP_ADVANCED=1.
"env": {
"LEADBAY_TOKEN": "<token>",
"LEADBAY_MCP_ADVANCED": "1",
"LEADBAY_MCP_WRITE": "0"
}
leadbay_report_outreach requires a verification field on every call (Gmail message id, Calendar event id, or user_confirmed with the user's literal text) so the agent can't poison your SDR pipeline with hallucinated outreach.
Note: leadbay_login is intentionally not exposed over MCP — see Security below.
leadbay_import_leads is a write tool (exposed by default since 0.3.0; set LEADBAY_MCP_WRITE=0 to hide it) for the case where you have a list of company domains from another system (CRM, analytics, email correspondents, etc.) and want stable Leadbay leadIds to chain into qualification:
Set up your environment:
export LEADBAY_TOKEN="<your-token>"
export LEADBAY_REGION="us"
(LEADBAY_MCP_WRITE defaults to "1" (ON) since 0.3.0 — no need to set it.)
Then wire in your MCP client per §2 and ask the agent:
"Import these domains: apple.com, microsoft.com, salesforce.com. Then qualify the matched leads."
The agent calls leadbay_import_leads({ domains: [...] }), gets back { leads: [{domain, leadId, name}], not_imported: [{domain, reason}], importIds, _meta }, then chains leads.map(l => l.leadId) into leadbay_bulk_qualify_leads.
⚠️ Writes user state. Internally wraps Leadbay's CRM-import wizard (the only domain-import primitive the backend ships today). Each call:
startFileless, onboarding step → PROCESSING)Suitable for occasional automation. Not suitable for high-cadence (>5 calls/day) — the right primitive is a clean async-import-with-crawl backend endpoint, tracked as a follow-up in leadbay/backend.
uncrawled rows are pending, not failed. The wedge matches domains the crawler already knows. A domain the crawler hasn't indexed yet lands in not_imported with reason: "uncrawled" — the import still completes, and Leadbay then crawls that domain in the background and adds the lead asynchronously (a late import), so those rows commonly resolve on their own within minutes to hours. Those late-added leads populate in the user's Leadbay account as the crawl completes. leadbay_import_status refreshes status/progress only (not the added leads), and leadbay_pull_leads reads the active lens's wishlist (so an imported lead outside that lens may not appear). For one named company, leadbay_research_lead_by_name_fuzzy searches across the visible corpus (not lens-scoped) and can surface it once crawled; for a bulk refresh, re-run the same import later to re-reconcile the now-crawled domains. uncrawled is not a failure and not a bad website — never surface it to the user as one.
leadbay_import_and_qualify collapses import → AI qualification into a single composite call. Returns per-lead qualification answers + ai_agent_lead_score inline when budget allows; otherwise returns a qualify_id UUID handle the agent can pass to leadbay_qualify_status later (handle persists 30 days, survives MCP restart). See MIGRATION.md for the full worked example (discover → preview → import → qualify_status), JSON shapes, error-code reference, per-tool prereqs, and not_in_lens partition semantics.
Companion tool: leadbay_list_mappable_fields returns the union of standard CRM fields and this org's custom fields (with mapping_value ready for mappings.fields paste-in). Optional for_records param runs the wizard's preprocess on a sample to attach mapping hints + custom-field name-match candidates in a single call.
Requires: LEADBAY_MCP_WRITE not set to 0 (it's ON by default since 0.3.0; or exposeWrite: true in OpenClaw); admin role on your Leadbay account; active billing.
Use dry_run: true to validate domain formatting and wizard reachability without committing the lead-CRM linking. (The CRM-imports row still appears — only a backend change can remove that.)
| Var | Required | Default | Purpose |
|---|---|---|---|
LEADBAY_TOKEN | yes | — | Bearer token (mint via install or login, or set manually) |
LEADBAY_REGION | strongly recommended | (auto-probe — see warning below) | us or fr |
LEADBAY_BASE_URL | no | derived from region | Override for staging/dev |
LEADBAY_MCP_ADVANCED | no | unset | "1" exposes the granular API tools |
LEADBAY_MCP_WRITE | no | "1" (ON) | Default ON since 0.3.0. Set to "0" / "false" / "no" / "off" to hide the composite write tools (refine_prompt, report_outreach, adjust_audience, etc.) and the system prompt that mentions them. Note: 0.2.x treated "true" / "yes" / "on" as OFF; 0.3.0+ treats them as ON. |
LEADBAY_MOCK | no | unset | "1" serves all reads from on-disk fixtures (dev only) |
LEADBAY_MOCK_DIR | no | ./.context/leadbay-live-shapes/ | Fixture dir for mock mode |
LEADBAY_LOG_LEVEL | no | error | debug | info | error, logs to stderr |
LEADBAY_TIMEOUT_MS | no | (client default) | Per-request timeout override |
⚠️ Set
LEADBAY_REGIONexplicitly. If you don't, the server probes BOTHapi-us.leadbay.appandapi-fr.leadbay.appin parallel with your bearer token attached, sending the token to a backend that doesn't own your account. Theinstallandloginsubcommands enforce--regionfor exactly this reason; the runtime auto-probe is a backwards-compat fallback, not a recommended setting.
api-{region}.leadbay.app.leadbay_login tool from the OpenClaw adapter is not registered on MCP: exposing a credential-taking tool to an LLM is a prompt-injection risk. Use the token path above.leadbay_add_note tool is a write action flagged optional: true. If your client supports per-tool opt-in, leave it disabled until you need it. leadbay_enrich_contacts is a granular tool exposed only when LEADBAY_MCP_ADVANCED=1.@leadbay/mcp sends product usage events to PostHog and reports unexpected errors to Sentry — same posture as the Leadbay web app. PostHog measures product usage (which tools fire, durations, error rates); Sentry catches crashes we'd otherwise never see.
These events are NOT anonymous. Each event is tied to your Leadbay account email (distinctId = me.email) so your MCP activity consolidates with your web-app activity under the same identity in our analytics — that's the same identity model the web app already uses. If you'd rather not have your MCP usage attributed to you, opt out (see below).
What we send to PostHog (per tool call):
| Event | When | Properties |
|---|---|---|
mcp tool called | Every tool invocation | tool, ok, duration_ms, format, bytes, error_code (if failed) |
mcp quota hit | When the API returns QUOTA_EXCEEDED (HTTP 429/402) | tool, retry_after_s, endpoint |
mcp topup link created | When leadbay_create_topup_link returns a checkout URL | tool (the URL itself is never captured) |
After your first authenticated call, your PostHog distinctId is set to your Leadbay account email so MCP events consolidate with web-app events for the same person. Events also carry $groups.organization so org-level rollups work.
What we never send: tool argument bodies, response bodies, lead emails / phones, Stripe URLs, lens descriptions, qualification answers.
Errors to Sentry: only unexpected throws (TypeError, network failures, parse bugs). Expected business outcomes — quota walls, missing resources, auth expiry, billing suspension — stay in PostHog only.
Opt out — the simplest way is to just ask the agent: "turn off telemetry" (or "is telemetry on?"). That calls the leadbay_set_telemetry tool, which stores your choice on your Leadbay account. The hosted/web connector honors it per-request (there's no local config to edit there). On a local install the server decides telemetry at startup from LEADBAY_TELEMETRY_ENABLED and does not read the account flag, so also set LEADBAY_TELEMETRY_ENABLED=false (below) to stop events locally.
You can also opt out via config: leadbay-mcp install writes LEADBAY_TELEMETRY_ENABLED=true into your MCP client's env block by default. Most clients (Claude Desktop, Cursor) render env-var booleans as a toggle in their settings UI, so you can flip it without editing the file. To opt out at install time, pass --no-telemetry; to opt out manually, flip the env value to "false":
{
"mcpServers": {
"leadbay": {
"command": "npx",
"args": ["-y", "@leadbay/mcp@latest"],
"env": {
"LEADBAY_TOKEN": "u.…",
"LEADBAY_REGION": "us",
"LEADBAY_TELEMETRY_ENABLED": "false"
}
}
}
}
Accepted values: "true"|"1"|"yes"|"on" enable; "false"|"0"|"no"|"off" disable (case-insensitive). Unset / unrecognized values default to enabled.
Override the destinations with LEADBAY_POSTHOG_KEY=<your-project-key> and/or LEADBAY_SENTRY_DSN=<your-dsn> if you'd rather pipe to your own projects. Telemetry is also disabled automatically when NODE_ENV=test.
Contact data fetched through this server stays local to your MCP client session — telemetry never carries it. Requests to Leadbay are subject to the Leadbay privacy policy.
Use this when you want to test changes to the MCP server in your real MCP clients (Claude Desktop, Claude Code, Cursor, Codex) without publishing to npm.
pnpm install
pnpm build
--localpnpm --filter @leadbay/mcp installer -- --local
This opens the installer wizard in your browser. Sign in with OAuth, select your clients, and click Install. The wizard writes node /absolute/path/to/dist/bin.js into each client's config instead of the usual npx @leadbay/mcp@latest invocation.
Restart Claude Desktop / Claude Code / Cursor / Codex to pick up the new config.
Run the installer again without --local to switch back to npm:
pnpm --filter @leadbay/mcp installer
Or use the published package directly:
npx -y -p @leadbay/mcp@latest installer
Releases are tag-driven via .github/workflows/release.yml. Bump packages/mcp/package.json#version, update packages/mcp/CHANGELOG.md, land on main, then:
git tag mcp-v0.3.0 && git push origin mcp-v0.3.0
See RELEASE.md for the full runbook.
MIT. See LICENSE.
FAQs
Model Context Protocol (MCP) server for Leadbay — AI lead discovery, qualification, and enrichment for Claude Desktop, Cursor, and Claude Code.
We found that @leadbay/mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.