@breaknorm_hu/mcp-server 0.2.0 → 1.0.0
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/index.js +91 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -59,6 +59,56 @@ function str(val) {
|
|
|
59
59
|
return String(val);
|
|
60
60
|
}
|
|
61
61
|
var tools = [
|
|
62
|
+
// ── PRIMARY TOOL — use this for everything ──
|
|
63
|
+
{
|
|
64
|
+
name: "find_leads",
|
|
65
|
+
description: "THE main tool. Finds leads (contacts + company data) in one call. Accepts natural language industry description \u2014 no need to call suggest_industry_codes first! Can also include cost estimate for reveals. Request up to 500 results at once.",
|
|
66
|
+
schema: z.object({
|
|
67
|
+
industryDescription: z.string().optional().describe("Natural language: e.g. 'marketing \xFCgyn\xF6ks\xE9gek', 'IT szolg\xE1ltat\xF3k'. Server converts to NAICS codes automatically."),
|
|
68
|
+
naicsCodes: z.array(z.string()).optional().describe("If you already have NAICS codes from a previous call, pass them here to skip AI generation"),
|
|
69
|
+
q: z.string().optional().describe("Free text search (name, title, company)"),
|
|
70
|
+
title: z.string().optional().describe("Job title keyword: '\xFCgyvezet\u0151', 'CEO', 'igazgat\xF3'"),
|
|
71
|
+
seniority: z.array(z.string()).optional().describe("c_level, vp, director, manager, head, senior, founder, partner, managing_director"),
|
|
72
|
+
department: z.array(z.string()).optional().describe("sales, marketing, it, hr, finance, engineering, c_suite"),
|
|
73
|
+
city: z.array(z.string()).optional().describe("City names"),
|
|
74
|
+
employee_min: z.number().int().optional().describe("Min company employees"),
|
|
75
|
+
employee_max: z.number().int().optional().describe("Max company employees"),
|
|
76
|
+
revenue_min: z.number().optional().describe("Min annual revenue HUF"),
|
|
77
|
+
revenue_max: z.number().optional().describe("Max annual revenue HUF"),
|
|
78
|
+
has_email: z.enum(["yes", "maybe", "no"]).optional().describe("Email availability filter"),
|
|
79
|
+
has_phone: z.enum(["yes", "maybe", "no"]).optional(),
|
|
80
|
+
includeEstimate: z.boolean().default(true).optional().describe("Include reveal cost estimate in response (default: true)"),
|
|
81
|
+
revealType: z.enum(["email", "phone", "all"]).default("email").optional().describe("For estimate: what to reveal"),
|
|
82
|
+
limit: z.number().int().min(1).max(500).default(100).optional().describe("Results to return (max 500, default 100)"),
|
|
83
|
+
page: z.number().int().default(1).optional(),
|
|
84
|
+
searchToken: z.string().optional().describe("For page 2+, from previous response")
|
|
85
|
+
}),
|
|
86
|
+
handler: async (client, args) => {
|
|
87
|
+
const result = await client.post("/leads/find", {
|
|
88
|
+
industryDescription: args.industryDescription,
|
|
89
|
+
naicsCodes: args.naicsCodes,
|
|
90
|
+
q: args.q,
|
|
91
|
+
title: args.title,
|
|
92
|
+
seniority: args.seniority,
|
|
93
|
+
department: args.department,
|
|
94
|
+
city: args.city,
|
|
95
|
+
employee_min: args.employee_min,
|
|
96
|
+
employee_max: args.employee_max,
|
|
97
|
+
revenue_min: args.revenue_min,
|
|
98
|
+
revenue_max: args.revenue_max,
|
|
99
|
+
has_email: args.has_email,
|
|
100
|
+
has_phone: args.has_phone,
|
|
101
|
+
includeEstimate: args.includeEstimate ?? true,
|
|
102
|
+
revealType: args.revealType || "email",
|
|
103
|
+
limit: args.limit || 100,
|
|
104
|
+
page: args.page || 1,
|
|
105
|
+
searchToken: args.searchToken
|
|
106
|
+
});
|
|
107
|
+
const d = result.data;
|
|
108
|
+
return d;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
// ── ADVANCED: direct search (for pagination with existing NAICS codes) ──
|
|
62
112
|
{
|
|
63
113
|
name: "search_leads",
|
|
64
114
|
description: "Search for leads (contacts + company data in one result). This is THE main search tool. Returns contacts with their company info. Use suggest_industry_codes FIRST to get NAICS codes, then pass them here. You can request up to 500 results at once (no need to paginate for small queries). NEVER search by company name one by one!",
|
|
@@ -85,7 +135,7 @@ var tools = [
|
|
|
85
135
|
searchToken: z.string().optional().describe("Required for page 2+, from page 1 response")
|
|
86
136
|
}),
|
|
87
137
|
handler: async (client, args) => {
|
|
88
|
-
|
|
138
|
+
const result = await client.get("/leads/search", {
|
|
89
139
|
q: str(args.q),
|
|
90
140
|
naicsCodes: arrayParam(args.naicsCodes),
|
|
91
141
|
industry: arrayParam(args.industry),
|
|
@@ -107,6 +157,28 @@ var tools = [
|
|
|
107
157
|
page: str(args.page),
|
|
108
158
|
searchToken: str(args.searchToken)
|
|
109
159
|
});
|
|
160
|
+
const r = result;
|
|
161
|
+
const leads = (r.data || []).map((lead) => ({
|
|
162
|
+
id: lead.id,
|
|
163
|
+
name: `${lead.firstName} ${lead.lastName}`,
|
|
164
|
+
title: lead.title,
|
|
165
|
+
seniority: lead.seniority,
|
|
166
|
+
email: lead.revealedEmail || (lead.hasEmail ? "available" : null),
|
|
167
|
+
phone: lead.revealedPhone || (lead.hasPhone ? "available" : null),
|
|
168
|
+
company: lead.companyName,
|
|
169
|
+
companyId: lead.companyId,
|
|
170
|
+
industry: lead.industry,
|
|
171
|
+
city: lead.city,
|
|
172
|
+
employees: lead.employeeCount,
|
|
173
|
+
revenue: lead.annualRevenue
|
|
174
|
+
}));
|
|
175
|
+
return {
|
|
176
|
+
leads,
|
|
177
|
+
total: r.pagination?.total,
|
|
178
|
+
page: r.pagination?.page,
|
|
179
|
+
hasMore: r.pagination?.hasMore,
|
|
180
|
+
searchToken: r.pagination?.searchToken
|
|
181
|
+
};
|
|
110
182
|
}
|
|
111
183
|
},
|
|
112
184
|
{
|
|
@@ -288,33 +360,27 @@ var SERVER_NAME = "breaknorm";
|
|
|
288
360
|
var SERVER_VERSION = "0.1.0";
|
|
289
361
|
var INSTRUCTIONS = `Breaknorm MCP Server \u2014 B2B contact database for the Hungarian market.
|
|
290
362
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
2. NEVER search by company name one by one! Use filters:
|
|
297
|
-
Wrong: search_leads(q: "Company A"), search_leads(q: "Company B"), ...
|
|
298
|
-
Right: suggest_industry_codes("marketing") \u2192 search_leads(naicsCodes: [...], seniority: ["c_level"], limit: 200)
|
|
363
|
+
USE find_leads FOR EVERYTHING. It does everything in ONE call:
|
|
364
|
+
- Converts industry description to NAICS codes automatically (no need for separate calls)
|
|
365
|
+
- Searches contacts WITH company data
|
|
366
|
+
- Includes cost estimate for reveals
|
|
367
|
+
- Returns up to 500 results at once
|
|
299
368
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
369
|
+
WORKFLOW (only 2 steps!):
|
|
370
|
+
1. find_leads(industryDescription: "marketing \xFCgyn\xF6ks\xE9gek", seniority: ["c_level"], has_email: "yes", limit: 100, includeEstimate: true)
|
|
371
|
+
\u2192 Returns leads + cost estimate in ONE call
|
|
372
|
+
2. User approves \u2192 bulk_reveal_contacts(contactIds: [...], type: "email")
|
|
373
|
+
\u2192 Done!
|
|
304
374
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
b. suggest_industry_codes \u2014 get NAICS codes (ONCE!)
|
|
308
|
-
c. search_leads \u2014 find leads with all filters, up to 500 at once
|
|
309
|
-
d. estimate_cost \u2014 calculate reveal cost
|
|
310
|
-
e. [Wait for user approval of the cost]
|
|
311
|
-
f. bulk_reveal_contacts \u2014 get emails (up to 1000 at once)
|
|
312
|
-
g. create_list + add_contacts_to_list \u2014 organize
|
|
313
|
-
h. export_list \u2014 CSV export
|
|
375
|
+
For page 2+: use the naicsCodesUsed + searchToken from the first response.
|
|
376
|
+
Pass naicsCodes instead of industryDescription to skip AI generation on subsequent pages.
|
|
314
377
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
378
|
+
RULES:
|
|
379
|
+
- NEVER search by company name one by one
|
|
380
|
+
- find_leads handles NAICS generation internally \u2014 don't call suggest_industry_codes separately
|
|
381
|
+
- Always includeEstimate: true so you can show the cost to the user
|
|
382
|
+
- Before reveal, ALWAYS show the cost and ask for user approval
|
|
383
|
+
- Credit costs: email=1, phone=10, both=11 per contact`;
|
|
318
384
|
async function main() {
|
|
319
385
|
const apiKey = process.env.BREAKNORM_API_KEY;
|
|
320
386
|
if (!apiKey) {
|