@coldiq/mcp 0.3.12 → 0.3.14

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.
Files changed (119) hide show
  1. package/dist/client.d.ts.map +1 -1
  2. package/dist/client.js +6 -1
  3. package/dist/client.js.map +1 -1
  4. package/dist/tools/enrich-company.d.ts +3 -9
  5. package/dist/tools/enrich-company.d.ts.map +1 -1
  6. package/dist/tools/enrich-company.js +3 -16
  7. package/dist/tools/enrich-company.js.map +1 -1
  8. package/dist/tools/enrich-person.d.ts +3 -9
  9. package/dist/tools/enrich-person.d.ts.map +1 -1
  10. package/dist/tools/enrich-person.js +3 -12
  11. package/dist/tools/enrich-person.js.map +1 -1
  12. package/dist/tools/fetch-page-content.d.ts +3 -9
  13. package/dist/tools/fetch-page-content.d.ts.map +1 -1
  14. package/dist/tools/fetch-page-content.js +3 -12
  15. package/dist/tools/fetch-page-content.js.map +1 -1
  16. package/dist/tools/find-email.d.ts +3 -9
  17. package/dist/tools/find-email.d.ts.map +1 -1
  18. package/dist/tools/find-email.js +3 -40
  19. package/dist/tools/find-email.js.map +1 -1
  20. package/dist/tools/find-emails.d.ts +3 -4
  21. package/dist/tools/find-emails.d.ts.map +1 -1
  22. package/dist/tools/find-emails.js +8 -423
  23. package/dist/tools/find-emails.js.map +1 -1
  24. package/dist/tools/find-influencers.d.ts +3 -9
  25. package/dist/tools/find-influencers.d.ts.map +1 -1
  26. package/dist/tools/find-influencers.js +3 -12
  27. package/dist/tools/find-influencers.js.map +1 -1
  28. package/dist/tools/find-people.d.ts +3 -8
  29. package/dist/tools/find-people.d.ts.map +1 -1
  30. package/dist/tools/find-people.js +3 -98
  31. package/dist/tools/find-people.js.map +1 -1
  32. package/dist/tools/find-phone.d.ts +3 -9
  33. package/dist/tools/find-phone.d.ts.map +1 -1
  34. package/dist/tools/find-phone.js +4 -41
  35. package/dist/tools/find-phone.js.map +1 -1
  36. package/dist/tools/find-signals.d.ts +3 -9
  37. package/dist/tools/find-signals.d.ts.map +1 -1
  38. package/dist/tools/find-signals.js +3 -83
  39. package/dist/tools/find-signals.js.map +1 -1
  40. package/dist/tools/get-place-reviews.d.ts +3 -9
  41. package/dist/tools/get-place-reviews.d.ts.map +1 -1
  42. package/dist/tools/get-place-reviews.js +3 -12
  43. package/dist/tools/get-place-reviews.js.map +1 -1
  44. package/dist/tools/search-ads.d.ts +3 -9
  45. package/dist/tools/search-ads.d.ts.map +1 -1
  46. package/dist/tools/search-ads.js +3 -12
  47. package/dist/tools/search-ads.js.map +1 -1
  48. package/dist/tools/search-companies.d.ts +3 -9
  49. package/dist/tools/search-companies.d.ts.map +1 -1
  50. package/dist/tools/search-companies.js +3 -24
  51. package/dist/tools/search-companies.js.map +1 -1
  52. package/dist/tools/search-jobs.d.ts +3 -9
  53. package/dist/tools/search-jobs.d.ts.map +1 -1
  54. package/dist/tools/search-jobs.js +3 -27
  55. package/dist/tools/search-jobs.js.map +1 -1
  56. package/dist/tools/search-places.d.ts +3 -15
  57. package/dist/tools/search-places.d.ts.map +1 -1
  58. package/dist/tools/search-places.js +5 -76
  59. package/dist/tools/search-places.js.map +1 -1
  60. package/dist/tools/search-reddit.d.ts +3 -9
  61. package/dist/tools/search-reddit.d.ts.map +1 -1
  62. package/dist/tools/search-reddit.js +3 -12
  63. package/dist/tools/search-reddit.js.map +1 -1
  64. package/dist/tools/search-seo.d.ts +3 -9
  65. package/dist/tools/search-seo.d.ts.map +1 -1
  66. package/dist/tools/search-seo.js +3 -12
  67. package/dist/tools/search-seo.js.map +1 -1
  68. package/dist/tools/search-web.d.ts +3 -9
  69. package/dist/tools/search-web.d.ts.map +1 -1
  70. package/dist/tools/search-web.js +3 -12
  71. package/dist/tools/search-web.js.map +1 -1
  72. package/dist/tools/verify-email.d.ts +3 -10
  73. package/dist/tools/verify-email.d.ts.map +1 -1
  74. package/dist/tools/verify-email.js +3 -68
  75. package/dist/tools/verify-email.js.map +1 -1
  76. package/dist/verb-client.d.ts +35 -0
  77. package/dist/verb-client.d.ts.map +1 -0
  78. package/dist/verb-client.js +57 -0
  79. package/dist/verb-client.js.map +1 -0
  80. package/package.json +1 -1
  81. package/src/client.ts +6 -1
  82. package/src/tools/enrich-company.ts +3 -16
  83. package/src/tools/enrich-person.ts +3 -12
  84. package/src/tools/fetch-page-content.ts +3 -12
  85. package/src/tools/find-email.ts +3 -42
  86. package/src/tools/find-emails.ts +8 -506
  87. package/src/tools/find-influencers.ts +3 -12
  88. package/src/tools/find-people.ts +3 -107
  89. package/src/tools/find-phone.ts +4 -42
  90. package/src/tools/find-signals.ts +3 -88
  91. package/src/tools/get-place-reviews.ts +3 -12
  92. package/src/tools/search-ads.ts +3 -12
  93. package/src/tools/search-companies.ts +3 -23
  94. package/src/tools/search-jobs.ts +3 -30
  95. package/src/tools/search-places.ts +5 -72
  96. package/src/tools/search-reddit.ts +3 -12
  97. package/src/tools/search-seo.ts +3 -12
  98. package/src/tools/search-web.ts +3 -12
  99. package/src/tools/verify-email.ts +3 -76
  100. package/src/verb-client.ts +93 -0
  101. package/tests/verb-client.test.ts +152 -0
  102. package/tests/tools/enrich-company.test.ts +0 -92
  103. package/tests/tools/enrich-person.test.ts +0 -140
  104. package/tests/tools/fetch-page-content.test.ts +0 -108
  105. package/tests/tools/find-email.test.ts +0 -137
  106. package/tests/tools/find-emails.test.ts +0 -818
  107. package/tests/tools/find-influencers.test.ts +0 -91
  108. package/tests/tools/find-people.test.ts +0 -621
  109. package/tests/tools/find-phone.test.ts +0 -100
  110. package/tests/tools/find-signals.test.ts +0 -175
  111. package/tests/tools/get-place-reviews.test.ts +0 -73
  112. package/tests/tools/search-ads.test.ts +0 -182
  113. package/tests/tools/search-companies.test.ts +0 -192
  114. package/tests/tools/search-jobs.test.ts +0 -210
  115. package/tests/tools/search-places.test.ts +0 -210
  116. package/tests/tools/search-reddit.test.ts +0 -194
  117. package/tests/tools/search-seo.test.ts +0 -183
  118. package/tests/tools/search-web.test.ts +0 -79
  119. package/tests/tools/verify-email.test.ts +0 -142
