mcp-server-andru-intelligence 1.0.0 → 1.1.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.
Files changed (3) hide show
  1. package/package.json +4 -3
  2. package/src/catalog.js +114 -1
  3. package/src/cli.js +202 -0
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "mcp-server-andru-intelligence",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "mcpName": "io.github.geter-andru/andru-intelligence",
5
- "description": "Buyer intelligence for technical founders who sell to enterprises — know who to target, what to say, and when to walk away. 15 MCP tools: ICP scoring, persona lookup, battlecards, deal classification, prospect discovery.",
5
+ "description": "Buyer intelligence for technical founders who sell to enterprises — know who to target, what to say, and when to walk away. 19 MCP tools + CLI: ICP scoring, persona simulation, battlecards, deal classification, prospect discovery, sales hiring, investor matching, founder wellness.",
6
6
  "type": "module",
7
7
  "bin": {
8
- "andru-mcp": "./src/index.js"
8
+ "andru-mcp": "./src/index.js",
9
+ "andru-intel": "./src/cli.js"
9
10
  },
10
11
  "main": "./src/index.js",
11
12
  "keywords": [
package/src/catalog.js CHANGED
@@ -30,7 +30,7 @@ const COLD_START_PARAMS = {
30
30
  },
31
31
  };
32
32
 
33
- // ── 15 Tools ────────────────────────────────────────────────────────────────
33
+ // ── 19 Tools ────────────────────────────────────────────────────────────────
34
34
 
35
35
  export const tools = [
36
36
  {
@@ -372,6 +372,119 @@ export const tools = [
372
372
  required: ['companies'],
373
373
  },
374
374
  },
375
+
376
+ {
377
+ name: 'get_sales_blueprint',
378
+ description: 'Builds everything you need to make your first sales hire — job description, comp structure, interview questions that actually reveal sales ability, 90-day ramp plan, and weekly activity targets tied to your ARR goal.',
379
+ inputSchema: {
380
+ type: 'object',
381
+ properties: {
382
+ companyStage: {
383
+ type: 'string',
384
+ enum: ['Pre-Seed', 'Seed', 'Series A', 'Series B'],
385
+ description: 'Current funding stage. Infer from conversation context if the user has mentioned it.',
386
+ },
387
+ arrTarget: {
388
+ type: 'string',
389
+ description: 'Annual recurring revenue target (e.g., "$2M", "$5M", "$10M"). Ask the user if not mentioned.',
390
+ },
391
+ dealSize: {
392
+ type: 'string',
393
+ description: 'Average deal size (e.g., "$15K ACV", "$50K ACV"). Infer from context or ask.',
394
+ },
395
+ avgCycleLength: {
396
+ type: 'string',
397
+ description: 'Average sales cycle length (e.g., "30 days", "60 days", "90+ days"). Infer or ask.',
398
+ },
399
+ teamSize: {
400
+ type: 'number',
401
+ description: 'Current team size. Infer from context if mentioned.',
402
+ },
403
+ },
404
+ required: ['companyStage', 'arrTarget'],
405
+ },
406
+ },
407
+
408
+ {
409
+ name: 'get_thesis_match',
410
+ description: 'Finds the 5 VCs whose investment thesis best matches your company — scores each on fit, explains why they\'d be interested, and tells you how to approach them. Saves weeks of investor research.',
411
+ inputSchema: {
412
+ type: 'object',
413
+ properties: {
414
+ productDescription: {
415
+ type: 'string',
416
+ description: 'What the company does and who it serves. Infer from conversation context if the user has already described their product.',
417
+ },
418
+ stage: {
419
+ type: 'string',
420
+ enum: ['Pre-Seed', 'Seed', 'Series A', 'Series B', 'Series C+'],
421
+ description: 'Current funding stage. Infer from context if mentioned.',
422
+ },
423
+ arrRange: {
424
+ type: 'string',
425
+ description: 'Current ARR range (e.g., "$0-$500K", "$500K-$2M", "$2M-$10M"). Infer or ask.',
426
+ },
427
+ vertical: {
428
+ type: 'string',
429
+ description: 'Industry vertical (e.g., "AI/ML", "FinTech", "HealthTech", "SaaS"). Infer from product description.',
430
+ },
431
+ },
432
+ required: ['productDescription', 'stage'],
433
+ },
434
+ },
435
+
436
+ {
437
+ name: 'get_founder_wellness',
438
+ description: 'Checks if you\'re burning out before you notice — tracks consecutive work days, late nights, and meeting density, then gives you a risk score and specific recovery actions. Because the founder who crashes can\'t close deals.',
439
+ inputSchema: {
440
+ type: 'object',
441
+ properties: {
442
+ userId: {
443
+ type: 'string',
444
+ description: 'The user\'s Andru account ID. Required for personalized wellness tracking.',
445
+ },
446
+ mode: {
447
+ type: 'string',
448
+ enum: ['assessment', 'dashboard'],
449
+ description: 'assessment = burnout risk score + recommendations. dashboard = full wellness data. Default: assessment.',
450
+ },
451
+ },
452
+ },
453
+ },
454
+
455
+ {
456
+ name: 'simulate_buyer_persona',
457
+ description: 'Practice your pitch against a realistic buyer — pick a CFO, CTO, COO, VP Sales, or VP Engineering and get their opening challenge. They\'ll push back the way real buyers do, so you can sharpen your story before the actual meeting.',
458
+ inputSchema: {
459
+ type: 'object',
460
+ properties: {
461
+ persona: {
462
+ type: 'string',
463
+ enum: ['CFO', 'CTO', 'COO', 'VP Sales', 'VP Engineering'],
464
+ description: 'Which buyer to simulate. Pick based on who the user is preparing to meet.',
465
+ },
466
+ stageId: {
467
+ type: 'number',
468
+ enum: [0, 1, 2, 3, 4, 5, 6, 7],
469
+ description: 'Buyer journey stage (0=Unaware through 7=Advocating). Default: 3.',
470
+ },
471
+ productDescription: {
472
+ type: 'string',
473
+ description: 'What the user\'s product does. Infer from conversation context.',
474
+ },
475
+ productName: {
476
+ type: 'string',
477
+ description: 'Product name. Infer from context.',
478
+ },
479
+ mode: {
480
+ type: 'string',
481
+ enum: ['opening', 'list'],
482
+ description: 'opening = buyer\'s opening message. list = available personas. Default: opening.',
483
+ },
484
+ },
485
+ required: ['persona'],
486
+ },
487
+ },
375
488
  ];
