@breaknorm_hu/mcp-server 0.1.3 → 0.1.4

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 (2) hide show
  1. package/dist/index.js +47 -27
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -61,13 +61,14 @@ function str(val) {
61
61
  var tools = [
62
62
  {
63
63
  name: "search_contacts",
64
- description: "Search the Breaknorm contact database. Returns contacts matching filters. Use get_search_filters first to discover available filter values. Results paginated (max 25/page). For page 2+, pass searchToken from page 1.",
64
+ description: "Search contacts with filters. Use suggest_industry_codes FIRST to convert industry descriptions to NAICS codes, then pass them here. NEVER search by company name one by one \u2014 always use filters to get bulk results!",
65
65
  schema: z.object({
66
66
  q: z.string().optional().describe("Free text search (name, title, company)"),
67
67
  industry: z.array(z.string()).optional().describe("Filter by industry names"),
68
+ naicsCodes: z.array(z.string()).optional().describe("NAICS codes from suggest_industry_codes \u2014 THIS IS THE BEST WAY TO FILTER BY INDUSTRY"),
68
69
  city: z.array(z.string()).optional().describe("Filter by city names"),
69
- seniority: z.array(z.string()).optional().describe("Filter by seniority: c_level, vp, director, manager, head, senior, founder, partner"),
70
- department: z.array(z.string()).optional().describe("Filter by department: sales, marketing, it, hr, finance, engineering, c_suite"),
70
+ seniority: z.array(z.string()).optional().describe("c_level, vp, director, manager, head, senior, founder, partner"),
71
+ department: z.array(z.string()).optional().describe("sales, marketing, it, hr, finance, engineering, c_suite"),
71
72
  employee_min: z.number().int().optional().describe("Min company employees"),
72
73
  employee_max: z.number().int().optional().describe("Max company employees"),
73
74
  has_email: z.enum(["yes", "maybe", "no"]).optional().describe("Filter by email availability"),
@@ -79,6 +80,7 @@ var tools = [
79
80
  return client.get("/contacts/search", {
80
81
  q: str(args.q),
81
82
  industry: arrayParam(args.industry),
83
+ naicsCodes: arrayParam(args.naicsCodes),
82
84
  city: arrayParam(args.city),
83
85
  seniority: arrayParam(args.seniority),
84
86
  department: arrayParam(args.department),
@@ -93,10 +95,11 @@ var tools = [
93
95
  },
94
96
  {
95
97
  name: "search_companies",
96
- description: "Search companies in the Breaknorm database.",
98
+ description: "Search companies with filters. Use suggest_industry_codes FIRST for industry filtering. NEVER search one by one \u2014 use filters!",
97
99
  schema: z.object({
98
100
  q: z.string().optional().describe("Company name search"),
99
101
  industry: z.array(z.string()).optional(),
102
+ naicsCodes: z.array(z.string()).optional().describe("NAICS codes from suggest_industry_codes \u2014 BEST way to filter by industry"),
100
103
  city: z.array(z.string()).optional(),
101
104
  employee_min: z.number().int().optional(),
102
105
  employee_max: z.number().int().optional(),
@@ -110,6 +113,7 @@ var tools = [
110
113
  return client.get("/companies/search", {
111
114
  q: str(args.q),
112
115
  industry: arrayParam(args.industry),
116
+ naicsCodes: arrayParam(args.naicsCodes),
113
117
  city: arrayParam(args.city),
114
118
  employee_min: str(args.employee_min),
115
119
  employee_max: str(args.employee_max),
@@ -150,6 +154,21 @@ var tools = [
150
154
  return { data: trimmed };
151
155
  }
152
156
  },
157
+ {
158
+ name: "suggest_industry_codes",
159
+ description: "IMPORTANT: Use this BEFORE searching by industry. Converts a natural language industry description (e.g. 'marketing \xFCgyn\xF6ks\xE9gek', 'IT szolg\xE1ltat\xF3k') into NAICS codes that the search endpoints understand. Pass the returned codes as the naicsCodes parameter in search_contacts or search_companies. This is how industry filtering works \u2014 do NOT search by company name one by one!",
160
+ schema: z.object({
161
+ description: z.string().describe("Industry description in natural language, e.g. 'rekl\xE1m \xE9s m\xE9dia \xFCgyn\xF6ks\xE9gek' or 'IT consulting'"),
162
+ precision: z.enum(["strict", "balanced", "broad"]).default("balanced").optional().describe("strict = exact match, balanced = recommended, broad = wider results")
163
+ }),
164
+ handler: async (client, args) => {
165
+ const result = await client.post("/search/naics-suggest", {
166
+ description: args.description,
167
+ precision: args.precision || "balanced"
168
+ });
169
+ return result;
170
+ }
171
+ },
153
172
  {
154
173
  name: "get_contact",
155
174
  description: "Get details of a single contact (public fields, no revealed data).",
@@ -286,33 +305,34 @@ var SERVER_NAME = "breaknorm";
286
305
  var SERVER_VERSION = "0.1.0";
287
306
  var INSTRUCTIONS = `Breaknorm MCP Server \u2014 B2B contact database for the Hungarian market.
288
307
 
289
- IMPORTANT RULES:
290
- 1. Before ANY paid operation (reveal_contact, bulk_reveal_contacts, score_companies),
291
- ALWAYS call estimate_cost first and present the cost to the user for approval.
292
- Never execute paid operations without explicit user confirmation.
308
+ CRITICAL RULES \u2014 READ CAREFULLY:
309
+
310
+ 1. NEVER search by company name one by one! ALWAYS use filters to get bulk results.
311
+ Wrong: search_contacts(q: "Company A"), search_contacts(q: "Company B"), ...
312
+ Right: suggest_industry_codes("marketing \xFCgyn\xF6ks\xE9gek") \u2192 search_contacts(naicsCodes: [...], seniority: ["c_level"])
293
313
 
294
- 2. Recommended workflow for building a lead list:
295
- a. get_credits \u2014 check current balance
296
- b. get_search_filters \u2014 discover available filter values
297
- c. search_companies \u2014 find target companies matching criteria
298
- d. search_contacts \u2014 find people at those companies
299
- e. estimate_cost \u2014 calculate total cost for reveals
300
- f. [Wait for user approval of the cost]
301
- g. bulk_reveal_contacts \u2014 get email/phone data
302
- h. create_list + add_contacts_to_list \u2014 organize results
303
- i. export_list \u2014 export as CSV if needed
314
+ 2. INDUSTRY SEARCH WORKFLOW \u2014 this is how it works:
315
+ a. suggest_industry_codes("rekl\xE1m \xE9s m\xE9dia \xFCgyn\xF6ks\xE9gek") \u2192 returns NAICS codes
316
+ b. search_companies(naicsCodes: [codes from step a], employee_min: 5) \u2192 returns ALL matching companies at once
317
+ c. search_contacts(naicsCodes: [same codes], seniority: ["c_level", "director"]) \u2192 returns ALL decision-makers at once
318
+ This gives you hundreds of results in 2-3 API calls instead of searching one by one!
304
319
 
305
- 3. Credit costs:
306
- - Email reveal: 1 credit per contact
307
- - Phone reveal: 10 credits per contact
308
- - Both (email + phone): 11 credits per contact
309
- - ICP company scoring: 1 credit per company
320
+ 3. Before ANY paid operation (reveal, scoring), call estimate_cost first and get user approval.
310
321
 
311
- 4. Search results are paginated (max 25 per page). For page 2+,
312
- you must pass the searchToken from the page 1 response.
322
+ 4. Recommended workflow for building a lead list:
323
+ a. get_credits \u2014 check balance
324
+ b. suggest_industry_codes \u2014 convert industry description to NAICS codes
325
+ c. search_companies \u2014 find companies with naicsCodes + size + location filters
326
+ d. search_contacts \u2014 find decision-makers with naicsCodes + seniority + department filters
327
+ e. estimate_cost \u2014 calculate cost
328
+ f. [Wait for user approval]
329
+ g. bulk_reveal_contacts \u2014 get emails (up to 1000 at once!)
330
+ h. create_list + add_contacts_to_list \u2014 organize
331
+ i. export_list \u2014 CSV export
313
332
 
314
- 5. Bulk operations (reveal, ICP scoring) are async. They return a jobId.
315
- Use check_job_status to poll for completion.`;
333
+ 5. Credit costs: email=1, phone=10, both=11, ICP scoring=1 per company
334
+ 6. Search is FREE and paginated (25/page). Use searchToken for page 2+.
335
+ 7. Bulk operations are async \u2014 poll with check_job_status.`;
316
336
  async function main() {
317
337
  const apiKey = process.env.BREAKNORM_API_KEY;
318
338
  if (!apiKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@breaknorm_hu/mcp-server",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Breaknorm MCP Server — AI agent interface for B2B contact database",
5
5
  "type": "module",
6
6
  "bin": {