@@ -0,0 +1,57 @@
1
+ import { callApi } from './client.js';
2
+ export async function callVerb(verbPath, input, opts) {
3
+ // 1. Rename any schema-drift field names before splitting the envelope.
4
+ let work = input;
5
+ if (opts?.remap) {
6
+ work = {};
7
+ for (const [k, v] of Object.entries(input)) {
8
+ work[opts.remap[k] ?? k] = v;
9
+ }
10
+ }
11
+ const { use_providers, fields, reveal, ...rest } = work;
12
+ // 2. Resolve the provider pin: explicit use_providers wins; otherwise a
13
+ // tool-specific provider field (e.g. search_places `provider`).
14
+ let providerPin = Array.isArray(use_providers) && use_providers.length ? use_providers : undefined;
15
+ if (opts?.providerFromField && rest[opts.providerFromField] !== undefined) {
16
+ const v = rest[opts.providerFromField];
17
+ delete rest[opts.providerFromField];
18
+ if (!providerPin && typeof v === 'string' && v)
19
+ providerPin = [v];
20
+ }
21
+ // 3. Build the envelope (single vs bulk).
22
+ let envelope;
23
+ let list;
24
+ if (opts?.bulkField) {
25
+ const { [opts.bulkField]: l, ...siblings } = rest;
26
+ list = Array.isArray(l) ? l : [];
27
+ envelope = { ...siblings, inputs: list };
28
+ }
29
+ else {
30
+ envelope = { input: rest };
31
+ }
32
+ if (providerPin)
33
+ envelope.provider = providerPin;
34
+ if (fields !== undefined)
35
+ envelope.fields = fields;
36
+ if (reveal !== undefined)
37
+ envelope.reveal = reveal;
38
+ const res = await callApi('POST', verbPath, envelope);
39
+ // 4. Re-attach the per-item correlation id to bulk results (positional).
40
+ let data = res.data;
41
+ if (opts?.reattachIdField && opts?.bulkField && list &&
42
+ data && typeof data === 'object' && Array.isArray(data.results)) {
43
+ const idField = opts.reattachIdField;
44
+ const results = data.results.map((r, i) => {
45
+ const id = list?.[i]?.[idField];
46
+ return id !== undefined && r && typeof r === 'object' && !Array.isArray(r)
47
+ ? { [idField]: id, ...r }
48
+ : r;
49
+ });
50
+ data = { ...data, results };
51
+ }
52
+ return {
53
+ content: [{ type: 'text', text: JSON.stringify(data) }],
54
+ isError: !res.ok,
55
+ };
56
+ }
57
+ //# sourceMappingURL=verb-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verb-client.js","sourceRoot":"","sources":["../src/verb-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coldiq/mcp",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/client.ts CHANGED
@@ -16,7 +16,12 @@ let _httpTimeoutMs: number
16
16
  export function initClient(apiUrl?: string, apiKey?: string): void {
17
17
  _apiUrl = apiUrl ?? process.env.COLDIQ_API_URL ?? 'https://api.coldiq.com'
18
18
  _apiKey = apiKey ?? process.env.COLDIQ_API_KEY ?? ''
19
- _httpTimeoutMs = parseInt(process.env.COLDIQ_HTTP_TIMEOUT_MS ?? '30000', 10)
19
+ // Default 120s: each tool now makes ONE call that runs the FULL provider
20
+ // waterfall server-side, and async-tier verbs (find_people via LeadsFactory,
21
+ // search_jobs/places, etc.) routinely take 20-90s. The old 30s default — fine
22
+ // when the waterfall ran locally with per-provider budgets — times out those
23
+ // verbs intermittently. Override with COLDIQ_HTTP_TIMEOUT_MS.
24
+ _httpTimeoutMs = parseInt(process.env.COLDIQ_HTTP_TIMEOUT_MS ?? '120000', 10)
20
25
  if (!_apiKey) {
21
26
  throw new Error('COLDIQ_API_KEY is required — set it in .mcp.json env or as an environment variable')
22
27
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
- import { executeWithFallback, isExecutionError } from '../executor.js'
3
- import { resolvePreferredProviders, getProvidersForCapability } from '../utils/provider-resolver.js'
2
+ import { callVerb } from '../verb-client.js'
3
+ import { getProvidersForCapability } from '../utils/provider-resolver.js'
4
4
 
5
5
  export const enrichCompanyName = 'enrich_company'
6
6
 
@@ -15,18 +15,5 @@ export const enrichCompanySchema = {
15
15
  }
16
16
 
17
17
  export async function enrichCompanyHandler(input: Record<string, unknown>) {
18
- const { use_providers: rawUseProviders, ...restInput } = input
19
- if (!restInput.domain && !restInput.linkedin_url && !restInput.name) {
20
- const err = { error: 'At least one of domain, linkedin_url, or name is required', providers_tried: [] }
21
- return { content: [{ type: 'text' as const, text: JSON.stringify(err) }], isError: true }
22
- }
23
- const resolved = resolvePreferredProviders('enrich_company', restInput, rawUseProviders)
24
- if (!resolved.ok) {
25
- return { content: [{ type: 'text' as const, text: JSON.stringify(resolved.error) }], isError: true }
26
- }
27
- const result = await executeWithFallback('enrich_company', restInput, { providers: resolved.providers, matchedFrom: resolved.matchedFrom })
28
- if (isExecutionError(result)) {
29
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }], isError: true }
30
- }
31
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] }
18
+ return callVerb('/company/enrich', input)
32
19
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
- import { executeWithFallback, isExecutionError } from '../executor.js'
3
- import { resolvePreferredProviders, getProvidersForCapability } from '../utils/provider-resolver.js'
2
+ import { callVerb } from '../verb-client.js'
3
+ import { getProvidersForCapability } from '../utils/provider-resolver.js'
4
4
 
