@leadbay/mcp 0.9.1 → 0.10.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,67 @@
1
1
  # Changelog — @leadbay/mcp
2
2
 
3
+ ## 0.10.0 — 2026-05-19
4
+
5
+ First stable cut of the 0.10 line. Consolidates everything since 0.9.1: host-native widget rendering, structured routing schema, the top-up flow, like/dislike write tools, the `research_lead` split, and PostHog + Sentry telemetry. See dev-iteration commits for granular per-PR history; this is the npm-shipped consolidation.
6
+
7
+ ### Host-native widgets + chat-native rendering (#42)
8
+
9
+ Iframe widget rendering via MCP Apps `_meta.ui` is **removed entirely** — it short-circuited Claude's native widget routing and never blended with chat themes. All tools now render via two surfaces only: (1) chat-native markdown (the canonical `RENDERING` block every tool description carries — tables, cards, chips, headings; inherits the chat's theme + dark-mode for free), and (2) Claude's three first-party widgets when the host exposes them: `places_map_display_v0` (≥2 locations / travel intent), `message_compose_v1` (outreach drafts), `ask_user_input_v0` (NEXT STEPS / clarifications). Same widget-routing pattern applies on ChatGPT via `_meta.openai/outputTemplate`. The `Tool.ui` field is removed from the `Tool` interface — DO NOT re-introduce it.
10
+
11
+ Hosts that auto-detect addresses in agent prose (Claude.ai web, cowork, Claude Desktop) now get fed per-lead blocks shaped for their Google-Place-card carousel — see the `leadbay_followup_check_in` "TRAVEL / IN-PERSON ROUTING" block as the canonical example.
12
+
13
+ ### Structured routing schema in promptforge (#42)
14
+
15
+ Every user-facing tool description follows a new 5-section convention enforced by promptforge + audit tests:
16
+
17
+ ```
18
+ [1] ## WHEN TO USE ← auto-emitted from frontmatter.routing
19
+ [2] ## RENDER (quick) ← auto-emitted from frontmatter.rendering_hint
20
+ ---
21
+ [3] <free-form body>
22
+ [4] {{include:rendering/…}}
23
+ [5] {{include:next-steps/…}}
24
+ ```
25
+
26
+ Routing frontmatter is structured YAML: `triggers`, `anti_triggers` (with `route_to` cross-references), `prefer_when` decision hint, and ≥3 positive + ≥3 negative example messages per [Anthropic's skill-author guide](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills). The audit (`routing-block.test.ts`) asserts the `## WHEN TO USE` block lands within the first 600 chars (the context-truncation window every host honors), anti-trigger `route_to` values resolve to registered tool names, and the example floor (≥2 of each) holds for every routed tool. Backfilled on the 7 user-facing composites in this release.
27
+
28
+ ### Top-up flow + billing tools always-on (#42)
29
+
30
+ `leadbay_create_topup_link` (POST `/stripe/topup_checkout` → Stripe checkout URL) and `leadbay_open_billing_portal` are now **always exposed** in `compositeReadTools` (not gated behind `LEADBAY_MCP_ADVANCED=1`) because they're the canonical recovery path from a `QUOTA_EXCEEDED` wall. Without them, the agent would know about the wall but not the door out.
31
+
32
+ `QUOTA_EXCEEDED` error hints now explicitly offer top-up as the path that clears the throttle immediately (vs. waiting for the daily/weekly/monthly window reset). The new `QUOTA_AND_TOPUP_PARAGRAPH` in the server instructions tells the agent to OFFER top-up on every quota wall and, after the user signals they've topped up, RESUME the originally-failed call rather than gate-keeping on a stale `account_status` snapshot.
33
+
34
+ New composite `leadbay_followups_map` for travel / itinerary / state-level intent — handles NYC/SF/LA city aliases and a universal `city` arg that resolves state/country/region levels server-side.
35
+
36
+ ### `research_lead` split (#43)
37
+
38
+ `leadbay_research_lead` / `leadbay_research_company` are replaced by a pair whose **input mode is in the name itself**:
39
+
40
+ - `leadbay_research_lead_by_id` — exact UUID lookup; rich composite carrying qualification + signals + firmographics + two-tier contacts + unified `recent_activities` + engagement counts + `web_insights_fetched_at` + `_meta`. The `_meta.has_reachable_contact` flag is the one-shot signal that drives NEXT STEPS (false → propose `leadbay_enrich_titles`; true → propose `leadbay_prepare_outreach`).
41
+ - `leadbay_research_lead_by_name_fuzzy` — thin wrapper that resolves a `companyName` against the active lens's top-50 wishlist by substring (highest score wins), then delegates to `_by_id`.
42
+
43
+ Routing collapses to a syntactic choice (UUID vs. name) instead of a semantic guess, which was the source of misroutes when an agent had both a name and a partial ID.
44
+
45
+ ### `leadbay_like_lead` + `leadbay_dislike_lead` write tools (#41)
46
+
47
+ The thumbs-up / thumbs-down actions already available on the Leadbay website are now MCP tools. Agents can send positive and negative lead signals back to the Leadbay scoring engine to improve future batch quality.
48
+
49
+ - `leadbay_like_lead` — POSTs to `/leads/{id}/like`. Fires on "this one looks good", "thumbs up", "I like this".
50
+ - `leadbay_dislike_lead` — POSTs to `/leads/{id}/dislike`. Fires on "not relevant", "wrong industry", "thumbs down". Distinct from `leadbay_set_pushback` (temporary deferral, not a permanent negative signal).
51
+
52
+ Both ship in the default write surface (no `LEADBAY_MCP_ADVANCED=1` required); gated by `LEADBAY_MCP_WRITE=1` (default ON since 0.3.0). Descriptions carry the new structured `routing` + `rendering_hint` frontmatter.
53
+
54
+ ### PostHog + Sentry telemetry (#44, closes #3631)
55
+
56
+ Every tool invocation now fires an `mcp tool called` event to PostHog (same project as the frontend, project id 23333, EU instance), with quota walls surfaced as `mcp quota hit` and successful top-up checkout-link generation as `mcp topup link created`. Unexpected throws (TypeError, network failures, parse bugs) report to a new MCP-specific Sentry DSN; expected `LeadbayError` envelopes (QUOTA_EXCEEDED, NOT_FOUND, AUTH_EXPIRED, FORBIDDEN, BILLING_SUSPENDED, API_ERROR) stay in PostHog only.
57
+
58
+ - **Identity by email**: PostHog `distinctId = me.email` so MCP events consolidate with web-app events under the same person. Person properties (`leadbay_id`, `leadbay_organization`, `leadbay_organization_id`, etc.) match the frontend's `usePostHog.tsx` shape. **Events are NOT anonymous** — explicitly stated in `--help`, the install banner, and README.
59
+ - **`$groups.organization` attached** so org-level rollups work out of the box.
60
+ - **Privacy**: we capture `tool`, `duration_ms`, `ok`, `format`, `bytes`, `error_code` — never tool argument bodies, response bodies, lead emails, or Stripe URLs (unit test enforces).
61
+ - **Opt-out as a first-class toggle**: `leadbay-mcp install` always writes `LEADBAY_TELEMETRY_ENABLED=true` into your client's env block (next to `LEADBAY_TOKEN` / `LEADBAY_REGION`), so MCP-client config UIs (Claude Desktop, Cursor) render it as a toggle the user can flip without editing files. Pass `--no-telemetry` to install with telemetry off, or flip the env value to `"false"` anytime. Accepted: `true|1|yes|on` (enable), `false|0|no|off` (disable), case-insensitive. Also disabled when `NODE_ENV=test`.
62
+ - **Override**: `LEADBAY_POSTHOG_KEY` and `LEADBAY_SENTRY_DSN` env vars override the baked-in defaults.
63
+ - **stdio safety**: both SDKs are configured to never write to stdout (the JSON-RPC channel). Sentry runs without its default integrations (no console capture) and shutdown is bounded at 2s to never block process exit.
64
+
3
65
  ## 0.9.1 — 2026-05-16
4
66
 
5
67
  **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).