376
489
 
377
490
  // ── 3 Resources ─────────────────────────────────────────────────────────────
package/src/cli.js ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Andru Intelligence CLI
5
+ *
6
+ * Direct command-line access to all 19 Andru intelligence tools.
7
+ * Works from any terminal — Claude Code, Cursor, Codex, plain shell.
8
+ *
9
+ * Usage:
10
+ * npx andru-intel <tool-name> [--param value ...]
11
+ * npx andru-intel list
12
+ * npx andru-intel help <tool-name>
13
+ *
14
+ * Examples:
15
+ * npx andru-intel get_thesis_match --productDescription "AI sales platform" --stage "Series A"
16
+ * npx andru-intel simulate_buyer_persona --persona CFO --productDescription "DevOps automation"
17
+ * npx andru-intel get_sales_blueprint --companyStage "Series A" --arrTarget "$5M"
18
+ * npx andru-intel get_icp_fit_score --companyName "Acme Corp" --industry "SaaS"
19
+ *
20
+ * Environment:
21
+ * ANDRU_API_KEY (required) — Your Andru Platform API key
22
+ * ANDRU_API_URL (optional) — API base URL (default: https://api.andru.ai)
23
+ */
24
+
25
+ import { tools } from './catalog.js';
26
+ import { AndruClient } from './client.js';
27
+
28
+ function printUsage() {
29
+ console.log(`
30
+ andru-intel — Buyer intelligence from your terminal
31
+
32
+ Usage:
33
+ andru-intel <tool-name> [--param value ...]
34
+ andru-intel list Show all available tools
35
+ andru-intel help <tool-name> Show tool parameters
36
+
37
+ Examples:
38
+ andru-intel get_thesis_match --productDescription "AI sales platform" --stage "Series A"
39
+ andru-intel simulate_buyer_persona --persona CFO
40
+ andru-intel get_sales_blueprint --companyStage "Series A" --arrTarget "$5M"
41
+
42
+ Environment:
43
+ ANDRU_API_KEY Your API key (get one at https://app.andru.ai/settings/api-keys)
44
+ ANDRU_API_URL API endpoint (default: https://api.andru.ai)
45
+
46
+ ${tools.length} tools available. Run 'andru-intel list' to see them all.
47
+ `);
48
+ }
49
+
50
+ function printToolList() {
51
+ console.log(`\n${tools.length} Andru Intelligence Tools:\n`);
52
+ const maxName = Math.max(...tools.map(t => t.name.length));
53
+ for (const tool of tools) {
54
+ const name = tool.name.padEnd(maxName + 2);
55
+ // Truncate description to fit terminal
56
+ const desc = tool.description.length > 80
57
+ ? tool.description.slice(0, 77) + '...'
58
+ : tool.description;
59
+ console.log(` ${name}${desc}`);
60
+ }
61
+ console.log(`\nRun 'andru-intel help <tool-name>' for parameters.\n`);
62
+ }
63
+
64
+ function printToolHelp(toolName) {
65
+ const tool = tools.find(t => t.name === toolName);
66
+ if (!tool) {
67
+ console.error(`Unknown tool: ${toolName}`);
68
+ console.error(`Run 'andru-intel list' to see available tools.`);
69
+ process.exit(1);
70
+ }
71
+
72
+ console.log(`\n${tool.name}`);
73
+ console.log(`${'─'.repeat(tool.name.length)}`);
74
+ console.log(tool.description);
75
+
76
+ const props = tool.inputSchema?.properties || {};
77
+ const required = new Set(tool.inputSchema?.required || []);
78
+
79
+ if (Object.keys(props).length > 0) {
80
+ console.log(`\nParameters:`);
81
+ for (const [name, schema] of Object.entries(props)) {
82
+ const req = required.has(name) ? ' (required)' : '';
83
+ const type = schema.enum ? schema.enum.join(' | ') : schema.type;
84
+ console.log(` --${name} [${type}]${req}`);
85
+ if (schema.description) {
86
+ // Indent description, truncate long ones
87
+ const desc = schema.description.length > 100
88
+ ? schema.description.slice(0, 97) + '...'
89
+ : schema.description;
90
+ console.log(` ${desc}`);
91
+ }
92
+ }
93
+ }
94
+
95
+ console.log(`\nExample:`);
96
+ const exampleArgs = [];
97
+ for (const [name, schema] of Object.entries(props)) {
98
+ if (required.has(name)) {
99
+ const val = schema.enum ? schema.enum[0] : `"..."`;
100
+ exampleArgs.push(`--${name} ${val}`);
101
+ }
102
+ }
103
+ console.log(` andru-intel ${tool.name} ${exampleArgs.join(' ')}\n`);
104
+ }
105
+
106
+ function parseArgs(argv) {
107
+ const args = {};
108
+ let i = 0;
109
+ while (i < argv.length) {
110
+ const arg = argv[i];
111
+ if (arg.startsWith('--')) {
112
+ const key = arg.slice(2);
113
+ const next = argv[i + 1];
114
+ if (next && !next.startsWith('--')) {
115
+ // Try to parse as JSON for arrays/objects/numbers
116
+ try {
117
+ args[key] = JSON.parse(next);
118
+ } catch {
119
+ args[key] = next;
120
+ }
121
+ i += 2;
122
+ } else {
123
+ args[key] = true;
124
+ i += 1;
125
+ }
126
+ } else {
127
+ i += 1;
128
+ }
129
+ }
130
+ return args;
131
+ }
132
+
133
+ async function main() {
134
+ const argv = process.argv.slice(2);
135
+
136
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
137
+ printUsage();
138
+ process.exit(0);
139
+ }
140
+
141
+ const command = argv[0];
142
+
143
+ if (command === 'list') {
144
+ printToolList();
145
+ process.exit(0);
146
+ }
147
+
148
+ if (command === 'help') {
149
+ if (!argv[1]) {
150
+ printUsage();
151
+ } else {
152
+ printToolHelp(argv[1]);
153
+ }
154
+ process.exit(0);
155
+ }
156
+
157
+ // Tool execution
158
+ const toolName = command;
159
+ const tool = tools.find(t => t.name === toolName);
160
+ if (!tool) {
161
+ console.error(`Unknown tool: ${toolName}`);
162
+ console.error(`Run 'andru-intel list' to see available tools.`);
163
+ process.exit(1);
164
+ }
165
+
166
+ const apiKey = process.env.ANDRU_API_KEY;
167
+ if (!apiKey) {
168
+ console.error('ANDRU_API_KEY not set.');
169
+ console.error('Get your API key at https://app.andru.ai/settings/api-keys');
170
+ console.error('');
171
+ console.error('Usage: ANDRU_API_KEY=sk_live_... andru-intel ' + toolName + ' [args]');
172
+ process.exit(1);
173
+ }
174
+
175
+ const apiUrl = process.env.ANDRU_API_URL || 'https://api.andru.ai';
176
+ const client = new AndruClient(apiKey, apiUrl);
177
+ const toolArgs = parseArgs(argv.slice(1));
178
+
179
+ try {
180
+ const result = await client.callTool(toolName, toolArgs);
181
+
182
+ if (result.isError) {
183
+ const text = result.content?.[0]?.text || 'Unknown error';
184
+ console.error(text);
185
+ process.exit(1);
186
+ }
187
+
188
+ // Print result — if it's JSON, pretty-print it
189
+ const text = result.content?.[0]?.text || '{}';
190
+ try {
191
+ const parsed = JSON.parse(text);
192
+ console.log(JSON.stringify(parsed, null, 2));
193
+ } catch {
194
+ console.log(text);
195
+ }
196
+ } catch (error) {
197
+ console.error(`Error: ${error.message}`);
198
+ process.exit(1);
199
+ }
200
+ }
201
+
202
+ main();