5
5
  export const enrichPersonName = 'enrich_person'
6
6
 
@@ -22,14 +22,5 @@ export const enrichPersonSchema = {
22
22
  }
23
23
 
24
24
  export async function enrichPersonHandler(input: Record<string, unknown>) {
25
- const { use_providers: rawUseProviders, ...restInput } = input
26
- const resolved = resolvePreferredProviders('enrich_person', restInput, rawUseProviders)
27
- if (!resolved.ok) {
28
- return { content: [{ type: 'text' as const, text: JSON.stringify(resolved.error) }], isError: true }
29
- }
30
- const result = await executeWithFallback('enrich_person', restInput, { providers: resolved.providers, matchedFrom: resolved.matchedFrom })
31
- if (isExecutionError(result)) {
32
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }], isError: true }
33
- }
34
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] }
25
+ return callVerb('/person/enrich', input)
35
26
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
- import { executeWithFallback, isExecutionError } from '../executor.js'
3
- import { resolvePreferredProviders, getProvidersForCapability } from '../utils/provider-resolver.js'
2
+ import { callVerb } from '../verb-client.js'
3
+ import { getProvidersForCapability } from '../utils/provider-resolver.js'
4
4
 
5
5
  export const fetchPageContentName = 'fetch_page_content'
6
6
 
