@sellable/mcp 0.1.224 → 0.1.226
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/tools/leads.js +274 -10
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +21 -3
- package/skills/find-leads/SKILL.md +19 -1
- package/skills/providers/prospeo.md +12 -1
package/dist/tools/leads.js
CHANGED
|
@@ -59,6 +59,51 @@ export const MAX_SIGNAL_DISCOVERY_POSTS = 10;
|
|
|
59
59
|
// capacity math instead of raw visible engagement counts.
|
|
60
60
|
const signalDiscoveryReactionFetchLimit = 1000;
|
|
61
61
|
const signalDiscoveryCommentFetchLimit = 1000;
|
|
62
|
+
const prospeoCompanySearchTokenRefs = new Map();
|
|
63
|
+
let prospeoCompanySearchTokenRefCounter = 0;
|
|
64
|
+
const PROSPEO_COMPANY_SEARCH_TOKEN_REF_PREFIX = "mcp-prospeo-company-search-token:";
|
|
65
|
+
const MAX_PROSPEO_COMPANY_SEARCH_TOKEN_REFS = 200;
|
|
66
|
+
const PROSPEO_LARGE_TITLE_INCLUDE_BOOLEAN_THRESHOLD = 8;
|
|
67
|
+
const prospeoCompanyKeywordIncludeAliases = new Map([
|
|
68
|
+
["ai", "artificial intelligence"],
|
|
69
|
+
["api", "application programming interface"],
|
|
70
|
+
["gtm", "go to market"],
|
|
71
|
+
["saas", "software as a service"],
|
|
72
|
+
]);
|
|
73
|
+
const prospeoCompanyIcpRegionAliases = new Map([
|
|
74
|
+
["north america", ["United States", "Canada"]],
|
|
75
|
+
["na", ["United States", "Canada"]],
|
|
76
|
+
["us", ["United States"]],
|
|
77
|
+
["usa", ["United States"]],
|
|
78
|
+
["u.s.", ["United States"]],
|
|
79
|
+
["u.s.a.", ["United States"]],
|
|
80
|
+
]);
|
|
81
|
+
const prospeoCompanyIcpDepartments = new Set([
|
|
82
|
+
"Consumers",
|
|
83
|
+
"Customer Success",
|
|
84
|
+
"Data",
|
|
85
|
+
"Design",
|
|
86
|
+
"Engineering",
|
|
87
|
+
"Finance",
|
|
88
|
+
"HR",
|
|
89
|
+
"IT",
|
|
90
|
+
"Legal",
|
|
91
|
+
"Marketing",
|
|
92
|
+
"Operations",
|
|
93
|
+
"Procurement",
|
|
94
|
+
"SMB Owners",
|
|
95
|
+
"Sales",
|
|
96
|
+
"Security",
|
|
97
|
+
]);
|
|
98
|
+
const prospeoKeyCustomerCompanionFilters = [
|
|
99
|
+
"company_attributes",
|
|
100
|
+
"company_headcount_range",
|
|
101
|
+
"company_headcount_custom",
|
|
102
|
+
"company_industry",
|
|
103
|
+
"company_keywords",
|
|
104
|
+
"company_website_search",
|
|
105
|
+
"company_icp",
|
|
106
|
+
];
|
|
62
107
|
const prospeoFilterValueSchema = {
|
|
63
108
|
type: "object",
|
|
64
109
|
description: "Include/exclude list filter (values must match Prospeo enums)",
|
|
@@ -477,12 +522,14 @@ search_prospeo_companies({
|
|
|
477
522
|
}
|
|
478
523
|
})
|
|
479
524
|
Do not invent company_oids. When seedCompanies or seedDomains are present, omit company_oids and let the backend resolve real Prospeo company IDs.
|
|
525
|
+
After account approval, copy the companySearchToken exactly into confirm_prospeo_company_accounts; package-backed MCP may return a short mcp-prospeo-company-search-token:* reference to avoid long-token copy errors.
|
|
480
526
|
For accounts in the news: { "company_news": { "categories": ["Funding & Investment"], "timeframe_days": 90 } }.
|
|
481
527
|
For awards: { "company_awards": { "include": ["G2"], "match_mode": "CONTAINS" } }.
|
|
482
528
|
For website traffic: { "company_website_traffic": { "min_monthly_visits": 50000 } }.
|
|
483
529
|
For products/services, integrations, key customers, and Google discovery use "company_products_services", "company_integrations", "company_key_customers", and "company_google_discovery".
|
|
484
530
|
For headcount by location: { "company_headcount_by_location": { "entries": [{ "country": "United States", "city": "Austin", "min_headcount": 10 }] } }.
|
|
485
531
|
For structured ICP: { "company_icp": { "titles_include": ["Head of RevOps"], "company_sizes": ["midmarket"], "departments": { "include": ["Sales"], "match_mode": "ANY" }, "geographic_scope": "multi_country", "geographic_markets": ["United States", "Canada"] }, "company_headcount_range": ["101-200", "201-500", "501-1000"] }. Pair company_icp.company_sizes with company_headcount_range or rely on MCP normalization that derives the range; inspect the account sample for size drift. Product is not a company_icp.departments value; use titles_include for product roles. geographic_scope only accepts single_country or multi_country.
|
|
532
|
+
Use company_key_customers as a standalone first-pass account filter. Do not combine company_key_customers with company_website_search, company_icp, company_keywords, or broad AI Attributes in the first call. Do not use AI, API, GTM, or SaaS as company keyword terms; use confirmed attributes or spell out artificial intelligence, application programming interface, go to market, and software as a service. Do not send company_keywords.exclude without an include keyword. For post-confirm people search, prefer person_job_title.boolean_search for long role synonym lists.
|
|
486
533
|
company_intent is unsupported; support-channel AI Attribute guesses like phone/email/chat/ticket/social are not exposed. public API rows do not include lookalike tier/score/reason.`;
|
|
487
534
|
function loadSignalDiscoveryConfig() {
|
|
488
535
|
if (!existsSync(signalProviderConfigPath)) {
|
|
@@ -2310,14 +2357,15 @@ export async function searchProspeoCompanies(input) {
|
|
|
2310
2357
|
campaignOfferId: input?.campaignOfferId,
|
|
2311
2358
|
});
|
|
2312
2359
|
const api = getApi();
|
|
2360
|
+
const safeInput = normalizeProspeoCompanySearchInputForMcp(input);
|
|
2313
2361
|
const response = await api.post("/api/v3/prospeo/company-search", removeUndefinedValues({
|
|
2314
|
-
campaignOfferId:
|
|
2315
|
-
seedCompanies:
|
|
2316
|
-
seedDomains:
|
|
2317
|
-
filters:
|
|
2318
|
-
limit:
|
|
2319
|
-
page:
|
|
2320
|
-
sort:
|
|
2362
|
+
campaignOfferId: safeInput?.campaignOfferId,
|
|
2363
|
+
seedCompanies: safeInput?.seedCompanies,
|
|
2364
|
+
seedDomains: safeInput?.seedDomains,
|
|
2365
|
+
filters: safeInput?.filters ?? {},
|
|
2366
|
+
limit: safeInput?.limit,
|
|
2367
|
+
page: safeInput?.page,
|
|
2368
|
+
sort: safeInput?.sort,
|
|
2321
2369
|
}));
|
|
2322
2370
|
return compactProspeoCompanySearchResponse(response);
|
|
2323
2371
|
}
|
|
@@ -2346,7 +2394,7 @@ export async function confirmProspeoCompanyAccounts(input) {
|
|
|
2346
2394
|
const api = getApi();
|
|
2347
2395
|
const response = await api.post("/api/v3/prospeo/company-search/confirm-domain-filter", removeUndefinedValues({
|
|
2348
2396
|
campaignOfferId: input?.campaignOfferId,
|
|
2349
|
-
companySearchToken: input.companySearchToken,
|
|
2397
|
+
companySearchToken: resolveProspeoCompanySearchTokenRef(input.companySearchToken),
|
|
2350
2398
|
selectedCompanyIds: input.selectedCompanyIds,
|
|
2351
2399
|
name: input.name,
|
|
2352
2400
|
}));
|
|
@@ -2355,6 +2403,221 @@ export async function confirmProspeoCompanyAccounts(input) {
|
|
|
2355
2403
|
function removeUndefinedValues(input) {
|
|
2356
2404
|
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
|
|
2357
2405
|
}
|
|
2406
|
+
function normalizeProspeoCompanySearchInputForMcp(input) {
|
|
2407
|
+
const filters = input?.filters && typeof input.filters === "object"
|
|
2408
|
+
? clonePlainObject(input.filters)
|
|
2409
|
+
: {};
|
|
2410
|
+
const hasSeeds = (input.seedCompanies?.length ?? 0) > 0 ||
|
|
2411
|
+
(input.seedDomains?.length ?? 0) > 0;
|
|
2412
|
+
if (hasSeeds) {
|
|
2413
|
+
const lookalike = filters.company_lookalike;
|
|
2414
|
+
if (lookalike &&
|
|
2415
|
+
typeof lookalike === "object" &&
|
|
2416
|
+
!Array.isArray(lookalike) &&
|
|
2417
|
+
"company_oids" in lookalike) {
|
|
2418
|
+
delete lookalike.company_oids;
|
|
2419
|
+
removeEmptyObjectFilter(filters, "company_lookalike");
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
normalizeMcpCompanyKeywords(filters);
|
|
2423
|
+
normalizeMcpCompanyIcp(filters);
|
|
2424
|
+
stripMcpDuplicateCompanyIndustry(filters);
|
|
2425
|
+
stripMcpKeyCustomerCompanionFilters(filters);
|
|
2426
|
+
return {
|
|
2427
|
+
...input,
|
|
2428
|
+
filters,
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
function normalizeProspeoSearchInputForMcp(input) {
|
|
2432
|
+
const filters = input?.filters && typeof input.filters === "object"
|
|
2433
|
+
? clonePlainObject(input.filters)
|
|
2434
|
+
: {};
|
|
2435
|
+
normalizeMcpPersonJobTitle(filters);
|
|
2436
|
+
return {
|
|
2437
|
+
...input,
|
|
2438
|
+
filters,
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
function normalizeMcpCompanyKeywords(filters) {
|
|
2442
|
+
const keywords = filters.company_keywords;
|
|
2443
|
+
if (!isPlainObject(keywords)) {
|
|
2444
|
+
return;
|
|
2445
|
+
}
|
|
2446
|
+
const include = normalizeStringArray(keywords.include).map((keyword) => {
|
|
2447
|
+
const alias = prospeoCompanyKeywordIncludeAliases.get(keyword.toLowerCase());
|
|
2448
|
+
return alias ?? keyword;
|
|
2449
|
+
});
|
|
2450
|
+
const validInclude = include.filter((keyword) => keyword.length >= 3);
|
|
2451
|
+
if (validInclude.length > 0) {
|
|
2452
|
+
keywords.include = uniqueStrings(validInclude);
|
|
2453
|
+
}
|
|
2454
|
+
else {
|
|
2455
|
+
delete keywords.include;
|
|
2456
|
+
delete keywords.exclude;
|
|
2457
|
+
}
|
|
2458
|
+
if (keywords.exclude !== undefined && validInclude.length === 0) {
|
|
2459
|
+
delete keywords.exclude;
|
|
2460
|
+
}
|
|
2461
|
+
removeEmptyObjectFilter(filters, "company_keywords");
|
|
2462
|
+
}
|
|
2463
|
+
function normalizeMcpCompanyIcp(filters) {
|
|
2464
|
+
const icp = filters.company_icp;
|
|
2465
|
+
if (!isPlainObject(icp)) {
|
|
2466
|
+
return;
|
|
2467
|
+
}
|
|
2468
|
+
const scope = typeof icp.geographic_scope === "string"
|
|
2469
|
+
? icp.geographic_scope.trim()
|
|
2470
|
+
: "";
|
|
2471
|
+
const scopeMarkets = expandMcpCompanyIcpMarket(scope);
|
|
2472
|
+
if (scopeMarkets.length > 0) {
|
|
2473
|
+
icp.geographic_scope = "multi_country";
|
|
2474
|
+
icp.geographic_markets = uniqueStrings([
|
|
2475
|
+
...scopeMarkets,
|
|
2476
|
+
...normalizeMcpCompanyIcpMarkets(icp.geographic_markets),
|
|
2477
|
+
]);
|
|
2478
|
+
}
|
|
2479
|
+
else if (scope &&
|
|
2480
|
+
scope !== "single_country" &&
|
|
2481
|
+
scope !== "multi_country") {
|
|
2482
|
+
delete icp.geographic_scope;
|
|
2483
|
+
}
|
|
2484
|
+
if (icp.geographic_markets !== undefined) {
|
|
2485
|
+
icp.geographic_markets = normalizeMcpCompanyIcpMarkets(icp.geographic_markets);
|
|
2486
|
+
if (Array.isArray(icp.geographic_markets) &&
|
|
2487
|
+
icp.geographic_markets.length === 0) {
|
|
2488
|
+
delete icp.geographic_markets;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
normalizeMcpCompanyIcpDepartments(icp);
|
|
2492
|
+
removeEmptyObjectFilter(filters, "company_icp");
|
|
2493
|
+
}
|
|
2494
|
+
function normalizeMcpCompanyIcpDepartments(icp) {
|
|
2495
|
+
const departments = icp.departments;
|
|
2496
|
+
if (Array.isArray(departments)) {
|
|
2497
|
+
const valid = departments
|
|
2498
|
+
.filter((department) => typeof department === "string")
|
|
2499
|
+
.filter((department) => prospeoCompanyIcpDepartments.has(department));
|
|
2500
|
+
if (valid.length > 0) {
|
|
2501
|
+
icp.departments = uniqueStrings(valid);
|
|
2502
|
+
}
|
|
2503
|
+
else {
|
|
2504
|
+
delete icp.departments;
|
|
2505
|
+
}
|
|
2506
|
+
return;
|
|
2507
|
+
}
|
|
2508
|
+
if (!isPlainObject(departments)) {
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2511
|
+
const include = normalizeStringArray(departments.include).filter((department) => prospeoCompanyIcpDepartments.has(department));
|
|
2512
|
+
const exclude = normalizeStringArray(departments.exclude).filter((department) => prospeoCompanyIcpDepartments.has(department));
|
|
2513
|
+
if (include.length > 0) {
|
|
2514
|
+
departments.include = uniqueStrings(include);
|
|
2515
|
+
}
|
|
2516
|
+
else {
|
|
2517
|
+
delete departments.include;
|
|
2518
|
+
}
|
|
2519
|
+
if (exclude.length > 0) {
|
|
2520
|
+
departments.exclude = uniqueStrings(exclude);
|
|
2521
|
+
}
|
|
2522
|
+
else {
|
|
2523
|
+
delete departments.exclude;
|
|
2524
|
+
}
|
|
2525
|
+
if (departments.include === undefined && departments.exclude === undefined) {
|
|
2526
|
+
delete icp.departments;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
function normalizeMcpCompanyIcpMarkets(input) {
|
|
2530
|
+
const markets = normalizeStringArray(input);
|
|
2531
|
+
return uniqueStrings(markets.flatMap(expandMcpCompanyIcpMarket));
|
|
2532
|
+
}
|
|
2533
|
+
function expandMcpCompanyIcpMarket(market) {
|
|
2534
|
+
const trimmed = market.trim();
|
|
2535
|
+
if (!trimmed) {
|
|
2536
|
+
return [];
|
|
2537
|
+
}
|
|
2538
|
+
return prospeoCompanyIcpRegionAliases.get(trimmed.toLowerCase()) ?? [trimmed];
|
|
2539
|
+
}
|
|
2540
|
+
function stripMcpDuplicateCompanyIndustry(filters) {
|
|
2541
|
+
const icp = filters.company_icp;
|
|
2542
|
+
if (isPlainObject(icp) &&
|
|
2543
|
+
Array.isArray(icp.industries) &&
|
|
2544
|
+
icp.industries.length > 0) {
|
|
2545
|
+
delete filters.company_industry;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
function stripMcpKeyCustomerCompanionFilters(filters) {
|
|
2549
|
+
const keyCustomers = filters.company_key_customers;
|
|
2550
|
+
if (!isPlainObject(keyCustomers)) {
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
const include = normalizeStringArray(keyCustomers.include);
|
|
2554
|
+
if (include.length === 0) {
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
for (const filterName of prospeoKeyCustomerCompanionFilters) {
|
|
2558
|
+
delete filters[filterName];
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
function normalizeMcpPersonJobTitle(filters) {
|
|
2562
|
+
const jobTitle = filters.person_job_title;
|
|
2563
|
+
if (!isPlainObject(jobTitle)) {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
const include = normalizeStringArray(jobTitle.include);
|
|
2567
|
+
const exclude = normalizeStringArray(jobTitle.exclude);
|
|
2568
|
+
if (include.length > PROSPEO_LARGE_TITLE_INCLUDE_BOOLEAN_THRESHOLD &&
|
|
2569
|
+
exclude.length === 0 &&
|
|
2570
|
+
typeof jobTitle.boolean_search !== "string") {
|
|
2571
|
+
delete jobTitle.include;
|
|
2572
|
+
jobTitle.boolean_search = include
|
|
2573
|
+
.map((title) => `"${title.replace(/"/g, '\\"')}"`)
|
|
2574
|
+
.join(" OR ");
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
function isPlainObject(input) {
|
|
2578
|
+
return Boolean(input) && typeof input === "object" && !Array.isArray(input);
|
|
2579
|
+
}
|
|
2580
|
+
function normalizeStringArray(input) {
|
|
2581
|
+
if (!Array.isArray(input)) {
|
|
2582
|
+
return [];
|
|
2583
|
+
}
|
|
2584
|
+
return input
|
|
2585
|
+
.filter((value) => typeof value === "string")
|
|
2586
|
+
.map((value) => value.trim())
|
|
2587
|
+
.filter((value) => value.length > 0);
|
|
2588
|
+
}
|
|
2589
|
+
function uniqueStrings(input) {
|
|
2590
|
+
return Array.from(new Set(input));
|
|
2591
|
+
}
|
|
2592
|
+
function removeEmptyObjectFilter(filters, filterName) {
|
|
2593
|
+
const filter = filters[filterName];
|
|
2594
|
+
if (isPlainObject(filter) && Object.keys(filter).length === 0) {
|
|
2595
|
+
delete filters[filterName];
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
function clonePlainObject(input) {
|
|
2599
|
+
return JSON.parse(JSON.stringify(input));
|
|
2600
|
+
}
|
|
2601
|
+
function storeProspeoCompanySearchTokenRef(token) {
|
|
2602
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
2603
|
+
return token;
|
|
2604
|
+
}
|
|
2605
|
+
if (token.startsWith(PROSPEO_COMPANY_SEARCH_TOKEN_REF_PREFIX)) {
|
|
2606
|
+
return token;
|
|
2607
|
+
}
|
|
2608
|
+
const ref = `${PROSPEO_COMPANY_SEARCH_TOKEN_REF_PREFIX}${Date.now().toString(36)}-${(++prospeoCompanySearchTokenRefCounter).toString(36)}`;
|
|
2609
|
+
prospeoCompanySearchTokenRefs.set(ref, token);
|
|
2610
|
+
while (prospeoCompanySearchTokenRefs.size > MAX_PROSPEO_COMPANY_SEARCH_TOKEN_REFS) {
|
|
2611
|
+
const oldest = prospeoCompanySearchTokenRefs.keys().next().value;
|
|
2612
|
+
if (!oldest)
|
|
2613
|
+
break;
|
|
2614
|
+
prospeoCompanySearchTokenRefs.delete(oldest);
|
|
2615
|
+
}
|
|
2616
|
+
return ref;
|
|
2617
|
+
}
|
|
2618
|
+
function resolveProspeoCompanySearchTokenRef(token) {
|
|
2619
|
+
return prospeoCompanySearchTokenRefs.get(token) ?? token;
|
|
2620
|
+
}
|
|
2358
2621
|
function compactProspeoCompanySearchResponse(response) {
|
|
2359
2622
|
if (!response || typeof response !== "object") {
|
|
2360
2623
|
return response;
|
|
@@ -2384,7 +2647,7 @@ function compactProspeoCompanySearchResponse(response) {
|
|
|
2384
2647
|
},
|
|
2385
2648
|
requestedFilters: response.normalizedFilters ?? response.filters ?? {},
|
|
2386
2649
|
warnings: Array.isArray(response.warnings) ? response.warnings : [],
|
|
2387
|
-
companySearchToken: response.companySearchToken
|
|
2650
|
+
companySearchToken: storeProspeoCompanySearchTokenRef(response.companySearchToken),
|
|
2388
2651
|
nextStep: "Review accounts, then call confirm_prospeo_company_accounts with companySearchToken and selectedCompanyIds. These accounts are not people leads yet.",
|
|
2389
2652
|
};
|
|
2390
2653
|
}
|
|
@@ -2464,7 +2727,8 @@ export async function searchProspeo(input) {
|
|
|
2464
2727
|
nestedCompany?.names !== undefined) {
|
|
2465
2728
|
throw new Error("search_prospeo does not accept filters.company.websites or filters.company.names. For known accounts, resolve names/domains into a domainFilterId with load_csv_domains or save_domain_filters. For company/account lookalikes, use search_prospeo_companies first, then confirm_prospeo_company_accounts.");
|
|
2466
2729
|
}
|
|
2467
|
-
const
|
|
2730
|
+
const safeInput = normalizeProspeoSearchInputForMcp(input);
|
|
2731
|
+
const response = await api.post(`/api/v3/prospeo/search`, safeInput);
|
|
2468
2732
|
return compactProspeoSearchResponse(response);
|
|
2469
2733
|
}
|
|
2470
2734
|
function compactProspeoSearchResponse(response) {
|
package/package.json
CHANGED
|
@@ -214,9 +214,11 @@ before person search, use the Prospeo account approval flow:
|
|
|
214
214
|
First return an account sample and ask the user to approve the account set.
|
|
215
215
|
Only call `confirm_prospeo_company_accounts` with the `companySearchToken`
|
|
216
216
|
returned by `search_prospeo_companies` and selected Prospeo company IDs; never
|
|
217
|
-
reconstruct raw account rows or domains manually
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
reconstruct raw account rows or domains manually; always copy the `companySearchToken` exactly.
|
|
218
|
+
Package-backed MCP may return a short `mcp-prospeo-company-search-token:*`
|
|
219
|
+
reference to avoid long-token copy errors. Account rows are not people leads
|
|
220
|
+
yet. The confirmation creates the `domainFilterId` that constrains the follow-on
|
|
221
|
+
`search_prospeo` people search.
|
|
220
222
|
|
|
221
223
|
Prospeo company/account search is useful when the source plan depends on
|
|
222
224
|
website traffic (`company_website_traffic`), confirmed AI Attributes including
|
|
@@ -238,6 +240,22 @@ company_icp.departments value; use `titles_include` for product roles.
|
|
|
238
240
|
`uses_ai` when that is the actual signal. Do not use `company_intent`, and do
|
|
239
241
|
not invent unsupported support-channel filters or AI Attribute guesses like
|
|
240
242
|
phone/email/chat/ticket/social.
|
|
243
|
+
Use `company_key_customers` as a standalone first-pass account filter; in short,
|
|
244
|
+
run company_key_customers as a standalone first-pass. Do not combine
|
|
245
|
+
`company_key_customers` with `company_website_search`, `company_icp`,
|
|
246
|
+
`company_keywords`, or broad AI Attributes in the first call. Do not use `AI`,
|
|
247
|
+
`API`, `GTM`, or `SaaS` as company keyword terms; use confirmed attributes or
|
|
248
|
+
spell out artificial intelligence, application programming interface, go to
|
|
249
|
+
market, and software as a service. Do not send `company_keywords.exclude`
|
|
250
|
+
without an include keyword, and do not duplicate `company_industry` when
|
|
251
|
+
`company_icp.industries` already carries the industry. For post-confirm people
|
|
252
|
+
search, prefer `person_job_title.boolean_search` for long role synonym lists
|
|
253
|
+
instead of many `person_job_title.include` values plus broad department/seniority
|
|
254
|
+
filters.
|
|
255
|
+
Do not use `AI`, `API`, `GTM`, or `SaaS` as company keyword terms.
|
|
256
|
+
Do not combine `company_key_customers` with ICP, website-search, keyword,
|
|
257
|
+
attribute, industry, or headcount filters until the standalone pass proves
|
|
258
|
+
useful.
|
|
241
259
|
|
|
242
260
|
After scouting, ask for a second approval on Start Import. For
|
|
243
261
|
LinkedIn engagement (`signal-discovery` internally), name how many
|
|
@@ -414,15 +414,33 @@ Use first for broad persona expansion, ABM/domain targeting, hiring-led targetin
|
|
|
414
414
|
- `company_keywords.include/exclude` values must be at least 3 characters; use
|
|
415
415
|
`artificial intelligence` instead of `AI`, or use confirmed attributes such
|
|
416
416
|
as `uses_ai` when that is the actual signal.
|
|
417
|
+
- Use `company_key_customers` as a standalone first-pass account filter; in
|
|
418
|
+
short, run company_key_customers as a standalone first-pass. Do not
|
|
419
|
+
combine `company_key_customers` with `company_website_search`, `company_icp`,
|
|
420
|
+
`company_keywords`, or broad AI Attributes in the first call.
|
|
421
|
+
- Do not combine `company_key_customers` with ICP, website-search, keyword,
|
|
422
|
+
attribute, industry, or headcount filters until the standalone pass proves
|
|
423
|
+
useful.
|
|
424
|
+
- Do not use `AI`, `API`, `GTM`, or `SaaS` as company keyword terms; use
|
|
425
|
+
confirmed attributes or spell out artificial intelligence, application
|
|
426
|
+
programming interface, go to market, and software as a service.
|
|
427
|
+
- Do not send `company_keywords.exclude` unless at least one include keyword is
|
|
428
|
+
present. Do not duplicate `company_industry` when `company_icp.industries`
|
|
429
|
+
already carries the industry.
|
|
417
430
|
- Do not use `company_intent`. Do not invent unsupported support-channel filters
|
|
418
431
|
or AI Attribute guesses like phone/email/chat/ticket/social.
|
|
419
432
|
- Company/account search returns an account sample only; account rows are not people leads yet. Ask the user to approve the account sample.
|
|
420
433
|
- After approval, call `confirm_prospeo_company_accounts` with the
|
|
421
434
|
`companySearchToken` and selected Prospeo company IDs from
|
|
422
435
|
`search_prospeo_companies`; do not reconstruct account rows or domains
|
|
423
|
-
manually.
|
|
436
|
+
manually. Always copy the `companySearchToken` exactly; package-backed MCP may
|
|
437
|
+
return a short `mcp-prospeo-company-search-token:*` reference to avoid
|
|
438
|
+
long-token copy errors.
|
|
424
439
|
- Use the returned `domainFilterId` in the follow-on `search_prospeo` people
|
|
425
440
|
search.
|
|
441
|
+
- For post-confirm people search, prefer `person_job_title.boolean_search` for
|
|
442
|
+
long role synonym lists instead of many `person_job_title.include` values plus
|
|
443
|
+
broad department/seniority filters.
|
|
426
444
|
- Prospeo is the terminal fallback for this chain. If projected fit is still
|
|
427
445
|
below the 10% planning floor after reasonable Prospeo refinement, stop and ask
|
|
428
446
|
for a tighter ICP/source direction instead of inventing another provider.
|
|
@@ -80,7 +80,7 @@ confirm_prospeo_company_accounts({
|
|
|
80
80
|
})
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
Use the returned `domainFilterId` in `search_prospeo` with people filters. Do not reconstruct raw account rows or domains manually as Prospeo-sourced provenance.
|
|
83
|
+
Use the returned `domainFilterId` in `search_prospeo` with people filters. Do not reconstruct raw account rows or domains manually as Prospeo-sourced provenance. Always copy the `companySearchToken` exactly from `search_prospeo_companies`; package-backed MCP may return a short `mcp-prospeo-company-search-token:*` reference so the model does not have to copy a long signed backend token.
|
|
84
84
|
|
|
85
85
|
When `seedDomains` or `seedCompanies` are present, omit `company_oids`; the MCP
|
|
86
86
|
backend resolves real Prospeo company IDs. Do not invent company_oids such as
|
|
@@ -100,6 +100,14 @@ company ICP departments include Consumers, Customer Success, Data, Design,
|
|
|
100
100
|
Engineering, Finance, HR, IT, Legal, Marketing, Operations, Procurement, SMB
|
|
101
101
|
Owners, Sales, and Security.
|
|
102
102
|
|
|
103
|
+
Avoidable-400 guardrails:
|
|
104
|
+
|
|
105
|
+
- Use `company_key_customers` as a standalone first-pass account filter; in short, run company_key_customers as a standalone first-pass. Do not combine `company_key_customers` with `company_website_search`, `company_icp`, `company_keywords`, or broad AI Attributes in the first call; inspect the account sample, then refine if needed.
|
|
106
|
+
- Do not use `AI`, `API`, `GTM`, or `SaaS` as company keyword terms. Use confirmed attributes such as `uses_ai` / `has_api`, or spell out `artificial intelligence`, `application programming interface`, `go to market`, and `software as a service`.
|
|
107
|
+
- Do not send `company_keywords.exclude` unless at least one include keyword is present.
|
|
108
|
+
- Do not duplicate `company_industry` when `company_icp.industries` already carries the industry.
|
|
109
|
+
- For post-confirm people search, prefer `person_job_title.boolean_search` for long role synonym lists instead of many `person_job_title.include` values plus broad department/seniority filters.
|
|
110
|
+
|
|
103
111
|
Unsupported/caveats:
|
|
104
112
|
|
|
105
113
|
- `company_intent` is unsupported by Prospeo public API.
|
|
@@ -234,10 +242,13 @@ Preference rules:
|
|
|
234
242
|
- If user input starts as company names, resolve names to domains first, then use `save_domain_filters`.
|
|
235
243
|
- Prefer comprehensive `person_job_title.include` lists (synonyms + role variants) for role precision.
|
|
236
244
|
- Use `person_department + person_seniority` as supporting constraints when title variance is expected.
|
|
245
|
+
- For long title synonym lists, prefer `person_job_title.boolean_search` with explicit OR terms instead of oversized include arrays.
|
|
237
246
|
- In security, AppSec, SOC, RevOps, Demand Gen, and similar function-specific lanes, do not rely on bare `Head` / `Director` / `VP` widening by itself. Pair seniority with explicit function keywords in `person_job_title` and verify the sample for off-function titles like `Head of Social Media`.
|
|
238
247
|
- Prefer `company_headcount_range` for most sizing; use `company_headcount_custom` for precise numeric bounds.
|
|
239
248
|
- Prefer `company_industry` before `company_keywords`; use keywords for refinement, not first-pass targeting.
|
|
240
249
|
- `company_keywords.include/exclude` values must be at least 3 characters; use `artificial intelligence` instead of `AI`, or use confirmed attributes such as `uses_ai` when that is the real signal.
|
|
250
|
+
- Do not use `AI`, `API`, `GTM`, or `SaaS` as company keyword terms; use longer phrases such as `artificial intelligence`, `application programming interface`, `go to market`, or `software as a service`.
|
|
251
|
+
- Run `company_key_customers` as a standalone first-pass filter. Do not combine `company_key_customers` with ICP, website-search, keyword, attribute, industry, or headcount filters until the standalone pass proves useful.
|
|
241
252
|
|
|
242
253
|
### Person Filters
|
|
243
254
|
|