@coldiq/mcp 0.1.17 → 0.1.19
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/registry.d.ts.map +1 -1
- package/dist/registry.js +37 -3
- package/dist/registry.js.map +1 -1
- package/dist/utils/provider-resolver.js +3 -0
- package/dist/utils/provider-resolver.js.map +1 -1
- package/package.json +2 -4
- package/src/registry.ts +44 -5
- package/src/utils/provider-resolver.ts +3 -0
- package/tests/live/fullenrich-upstream-probe.ts +55 -0
- package/tests/live/pdl-upstream-probe.ts +83 -0
- package/tests/registry-find-people.test.ts +206 -9
- package/tests/tools/find-people.test.ts +19 -6
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACpC;;;;OAIG;IACH,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;IACtD,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,qCAAqC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;IACtC,kDAAkD;IAClD,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAA;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IACvG,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;IACrC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;IAC1D;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;CACxE;AAED,MAAM,MAAM,UAAU,GAClB,kBAAkB,GAClB,aAAa,GACb,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,gBAAgB,GAChB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,cAAc,GACd,oBAAoB,CAAA;AA0CxB,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOrD;AAgCD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAclE;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAGpF;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACpC;;;;OAIG;IACH,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;IACtD,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,qCAAqC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;IACtC,kDAAkD;IAClD,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAA;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IACvG,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;IACrC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;IAC1D;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAA;CACxE;AAED,MAAM,MAAM,UAAU,GAClB,kBAAkB,GAClB,aAAa,GACb,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,gBAAgB,GAChB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,cAAc,GACd,oBAAoB,CAAA;AA0CxB,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOrD;AAgCD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAclE;AAKD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAGpF;AAi/FD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,CAE1E;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,GACjB,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,SAAS,CAI3D;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,EAAE,CASpE;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,OAAO,GAAG,aAAa,EAAE,CAkB5E"}
|
package/dist/registry.js
CHANGED
|
@@ -979,9 +979,20 @@ const findPeopleProviders = [
|
|
|
979
979
|
};
|
|
980
980
|
},
|
|
981
981
|
hasResult: (data) => {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
982
|
+
// Each entry in companies_personas is { company, personas: unknown[][], ... }.
|
|
983
|
+
// The wrapper array is always populated (one entry per requested domain), so
|
|
984
|
+
// checking only `isNonEmptyArray(d.companies_personas)` returns true even when
|
|
985
|
+
// every entry's inner `personas` is empty (no contacts found). Count the
|
|
986
|
+
// actual contacts so the waterfall falls through to apollo on empty results.
|
|
987
|
+
const d = data;
|
|
988
|
+
const groups = d.companies_personas;
|
|
989
|
+
if (Array.isArray(groups)) {
|
|
990
|
+
const totalContacts = groups.reduce((sum, g) => sum + ((g.personas ?? []).flat().length), 0);
|
|
991
|
+
return totalContacts > 0;
|
|
992
|
+
}
|
|
993
|
+
// Defensive fallback: if upstream omits companies_personas entirely, trust the
|
|
994
|
+
// job-completion counter. Not observed in practice; kept for safety.
|
|
995
|
+
return d.status === 'SUCCESSFUL' && d.nb_jobs_complete != null && d.nb_jobs_complete > 0;
|
|
985
996
|
},
|
|
986
997
|
async: {
|
|
987
998
|
pollEndpoint: (id) => `/leadsfactory/contact-finder/searches/${id}`,
|
|
@@ -1062,12 +1073,24 @@ const findPeopleProviders = [
|
|
|
1062
1073
|
endpoint: '/pdl/person/search',
|
|
1063
1074
|
method: 'POST',
|
|
1064
1075
|
priority: 3,
|
|
1076
|
+
// Refuse fully-unbounded queries: PDL accepts an empty `must` and would return its
|
|
1077
|
+
// entire index — turning the waterfall into a "random 25 humans" generator.
|
|
1078
|
+
isApplicable: (input) => isNonEmptyArray(input.company_domains) ||
|
|
1079
|
+
isNonEmptyArray(input.company_linkedin_urls) ||
|
|
1080
|
+
isNonEmptyArray(input.job_titles) ||
|
|
1081
|
+
isNonEmptyArray(input.seniorities),
|
|
1065
1082
|
mapParams: (input) => {
|
|
1066
1083
|
const must = [];
|
|
1067
1084
|
if (isNonEmptyArray(input.job_titles))
|
|
1068
1085
|
must.push({ terms: { job_title: input.job_titles } });
|
|
1069
1086
|
if (isNonEmptyArray(input.company_domains))
|
|
1070
1087
|
must.push({ terms: { job_company_website: input.company_domains } });
|
|
1088
|
+
if (isNonEmptyArray(input.company_linkedin_urls)) {
|
|
1089
|
+
// PDL indexes LinkedIn URLs in canonical short form (`linkedin.com/company/x`)
|
|
1090
|
+
// and `terms` is exact-match — full URLs from callers silently return 0 hits.
|
|
1091
|
+
const normalized = input.company_linkedin_urls.map((u) => u.toLowerCase().replace(/^https?:\/\//, '').replace(/^www\./, '').replace(/\/+$/, ''));
|
|
1092
|
+
must.push({ terms: { job_company_linkedin_url: normalized } });
|
|
1093
|
+
}
|
|
1071
1094
|
if (isNonEmptyArray(input.seniorities))
|
|
1072
1095
|
must.push({ terms: { job_title_levels: input.seniorities } });
|
|
1073
1096
|
if (isNonEmptyArray(input.locations))
|
|
@@ -1089,10 +1112,15 @@ const findPeopleProviders = [
|
|
|
1089
1112
|
endpoint: '/companyenrich/people/search',
|
|
1090
1113
|
method: 'POST',
|
|
1091
1114
|
priority: 4,
|
|
1115
|
+
// Upstream `filters.companies` accepts domains only — no LinkedIn-URL field exists.
|
|
1116
|
+
// Skip when the caller supplied only LinkedIn URLs so we don't fall back to a
|
|
1117
|
+
// titles-only global search that masquerades as company-scoped.
|
|
1118
|
+
isApplicable: (input) => isNonEmptyArray(input.company_domains) || !isNonEmptyArray(input.company_linkedin_urls),
|
|
1092
1119
|
mapParams: (input) => ({
|
|
1093
1120
|
body: {
|
|
1094
1121
|
filters: {
|
|
1095
1122
|
jobTitles: input.job_titles,
|
|
1123
|
+
companies: isNonEmptyArray(input.company_domains) ? input.company_domains : undefined,
|
|
1096
1124
|
countries: input.locations,
|
|
1097
1125
|
},
|
|
1098
1126
|
pageSize: input.limit ?? 25,
|
|
@@ -1224,6 +1252,12 @@ const findPeopleProviders = [
|
|
|
1224
1252
|
endpoint: '/fullenrich/people/search',
|
|
1225
1253
|
method: 'POST',
|
|
1226
1254
|
priority: 9,
|
|
1255
|
+
// Requires company_domains: the upstream rejects LinkedIn-URL variants as
|
|
1256
|
+
// `error.filters.empty` (despite the schema declaring `current_company_linkedin_urls`,
|
|
1257
|
+
// the live API doesn't honor it). Without any company filter, FullEnrich silently
|
|
1258
|
+
// degrades to a 50k-result titles-only search whose first 25 short-circuit the
|
|
1259
|
+
// waterfall via hasResult.
|
|
1260
|
+
isApplicable: (input) => isNonEmptyArray(input.company_domains),
|
|
1227
1261
|
mapParams: (input) => ({
|
|
1228
1262
|
body: {
|
|
1229
1263
|
current_company_domains: isNonEmptyArray(input.company_domains)
|