@@ -30,14 +30,5 @@ export const fetchPageContentSchema = {
30
30
  }
31
31
 
32
32
  export async function fetchPageContentHandler(input: Record<string, unknown>) {
33
- const { use_providers: rawUseProviders, ...restInput } = input
34
- const resolved = resolvePreferredProviders('fetch_page_content', restInput, rawUseProviders)
35
- if (!resolved.ok) {
36
- return { content: [{ type: 'text' as const, text: JSON.stringify(resolved.error) }], isError: true }
37
- }
38
- const result = await executeWithFallback('fetch_page_content', restInput, { providers: resolved.providers, matchedFrom: resolved.matchedFrom })
39
- if (isExecutionError(result)) {
40
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }], isError: true }
41
- }
42
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] }
33
+ return callVerb('/web/fetch', input)
43
34
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
- import { executeWithFallback, isExecutionError } from '../executor.js'
3
- import { resolvePreferredProviders, getProvidersForCapability } from '../utils/provider-resolver.js'
2
+ import { callVerb } from '../verb-client.js'
3
+ import { getProvidersForCapability } from '../utils/provider-resolver.js'
4
4
 
5
5
  export const findEmailName = 'find_email'
6
6
 
@@ -19,45 +19,6 @@ export const findEmailSchema = {
19
19
  use_providers: z.array(z.string()).optional().describe(`Optional ordered list of providers to use. Leave empty to let ColdIQ automatically pick the best tool for your inputs — recommended for most use cases. Available providers: ${getProvidersForCapability('find_email').join(', ')}. Provider names are matched fuzzily, so minor typos are tolerated.`),
20
20
  }
21
21
 
22
- const inputSchema = z
23
- .object({
24
- first_name: z.string().optional(),
25
- last_name: z.string().optional(),
26
- domain: z.string().optional(),
27
- company_name: z.string().optional(),
28
- linkedin_url: z.string().optional(),
29
- })
30
- .superRefine((val, ctx) => {
31
- const hasLinkedIn = typeof val.linkedin_url === 'string' && val.linkedin_url.length > 0
32
- const hasName = typeof val.first_name === 'string' && val.first_name.length > 0
33
- const hasDomain =
34
- (typeof val.domain === 'string' && val.domain.length > 0) ||
35
- (typeof val.company_name === 'string' && val.company_name.length > 0)
36
- if (!hasLinkedIn && !(hasName && hasDomain)) {
37
- ctx.addIssue({
38
- code: 'custom',
39
- message: 'Provide either linkedin_url or both first_name and domain/company_name',
40
- })
41
- }
42
- })
43
-
44
22
  export async function findEmailHandler(input: Record<string, unknown>) {
45
- const { use_providers: rawUseProviders, ...restInput } = input
46
- const resolved = resolvePreferredProviders('find_email', restInput, rawUseProviders)
47
- if (!resolved.ok) {
48
- return { content: [{ type: 'text' as const, text: JSON.stringify(resolved.error) }], isError: true }
49
- }
50
- const validation = inputSchema.safeParse(restInput)
51
- if (!validation.success) {
52
- const msg = validation.error.issues.map((i) => i.message).join('; ')
53
- return {
54
- content: [{ type: 'text' as const, text: JSON.stringify({ error: msg }) }],
55
- isError: true,
56
- }
57
- }
58
- const result = await executeWithFallback('find_email', restInput, { providers: resolved.providers, matchedFrom: resolved.matchedFrom })
59
- if (isExecutionError(result)) {
60
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }], isError: true }
61
- }
62
- return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] }
23
+ return callVerb('/email/find', input)
63
24
  }