@leadbay/mcp 0.32.4 → 0.32.5
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 +29 -1
- package/dist/bin.js +16 -5
- package/dist/http-server.js +16 -5
- 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,34 @@
|
|
|
1
1
|
# Changelog — @leadbay/mcp
|
|
2
2
|
|
|
3
|
+
## 0.32.5 — 2026-09-01
|
|
4
|
+
|
|
5
|
+
`leadbay_update_contact` returned `NOT_FOUND` / 404 on 100% of the calls ever
|
|
6
|
+
made to it (product#3997). Not a missing route and not a backend bug.
|
|
7
|
+
|
|
8
|
+
Leadbay holds contacts in two id namespaces — `org_contacts` (the org's own
|
|
9
|
+
directory) and `paid_contacts` (enrichment results) — with separate models,
|
|
10
|
+
separate DAOs and separate ids. `POST /contacts/{id}/update` resolves
|
|
11
|
+
`orgContacts.findById` only, so a paid id can only ever 404.
|
|
12
|
+
|
|
13
|
+
`research_lead_by_id` merges `/leads/{id}/enrich/contacts` and
|
|
14
|
+
`/leads/{id}/contacts` into `contacts.reachable` / `contacts.candidates`, split
|
|
15
|
+
by **whether the person is messagable right now, not by which endpoint they came
|
|
16
|
+
from**. That split is right for outreach and wrong for identity: an enriched
|
|
17
|
+
paid contact sits in the same list as an org contact, and the agent had nothing
|
|
18
|
+
to distinguish them by. Roughly half the ids we handed out were unusable by a
|
|
19
|
+
tool the server instructions tell the agent to call after every outreach.
|
|
20
|
+
|
|
21
|
+
- The `source` field (`"org"` / `"paid"`) was already on the wire but undeclared
|
|
22
|
+
and unexplained. It is now documented in `research_lead_by_id`'s output schema
|
|
23
|
+
as the thing that decides whether an id can be passed to
|
|
24
|
+
`leadbay_update_contact`.
|
|
25
|
+
- `leadbay_update_contact`'s description states which namespace it accepts,
|
|
26
|
+
what a 404 means, and routes a correction to a paid contact through
|
|
27
|
+
`leadbay_add_contact` instead — the enrichment row is a provider's answer and
|
|
28
|
+
is not ours to edit.
|
|
29
|
+
- New: `research-contact-source-provenance.test.ts`, covering the case the
|
|
30
|
+
reachability split hides — an enriched paid contact and an org contact in the
|
|
31
|
+
SAME `reachable` list, distinguished only by `source`.
|
|
3
32
|
## 0.32.4 — 2026-09-01
|
|
4
33
|
|
|
5
34
|
`leadbay_account_status.notifications` was permanently `[]` on the hosted server
|
|
@@ -27,7 +56,6 @@ answer, and the ledger is not called.
|
|
|
27
56
|
responses.** Reviving it would mean a `GET /notifications` per tool call to
|
|
28
57
|
decorate every response. The cost lands on the check-in entry point only,
|
|
29
58
|
which is where the daily-rhythm channel is actually read.
|
|
30
|
-
|
|
31
59
|
## 0.32.0 — 2026-09-01
|
|
32
60
|
|
|
33
61
|
A poll-budget timeout stops being an error (product#4007). The import wizard's
|
package/dist/bin.js
CHANGED
|
@@ -10289,9 +10289,9 @@ Trigger phrases: "update this contact", "fix this contact's title", "change thei
|
|
|
10289
10289
|
|
|
10290
10290
|
**Memory:** recall + capture via \`leadbay_agent_memory_*\` tools.
|
|
10291
10291
|
|
|
10292
|
-
Do NOT use for: "add a new contact to this company" \u2192 \`leadbay_add_contact\`; "remove / delete this contact" \u2192 \`leadbay_remove_contact\`; "get email/phone for a contact (enrichment)" \u2192 \`leadbay_enrich_titles\`.
|
|
10292
|
+
Do NOT use for: "add a new contact to this company" \u2192 \`leadbay_add_contact\`; "remove / delete this contact" \u2192 \`leadbay_remove_contact\`; "get email/phone for a contact (enrichment)" \u2192 \`leadbay_enrich_titles\`; "fix an enriched contact's details" \u2192 \`leadbay_add_contact\`.
|
|
10293
10293
|
|
|
10294
|
-
Prefer when: user wants to change details on
|
|
10294
|
+
Prefer when: user wants to change details on a contact that is in their own directory (\`source: "org"\`) \u2014 pass that contact's own \`contact_id\` plus first_name + last_name (required) and the fields to change
|
|
10295
10295
|
|
|
10296
10296
|
Examples that SHOULD invoke this tool:
|
|
10297
10297
|
- "Update Jane's title to SVP Engineering."
|
|
@@ -10311,7 +10311,18 @@ One-line confirmation naming the contact and what changed. No table.
|
|
|
10311
10311
|
|
|
10312
10312
|
Edit an existing contact in place \u2014 change their \`job_title\`, \`linkedin_page\`, \`email\`, \`phone_number\`, or name.
|
|
10313
10313
|
|
|
10314
|
-
Pass the contact's **own** \`contact_id\`
|
|
10314
|
+
Pass the contact's **own** \`contact_id\` \u2014 **not** the parent lead id.
|
|
10315
|
+
|
|
10316
|
+
**Only your organization's own directory contacts can be edited.** Leadbay holds contacts in two separate id namespaces and this endpoint resolves one of them:
|
|
10317
|
+
|
|
10318
|
+
| \`source\` on the contact | What it is | Editable here |
|
|
10319
|
+
|---|---|---|
|
|
10320
|
+
| \`"org"\` | A row in your organization's contact directory \u2014 added by you or your team, or promoted from an import | **yes** |
|
|
10321
|
+
| \`"paid"\` | An enrichment result bought from a data provider | **no** \u2014 returns \`NOT_FOUND\` / 404 |
|
|
10322
|
+
|
|
10323
|
+
\`leadbay_research_lead_by_id\` returns both, merged into \`contacts.reachable\` / \`contacts.candidates\` and split by whether the person is messagable right now \u2014 **not** by which namespace they came from. So read \`source\` on the contact before calling this. If it is \`"paid"\` and the user wants different details on record, add the corrected person with \`leadbay_add_contact\` instead; the enrichment row is a provider's answer and is not ours to edit.
|
|
10324
|
+
|
|
10325
|
+
A 404 from this tool almost always means a \`"paid"\` id was passed. Re-read the contact, check \`source\`, and do not retry the same id.
|
|
10315
10326
|
|
|
10316
10327
|
**\`first_name\` + \`last_name\` are required even on an edit.** The backend validates the full contact identity and rejects a partial body (\`invalid contact\`). So pass the contact's *current* first/last name even when you're only changing the title \u2014 read the current values via \`leadbay_research_lead_by_id\` first if you don't have them.
|
|
10317
10328
|
|
|
@@ -19141,7 +19152,7 @@ var init_research_lead_by_id = __esm({
|
|
|
19141
19152
|
},
|
|
19142
19153
|
contacts: {
|
|
19143
19154
|
type: "object",
|
|
19144
|
-
description:
|
|
19155
|
+
description: 'Two-tier contact set, partitioned by reachability \u2014 agent-friendly framing of the backend\'s paid-vs-org split. `reachable`: contacts with an email or phone right now (org-directory entries that ship with channels, PLUS paid contacts whose enrichment has completed). The agent can message these without buying enrichment. `candidates`: paid-contact entries WITHOUT resolved channels yet \u2014 typically LinkedIn URL only, `enrichment_done: false`. The agent must call leadbay_enrich_titles (or leadbay_prepare_outreach with enrich:true) before these become messagable. Every contact in both lists carries `source`: `"org"` means it is a row in your organization\'s own contact directory, `"paid"` means it came from enrichment. The two are separate id namespaces on the backend, so only a `source:"org"` id can be passed to leadbay_update_contact / leadbay_remove_contact \u2014 a `"paid"` id returns NOT_FOUND there.',
|
|
19145
19156
|
properties: {
|
|
19146
19157
|
reachable: { type: "array", items: { type: "object" } },
|
|
19147
19158
|
candidates: { type: "array", items: { type: "object" } }
|
|
@@ -32961,7 +32972,7 @@ var OAUTH_BASE_URLS = {
|
|
|
32961
32972
|
fr: "https://staging.api.leadbay.app"
|
|
32962
32973
|
}
|
|
32963
32974
|
};
|
|
32964
|
-
var VERSION = "0.32.
|
|
32975
|
+
var VERSION = "0.32.5";
|
|
32965
32976
|
var HELP = `
|
|
32966
32977
|
leadbay-mcp ${VERSION} \u2014 Leadbay Model Context Protocol server
|
|
32967
32978
|
|
package/dist/http-server.js
CHANGED
|
@@ -12682,9 +12682,9 @@ Trigger phrases: "update this contact", "fix this contact's title", "change thei
|
|
|
12682
12682
|
|
|
12683
12683
|
**Memory:** recall + capture via \`leadbay_agent_memory_*\` tools.
|
|
12684
12684
|
|
|
12685
|
-
Do NOT use for: "add a new contact to this company" \u2192 \`leadbay_add_contact\`; "remove / delete this contact" \u2192 \`leadbay_remove_contact\`; "get email/phone for a contact (enrichment)" \u2192 \`leadbay_enrich_titles\`.
|
|
12685
|
+
Do NOT use for: "add a new contact to this company" \u2192 \`leadbay_add_contact\`; "remove / delete this contact" \u2192 \`leadbay_remove_contact\`; "get email/phone for a contact (enrichment)" \u2192 \`leadbay_enrich_titles\`; "fix an enriched contact's details" \u2192 \`leadbay_add_contact\`.
|
|
12686
12686
|
|
|
12687
|
-
Prefer when: user wants to change details on
|
|
12687
|
+
Prefer when: user wants to change details on a contact that is in their own directory (\`source: "org"\`) \u2014 pass that contact's own \`contact_id\` plus first_name + last_name (required) and the fields to change
|
|
12688
12688
|
|
|
12689
12689
|
Examples that SHOULD invoke this tool:
|
|
12690
12690
|
- "Update Jane's title to SVP Engineering."
|
|
@@ -12704,7 +12704,18 @@ One-line confirmation naming the contact and what changed. No table.
|
|
|
12704
12704
|
|
|
12705
12705
|
Edit an existing contact in place \u2014 change their \`job_title\`, \`linkedin_page\`, \`email\`, \`phone_number\`, or name.
|
|
12706
12706
|
|
|
12707
|
-
Pass the contact's **own** \`contact_id\`
|
|
12707
|
+
Pass the contact's **own** \`contact_id\` \u2014 **not** the parent lead id.
|
|
12708
|
+
|
|
12709
|
+
**Only your organization's own directory contacts can be edited.** Leadbay holds contacts in two separate id namespaces and this endpoint resolves one of them:
|
|
12710
|
+
|
|
12711
|
+
| \`source\` on the contact | What it is | Editable here |
|
|
12712
|
+
|---|---|---|
|
|
12713
|
+
| \`"org"\` | A row in your organization's contact directory \u2014 added by you or your team, or promoted from an import | **yes** |
|
|
12714
|
+
| \`"paid"\` | An enrichment result bought from a data provider | **no** \u2014 returns \`NOT_FOUND\` / 404 |
|
|
12715
|
+
|
|
12716
|
+
\`leadbay_research_lead_by_id\` returns both, merged into \`contacts.reachable\` / \`contacts.candidates\` and split by whether the person is messagable right now \u2014 **not** by which namespace they came from. So read \`source\` on the contact before calling this. If it is \`"paid"\` and the user wants different details on record, add the corrected person with \`leadbay_add_contact\` instead; the enrichment row is a provider's answer and is not ours to edit.
|
|
12717
|
+
|
|
12718
|
+
A 404 from this tool almost always means a \`"paid"\` id was passed. Re-read the contact, check \`source\`, and do not retry the same id.
|
|
12708
12719
|
|
|
12709
12720
|
**\`first_name\` + \`last_name\` are required even on an edit.** The backend validates the full contact identity and rejects a partial body (\`invalid contact\`). So pass the contact's *current* first/last name even when you're only changing the title \u2014 read the current values via \`leadbay_research_lead_by_id\` first if you don't have them.
|
|
12710
12721
|
|
|
@@ -20921,7 +20932,7 @@ var researchLeadById = {
|
|
|
20921
20932
|
},
|
|
20922
20933
|
contacts: {
|
|
20923
20934
|
type: "object",
|
|
20924
|
-
description:
|
|
20935
|
+
description: 'Two-tier contact set, partitioned by reachability \u2014 agent-friendly framing of the backend\'s paid-vs-org split. `reachable`: contacts with an email or phone right now (org-directory entries that ship with channels, PLUS paid contacts whose enrichment has completed). The agent can message these without buying enrichment. `candidates`: paid-contact entries WITHOUT resolved channels yet \u2014 typically LinkedIn URL only, `enrichment_done: false`. The agent must call leadbay_enrich_titles (or leadbay_prepare_outreach with enrich:true) before these become messagable. Every contact in both lists carries `source`: `"org"` means it is a row in your organization\'s own contact directory, `"paid"` means it came from enrichment. The two are separate id namespaces on the backend, so only a `source:"org"` id can be passed to leadbay_update_contact / leadbay_remove_contact \u2014 a `"paid"` id returns NOT_FOUND there.',
|
|
20925
20936
|
properties: {
|
|
20926
20937
|
reachable: { type: "array", items: { type: "object" } },
|
|
20927
20938
|
candidates: { type: "array", items: { type: "object" } }
|
|
@@ -29547,7 +29558,7 @@ function parseWriteEnv(env = process.env) {
|
|
|
29547
29558
|
}
|
|
29548
29559
|
|
|
29549
29560
|
// src/http-server.ts
|
|
29550
|
-
var VERSION = true ? "0.32.
|
|
29561
|
+
var VERSION = true ? "0.32.5" : "0.0.0-dev";
|
|
29551
29562
|
var PORT = Number(process.env.PORT ?? 8080);
|
|
29552
29563
|
var HOST = process.env.HOST ?? "0.0.0.0";
|
|
29553
29564
|
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.5",
|
|
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",
|