@leadbay/mcp 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog — @leadbay/mcp
|
|
2
2
|
|
|
3
|
+
## 0.17.0 — 2026-05-29
|
|
4
|
+
|
|
5
|
+
- **Lens extension** (product#3654): two new composites that expose the
|
|
6
|
+
backend's agent-driven on-demand lens fill (backend#1844 / api-specs#205).
|
|
7
|
+
- `leadbay_extend_lens` (write, gated by `LEADBAY_MCP_WRITE=1`) —
|
|
8
|
+
`POST /lenses/{id}/extra_refill`. Translates the backend's 429
|
|
9
|
+
`quota_exceeded` / 409 `refresh_in_progress` / 400 `no_valid_seeds`
|
|
10
|
+
errors into routable `status` envelopes. On 429 the response carries
|
|
11
|
+
`quota.used_today` + `quota.resets_at` and a message instructing the
|
|
12
|
+
agent to surface three options to the user (smaller `extra_count` /
|
|
13
|
+
wait for reset / upgrade plan).
|
|
14
|
+
- `leadbay_seed_candidates` (read) — internal scaffolding for the
|
|
15
|
+
extend flow. Returns ranked candidate leads with rich signal
|
|
16
|
+
(description, sector, tags, qq_answers, engagement). The agent picks
|
|
17
|
+
3–5 seeds silently and chains to `extend_lens`; the user never
|
|
18
|
+
reviews the seed list.
|
|
19
|
+
- New prompt `leadbay_extend_my_lens` orchestrates the four-phase flow:
|
|
20
|
+
quota pre-check → silent seed pick → fire extend → react to status.
|
|
21
|
+
- `leadbay_account_status` description now mentions the per-org daily
|
|
22
|
+
`LENS_EXTRA_REFILL` quota — pre-check it before calling
|
|
23
|
+
`leadbay_extend_lens`.
|
|
24
|
+
|
|
3
25
|
## 0.16.2 — 2026-05-29
|
|
4
26
|
|
|
5
27
|
- **Tighter `_triggered_by` description on composite tools.** Live test of
|
package/dist/bin.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
granularWriteTools,
|
|
13
13
|
resolveAgentMemorySummary,
|
|
14
14
|
resolveRegion
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ASAKITU3.js";
|
|
16
16
|
|
|
17
17
|
// src/bin.ts
|
|
18
18
|
import { realpathSync } from "fs";
|
|
@@ -972,6 +972,7 @@ day's batch", "let's prospect". Do NOT trigger on follow-up phrasings
|
|
|
972
972
|
("what should I follow up on", "before my trip") \u2014 those go to
|
|
973
973
|
\`leadbay_followup_check_in\`.
|
|
974
974
|
`, "arguments": [], "expected_calls": ["leadbay_account_status", "leadbay_pull_leads", "leadbay_research_lead_by_id", "leadbay_bulk_qualify_leads", "leadbay_enrich_contacts"], "failure_modes": ["Calls leadbay_report_outreach without explicit user authorization", "Surfaces fewer than 10 leads when more are available, or fails to top up via leadbay_qualify_top_n when the batch is short", `Replaces the canonical pull_leads table layout with prose per row (the per-tool RENDERING block is the structural contract; "Today's nudges" goes above it, not in place of it)`, "Skips the nudge paragraph entirely \u2014 the table alone is fine but adding the nudge is the value-add", "Skips deep research on promising leads (Phase 4) \u2014 the agent must call leadbay_research_lead_by_id on each, not just one", "Triggers contact enrichment without asking the user first (it consumes quota)", "Skips the STOP byproduct and proposes next actions on its own", 'Fires 10 parallel leadbay_research_lead_by_id calls and treats "stream closed" errors as terminal \u2014 must serialize and retry singletons', "Re-pulls leadbay_pull_leads without passing the captured lensId, allowing a backend lens shift to discard the Phase 2 batch", 'Treats a "Request timed out" from leadbay_bulk_qualify_leads as terminal instead of retrying with wait_for_completion:false + qualify_status polling', 'Triggers on a follow-up query (e.g., "leads I should follow up with") that should have routed to `leadbay_followup_check_in` \u2014 the two entry points are different data sources (Discover wishlist vs Monitor view) per \xA71.6'] },
|
|
975
|
+
leadbay_extend_my_lens: { "name": "leadbay_extend_my_lens", "short_description": "Add more leads to the current lens on demand \u2014 for users whose appetite\nexceeds the standard daily fill. The agent picks seeds silently from\nwhat's already on the lens, fires the extra refill, and surfaces the\nqueue confirmation. The user never reviews the seed list.\n", "arguments": [{ "name": "extra_count", "description": "How many extra leads to add. Optional. Omit to use the backend default.", "required": false }], "expected_calls": ["leadbay_account_status", "leadbay_seed_candidates", "leadbay_extend_lens", "leadbay_pull_leads"], "failure_modes": ["Surfaces the seed candidate list to the user instead of picking silently \u2014 the user asked for MORE LEADS, not a candidate review meeting", "Skips the seeded path and calls `leadbay_extend_lens` with no `seed_lead_ids`, losing the bias signal the recommender needs", "On 429, silently retries instead of surfacing the three options (smaller / wait / upgrade) via `ask_user_input_v0`", "Forgets to pre-check `LENS_EXTRA_REFILL` quota in `leadbay_account_status` and burns a wasted API call", "Skips the post-queue pull-leads suggestion, so the user doesn't see what just got added"] },
|
|
975
976
|
leadbay_followup_check_in: { "name": "leadbay_followup_check_in", "short_description": `Run the canonical follow-up check-in: surface KNOWN leads from the
|
|
976
977
|
Monitor view that need re-engagement today, ranked by AI urgency,
|
|
977
978
|
with the canonical pull_followups table layout. Trigger when the
|
|
@@ -999,6 +1000,7 @@ should I follow up on" to "I'll send via lemlist".
|
|
|
999
1000
|
var PROMPT_CATALOG_HEADER = `This server exposes the following workflow prompts via \`prompts/list\` and \`prompts/get\`. Some MCP clients render them as slash commands; if your client does not, you (the agent) should invoke them directly via \`prompts/get\` when the user's request matches one of the triggers described below.`;
|
|
1000
1001
|
var PROMPT_CATALOG_BULLETS = {
|
|
1001
1002
|
leadbay_daily_check_in: `- \`leadbay_daily_check_in\`: Run the canonical daily check-in: account state, fresh batch, triage top 10, deep-dive every promising one, offer contact enrichment. The morning DISCOVERY workflow (new leads from the lens wishlist). Trigger on "leadbay leads", "best NEW leads", "what's new today", "show me the day's batch", "let's prospect". Do NOT trigger on follow-up phrasings ("what should I follow up on", "before my trip") \u2014 those go to \`leadbay_followup_check_in\`.`,
|
|
1003
|
+
leadbay_extend_my_lens: `- \`leadbay_extend_my_lens\` (optional args: extra_count): Add more leads to the current lens on demand \u2014 for users whose appetite exceeds the standard daily fill. The agent picks seeds silently from what's already on the lens, fires the extra refill, and surfaces the queue confirmation. The user never reviews the seed list.`,
|
|
1002
1004
|
leadbay_followup_check_in: `- \`leadbay_followup_check_in\`: Run the canonical follow-up check-in: surface KNOWN leads from the Monitor view that need re-engagement today, ranked by AI urgency, with the canonical pull_followups table layout. Trigger when the user asks "follow up", "already known leads", "leads I haven't contacted", "leads in [city]", "before my trip", "this week", "this month", "what's overdue", "who should I re-engage", or anything that implies pre-existing pipeline context.`,
|
|
1003
1005
|
leadbay_import_file: `- \`leadbay_import_file\` (optional args: file, instruction): Import a user-supplied CSV/file into Leadbay through five phases with evidence gates \u2014 scan, derive, resolve identities, preserve & commit, then optionally qualify and report. The job is to maximize how many rows the Leadbay system actually ingests and matches.`,
|
|
1004
1006
|
leadbay_log_outreach: `- \`leadbay_log_outreach\` (required args: lead_id, summary): Log outreach (an email I sent, a call I made, a meeting I had) on a specific lead. Captures verification so the SDR pipeline trusts the entry.`,
|
|
@@ -3189,7 +3191,7 @@ var OAUTH_BASE_URLS = {
|
|
|
3189
3191
|
fr: "https://staging.api.leadbay.app"
|
|
3190
3192
|
}
|
|
3191
3193
|
};
|
|
3192
|
-
var VERSION = "0.
|
|
3194
|
+
var VERSION = "0.17.0";
|
|
3193
3195
|
var HELP = `
|
|
3194
3196
|
leadbay-mcp ${VERSION} \u2014 Leadbay Model Context Protocol server
|
|
3195
3197
|
|
|
@@ -3721,7 +3723,7 @@ async function runLogin(args) {
|
|
|
3721
3723
|
}
|
|
3722
3724
|
try {
|
|
3723
3725
|
if (pinnedRegion && !allowFallback) {
|
|
3724
|
-
const { REGIONS } = await import("./dist-
|
|
3726
|
+
const { REGIONS } = await import("./dist-3NYTS7OH.js");
|
|
3725
3727
|
const baseUrl = REGIONS[pinnedRegion];
|
|
3726
3728
|
const c = createClient({ region: pinnedRegion });
|
|
3727
3729
|
const token = await loginAt(baseUrl, email, password);
|
|
@@ -4224,7 +4226,7 @@ leadbay-mcp install \u2014 detected MCP clients on this machine:
|
|
|
4224
4226
|
let region;
|
|
4225
4227
|
try {
|
|
4226
4228
|
if (pinnedRegion && !allowFallback) {
|
|
4227
|
-
const { REGIONS } = await import("./dist-
|
|
4229
|
+
const { REGIONS } = await import("./dist-3NYTS7OH.js");
|
|
4228
4230
|
const baseUrl = REGIONS[pinnedRegion];
|
|
4229
4231
|
token = await loginAt(baseUrl, email, password);
|
|
4230
4232
|
region = pinnedRegion;
|
|
@@ -4960,6 +4960,7 @@ var COMPOSITE_FILE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
4960
4960
|
"leadbay_campaign_progression",
|
|
4961
4961
|
"leadbay_create_campaign",
|
|
4962
4962
|
"leadbay_enrich_titles",
|
|
4963
|
+
"leadbay_extend_lens",
|
|
4963
4964
|
"leadbay_followups_map",
|
|
4964
4965
|
"leadbay_import_and_qualify",
|
|
4965
4966
|
"leadbay_import_leads",
|
|
@@ -4977,6 +4978,7 @@ var COMPOSITE_FILE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
4977
4978
|
"leadbay_research_lead_by_id",
|
|
4978
4979
|
"leadbay_research_lead_by_name_fuzzy",
|
|
4979
4980
|
"leadbay_resolve_import_rows",
|
|
4981
|
+
"leadbay_seed_candidates",
|
|
4980
4982
|
"leadbay_tour_plan"
|
|
4981
4983
|
]);
|
|
4982
4984
|
|
|
@@ -5008,7 +5010,7 @@ prominently if mid-regen.
|
|
|
5008
5010
|
|
|
5009
5011
|
---
|
|
5010
5012
|
|
|
5011
|
-
Show the user's account state \u2014 admin rights, language, last-active lens, current quota usage across daily/weekly/monthly windows for llm_completion / ai_rescore / web_fetch resources, and whether the org's intelligence is mid-regeneration. Quota windows also hint at the user's consumption pace: heavy recent activity (ai_rescore / web_fetch near their window limits) is a signal that Leadbay will deliver a larger fresh batch next time the user logs back in, since batch size is paced by real consumption.
|
|
5013
|
+
Show the user's account state \u2014 admin rights, language, last-active lens, current quota usage across daily/weekly/monthly windows for llm_completion / ai_rescore / web_fetch / LENS_EXTRA_REFILL resources, and whether the org's intelligence is mid-regeneration. **Pre-check \`LENS_EXTRA_REFILL\` here before calling \`leadbay_extend_lens\`** \u2014 its full requested batch must fit into the remaining daily quota or the call is rejected outright. Quota windows also hint at the user's consumption pace: heavy recent activity (ai_rescore / web_fetch near their window limits) is a signal that Leadbay will deliver a larger fresh batch next time the user logs back in, since batch size is paced by real consumption.
|
|
5012
5014
|
|
|
5013
5015
|
**Top-ups always beat waiting.** When a quota window is hit, the user has two options: wait for the window reset (\`resets_at\` in each quota entry) OR top up AI credits. Top-ups clear the throttle IMMEDIATELY; they are not subject to the same window. When you tell the user about a 429 / quota exhaustion, ALWAYS surface both options \u2014 "wait until <reset>" or "top up now (I can generate the link)" \u2014 and let them pick. Never default-recommend "wait until tomorrow" when a 30-second top-up unblocks the same operation.
|
|
5014
5016
|
|
|
@@ -5592,6 +5594,102 @@ WHEN NOT TO USE: to enrich a single contact \u2014 that's leadbay_enrich_contact
|
|
|
5592
5594
|
|
|
5593
5595
|
This tool MUTATES state. The caller (agent or human-in-the-loop) is responsible for confirming intent before invocation; the MCP server does not soft-prompt for confirmation. See \`annotations.destructiveHint\`.
|
|
5594
5596
|
`;
|
|
5597
|
+
var leadbay_extend_lens = `## WHEN TO USE
|
|
5598
|
+
|
|
5599
|
+
Trigger phrases: "I want more leads on this lens", "extend the lens", "I need a bigger batch today", "fill more leads, I've burned through these", "more leads like the ones in this lens".
|
|
5600
|
+
|
|
5601
|
+
**Memory:** recall + capture via \`leadbay_agent_memory_*\` tools.
|
|
5602
|
+
|
|
5603
|
+
Do NOT use for: "show me today's leads" \u2192 \`leadbay_pull_leads\`; "narrow the audience" \u2192 \`leadbay_adjust_audience\`; "stop showing me X" \u2192 \`leadbay_refine_prompt\`.
|
|
5604
|
+
|
|
5605
|
+
Prefer when: user has bigger appetite than the daily lens fill delivers \u2014 additive refill on same criteria
|
|
5606
|
+
|
|
5607
|
+
Examples that SHOULD invoke this tool:
|
|
5608
|
+
- "Give me more leads on this lens \u2014 I want a bigger batch."
|
|
5609
|
+
- "Extend the lens, I've burned through what I had."
|
|
5610
|
+
- "Add 30 more leads like the ones in this batch."
|
|
5611
|
+
|
|
5612
|
+
Examples that should NOT invoke this tool (sound similar, route elsewhere):
|
|
5613
|
+
- "Show me today's leads."
|
|
5614
|
+
- "Narrow the audience to fintech only."
|
|
5615
|
+
- "Which leads should I follow up with this week?"
|
|
5616
|
+
|
|
5617
|
+
## RENDER (quick)
|
|
5618
|
+
|
|
5619
|
+
\`queued\` \u2192 \u2705 "Queued <N> extra leads on lens <id>. Pull in ~30s." Do NOT
|
|
5620
|
+
list \`accepted_seeds\`; they're internal.
|
|
5621
|
+
\`quota_exceeded\` \u2192 render three options via \`ask_user_input_v0\` (smaller
|
|
5622
|
+
count / wait until reset / upgrade).
|
|
5623
|
+
\`refresh_in_progress\` \u2192 "lens is filling, retry in a minute".
|
|
5624
|
+
\`no_valid_seeds\` \u2192 silently re-call \`leadbay_seed_candidates\`, retry once.
|
|
5625
|
+
|
|
5626
|
+
---
|
|
5627
|
+
|
|
5628
|
+
Queue an additive extra-refill on a lens \u2014 more leads on the same criteria, without changing the audience. For users whose daily appetite exceeds what the standard fill delivers. Wraps \`POST /lenses/{lensId}/extra_refill\`. The fill happens asynchronously; new leads stream in over ~30s, observable through \`leadbay_pull_leads\`.
|
|
5629
|
+
|
|
5630
|
+
**Mandatory chain \u2014 agent picks seeds silently.** Unless the user has explicitly said "no seeds, just fill it", the agent MUST call \`leadbay_seed_candidates\` FIRST, pick 3\u20135 seed leads using the heuristics in that tool's description, and pass them here as \`seed_lead_ids\`. The seed list is **never shown to the user** \u2014 the user asked for more leads, not a candidate review meeting. The canonical \`leadbay_extend_my_lens\` prompt drives this chain.
|
|
5631
|
+
|
|
5632
|
+
**Seeds are optional at the wire level** \u2014 omit or empty array \u2192 backend falls back to default centroid strategies (same behaviour as a normal fill). The response's \`accepted_seeds\` echoes the subset that passed validation. Prefer the seeded path because it gives the recommender a signal beyond the lens centroid (which it already biases on).
|
|
5633
|
+
|
|
5634
|
+
**Quota gate.** Each call is charged against the per-org daily \`LENS_EXTRA_REFILL\` quota at pre-flight time (FREEMIUM=0 / TIER1=150 / TIER2=1000). The **full requested batch** must fit \u2014 there is no partial fulfillment. **Pre-check via \`leadbay_account_status\`**: look at \`quota.org.resources[]\` for the \`LENS_EXTRA_REFILL\` entry to see how much was used today and when it resets.
|
|
5635
|
+
|
|
5636
|
+
**Status envelope (translated from raw API errors so the agent routes on \`status\`).**
|
|
5637
|
+
|
|
5638
|
+
- \`status: "queued"\` \u2014 fill is queued. \`accepted_seeds\` lists IDs that passed validation. NEXT STEP: call \`leadbay_pull_leads\` in ~30s.
|
|
5639
|
+
- \`status: "quota_exceeded"\` \u2014 daily LENS_EXTRA_REFILL hit. Response carries \`quota: {used_today, resets_at}\` + a \`message\` to surface. **Render three options via \`ask_user_input_v0\`**: (1) smaller \`extra_count\`, (2) wait until \`resets_at\`, (3) upgrade plan (TIER1=150, TIER2=1000). Do NOT silently retry.
|
|
5640
|
+
- \`status: "refresh_in_progress"\` \u2014 a refresh or extra-refill is already running. Tell the user to wait and call \`leadbay_pull_leads\` in ~30s.
|
|
5641
|
+
- \`status: "no_valid_seeds"\` \u2014 seeds went stale. Silently re-call \`leadbay_seed_candidates\` and retry once; only surface to the user if the second attempt also fails.
|
|
5642
|
+
|
|
5643
|
+
WHEN TO USE: when the user has a bigger appetite than the daily lens fill delivers \u2014 they want MORE of the same kind of leads, on demand. Canonical phrasings: "I want more leads on this lens", "extend the lens", "give me a bigger batch today". The \`leadbay_extend_my_lens\` prompt is the user-facing entry point that orchestrates the whole flow.
|
|
5644
|
+
|
|
5645
|
+
WHEN NOT TO USE: for daily inbox pulls (\`leadbay_pull_leads\`). Not for audience criteria changes (\`leadbay_adjust_audience\` / \`leadbay_refine_prompt\`). Never call this without seeds unless the user explicitly opted out \u2014 the seeded path produces materially better fill.
|
|
5646
|
+
|
|
5647
|
+
This tool MUTATES state. The caller (agent or human-in-the-loop) is responsible for confirming intent before invocation; the MCP server does not soft-prompt for confirmation. See \`annotations.destructiveHint\`.
|
|
5648
|
+
|
|
5649
|
+
|
|
5650
|
+
---
|
|
5651
|
+
|
|
5652
|
+
## NEXT STEPS \u2014 after \`leadbay_extend_lens\`
|
|
5653
|
+
|
|
5654
|
+
**RENDER NEXT STEPS via \`ask_user_input_v0\` when the host exposes it.**
|
|
5655
|
+
|
|
5656
|
+
The (Observation, Suggest, Calls) table below is the source of truth for which moves are valid. Pick the 2\u20134 most relevant rows based on what the response actually contains, then surface them as a \`single_select\` quick-select widget:
|
|
5657
|
+
|
|
5658
|
+
\`\`\`
|
|
5659
|
+
ask_user_input_v0({
|
|
5660
|
+
questions: [{
|
|
5661
|
+
question: "What next?",
|
|
5662
|
+
type: "single_select",
|
|
5663
|
+
options: [
|
|
5664
|
+
"<Suggest column from row 1>",
|
|
5665
|
+
"<Suggest column from row 2>",
|
|
5666
|
+
"<Suggest column from row 3>"
|
|
5667
|
+
]
|
|
5668
|
+
}]
|
|
5669
|
+
})
|
|
5670
|
+
\`\`\`
|
|
5671
|
+
|
|
5672
|
+
When the user picks an option, you call the matching tool from the \`Calls\` column. Constraints carried over from the widget contract: 2\u20134 mutually-exclusive options per question, button-sized labels (\u22646 words), max 3 questions per call.
|
|
5673
|
+
|
|
5674
|
+
**Fallback prose mode** \u2014 when the host doesn't expose \`ask_user_input_v0\` (or it returned an error): surface the same 2\u20133 picks as a short bulleted list of "Suggest" phrasings. The table itself stays internal; never recite the whole table to the user.
|
|
5675
|
+
|
|
5676
|
+
---
|
|
5677
|
+
|
|
5678
|
+
|
|
5679
|
+
|
|
5680
|
+
Pick the row matching the response \`status\`. Seed-picking is internal; do NOT add chips that imply the user reviewed candidates.
|
|
5681
|
+
|
|
5682
|
+
| \`status\` | Suggest | Calls |
|
|
5683
|
+
|-------------------------|---------------------------------------------------------------|--------------------------------------------------------|
|
|
5684
|
+
| \`queued\` | "Pull leads in ~30s to see the new ones" | \`leadbay_pull_leads()\` (after a short wait) |
|
|
5685
|
+
| \`quota_exceeded\` | "Try with a smaller \`extra_count\`" | \`leadbay_extend_lens(extra_count=<smaller>)\` |
|
|
5686
|
+
| \`quota_exceeded\` | "Wait until the daily quota resets at \`<resets_at>\`" | (no call \u2014 surface the reset time to the user) |
|
|
5687
|
+
| \`quota_exceeded\` | "Upgrade plan for a higher daily limit" | (no call \u2014 direct user to contact account manager / sales) |
|
|
5688
|
+
| \`refresh_in_progress\` | "Lens is already filling \u2014 pull leads in a minute" | \`leadbay_pull_leads()\` (after a short wait) |
|
|
5689
|
+
| \`no_valid_seeds\` | (silent retry \u2014 re-call \`leadbay_seed_candidates\` then \`leadbay_extend_lens\`) | internal \u2014 only surface if the second attempt also fails |
|
|
5690
|
+
|
|
5691
|
+
If nothing matches cleanly, default to "pull leads now to see what's queued" \u2014 never invent a tool that doesn't exist.
|
|
5692
|
+
`;
|
|
5595
5693
|
var leadbay_followups_map = `## WHEN TO USE
|
|
5596
5694
|
|
|
5597
5695
|
Trigger phrases: "I'm going to <city>", "visit in person", "map of leads", "plan my itinerary".
|
|
@@ -7389,6 +7487,56 @@ Below the table, a one-liner: \`"Ready: K rows \xB7 Ambiguous: A rows \xB7 Unmat
|
|
|
7389
7487
|
| Unmatched rows but websites present | "Import anyway \u2014 Leadbay will crawl and match later" | leadbay_import_leads (status check after) |
|
|
7390
7488
|
| User wants to skip rows they can't ID | "Drop unmatched rows and import the rest" | leadbay_import_leads (with filtered records) |
|
|
7391
7489
|
`;
|
|
7490
|
+
var leadbay_seed_candidates = `## WHEN TO USE
|
|
7491
|
+
|
|
7492
|
+
Trigger phrases: "(internal) agent decided to extend the lens \u2014 fetch seed candidates".
|
|
7493
|
+
|
|
7494
|
+
**Memory:** recall + capture via \`leadbay_agent_memory_*\` tools.
|
|
7495
|
+
|
|
7496
|
+
Do NOT use for: "show me today's leads" \u2192 \`leadbay_pull_leads\`; "leads I should follow up with" \u2192 \`leadbay_pull_followups\`; "narrow the audience" \u2192 \`leadbay_adjust_audience\`; "stop showing me X" \u2192 \`leadbay_refine_prompt\`.
|
|
7497
|
+
|
|
7498
|
+
Prefer when: agent is mid-\`leadbay_extend_my_lens\` flow and needs to pick seeds before calling \`leadbay_extend_lens\`
|
|
7499
|
+
|
|
7500
|
+
Examples that SHOULD invoke this tool:
|
|
7501
|
+
- "(agent-internal) user asked for more leads \u2014 fetch seeds before calling extend_lens"
|
|
7502
|
+
|
|
7503
|
+
Examples that should NOT invoke this tool (sound similar, route elsewhere):
|
|
7504
|
+
- "Show me today's leads."
|
|
7505
|
+
- "Restrict the audience to fintech only."
|
|
7506
|
+
- "Which leads should I follow up with this week?"
|
|
7507
|
+
|
|
7508
|
+
## RENDER (quick)
|
|
7509
|
+
|
|
7510
|
+
DO NOT RENDER TO THE USER. This is internal data the agent reasons over
|
|
7511
|
+
before calling \`leadbay_extend_lens\`. No table, no list of company names,
|
|
7512
|
+
no "here are your candidates". The user asked for more leads; surface the
|
|
7513
|
+
*outcome* of extend_lens, not the picking step.
|
|
7514
|
+
|
|
7515
|
+
---
|
|
7516
|
+
|
|
7517
|
+
**INTERNAL TOOL \u2014 do not surface candidates to the user.** The user asked for more leads on the lens (a higher daily appetite than the standard fill delivers), not to manually review candidates. This tool exists so the agent can pick seeds *silently*, then chain to \`leadbay_extend_lens\`. Picking is an agent decision; the user only sees the extend confirmation.
|
|
7518
|
+
|
|
7519
|
+
Backed by \`GET /lenses/{lensId}/seed_candidates\`. By construction every lead returned is a valid input to \`extra_refill\` (same eligibility query). Defaults to the user's last-active lens.
|
|
7520
|
+
|
|
7521
|
+
**Pick 3\u20135 seeds that represent the *kind* of leads the user wants more of**, using these signals in priority order:
|
|
7522
|
+
|
|
7523
|
+
1. **\`engagement\`** (load-bearing) \u2014 \`liked: true\`, \`org_contacts_count > 0\`, and \`prospecting_actions_count > 0\` mean the user (or their team) already validated this lead. These are the strongest signal.
|
|
7524
|
+
2. **\`qq_answers\`** \u2014 what the AI agent already answered when qualifying this lead. Match candidates whose answers align with the target profile.
|
|
7525
|
+
3. **\`tags\`** \u2014 purchase-intent alignment, ordered by score (most-relevant first).
|
|
7526
|
+
4. **\`sector\`, \`size_min\`, \`size_max\`** \u2014 shape similarity to known-good prospects.
|
|
7527
|
+
5. **\`ai_agent_score\`** \u2014 overall AI fit (0\u201399); null when the lead has not been AI-rescored.
|
|
7528
|
+
6. **\`description\`** \u2014 short company blurb for the final tie-breaker.
|
|
7529
|
+
|
|
7530
|
+
**Default heuristic** (no explicit user steering): top 3 by engagement (prefer \`liked: true\`; break ties by \`org_contacts_count + prospecting_actions_count\`), then fill to 5 with the top \`ai_agent_score\` rows whose \`tags\` overlap the engagement leaders' tags.
|
|
7531
|
+
|
|
7532
|
+
**Once seeds are picked, call \`leadbay_extend_lens\` immediately with \`seed_lead_ids=[...picked lead_ids]\`.** Do not pause for user approval; the user wants more leads, not a seed-review meeting.
|
|
7533
|
+
|
|
7534
|
+
WHEN TO USE: only as the scaffolding step inside an extend-the-lens flow. The \`leadbay_extend_my_lens\` prompt orchestrates this; agents called this tool by themselves should be rare.
|
|
7535
|
+
|
|
7536
|
+
WHEN NOT TO USE: when the user wants to CHANGE the audience (sector / size / criteria) \u2014 route to \`leadbay_adjust_audience\` or \`leadbay_refine_prompt\`. Not for the daily inbox pull \u2014 route to \`leadbay_pull_leads\`. Never as a "here are some candidates, which do you want?" user-facing surface.
|
|
7537
|
+
|
|
7538
|
+
Response shape (relayed verbatim from the backend): \`{ candidates: [{lead_id, name, description?, sector?, size_min?, size_max?, website?, ai_agent_score?, tags[], qq_answers[], org_lead_status?, engagement: {liked, org_contacts_count, prospecting_actions_count}}] }\`.
|
|
7539
|
+
`;
|
|
7392
7540
|
var leadbay_select_leads = `Add leads to the user's transient selection (used by selection-scoped bulk operations). Accepts 1-1000 \`leadIds\` per call.
|
|
7393
7541
|
|
|
7394
7542
|
WHEN TO USE: low-level. The user's selection is a per-token global state \u2014 be careful when invoking directly.
|
|
@@ -13657,7 +13805,7 @@ var accountStatus = {
|
|
|
13657
13805
|
},
|
|
13658
13806
|
quota: {
|
|
13659
13807
|
type: ["object", "null"],
|
|
13660
|
-
description: "Per-resource quota state (llm_completion, ai_rescore, web_fetch) across daily/weekly/monthly windows. Null if /quota_status failed (logged in stderr)."
|
|
13808
|
+
description: "Per-resource quota state (llm_completion, ai_rescore, web_fetch, LENS_EXTRA_REFILL) across daily/weekly/monthly windows. Null if /quota_status failed (logged in stderr). Pre-check the LENS_EXTRA_REFILL entry before calling leadbay_extend_lens."
|
|
13661
13809
|
},
|
|
13662
13810
|
_meta: {
|
|
13663
13811
|
type: "object",
|
|
@@ -17066,6 +17214,182 @@ var refinePrompt = {
|
|
|
17066
17214
|
}
|
|
17067
17215
|
};
|
|
17068
17216
|
|
|
17217
|
+
// ../core/dist/composite/seed-candidates.js
|
|
17218
|
+
var seedCandidates = {
|
|
17219
|
+
name: "leadbay_seed_candidates",
|
|
17220
|
+
annotations: {
|
|
17221
|
+
title: "List candidate seeds for a lens extra-refill",
|
|
17222
|
+
readOnlyHint: true,
|
|
17223
|
+
destructiveHint: false,
|
|
17224
|
+
idempotentHint: true,
|
|
17225
|
+
openWorldHint: true
|
|
17226
|
+
},
|
|
17227
|
+
description: leadbay_seed_candidates,
|
|
17228
|
+
inputSchema: {
|
|
17229
|
+
type: "object",
|
|
17230
|
+
properties: {
|
|
17231
|
+
lensId: {
|
|
17232
|
+
type: "number",
|
|
17233
|
+
description: "Lens to fetch candidates for. Defaults to the user's last-active lens."
|
|
17234
|
+
},
|
|
17235
|
+
limit: {
|
|
17236
|
+
type: "number",
|
|
17237
|
+
description: "Max candidates to return, 1\u201350 (backend default 20)."
|
|
17238
|
+
}
|
|
17239
|
+
},
|
|
17240
|
+
additionalProperties: false
|
|
17241
|
+
},
|
|
17242
|
+
outputSchema: {
|
|
17243
|
+
type: "object",
|
|
17244
|
+
properties: {
|
|
17245
|
+
lens: {
|
|
17246
|
+
type: "object",
|
|
17247
|
+
properties: { id: { type: "number" } }
|
|
17248
|
+
},
|
|
17249
|
+
candidates: {
|
|
17250
|
+
type: "array",
|
|
17251
|
+
description: "Ranked candidate leads \u2014 each is a valid seed for leadbay_extend_lens. Pick 3\u20135 that represent the kind of leads the user wants more of.",
|
|
17252
|
+
items: { type: "object" }
|
|
17253
|
+
}
|
|
17254
|
+
},
|
|
17255
|
+
required: ["lens", "candidates"]
|
|
17256
|
+
},
|
|
17257
|
+
execute: async (client, params) => {
|
|
17258
|
+
const lensId = params.lensId ?? await client.resolveDefaultLens();
|
|
17259
|
+
const limit = params.limit != null ? Math.max(1, Math.min(params.limit, 50)) : 20;
|
|
17260
|
+
const res = await client.request("GET", `/lenses/${lensId}/seed_candidates?limit=${limit}`);
|
|
17261
|
+
return {
|
|
17262
|
+
lens: { id: lensId },
|
|
17263
|
+
candidates: res.candidates
|
|
17264
|
+
};
|
|
17265
|
+
}
|
|
17266
|
+
};
|
|
17267
|
+
|
|
17268
|
+
// ../core/dist/composite/extend-lens.js
|
|
17269
|
+
function httpStatus(err) {
|
|
17270
|
+
return err?._meta?.http_status;
|
|
17271
|
+
}
|
|
17272
|
+
async function readExtraRefillQuota(client) {
|
|
17273
|
+
try {
|
|
17274
|
+
const me = await client.resolveMe();
|
|
17275
|
+
const quota = await client.request("GET", `/organizations/${me.organization.id}/quota_status`);
|
|
17276
|
+
const entry = quota.org?.resources?.find((r) => r.resource_type === "LENS_EXTRA_REFILL");
|
|
17277
|
+
return {
|
|
17278
|
+
count: entry?.count ?? null,
|
|
17279
|
+
resets_at: entry?.resets_at ?? null
|
|
17280
|
+
};
|
|
17281
|
+
} catch {
|
|
17282
|
+
return { count: null, resets_at: null };
|
|
17283
|
+
}
|
|
17284
|
+
}
|
|
17285
|
+
var extendLens = {
|
|
17286
|
+
name: "leadbay_extend_lens",
|
|
17287
|
+
annotations: {
|
|
17288
|
+
title: "Extend a lens with additional leads (extra refill)",
|
|
17289
|
+
readOnlyHint: false,
|
|
17290
|
+
destructiveHint: false,
|
|
17291
|
+
idempotentHint: false,
|
|
17292
|
+
openWorldHint: true
|
|
17293
|
+
},
|
|
17294
|
+
description: leadbay_extend_lens,
|
|
17295
|
+
optional: true,
|
|
17296
|
+
// gated behind LEADBAY_MCP_WRITE=1 in MCP
|
|
17297
|
+
inputSchema: {
|
|
17298
|
+
type: "object",
|
|
17299
|
+
properties: {
|
|
17300
|
+
lensId: {
|
|
17301
|
+
type: "number",
|
|
17302
|
+
description: "Lens to extend. Defaults to the user's last-active lens."
|
|
17303
|
+
},
|
|
17304
|
+
seed_lead_ids: {
|
|
17305
|
+
type: "array",
|
|
17306
|
+
description: "Optional list of lead UUIDs from leadbay_seed_candidates to bias the recommender. Omit or empty array \u2192 default-strategy fallback (same behaviour as a normal fill).",
|
|
17307
|
+
items: { type: "string" }
|
|
17308
|
+
},
|
|
17309
|
+
extra_count: {
|
|
17310
|
+
type: "number",
|
|
17311
|
+
description: "How many extra leads to request. Omit to use the backend default. The full requested count must fit into the remaining daily LENS_EXTRA_REFILL quota \u2014 otherwise the call is rejected outright (status: quota_exceeded)."
|
|
17312
|
+
}
|
|
17313
|
+
},
|
|
17314
|
+
additionalProperties: false
|
|
17315
|
+
},
|
|
17316
|
+
outputSchema: {
|
|
17317
|
+
type: "object",
|
|
17318
|
+
properties: {
|
|
17319
|
+
status: {
|
|
17320
|
+
type: "string",
|
|
17321
|
+
description: "queued | quota_exceeded | refresh_in_progress | no_valid_seeds"
|
|
17322
|
+
},
|
|
17323
|
+
lens: {
|
|
17324
|
+
type: "object",
|
|
17325
|
+
properties: { id: { type: "number" } }
|
|
17326
|
+
},
|
|
17327
|
+
accepted_seeds: {
|
|
17328
|
+
type: "array",
|
|
17329
|
+
description: "Subset of seed_lead_ids that passed validation and will bias the fill. Empty when no seeds were submitted (default-strategies fallback). Present only on status=queued.",
|
|
17330
|
+
items: { type: "string" }
|
|
17331
|
+
},
|
|
17332
|
+
message: {
|
|
17333
|
+
type: "string",
|
|
17334
|
+
description: "Human-readable summary. On error statuses, this is the line to surface to the user."
|
|
17335
|
+
},
|
|
17336
|
+
quota: {
|
|
17337
|
+
type: "object",
|
|
17338
|
+
description: "Only present on status=quota_exceeded. Shows the org's daily LENS_EXTRA_REFILL state.",
|
|
17339
|
+
properties: {
|
|
17340
|
+
used_today: { type: ["number", "null"] },
|
|
17341
|
+
resets_at: { type: ["string", "null"] }
|
|
17342
|
+
}
|
|
17343
|
+
}
|
|
17344
|
+
},
|
|
17345
|
+
required: ["status", "lens"]
|
|
17346
|
+
},
|
|
17347
|
+
execute: async (client, params) => {
|
|
17348
|
+
const lensId = params.lensId ?? await client.resolveDefaultLens();
|
|
17349
|
+
const body = {
|
|
17350
|
+
seed_lead_ids: params.seed_lead_ids ?? []
|
|
17351
|
+
};
|
|
17352
|
+
if (params.extra_count != null) {
|
|
17353
|
+
body.extra_count = params.extra_count;
|
|
17354
|
+
}
|
|
17355
|
+
try {
|
|
17356
|
+
const res = await client.request("POST", `/lenses/${lensId}/extra_refill`, body);
|
|
17357
|
+
return {
|
|
17358
|
+
status: "queued",
|
|
17359
|
+
lens: { id: lensId },
|
|
17360
|
+
accepted_seeds: res.accepted_seeds,
|
|
17361
|
+
message: "Extra refill queued. Leads stream in asynchronously \u2014 call leadbay_pull_leads in ~30s to see them."
|
|
17362
|
+
};
|
|
17363
|
+
} catch (err) {
|
|
17364
|
+
const status = httpStatus(err);
|
|
17365
|
+
if (status === 429) {
|
|
17366
|
+
const q = await readExtraRefillQuota(client);
|
|
17367
|
+
return {
|
|
17368
|
+
status: "quota_exceeded",
|
|
17369
|
+
lens: { id: lensId },
|
|
17370
|
+
quota: { used_today: q.count, resets_at: q.resets_at },
|
|
17371
|
+
message: "Daily LENS_EXTRA_REFILL quota exhausted. Surface to user: (1) try a smaller extra_count, (2) wait for the daily reset" + (q.resets_at ? ` (resets at ${q.resets_at})` : "") + ", or (3) upgrade plan for a higher daily limit (TIER1=150, TIER2=1000)."
|
|
17372
|
+
};
|
|
17373
|
+
}
|
|
17374
|
+
if (status === 409) {
|
|
17375
|
+
return {
|
|
17376
|
+
status: "refresh_in_progress",
|
|
17377
|
+
lens: { id: lensId },
|
|
17378
|
+
message: "A refresh or extra-refill is already running on this lens. Wait, then call leadbay_pull_leads in ~30s."
|
|
17379
|
+
};
|
|
17380
|
+
}
|
|
17381
|
+
if (status === 400) {
|
|
17382
|
+
return {
|
|
17383
|
+
status: "no_valid_seeds",
|
|
17384
|
+
lens: { id: lensId },
|
|
17385
|
+
message: "Every submitted seed failed validation (likely stale \u2014 the lens shape may have changed). Refetch via leadbay_seed_candidates and retry."
|
|
17386
|
+
};
|
|
17387
|
+
}
|
|
17388
|
+
throw err;
|
|
17389
|
+
}
|
|
17390
|
+
}
|
|
17391
|
+
};
|
|
17392
|
+
|
|
17069
17393
|
// ../core/dist/composite/answer-clarification.js
|
|
17070
17394
|
var answerClarification = {
|
|
17071
17395
|
name: "leadbay_answer_clarification",
|
|
@@ -17649,6 +17973,9 @@ var compositeReadTools = [
|
|
|
17649
17973
|
qualifyStatus,
|
|
17650
17974
|
importStatus,
|
|
17651
17975
|
resolveImportRows,
|
|
17976
|
+
// seed-candidates is a read-only discovery surface for the extend flow.
|
|
17977
|
+
// Always exposed so the agent can show candidates even in read-only deployments.
|
|
17978
|
+
seedCandidates,
|
|
17652
17979
|
// listMappableFields is granular-shaped but the import composites depend on
|
|
17653
17980
|
// it for discoverability; expose it always-on so agents can find custom fields
|
|
17654
17981
|
// without needing LEADBAY_MCP_ADVANCED=1.
|
|
@@ -17692,7 +18019,10 @@ var compositeWriteTools = [
|
|
|
17692
18019
|
// Backend POST endpoints; gated behind LEADBAY_MCP_WRITE=1 in MCP.
|
|
17693
18020
|
createCampaign,
|
|
17694
18021
|
addLeadsToCampaign,
|
|
17695
|
-
removeLeadsFromCampaign
|
|
18022
|
+
removeLeadsFromCampaign,
|
|
18023
|
+
// Lens extend — agent-driven on-demand fill (additive). Gated behind
|
|
18024
|
+
// LEADBAY_MCP_WRITE=1. Subject to per-org daily LENS_EXTRA_REFILL quota.
|
|
18025
|
+
extendLens
|
|
17696
18026
|
];
|
|
17697
18027
|
var compositeTools = [
|
|
17698
18028
|
...compositeReadTools,
|
|
@@ -17815,6 +18145,8 @@ export {
|
|
|
17815
18145
|
bulkEnrichStatus,
|
|
17816
18146
|
adjustAudience,
|
|
17817
18147
|
refinePrompt,
|
|
18148
|
+
seedCandidates,
|
|
18149
|
+
extendLens,
|
|
17818
18150
|
answerClarification,
|
|
17819
18151
|
reportOutreach,
|
|
17820
18152
|
reportFriction,
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
enrichContacts,
|
|
51
51
|
enrichTitles,
|
|
52
52
|
ensureAgentMemorySummary,
|
|
53
|
+
extendLens,
|
|
53
54
|
followupsMap,
|
|
54
55
|
formatLoginError,
|
|
55
56
|
getClarification,
|
|
@@ -115,6 +116,7 @@ import {
|
|
|
115
116
|
resolveAgentMemorySummary,
|
|
116
117
|
resolveImportRows,
|
|
117
118
|
resolveRegion,
|
|
119
|
+
seedCandidates,
|
|
118
120
|
selectLeads,
|
|
119
121
|
setActiveLens,
|
|
120
122
|
setEpilogueStatus,
|
|
@@ -125,7 +127,7 @@ import {
|
|
|
125
127
|
updateLens,
|
|
126
128
|
updateLensFilter,
|
|
127
129
|
withAgentMemoryMeta
|
|
128
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-ASAKITU3.js";
|
|
129
131
|
export {
|
|
130
132
|
AgentMemoryCaptureInputSchema,
|
|
131
133
|
AgentMemoryEntrySchema,
|
|
@@ -177,6 +179,7 @@ export {
|
|
|
177
179
|
enrichContacts,
|
|
178
180
|
enrichTitles,
|
|
179
181
|
ensureAgentMemorySummary,
|
|
182
|
+
extendLens,
|
|
180
183
|
followupsMap,
|
|
181
184
|
formatLoginError,
|
|
182
185
|
getClarification,
|
|
@@ -242,6 +245,7 @@ export {
|
|
|
242
245
|
resolveAgentMemorySummary,
|
|
243
246
|
resolveImportRows,
|
|
244
247
|
resolveRegion,
|
|
248
|
+
seedCandidates,
|
|
245
249
|
selectLeads,
|
|
246
250
|
setActiveLens,
|
|
247
251
|
setEpilogueStatus,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadbay/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"mcpName": "io.github.leadbay/leadbay-mcp",
|
|
5
5
|
"description": "Model Context Protocol (MCP) server for Leadbay — AI lead discovery, qualification, and enrichment for Claude Desktop, Cursor, and Claude Code.",
|
|
6
6
|
"type": "module",
|