@leadbay/mcp 0.39.1 → 0.39.2
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/dist/bin.js +58 -16
- package/dist/http-server.js +56 -15
- package/dist/installer-electron.js +1 -1
- package/dist/installer-gui.js +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -6731,7 +6731,7 @@ prose paragraph. Full recipe below.
|
|
|
6731
6731
|
|
|
6732
6732
|
Build a single-call mixed-mode itinerary for a field sales tour. Combines \`leadbay_pull_followups\` (Monitor leads in the city \u2014 known accounts) with \`leadbay_pull_leads\` (Discover wishlist \u2014 new prospects, then client-side filtered by city) so the agent can answer the canonical #3630 US1 ask: *"I'm visiting Limoges in 4 days \u2014 propose 3 customers + 3 qualified prospects + 3 new high-potential discoveries."*
|
|
6733
6733
|
|
|
6734
|
-
**Geo resolution** is identical to \`leadbay_followups_map\`: pass \`city\` (any level from state down to neighborhood \u2014 state, *r\xE9gion*, county, city \u2014 the \`/geo/search\` resolver picks the best match), or a pre-resolved \`city_id\`. Ambiguous matches surface as \`status: "ambiguous_locations"\` + \`location_ambiguities[]\`; pick
|
|
6734
|
+
**Geo resolution** is identical to \`leadbay_followups_map\`: pass \`city\` (any level from state down to neighborhood \u2014 state, *r\xE9gion*, county, city \u2014 the \`/geo/search\` resolver picks the best match), or a pre-resolved \`city_id\`. Ambiguous matches surface as \`status: "ambiguous_locations"\` + \`location_ambiguities[]\`; re-call with \`city_id\` set to the id you pick AND \`city\` set to that candidate's \`name\`. Both are needed: the id scopes the follow-ups, the name scopes the Discover leads, and with \`city_id\` alone \`discover_leads\` comes back empty.
|
|
6735
6735
|
|
|
6736
6736
|
**One workspace = one country \u2014 a country name is NEVER a location filter.** The admin-area index holds no country nodes, so \`"France"\` matches the *commune of Francs* and \`"United States"\` matches *Statesboro*: the call is silently fenced to one village and every conclusion from it is wrong. City AND country named? Keep the city, drop the country.
|
|
6737
6737
|
|
|
@@ -6761,7 +6761,7 @@ not an itinerary. So for ANY country-level \`city\` \u2014 this workspace's own
|
|
|
6761
6761
|
visiting and re-call with that. \`status: "country_level_location"\` carries the
|
|
6762
6762
|
same instruction in its \`hint\`.
|
|
6763
6763
|
|
|
6764
|
-
**Counts**: \`followups_count\` (default 6 \u2014 generous so the agent can split into "customers + qualified" client-side) and \`discover_count\` (default 6 after client-side geo filter). The composite over-pulls Discover (30 raw) because the wishlist endpoint has no server-side geo filter \u2014 it then
|
|
6764
|
+
**Counts**: \`followups_count\` (default 6 \u2014 generous so the agent can split into "customers + qualified" client-side) and \`discover_count\` (default 6 after client-side geo filter). The composite over-pulls Discover (30 raw) because the wishlist endpoint has no server-side geo filter \u2014 it then keeps the leads whose own \`location.city\` names the requested city, and falls back to \`location.state\` only when no city matched (which is what a regional ask like "Texas" or "\xCEle-de-France" looks like). \`location.country\` is never consulted. \`discover_filter_note\` reports the ratio and which field carried it, so the agent can be honest about coverage. **When it says no Discover lead is in the city, say that** \u2014 return the Monitor half and offer \`leadbay_find_new_leads\` for that city. Never fill the gap with leads from elsewhere.
|
|
6765
6765
|
|
|
6766
6766
|
**What \`tour_plan\` does NOT do**: it doesn't persist the tour as a campaign artifact. To do that \u2014 create a "Limoges Tour \u2013 May 24" campaign and attach the selected accounts \u2014 chain into \`leadbay_create_campaign({lead_ids: [...selected_ids], name: 'Limoges Tour \u2013 <date>'})\` after the user picks. See the \`leadbay_plan_tour_in_city\` prompt for the full end-to-end orchestrator.
|
|
6767
6767
|
|
|
@@ -14962,13 +14962,33 @@ var init_followups_map = __esm({
|
|
|
14962
14962
|
});
|
|
14963
14963
|
|
|
14964
14964
|
// ../core/dist/composite/tour-plan.js
|
|
14965
|
-
function
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14965
|
+
function normalizeGeo(value) {
|
|
14966
|
+
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
14967
|
+
}
|
|
14968
|
+
function townName(value) {
|
|
14969
|
+
return normalizeGeo(value).replace(ADMIN_PREFIX, "");
|
|
14970
|
+
}
|
|
14971
|
+
function cityHintCore(cityHint) {
|
|
14972
|
+
const head = cityHint.split(",")[0] ?? "";
|
|
14973
|
+
const expanded = expandAlias(head);
|
|
14974
|
+
return { name: townName(expanded), isCity: expanded !== head };
|
|
14975
|
+
}
|
|
14976
|
+
function stateFieldOf(lead) {
|
|
14977
|
+
const state = lead?.location?.state;
|
|
14978
|
+
return typeof state === "string" ? normalizeGeo(state) : "";
|
|
14979
|
+
}
|
|
14980
|
+
function filterDiscoverByCity(leads, cityHint) {
|
|
14981
|
+
const hint = cityHint ? cityHintCore(cityHint) : { name: "", isCity: false };
|
|
14982
|
+
if (!hint.name)
|
|
14983
|
+
return { leads, matchedOn: null };
|
|
14984
|
+
const cityOf = (l) => typeof l?.location?.city === "string" ? townName(l.location.city) : "";
|
|
14985
|
+
const byCity = leads.filter((l) => cityOf(l) === hint.name);
|
|
14986
|
+
if (byCity.length > 0)
|
|
14987
|
+
return { leads: byCity, matchedOn: "city" };
|
|
14988
|
+
if (hint.isCity)
|
|
14989
|
+
return { leads: [], matchedOn: "city" };
|
|
14990
|
+
const byState = leads.filter((l) => stateFieldOf(l) === hint.name);
|
|
14991
|
+
return { leads: byState, matchedOn: "state" };
|
|
14972
14992
|
}
|
|
14973
14993
|
function toMapLocation(lead, mode) {
|
|
14974
14994
|
const pos = lead?.location?.pos;
|
|
@@ -15018,7 +15038,7 @@ function buildMap(monitorLeads, discoverLeads2) {
|
|
|
15018
15038
|
}
|
|
15019
15039
|
};
|
|
15020
15040
|
}
|
|
15021
|
-
var DEFAULT_FOLLOWUPS_COUNT, DEFAULT_DISCOVER_COUNT, DISCOVER_OVER_PULL, tourPlan;
|
|
15041
|
+
var DEFAULT_FOLLOWUPS_COUNT, DEFAULT_DISCOVER_COUNT, DISCOVER_OVER_PULL, ADMIN_PREFIX, tourPlan;
|
|
15022
15042
|
var init_tour_plan = __esm({
|
|
15023
15043
|
"../core/dist/composite/tour-plan.js"() {
|
|
15024
15044
|
"use strict";
|
|
@@ -15026,10 +15046,12 @@ var init_tour_plan = __esm({
|
|
|
15026
15046
|
init_pull_leads();
|
|
15027
15047
|
init_interactions();
|
|
15028
15048
|
init_country_guard();
|
|
15049
|
+
init_geo_helpers();
|
|
15029
15050
|
init_tool_descriptions_generated();
|
|
15030
15051
|
DEFAULT_FOLLOWUPS_COUNT = 6;
|
|
15031
15052
|
DEFAULT_DISCOVER_COUNT = 6;
|
|
15032
15053
|
DISCOVER_OVER_PULL = 30;
|
|
15054
|
+
ADMIN_PREFIX = /^(?:city|town|village|borough|township|municipality) of /;
|
|
15033
15055
|
tourPlan = {
|
|
15034
15056
|
name: "leadbay_tour_plan",
|
|
15035
15057
|
annotations: {
|
|
@@ -15049,7 +15071,7 @@ var init_tour_plan = __esm({
|
|
|
15049
15071
|
},
|
|
15050
15072
|
city_id: {
|
|
15051
15073
|
type: "string",
|
|
15052
|
-
description: "Pre-resolved admin_area id (numeric string). Bypasses the resolver."
|
|
15074
|
+
description: "Pre-resolved admin_area id (numeric string). Bypasses the resolver. Pass `city` alongside it with the NAME of the area you picked: the id scopes the Monitor half, and the name is the only thing that can scope the Discover half, which has no server-side geo filter. With `city_id` alone, `discover_leads` comes back empty."
|
|
15053
15075
|
},
|
|
15054
15076
|
followups_count: {
|
|
15055
15077
|
type: "number",
|
|
@@ -15156,7 +15178,13 @@ var init_tour_plan = __esm({
|
|
|
15156
15178
|
const discoverCount = params.discover_count ?? DEFAULT_DISCOVER_COUNT;
|
|
15157
15179
|
const [followupsResult, leadsResult] = await Promise.allSettled([
|
|
15158
15180
|
pullFollowups.execute(client, {
|
|
15159
|
-
|
|
15181
|
+
// A pre-resolved id bypasses the resolver, which is what its own
|
|
15182
|
+
// schema promises. Forwarding the free text alongside it sends the
|
|
15183
|
+
// name back through /geo/search, and the name is the thing that was
|
|
15184
|
+
// ambiguous — so an agent recovering from `ambiguous_locations` by
|
|
15185
|
+
// picking an id would be handed the same ambiguity again. Here the
|
|
15186
|
+
// free text stays behind and scopes the Discover half instead.
|
|
15187
|
+
city: params.city_id ? void 0 : params.city,
|
|
15160
15188
|
city_id: params.city_id,
|
|
15161
15189
|
count: followupsCount
|
|
15162
15190
|
}, ctx),
|
|
@@ -15170,7 +15198,7 @@ var init_tour_plan = __esm({
|
|
|
15170
15198
|
location_ambiguities: r.location_ambiguities,
|
|
15171
15199
|
monitor_leads: [],
|
|
15172
15200
|
discover_leads: [],
|
|
15173
|
-
discover_filter_note: "City was ambiguous; pick
|
|
15201
|
+
discover_filter_note: "City was ambiguous; re-call with `city_id` set to the id you pick AND `city` set to that candidate's `name`. The id scopes the follow-ups; the name is what scopes the Discover leads.",
|
|
15174
15202
|
map_locations: [],
|
|
15175
15203
|
map_summary: {
|
|
15176
15204
|
total_leads: 0,
|
|
@@ -15194,13 +15222,27 @@ var init_tour_plan = __esm({
|
|
|
15194
15222
|
if (leadsResult.status === "rejected") {
|
|
15195
15223
|
ctx?.logger?.warn?.(`tour_plan: pull_leads failed: ${leadsResult.reason?.message ?? leadsResult.reason}`);
|
|
15196
15224
|
}
|
|
15197
|
-
const
|
|
15225
|
+
const cityName = params.city && !/^\d+$/.test(params.city.trim()) ? params.city : void 0;
|
|
15226
|
+
const knownId = params.city_id ?? (cityName ? void 0 : params.city);
|
|
15227
|
+
const idOnly = Boolean(knownId) && !cityName;
|
|
15228
|
+
const { leads: filtered, matchedOn } = idOnly ? { leads: [], matchedOn: null } : filterDiscoverByCity(rawDiscover, cityName);
|
|
15198
15229
|
const discoverLeads2 = filtered.slice(0, discoverCount);
|
|
15199
15230
|
const pulledLensId = leadsResult.status === "fulfilled" ? leadsResult.value?.lens?.id : null;
|
|
15200
15231
|
if (pulledLensId != null) {
|
|
15201
15232
|
reportLeadInteractions(client, pulledLensId, discoverLeads2.map((l) => l.id), ["LEAD_SEEN"], ctx?.logger);
|
|
15202
15233
|
}
|
|
15203
|
-
|
|
15234
|
+
let filterNote;
|
|
15235
|
+
if (idOnly) {
|
|
15236
|
+
filterNote = `Discover leads need the NAME of the place, and this call passed an area id (${knownId}) and no name. Re-call with \`city\` set to the name of that area, keeping \`city_id\` so the Monitor half stays on the area you picked. The follow-ups below are already scoped to it.`;
|
|
15237
|
+
} else if (!cityName) {
|
|
15238
|
+
filterNote = `No city filter applied; returning top ${discoverLeads2.length} Discover leads.`;
|
|
15239
|
+
} else if (matchedOn === null) {
|
|
15240
|
+
filterNote = `No usable city filter in '${params.city}'; returning top ${discoverLeads2.length} Discover leads.`;
|
|
15241
|
+
} else if (filtered.length === 0) {
|
|
15242
|
+
filterNote = `No Discover lead in the active lens is in '${params.city}' (checked ${rawDiscover.length} candidates by city, then by state/region). Say so; do NOT present leads from elsewhere as if they were in '${params.city}'.`;
|
|
15243
|
+
} else {
|
|
15244
|
+
filterNote = `Matched ${filtered.length}/${rawDiscover.length} Discover leads to '${params.city}' by ${matchedOn === "city" ? "city" : "state/region"}; returning top ${discoverLeads2.length}.`;
|
|
15245
|
+
}
|
|
15204
15246
|
return {
|
|
15205
15247
|
city: params.city ?? null,
|
|
15206
15248
|
city_id: params.city_id ?? null,
|
|
@@ -31336,7 +31378,7 @@ var OAUTH_BASE_URLS = {
|
|
|
31336
31378
|
fr: "https://staging.api.leadbay.app"
|
|
31337
31379
|
}
|
|
31338
31380
|
};
|
|
31339
|
-
var VERSION = "0.39.
|
|
31381
|
+
var VERSION = "0.39.2";
|
|
31340
31382
|
var HELP = `
|
|
31341
31383
|
leadbay-mcp ${VERSION} \u2014 Leadbay Model Context Protocol server
|
|
31342
31384
|
|
package/dist/http-server.js
CHANGED
|
@@ -9679,7 +9679,7 @@ prose paragraph. Full recipe below.
|
|
|
9679
9679
|
|
|
9680
9680
|
Build a single-call mixed-mode itinerary for a field sales tour. Combines \`leadbay_pull_followups\` (Monitor leads in the city \u2014 known accounts) with \`leadbay_pull_leads\` (Discover wishlist \u2014 new prospects, then client-side filtered by city) so the agent can answer the canonical #3630 US1 ask: *"I'm visiting Limoges in 4 days \u2014 propose 3 customers + 3 qualified prospects + 3 new high-potential discoveries."*
|
|
9681
9681
|
|
|
9682
|
-
**Geo resolution** is identical to \`leadbay_followups_map\`: pass \`city\` (any level from state down to neighborhood \u2014 state, *r\xE9gion*, county, city \u2014 the \`/geo/search\` resolver picks the best match), or a pre-resolved \`city_id\`. Ambiguous matches surface as \`status: "ambiguous_locations"\` + \`location_ambiguities[]\`; pick
|
|
9682
|
+
**Geo resolution** is identical to \`leadbay_followups_map\`: pass \`city\` (any level from state down to neighborhood \u2014 state, *r\xE9gion*, county, city \u2014 the \`/geo/search\` resolver picks the best match), or a pre-resolved \`city_id\`. Ambiguous matches surface as \`status: "ambiguous_locations"\` + \`location_ambiguities[]\`; re-call with \`city_id\` set to the id you pick AND \`city\` set to that candidate's \`name\`. Both are needed: the id scopes the follow-ups, the name scopes the Discover leads, and with \`city_id\` alone \`discover_leads\` comes back empty.
|
|
9683
9683
|
|
|
9684
9684
|
**One workspace = one country \u2014 a country name is NEVER a location filter.** The admin-area index holds no country nodes, so \`"France"\` matches the *commune of Francs* and \`"United States"\` matches *Statesboro*: the call is silently fenced to one village and every conclusion from it is wrong. City AND country named? Keep the city, drop the country.
|
|
9685
9685
|
|
|
@@ -9709,7 +9709,7 @@ not an itinerary. So for ANY country-level \`city\` \u2014 this workspace's own
|
|
|
9709
9709
|
visiting and re-call with that. \`status: "country_level_location"\` carries the
|
|
9710
9710
|
same instruction in its \`hint\`.
|
|
9711
9711
|
|
|
9712
|
-
**Counts**: \`followups_count\` (default 6 \u2014 generous so the agent can split into "customers + qualified" client-side) and \`discover_count\` (default 6 after client-side geo filter). The composite over-pulls Discover (30 raw) because the wishlist endpoint has no server-side geo filter \u2014 it then
|
|
9712
|
+
**Counts**: \`followups_count\` (default 6 \u2014 generous so the agent can split into "customers + qualified" client-side) and \`discover_count\` (default 6 after client-side geo filter). The composite over-pulls Discover (30 raw) because the wishlist endpoint has no server-side geo filter \u2014 it then keeps the leads whose own \`location.city\` names the requested city, and falls back to \`location.state\` only when no city matched (which is what a regional ask like "Texas" or "\xCEle-de-France" looks like). \`location.country\` is never consulted. \`discover_filter_note\` reports the ratio and which field carried it, so the agent can be honest about coverage. **When it says no Discover lead is in the city, say that** \u2014 return the Monitor half and offer \`leadbay_find_new_leads\` for that city. Never fill the gap with leads from elsewhere.
|
|
9713
9713
|
|
|
9714
9714
|
**What \`tour_plan\` does NOT do**: it doesn't persist the tour as a campaign artifact. To do that \u2014 create a "Limoges Tour \u2013 May 24" campaign and attach the selected accounts \u2014 chain into \`leadbay_create_campaign({lead_ids: [...selected_ids], name: 'Limoges Tour \u2013 <date>'})\` after the user picks. See the \`leadbay_plan_tour_in_city\` prompt for the full end-to-end orchestrator.
|
|
9715
9715
|
|
|
@@ -17373,13 +17373,34 @@ var followupsMap = {
|
|
|
17373
17373
|
var DEFAULT_FOLLOWUPS_COUNT = 6;
|
|
17374
17374
|
var DEFAULT_DISCOVER_COUNT = 6;
|
|
17375
17375
|
var DISCOVER_OVER_PULL = 30;
|
|
17376
|
-
function
|
|
17377
|
-
|
|
17378
|
-
|
|
17379
|
-
|
|
17380
|
-
|
|
17381
|
-
|
|
17382
|
-
|
|
17376
|
+
function normalizeGeo(value) {
|
|
17377
|
+
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
17378
|
+
}
|
|
17379
|
+
var ADMIN_PREFIX = /^(?:city|town|village|borough|township|municipality) of /;
|
|
17380
|
+
function townName(value) {
|
|
17381
|
+
return normalizeGeo(value).replace(ADMIN_PREFIX, "");
|
|
17382
|
+
}
|
|
17383
|
+
function cityHintCore(cityHint) {
|
|
17384
|
+
const head = cityHint.split(",")[0] ?? "";
|
|
17385
|
+
const expanded = expandAlias(head);
|
|
17386
|
+
return { name: townName(expanded), isCity: expanded !== head };
|
|
17387
|
+
}
|
|
17388
|
+
function stateFieldOf(lead) {
|
|
17389
|
+
const state = lead?.location?.state;
|
|
17390
|
+
return typeof state === "string" ? normalizeGeo(state) : "";
|
|
17391
|
+
}
|
|
17392
|
+
function filterDiscoverByCity(leads, cityHint) {
|
|
17393
|
+
const hint = cityHint ? cityHintCore(cityHint) : { name: "", isCity: false };
|
|
17394
|
+
if (!hint.name)
|
|
17395
|
+
return { leads, matchedOn: null };
|
|
17396
|
+
const cityOf = (l) => typeof l?.location?.city === "string" ? townName(l.location.city) : "";
|
|
17397
|
+
const byCity = leads.filter((l) => cityOf(l) === hint.name);
|
|
17398
|
+
if (byCity.length > 0)
|
|
17399
|
+
return { leads: byCity, matchedOn: "city" };
|
|
17400
|
+
if (hint.isCity)
|
|
17401
|
+
return { leads: [], matchedOn: "city" };
|
|
17402
|
+
const byState = leads.filter((l) => stateFieldOf(l) === hint.name);
|
|
17403
|
+
return { leads: byState, matchedOn: "state" };
|
|
17383
17404
|
}
|
|
17384
17405
|
function toMapLocation(lead, mode) {
|
|
17385
17406
|
const pos = lead?.location?.pos;
|
|
@@ -17448,7 +17469,7 @@ var tourPlan = {
|
|
|
17448
17469
|
},
|
|
17449
17470
|
city_id: {
|
|
17450
17471
|
type: "string",
|
|
17451
|
-
description: "Pre-resolved admin_area id (numeric string). Bypasses the resolver."
|
|
17472
|
+
description: "Pre-resolved admin_area id (numeric string). Bypasses the resolver. Pass `city` alongside it with the NAME of the area you picked: the id scopes the Monitor half, and the name is the only thing that can scope the Discover half, which has no server-side geo filter. With `city_id` alone, `discover_leads` comes back empty."
|
|
17452
17473
|
},
|
|
17453
17474
|
followups_count: {
|
|
17454
17475
|
type: "number",
|
|
@@ -17555,7 +17576,13 @@ var tourPlan = {
|
|
|
17555
17576
|
const discoverCount = params.discover_count ?? DEFAULT_DISCOVER_COUNT;
|
|
17556
17577
|
const [followupsResult, leadsResult] = await Promise.allSettled([
|
|
17557
17578
|
pullFollowups.execute(client, {
|
|
17558
|
-
|
|
17579
|
+
// A pre-resolved id bypasses the resolver, which is what its own
|
|
17580
|
+
// schema promises. Forwarding the free text alongside it sends the
|
|
17581
|
+
// name back through /geo/search, and the name is the thing that was
|
|
17582
|
+
// ambiguous — so an agent recovering from `ambiguous_locations` by
|
|
17583
|
+
// picking an id would be handed the same ambiguity again. Here the
|
|
17584
|
+
// free text stays behind and scopes the Discover half instead.
|
|
17585
|
+
city: params.city_id ? void 0 : params.city,
|
|
17559
17586
|
city_id: params.city_id,
|
|
17560
17587
|
count: followupsCount
|
|
17561
17588
|
}, ctx),
|
|
@@ -17569,7 +17596,7 @@ var tourPlan = {
|
|
|
17569
17596
|
location_ambiguities: r.location_ambiguities,
|
|
17570
17597
|
monitor_leads: [],
|
|
17571
17598
|
discover_leads: [],
|
|
17572
|
-
discover_filter_note: "City was ambiguous; pick
|
|
17599
|
+
discover_filter_note: "City was ambiguous; re-call with `city_id` set to the id you pick AND `city` set to that candidate's `name`. The id scopes the follow-ups; the name is what scopes the Discover leads.",
|
|
17573
17600
|
map_locations: [],
|
|
17574
17601
|
map_summary: {
|
|
17575
17602
|
total_leads: 0,
|
|
@@ -17593,13 +17620,27 @@ var tourPlan = {
|
|
|
17593
17620
|
if (leadsResult.status === "rejected") {
|
|
17594
17621
|
ctx?.logger?.warn?.(`tour_plan: pull_leads failed: ${leadsResult.reason?.message ?? leadsResult.reason}`);
|
|
17595
17622
|
}
|
|
17596
|
-
const
|
|
17623
|
+
const cityName = params.city && !/^\d+$/.test(params.city.trim()) ? params.city : void 0;
|
|
17624
|
+
const knownId = params.city_id ?? (cityName ? void 0 : params.city);
|
|
17625
|
+
const idOnly = Boolean(knownId) && !cityName;
|
|
17626
|
+
const { leads: filtered, matchedOn } = idOnly ? { leads: [], matchedOn: null } : filterDiscoverByCity(rawDiscover, cityName);
|
|
17597
17627
|
const discoverLeads2 = filtered.slice(0, discoverCount);
|
|
17598
17628
|
const pulledLensId = leadsResult.status === "fulfilled" ? leadsResult.value?.lens?.id : null;
|
|
17599
17629
|
if (pulledLensId != null) {
|
|
17600
17630
|
reportLeadInteractions(client, pulledLensId, discoverLeads2.map((l) => l.id), ["LEAD_SEEN"], ctx?.logger);
|
|
17601
17631
|
}
|
|
17602
|
-
|
|
17632
|
+
let filterNote;
|
|
17633
|
+
if (idOnly) {
|
|
17634
|
+
filterNote = `Discover leads need the NAME of the place, and this call passed an area id (${knownId}) and no name. Re-call with \`city\` set to the name of that area, keeping \`city_id\` so the Monitor half stays on the area you picked. The follow-ups below are already scoped to it.`;
|
|
17635
|
+
} else if (!cityName) {
|
|
17636
|
+
filterNote = `No city filter applied; returning top ${discoverLeads2.length} Discover leads.`;
|
|
17637
|
+
} else if (matchedOn === null) {
|
|
17638
|
+
filterNote = `No usable city filter in '${params.city}'; returning top ${discoverLeads2.length} Discover leads.`;
|
|
17639
|
+
} else if (filtered.length === 0) {
|
|
17640
|
+
filterNote = `No Discover lead in the active lens is in '${params.city}' (checked ${rawDiscover.length} candidates by city, then by state/region). Say so; do NOT present leads from elsewhere as if they were in '${params.city}'.`;
|
|
17641
|
+
} else {
|
|
17642
|
+
filterNote = `Matched ${filtered.length}/${rawDiscover.length} Discover leads to '${params.city}' by ${matchedOn === "city" ? "city" : "state/region"}; returning top ${discoverLeads2.length}.`;
|
|
17643
|
+
}
|
|
17603
17644
|
return {
|
|
17604
17645
|
city: params.city ?? null,
|
|
17605
17646
|
city_id: params.city_id ?? null,
|
|
@@ -28619,7 +28660,7 @@ function parseWriteEnv(env = process.env) {
|
|
|
28619
28660
|
}
|
|
28620
28661
|
|
|
28621
28662
|
// src/http-server.ts
|
|
28622
|
-
var VERSION = true ? "0.39.
|
|
28663
|
+
var VERSION = true ? "0.39.2" : "0.0.0-dev";
|
|
28623
28664
|
var PORT = Number(process.env.PORT ?? 8080);
|
|
28624
28665
|
var HOST = process.env.HOST ?? "0.0.0.0";
|
|
28625
28666
|
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.39.
|
|
3
|
+
"version": "0.39.2",
|
|
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",
|