package/README.md CHANGED
@@ -379,7 +379,7 @@ The user's literal text replaces `verification.ref` in the outreach record, and
379
379
 
380
380
  ### Exposing the granular tools and disabling write tools
381
381
 
382
- By default the server exposes the **composite workflow tools** — both reads (`leadbay_pull_leads`, `leadbay_research_lead`, `leadbay_account_status`, `leadbay_recall_ordered_titles`, `leadbay_research_company`, `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.
382
+ 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.
383
383
 
384
384
  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.
385
385
 
@@ -459,9 +459,49 @@ Use `dry_run: true` to validate domain formatting and wizard reachability withou
459
459
  - The `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.
460
460
  - The `leadbay_add_note` and `leadbay_enrich_contacts` tools are write actions flagged `optional: true`. If your client supports per-tool opt-in, leave them disabled until you need them.
461
461
 
462
- ### Privacy
462
+ ### Privacy & telemetry
463
463
 
464
- Contact data fetched through this server stays local to your MCP client session. No analytics or telemetry is sent by `@leadbay/mcp`. Requests to Leadbay are subject to the [Leadbay privacy policy](https://leadbay.ai/privacy).
464
+ `@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.
465
+
466
+ **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).
467
+
468
+ **What we send to PostHog** (per tool call):
469
+
470
+ | Event | When | Properties |
471
+ |---|---|---|
472
+ | `mcp tool called` | Every tool invocation | `tool`, `ok`, `duration_ms`, `format`, `bytes`, `error_code` (if failed) |
473
+ | `mcp quota hit` | When the API returns `QUOTA_EXCEEDED` (HTTP 429/402) | `tool`, `retry_after_s`, `endpoint` |
474
+ | `mcp topup link created` | When `leadbay_create_topup_link` returns a checkout URL | `tool` (the URL itself is **never** captured) |
475
+
476
+ 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.
477
+
478
+ **What we never send**: tool argument bodies, response bodies, lead emails / phones, Stripe URLs, lens descriptions, qualification answers.
479
+
480
+ **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.
481
+
482
+ **Opt out** — `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"`:
483
+
484
+ ```jsonc
485
+ {
486
+ "mcpServers": {
487
+ "leadbay": {
488
+ "command": "npx",
489
+ "args": ["-y", "@leadbay/mcp@0.10"],
490
+ "env": {
491
+ "LEADBAY_TOKEN": "u.…",
492
+ "LEADBAY_REGION": "us",
493
+ "LEADBAY_TELEMETRY_ENABLED": "false"
494
+ }
495
+ }
496
+ }
497
+ }
498
+ ```
499
+
500
+ Accepted values: `"true"|"1"|"yes"|"on"` enable; `"false"|"0"|"no"|"off"` disable (case-insensitive). Unset / unrecognized values default to enabled.
501
+
502
+ **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`.
503
+
504
+ 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](https://leadbay.ai/privacy).
465
505
 
466
506
  ## 7. For maintainers — publishing
467
507