@leadbay/mcp 0.32.1 → 0.32.4
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 +28 -0
- package/dist/bin.js +34 -13
- package/dist/http-server.js +85 -11
- package/dist/installer-electron.js +1 -1
- package/dist/installer-gui.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog — @leadbay/mcp
|
|
2
2
|
|
|
3
|
+
## 0.32.4 — 2026-09-01
|
|
4
|
+
|
|
5
|
+
`leadbay_account_status.notifications` was permanently `[]` on the hosted server
|
|
6
|
+
(product#4009). Same shape as product#4005: `buildServerFromClient` builds every
|
|
7
|
+
hosted server without a `notificationsInbox`, `BuildServerOptions` makes it
|
|
8
|
+
optional, so it compiled and failed silently.
|
|
9
|
+
|
|
10
|
+
**Not fixed by wiring the inbox, because the inbox cannot exist there.** It is
|
|
11
|
+
fed by a WS listener whose ticket (`GET /auth/ws`) is per-account, which is
|
|
12
|
+
meaningless on a multi-tenant process, and the streamable transport builds a
|
|
13
|
+
fresh `Server` per request so nothing would survive to be cached. Porting it
|
|
14
|
+
would be the same mistake in a third place.
|
|
15
|
+
|
|
16
|
+
`GET /notifications` is already per-account and already durable. On hosted the
|
|
17
|
+
ledger IS the inbox, so `account_status` reads it on demand when no inbox is
|
|
18
|
+
wired. Stdio is unchanged and still free — the WS listener already has the
|
|
19
|
+
answer, and the ledger is not called.
|
|
20
|
+
|
|
21
|
+
- `fetchTerminalNotifications(client)` in `notifications/catch-up.ts` returns
|
|
22
|
+
terminal, unseen entries directly. `isTerminalUnseen` is extracted so inbox
|
|
23
|
+
seeding and the inbox-less read cannot disagree about what counts.
|
|
24
|
+
- A notifications failure resolves to `[]` rather than throwing. `account_status`
|
|
25
|
+
is the daily entry point; a ledger hiccup must not take the check-in down.
|
|
26
|
+
- **Deliberately not done: `_meta.notifications` still does not ride hosted tool
|
|
27
|
+
responses.** Reviving it would mean a `GET /notifications` per tool call to
|
|
28
|
+
decorate every response. The cost lands on the check-in entry point only,
|
|
29
|
+
which is where the daily-rhythm channel is actually read.
|
|
30
|
+
|
|
3
31
|
## 0.32.0 — 2026-09-01
|
|
4
32
|
|
|
5
33
|
A poll-budget timeout stops being an error (product#4007). The import wizard's
|
package/dist/bin.js
CHANGED
|
@@ -5568,6 +5568,28 @@ var init_inbox = __esm({
|
|
|
5568
5568
|
});
|
|
5569
5569
|
|
|
5570
5570
|
// ../core/dist/notifications/catch-up.js
|
|
5571
|
+
function isTerminalUnseen(n) {
|
|
5572
|
+
if (!n.bulk_progress)
|
|
5573
|
+
return false;
|
|
5574
|
+
if (n.in_progress)
|
|
5575
|
+
return false;
|
|
5576
|
+
if (n.first_seen_at)
|
|
5577
|
+
return false;
|
|
5578
|
+
return true;
|
|
5579
|
+
}
|
|
5580
|
+
async function fetchTerminalNotifications(client, opts = {}) {
|
|
5581
|
+
try {
|
|
5582
|
+
const page = await client.listNotifications({
|
|
5583
|
+
archived: false,
|
|
5584
|
+
page: 0,
|
|
5585
|
+
count: opts.count ?? DEFAULT_COUNT
|
|
5586
|
+
});
|
|
5587
|
+
return page.items.filter(isTerminalUnseen).map(toInboxEntry);
|
|
5588
|
+
} catch (err) {
|
|
5589
|
+
opts.logger?.warn?.(`notifications.fetch_terminal failed: ${err?.message ?? err?.code ?? err}`);
|
|
5590
|
+
return [];
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5571
5593
|
async function catchUpNotifications(client, inbox, opts = {}) {
|
|
5572
5594
|
const count = opts.count ?? DEFAULT_COUNT;
|
|
5573
5595
|
let added = 0;
|
|
@@ -5578,11 +5600,7 @@ async function catchUpNotifications(client, inbox, opts = {}) {
|
|
|
5578
5600
|
count
|
|
5579
5601
|
});
|
|
5580
5602
|
for (const n of page.items) {
|
|
5581
|
-
if (!n
|
|
5582
|
-
continue;
|
|
5583
|
-
if (n.in_progress)
|
|
5584
|
-
continue;
|
|
5585
|
-
if (n.first_seen_at)
|
|
5603
|
+
if (!isTerminalUnseen(n))
|
|
5586
5604
|
continue;
|
|
5587
5605
|
const sizeBefore = inbox.size();
|
|
5588
5606
|
inbox.record(n);
|
|
@@ -5599,6 +5617,7 @@ var DEFAULT_COUNT;
|
|
|
5599
5617
|
var init_catch_up = __esm({
|
|
5600
5618
|
"../core/dist/notifications/catch-up.js"() {
|
|
5601
5619
|
"use strict";
|
|
5620
|
+
init_revise_hint();
|
|
5602
5621
|
DEFAULT_COUNT = 50;
|
|
5603
5622
|
}
|
|
5604
5623
|
});
|
|
@@ -20718,6 +20737,7 @@ var init_account_status = __esm({
|
|
|
20718
20737
|
"../core/dist/composite/account-status.js"() {
|
|
20719
20738
|
"use strict";
|
|
20720
20739
|
init_agent_memory();
|
|
20740
|
+
init_catch_up();
|
|
20721
20741
|
init_credits_helpers();
|
|
20722
20742
|
init_tool_descriptions_generated();
|
|
20723
20743
|
accountStatus = {
|
|
@@ -20839,6 +20859,8 @@ var init_account_status = __esm({
|
|
|
20839
20859
|
ctx?.logger?.warn?.(`account_status: quota_status failed: ${err?.message ?? err?.code ?? err}`);
|
|
20840
20860
|
}
|
|
20841
20861
|
}
|
|
20862
|
+
const inbox = ctx?.notificationsInbox;
|
|
20863
|
+
const notifications = inbox ? inbox.list() : await fetchTerminalNotifications(client, { logger: ctx?.logger });
|
|
20842
20864
|
const lensId = me.last_requested_lens ?? null;
|
|
20843
20865
|
const lensAsked = typeof ctx?.triggered_by === "string" && /\b(lens|lenses|audience|targeting|segment|filter)\b/i.test(ctx.triggered_by);
|
|
20844
20866
|
let last_requested_lens_name = null;
|
|
@@ -20879,13 +20901,12 @@ var init_account_status = __esm({
|
|
|
20879
20901
|
// on /me are intentionally NOT surfaced — they're defunct (see
|
|
20880
20902
|
// SHAPE-DRIFT.md probe round 4).
|
|
20881
20903
|
quota,
|
|
20882
|
-
//
|
|
20883
|
-
//
|
|
20884
|
-
//
|
|
20885
|
-
//
|
|
20886
|
-
//
|
|
20887
|
-
|
|
20888
|
-
notifications: ctx?.notificationsInbox?.list() ?? [],
|
|
20904
|
+
// Terminal bulk-progress notifications. Same shape the MCP server
|
|
20905
|
+
// attaches to `_meta.notifications` on every tool response — carried
|
|
20906
|
+
// here as a top-level field so the agent's daily-rhythm check-in (this
|
|
20907
|
+
// composite) sees them without reading _meta. See the read above for
|
|
20908
|
+
// why hosted takes a different path to the same list.
|
|
20909
|
+
notifications,
|
|
20889
20910
|
// Non-null ONLY when the quota_status call failed. The agent must treat
|
|
20890
20911
|
// this as "could not read quota" — NOT as zero usage, and NOT as a broken
|
|
20891
20912
|
// login (the token just authenticated /users/me above). product#3761.
|
|
@@ -32940,7 +32961,7 @@ var OAUTH_BASE_URLS = {
|
|
|
32940
32961
|
fr: "https://staging.api.leadbay.app"
|
|
32941
32962
|
}
|
|
32942
32963
|
};
|
|
32943
|
-
var VERSION = "0.32.
|
|
32964
|
+
var VERSION = "0.32.4";
|
|
32944
32965
|
var HELP = `
|
|
32945
32966
|
leadbay-mcp ${VERSION} \u2014 Leadbay Model Context Protocol server
|
|
32946
32967
|
|
package/dist/http-server.js
CHANGED
|
@@ -8101,9 +8101,82 @@ var COMPOSITE_FILE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
8101
8101
|
"leadbay_tour_plan"
|
|
8102
8102
|
]);
|
|
8103
8103
|
|
|
8104
|
+
// ../core/dist/notifications/revise-hint.js
|
|
8105
|
+
var HINT_BULK_ENRICH = "Contact enrichment just finished. Revise any prior output that named these leads' contacts (outreach drafts, contact lists, recommended-lead lists with contact_count, NEXT STEPS asking the user to wait for emails / phones). Re-fetch contacts via leadbay_get_contacts for the affected leads.";
|
|
8106
|
+
var HINT_BULK_QUALIFY = "Lead qualification just finished. Revise any prior lead list / ranking / outreach shortlist that depended on ai_agent_lead_score for these leads \u2014 today's leads, top-of-inbox, followups maps, prepare-outreach shortlists. Re-pull qualification answers via leadbay_research_lead_by_id or re-rank via leadbay_pull_leads.";
|
|
8107
|
+
var HINT_IMPORT = "CSV / CRM import just finished. Revise any prior output that referenced 'leads available' before the import landed \u2014 lead lists pulled from the affected lens, 'what's new today', followup planning. Re-pull the affected lens via leadbay_pull_leads / leadbay_pull_followups.";
|
|
8108
|
+
var HINT_OTHER = "Background work just completed. If you referenced its subject in prior output, re-fetch the affected data and revise.";
|
|
8109
|
+
function reviseHintFor(kind) {
|
|
8110
|
+
switch (kind) {
|
|
8111
|
+
case "bulk_enrich":
|
|
8112
|
+
return HINT_BULK_ENRICH;
|
|
8113
|
+
case "bulk_qualify":
|
|
8114
|
+
return HINT_BULK_QUALIFY;
|
|
8115
|
+
case "import":
|
|
8116
|
+
return HINT_IMPORT;
|
|
8117
|
+
default:
|
|
8118
|
+
return HINT_OTHER;
|
|
8119
|
+
}
|
|
8120
|
+
}
|
|
8121
|
+
function inferKind(n) {
|
|
8122
|
+
if (n.links.some((l) => l.type === "bulk_enrichment"))
|
|
8123
|
+
return "bulk_enrich";
|
|
8124
|
+
if (n.file_import_id)
|
|
8125
|
+
return "import";
|
|
8126
|
+
if (n.bulk_progress)
|
|
8127
|
+
return "bulk_qualify";
|
|
8128
|
+
return "other";
|
|
8129
|
+
}
|
|
8130
|
+
function anchorIdFor(n, kind) {
|
|
8131
|
+
if (kind === "bulk_enrich") {
|
|
8132
|
+
const link = n.links.find((l) => l.type === "bulk_enrichment");
|
|
8133
|
+
return link ? String(link.id) : null;
|
|
8134
|
+
}
|
|
8135
|
+
if (kind === "import")
|
|
8136
|
+
return n.file_import_id;
|
|
8137
|
+
return null;
|
|
8138
|
+
}
|
|
8139
|
+
function toInboxEntry(n) {
|
|
8140
|
+
const kind = inferKind(n);
|
|
8141
|
+
return {
|
|
8142
|
+
notification_id: n.id,
|
|
8143
|
+
kind,
|
|
8144
|
+
anchor_id: anchorIdFor(n, kind),
|
|
8145
|
+
title: n.title,
|
|
8146
|
+
bulk_progress: n.bulk_progress,
|
|
8147
|
+
completed_at: n.updated_at,
|
|
8148
|
+
revise_hint: reviseHintFor(kind)
|
|
8149
|
+
};
|
|
8150
|
+
}
|
|
8151
|
+
|
|
8104
8152
|
// ../core/dist/notifications/inbox.js
|
|
8105
8153
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8106
8154
|
|
|
8155
|
+
// ../core/dist/notifications/catch-up.js
|
|
8156
|
+
var DEFAULT_COUNT = 50;
|
|
8157
|
+
function isTerminalUnseen(n) {
|
|
8158
|
+
if (!n.bulk_progress)
|
|
8159
|
+
return false;
|
|
8160
|
+
if (n.in_progress)
|
|
8161
|
+
return false;
|
|
8162
|
+
if (n.first_seen_at)
|
|
8163
|
+
return false;
|
|
8164
|
+
return true;
|
|
8165
|
+
}
|
|
8166
|
+
async function fetchTerminalNotifications(client, opts = {}) {
|
|
8167
|
+
try {
|
|
8168
|
+
const page = await client.listNotifications({
|
|
8169
|
+
archived: false,
|
|
8170
|
+
page: 0,
|
|
8171
|
+
count: opts.count ?? DEFAULT_COUNT
|
|
8172
|
+
});
|
|
8173
|
+
return page.items.filter(isTerminalUnseen).map(toInboxEntry);
|
|
8174
|
+
} catch (err) {
|
|
8175
|
+
opts.logger?.warn?.(`notifications.fetch_terminal failed: ${err?.message ?? err?.code ?? err}`);
|
|
8176
|
+
return [];
|
|
8177
|
+
}
|
|
8178
|
+
}
|
|
8179
|
+
|
|
8107
8180
|
// ../core/dist/tool-descriptions.generated.js
|
|
8108
8181
|
var leadbay_account_history = `## WHEN TO USE
|
|
8109
8182
|
|
|
@@ -22490,6 +22563,8 @@ var accountStatus = {
|
|
|
22490
22563
|
ctx?.logger?.warn?.(`account_status: quota_status failed: ${err?.message ?? err?.code ?? err}`);
|
|
22491
22564
|
}
|
|
22492
22565
|
}
|
|
22566
|
+
const inbox = ctx?.notificationsInbox;
|
|
22567
|
+
const notifications = inbox ? inbox.list() : await fetchTerminalNotifications(client, { logger: ctx?.logger });
|
|
22493
22568
|
const lensId = me.last_requested_lens ?? null;
|
|
22494
22569
|
const lensAsked = typeof ctx?.triggered_by === "string" && /\b(lens|lenses|audience|targeting|segment|filter)\b/i.test(ctx.triggered_by);
|
|
22495
22570
|
let last_requested_lens_name = null;
|
|
@@ -22530,13 +22605,12 @@ var accountStatus = {
|
|
|
22530
22605
|
// on /me are intentionally NOT surfaced — they're defunct (see
|
|
22531
22606
|
// SHAPE-DRIFT.md probe round 4).
|
|
22532
22607
|
quota,
|
|
22533
|
-
//
|
|
22534
|
-
//
|
|
22535
|
-
//
|
|
22536
|
-
//
|
|
22537
|
-
//
|
|
22538
|
-
|
|
22539
|
-
notifications: ctx?.notificationsInbox?.list() ?? [],
|
|
22608
|
+
// Terminal bulk-progress notifications. Same shape the MCP server
|
|
22609
|
+
// attaches to `_meta.notifications` on every tool response — carried
|
|
22610
|
+
// here as a top-level field so the agent's daily-rhythm check-in (this
|
|
22611
|
+
// composite) sees them without reading _meta. See the read above for
|
|
22612
|
+
// why hosted takes a different path to the same list.
|
|
22613
|
+
notifications,
|
|
22540
22614
|
// Non-null ONLY when the quota_status call failed. The agent must treat
|
|
22541
22615
|
// this as "could not read quota" — NOT as zero usage, and NOT as a broken
|
|
22542
22616
|
// login (the token just authenticated /users/me above). product#3761.
|
|
@@ -22550,7 +22624,7 @@ var accountStatus = {
|
|
|
22550
22624
|
|
|
22551
22625
|
// ../core/dist/composite/bulk-qualify-leads.js
|
|
22552
22626
|
var PAGE_SIZE = 50;
|
|
22553
|
-
var
|
|
22627
|
+
var DEFAULT_COUNT2 = 10;
|
|
22554
22628
|
var MAX_COUNT = 25;
|
|
22555
22629
|
var DEFAULT_PER_LEAD_BUDGET_MS = 9e4;
|
|
22556
22630
|
var DEFAULT_TOTAL_BUDGET_MS2 = 5 * 6e4;
|
|
@@ -22598,7 +22672,7 @@ var bulkQualifyLeads = {
|
|
|
22598
22672
|
properties: {
|
|
22599
22673
|
count: {
|
|
22600
22674
|
type: "number",
|
|
22601
|
-
description: `How many fresh leads to qualify (default ${
|
|
22675
|
+
description: `How many fresh leads to qualify (default ${DEFAULT_COUNT2}, max ${MAX_COUNT})`
|
|
22602
22676
|
},
|
|
22603
22677
|
leadIds: {
|
|
22604
22678
|
type: "array",
|
|
@@ -22689,7 +22763,7 @@ var bulkQualifyLeads = {
|
|
|
22689
22763
|
]
|
|
22690
22764
|
},
|
|
22691
22765
|
execute: async (client, params, ctx) => {
|
|
22692
|
-
const wantCount = Math.min(params.count ??
|
|
22766
|
+
const wantCount = Math.min(params.count ?? DEFAULT_COUNT2, MAX_COUNT);
|
|
22693
22767
|
const perLeadBudget = params.per_lead_budget_ms ?? DEFAULT_PER_LEAD_BUDGET_MS;
|
|
22694
22768
|
const totalBudget = params.total_budget_ms ?? DEFAULT_TOTAL_BUDGET_MS2;
|
|
22695
22769
|
const totalDeadline = Date.now() + totalBudget;
|
|
@@ -29473,7 +29547,7 @@ function parseWriteEnv(env = process.env) {
|
|
|
29473
29547
|
}
|
|
29474
29548
|
|
|
29475
29549
|
// src/http-server.ts
|
|
29476
|
-
var VERSION = true ? "0.32.
|
|
29550
|
+
var VERSION = true ? "0.32.4" : "0.0.0-dev";
|
|
29477
29551
|
var PORT = Number(process.env.PORT ?? 8080);
|
|
29478
29552
|
var HOST = process.env.HOST ?? "0.0.0.0";
|
|
29479
29553
|
var logger = {
|
package/dist/installer-gui.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadbay/mcp",
|
|
3
|
-
"version": "0.32.
|
|
3
|
+
"version": "0.32.4",
|
|
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",
|