@leadbay/mcp 0.8.0 → 0.9.1

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,51 @@
1
1
  # Changelog — @leadbay/mcp
2
2
 
3
+ ## 0.9.1 — 2026-05-16
4
+
5
+ **B23 fix — prompts no longer override per-tool RENDERING blocks**: 0.9.0 shipped RENDERING + NEXT STEPS blocks on every composite tool description. But agents still rendered prose for the daily-leads workflow, because the orchestrating `leadbay_daily_check_in` prompt's Phase 3 directed motivational one-line summaries that "won" over the per-tool RENDERING block in pull_leads. Phase 3 is rewritten to defer to the canonical pull_leads table layout (score bars, three columns, hide-list) and to add a 2–4 sentence "Today's nudges" paragraph ABOVE the table for the 3 most-promising rows — never in place of it. The same pattern is applied to `leadbay_qualify_top_n` (Phase 3 re-pulls newly-qualified leads via pull_leads and renders the canonical table, with a "Standouts from this batch" line above) and `leadbay_research_a_domain` (Phase 2 renders the research-company-card layout for the deep-dive result, with a 2–3 sentence summary above).
6
+
7
+ **New `gates/defer-to-tool-rendering` snippet — architectural prevention**: a new gate snippet codifies the rule "the tool's RENDERING wins for the structural layout; the prompt's voice wins for the commentary that surrounds it." Included from every prompt that orchestrates a composite carrying a RENDERING block (`leadbay_daily_check_in`, `leadbay_qualify_top_n`, `leadbay_research_a_domain`, `leadbay_import_file`, `leadbay_prospecting_overview`, and the new `leadbay_followup_check_in`). A new assembler test enforces the gate include: any prompt whose `expected_calls` lists a composite with a RENDERING block MUST include the snippet — CI fails otherwise. Closes the door on future prompts quietly bypassing the contract.
8
+
9
+ **Discover-vs-Monitor routing fix (companion to B23)**: 0.9.0 shipped `leadbay_pull_followups` (the Monitor view) and `leadbay_pull_leads` (Discover wishlist) as parallel entry points but no orchestrator prompt parallel to `leadbay_daily_check_in` for the follow-up flow. When the user asked "leads I should follow up with today", no prompt auto-triggered and the agent freelanced — typically iterating pages of `pull_leads` filtering by `prospecting_actions_count > 0` (the wrong backend table). Four fixes:
10
+
11
+ - **New `leadbay_followup_check_in` prompt** — Monitor-view orchestrator paired 1:1 with `leadbay_daily_check_in` (Discovery). Triggers on "follow up", "already known leads", "leads I haven't contacted", "leads in [city]", "before my trip", "this week", "what's overdue", "who should I re-engage". Calls `leadbay_pull_followups` (never `pull_leads`), renders the canonical followups-table with a "Where to start today" paragraph above. Auto-emits as a Claude Code skill via the existing skills pipeline.
12
+ - **Narrowed `leadbay_daily_check_in` triggers** — `short_description` rewritten to scope to DISCOVERY phrasings ("best NEW leads", "what's new today", "let's prospect"); explicitly does NOT trigger on "what should I follow up on", "before my trip", etc. New failure_mode entry catches accidental routing into discovery from follow-up queries.
13
+ - **Anti-confusion guardrail in `leadbay_pull_followups` description** — names the specific failure mode ("iterating pages of `pull_leads` looking for rows with `prospecting_actions_count > 0` or `notes_count > 0` → STOP, wrong entry point") and points to `leadbay_followup_check_in` as the canonical orchestrator. The pair of backend tables doesn't share rows — a touched lead may age out of the new-leads queue entirely.
14
+ - **Routing-pair section in `leadbay_prospecting_overview`** — explicit mapping from user phrasing to orchestrator prompt, plus a hard rule never to call `pull_leads` directly for a follow-up query (or `pull_followups` for a discovery query).
15
+
16
+ **Server-side fix to the catalog filter**: the `buildPromptsCatalogParagraph` filter that drops bullets referencing unexposed `leadbay_*` tools now exempts prompt-name references too (prompts are always exposed). Previously a discovery bullet that pointed the follow-up flow to `leadbay_followup_check_in` would have been silently dropped from the catalog.
17
+
18
+ **Six new regression eval scenarios**: B23 rendering — `daily-check-in/rendering-table-contract`, `qualify-top-n/rendering-refresh-table`, `research-a-domain/rendering-card-contract`. Routing — `followup-check-in/routing-regression` (calls `pull_followups`, NEVER `pull_leads`), `followup-check-in/cross-mode-pivot` (recognizes the pivot offer to discovery), `followup-check-in/geo-followup` (handles geo without fabricating an `admin_area_id`). Picked up automatically by the existing eval framework via the per-prompt eval files; the new `leadbay_followup_check_in.eval.ts` runs all three.
19
+
20
+ **Files touched**: 1 new gate snippet, 1 new prompt (`leadbay_followup_check_in`), 5 modified prompts (`leadbay_daily_check_in`, `leadbay_qualify_top_n`, `leadbay_research_a_domain`, `leadbay_import_file`, `leadbay_prospecting_overview`), 1 modified tool description (`leadbay_pull_followups`), 1 server.ts catalog-filter fix, 1 new assembler test, 6 new scenario files, 4 modified/new eval files, 1 new invariants module, touchfile registry updated. No backend schema changes; no tool surface changes; same wire protocol as 0.9.0.
21
+
22
+ ## 0.9.0 — 2026-05-16
23
+
24
+ **RENDERING + NEXT STEPS blocks in every composite tool description**: agents consuming composite tools today default to prose summaries when they don't know how to present the data. Tool descriptions now carry two new prescriptive blocks the agent reads verbatim — `RENDERING` (a recipe for how to present the response: table columns, glyph palette, link targets, fields to hide) and `NEXT STEPS` (an observation → suggestion table the agent picks 2–3 contextually relevant offers from, never reciting the whole menu). Lands on the seven highest-leverage composites: `leadbay_pull_leads`, `leadbay_research_company`, `leadbay_prepare_outreach`, `leadbay_bulk_qualify_leads`, `leadbay_import_leads`, `leadbay_import_and_qualify`, `leadbay_import_status`, `leadbay_list_mappable_fields`, `leadbay_resolve_import_rows`. The blocks add ~5–7k chars per description, so the audit's per-tool char budget was raised from 3500 → 12000 with a comment explaining the design tradeoff.
25
+
26
+ **Three new snippet categories in promptforge** — `snippets/rendering/` (response-shape recipes: `score-bar`, `pull-leads-table`, `research-company-card`, `prepare-outreach-brief`, `import-result`, `status-inline`), `snippets/next-steps/` (one observation→suggestion table per composite), and `snippets/linking/` (`contact-linkedin` for the priority chain → real `linkedin_page` → people-search fallback with `°`-flag; `company-socials` for the multi-platform `social_urls` pill row). Each composite's `.md.tmpl` now `{{include:rendering/...}}` + `{{include:next-steps/...}}` instead of inlining the rules.
27
+
28
+ **New iron-law `outcome-after-outreach`**: when the user reports outreach happened ("I sent it", "she didn't pick up", a forwarded email thread), the agent MUST (a) call `leadbay_report_outreach` with verification AND (b) ask about the outcome and set `epilogue_status` to one of the 4 canonical values. User-facing dialogue uses "outcome" not "epilogue"; "follow-ups" not "Monitor". Included from `prepare_outreach.md.tmpl` and the new prospecting-overview prompt. Closes the loop that was silently de-ranking every future follow-up suggestion.
29
+
30
+ **New `leadbay_prospecting_overview` prompt → Claude Code skill**: ships at `prompts/leadbay_prospecting_overview.md.tmpl` and auto-emits `SKILL.md` via the existing skills pipeline. Orients the agent to the two-entry-point workflow (discovery via `pull_leads` vs follow-up via the app's Monitor view), natural-language signal routing, the outreach loop, adaptive drafting based on connected outreach tools (Lemlist / Outreach.io / Salesloft / Apollo / HubSpot / Instantly / Attio / Amplemarket / generic), outcome-recording habit, snooze/pushback semantics, and the lens-pinning rule. Auto-triggers on Leadbay-related conversation; stays dormant otherwise.
31
+
32
+ **Composite output-shape fixes**:
33
+
34
+ - **B1 / B6 / B7 — contact `linkedin_page` is canonical and never the literal string `"null"`**: `pull_leads`, `research_lead`, `prepare_outreach`, and `get_lead_profile` all propagate `linkedin_page` on `recommended_contact` and every `contacts[]` entry, coercing the legacy `"null"` four-character string (a backend serialization bug) to real JSON null on the way out.
35
+ - **B4 — `leadbay_research_lead` outputSchema fix**: `firmographics.size` was declared as `string|null` while the composite returns `{min,max,low,high,label}`; `firmographics.location` was `string|null` while the composite returns `{city,state,country,full,pos}`; `firmographics.tags` items were `string` while the composite returns `{id,display_name,tag,score}`. All three corrected to match the actual `LeadSimplified` shape. Also tightened `social_presence` and `social_urls` declarations to typed objects (was `["object","string","null"]` etc.). The tool was unusable before this fix — every call rejected by MCP schema validation.
36
+ - **B8 — `recommended_contact_title` dropped**: this field duplicated `recommended_contact.job_title` everywhere it appeared (`pull_leads`, `research_lead`, `get_lead_profile`). Removed.
37
+ - **B12 / B15 — `leadbay_prepare_outreach` expanded `lead` block**: was a two-field stub (`{name, ai_summary, website}`); now includes `score`, `ai_agent_lead_score`, `split_ai_summary`, `location`, `size`, `phone_numbers`, `description`, `short_description`, `social_presence`, `social_urls`. The agent no longer needs a second `research_company` call to render basic context.
38
+ - **B13 — self-polling enrichment**: `enrichment.complete: boolean` added. The brief now re-fetches contacts ONCE after triggering enrichment, and exposes `complete: true` when the recommended contact has either email or phone. The agent just re-calls `leadbay_prepare_outreach(leadId)` (no `enrich`) to poll; no separate `leadbay_get_contacts` tool needed.
39
+ - **B16 — `additional_contacts_count`**: clearer name. `other_contacts_count` kept as a deprecated alias for one release.
40
+ - **B21 — recommended_contact shape standardized**: always emit the post-enrichment field shape (`contact_id`, `first_name`, `last_name`, `job_title`, `email`, `phone_number`, `linkedin_page`, `is_org_contact`) with nulls in un-enriched fields — no more shape-flipping between pre- and post-enrichment.
41
+ - **`pull_leads` augmented**: trimmed shape now includes `ai_summary`, `split_ai_summary`, `phone_numbers`, `social_presence`, `social_urls`. Agents can render rich tables without verbose mode.
42
+
43
+ **Audit budget raised**: tool description per-tool char cap raised from 3500 → 12000. The largest tool descriptions are now `leadbay_research_company` (~10.5k chars) and `leadbay_prepare_outreach` (~10.1k chars). The plan was designed knowing this cost — the new char budget is justified by what the agent now does without prompting (table layout, glyph palette, observation→suggestion menu).
44
+
45
+ **New composite `leadbay_pull_followups`** — the Monitor view (re-engagement workflow), distinct from `leadbay_pull_leads` (discovery). Wraps `GET /1.5/monitor?personal=&liked=&filtered=&count=&page=` plus `GET/POST /1.5/monitor/filter` (server-persisted FilterItem). Accepts a `set_filter: { criteria: FilterCriterion[] }` parameter that POSTs first, then re-pulls — the same store-then-apply mechanism the Leadbay app uses. The composite excludes leads with active pushback client-side (defense-in-depth — the backend likely already does this) and reports `total_excluded_by_pushback`. Status-badge derived in the rendering rule from existing fields (`epilogue_status` + `last_prospecting_action_at` + `new`) — no new backend field needed. Endpoints verified live via the discover-monitor-activate wiki page; backend handler is `MonitorRoutes.kt:getMonitor()` → `Database.monitor.findAll`.
46
+
47
+ **Two new granular tools — `leadbay_set_pushback` / `leadbay_remove_pushback`**: snooze a lead (or a bulk set, up to 1000) for 3 / 6 / 12 months. Wraps `POST /leads/pushback` and `POST /leads/remove_pushback` (mirrors the existing `/leads/epilogue` / `/leads/remove_epilogue` pattern). Accepts short labels (`"3"` / `"6"` / `"12"`) or the wire-format enum (`PUSHBACK_3` / `PUSHBACK_6` / `PUSHBACK_12`). User-facing dialogue says "snooze for N months" — never "pushback status". Pull_followups excludes leads with active pushback from its results until expiry. Available behind `LEADBAY_MCP_ADVANCED=1 + LEADBAY_MCP_WRITE=1` (granular write).
48
+
3
49
  ## 0.8.0 — 2026-05-15
4
50
 
5
51
  **Prompts ship as Claude Code skills + initialize advertises the prompt catalog**: the six MCP prompts (`leadbay_daily_check_in`, `leadbay_research_a_domain`, `leadbay_import_file`, `leadbay_log_outreach`, `leadbay_qualify_top_n`, `leadbay_refine_audience`) now also emit as auto-discovered Claude Code skills under `.claude-plugin/plugins/leadbay/skills/<name>/SKILL.md` from the same `.md.tmpl` source. `{{arg:NAME}}` placeholders are rewritten in-place as natural-language extraction instructions because skills have no structured-argument system. The MCP server's `initialize` response now splices a `PROMPT_CATALOG_INSTRUCTIONS` paragraph into the `instructions` payload so UI-blind clients (Cowork is the prototypical case) learn the prompt set; bullets that reference a tool gated off by the current config are suppressed (preserves the iter-12 invariant that the system prompt never names a tool the agent cannot call). Plugin manifest bumped `0.6.2` → `0.6.3`.