salesflare-mcp-server 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.
Files changed (73) hide show
  1. package/API.md +691 -0
  2. package/CHANGELOG.md +49 -0
  3. package/CLAUDE.md +117 -0
  4. package/CONTRIBUTING.md +399 -0
  5. package/FIX_PLAN.md +70 -0
  6. package/INSPECTOR.md +191 -0
  7. package/LICENSE +21 -0
  8. package/PUBLISH.md +73 -0
  9. package/README.md +383 -0
  10. package/dist/auth/api-key-auth.d.ts +75 -0
  11. package/dist/auth/api-key-auth.d.ts.map +1 -0
  12. package/dist/auth/api-key-auth.js +103 -0
  13. package/dist/auth/oauth-auth.d.ts +81 -0
  14. package/dist/auth/oauth-auth.d.ts.map +1 -0
  15. package/dist/auth/oauth-auth.js +123 -0
  16. package/dist/auth/token-manager.d.ts +105 -0
  17. package/dist/auth/token-manager.d.ts.map +1 -0
  18. package/dist/auth/token-manager.js +87 -0
  19. package/dist/client/salesflare-client.d.ts +219 -0
  20. package/dist/client/salesflare-client.d.ts.map +1 -0
  21. package/dist/client/salesflare-client.js +484 -0
  22. package/dist/index.d.ts +15 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +82 -0
  25. package/dist/server.d.ts +39 -0
  26. package/dist/server.d.ts.map +1 -0
  27. package/dist/server.js +140 -0
  28. package/dist/tools/companies.d.ts +45 -0
  29. package/dist/tools/companies.d.ts.map +1 -0
  30. package/dist/tools/companies.js +392 -0
  31. package/dist/tools/contacts.d.ts +45 -0
  32. package/dist/tools/contacts.d.ts.map +1 -0
  33. package/dist/tools/contacts.js +290 -0
  34. package/dist/tools/deals.d.ts +46 -0
  35. package/dist/tools/deals.d.ts.map +1 -0
  36. package/dist/tools/deals.js +442 -0
  37. package/dist/tools/pipeline.d.ts +43 -0
  38. package/dist/tools/pipeline.d.ts.map +1 -0
  39. package/dist/tools/pipeline.js +328 -0
  40. package/dist/tools/tasks.d.ts +44 -0
  41. package/dist/tools/tasks.d.ts.map +1 -0
  42. package/dist/tools/tasks.js +406 -0
  43. package/dist/transport/http-transport.d.ts +36 -0
  44. package/dist/transport/http-transport.d.ts.map +1 -0
  45. package/dist/transport/http-transport.js +173 -0
  46. package/dist/transport/stdio-transport.d.ts +37 -0
  47. package/dist/transport/stdio-transport.d.ts.map +1 -0
  48. package/dist/transport/stdio-transport.js +129 -0
  49. package/dist/types/company.d.ts +223 -0
  50. package/dist/types/company.d.ts.map +1 -0
  51. package/dist/types/company.js +8 -0
  52. package/dist/types/contact.d.ts +166 -0
  53. package/dist/types/contact.d.ts.map +1 -0
  54. package/dist/types/contact.js +8 -0
  55. package/dist/types/deal.d.ts +203 -0
  56. package/dist/types/deal.d.ts.map +1 -0
  57. package/dist/types/deal.js +8 -0
  58. package/dist/types/pipeline.d.ts +116 -0
  59. package/dist/types/pipeline.d.ts.map +1 -0
  60. package/dist/types/pipeline.js +8 -0
  61. package/dist/types/task.d.ts +154 -0
  62. package/dist/types/task.d.ts.map +1 -0
  63. package/dist/types/task.js +8 -0
  64. package/dist/utils/errors.d.ts +128 -0
  65. package/dist/utils/errors.d.ts.map +1 -0
  66. package/dist/utils/errors.js +205 -0
  67. package/dist/utils/validation.d.ts +354 -0
  68. package/dist/utils/validation.d.ts.map +1 -0
  69. package/dist/utils/validation.js +716 -0
  70. package/package.json +49 -0
  71. package/test-tasks-debug.js +21 -0
  72. package/test-tasks-params.js +52 -0
  73. package/test-tools.js +171 -0
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "salesflare-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP Server for Salesflare CRM - enables LLMs to interact with Salesflare API",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "salesflare-mcp": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node ./dist/index.js",
15
+ "test": "jest",
16
+ "test:integration": "jest --config jest.integration.config.js",
17
+ "inspector": "npx @modelcontextprotocol/inspector node ./dist/index.js"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "salesflare",
22
+ "crm",
23
+ "model-context-protocol"
24
+ ],
25
+ "author": "",
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@modelcontextprotocol/sdk": "^1.0.0",
29
+ "axios": "^1.6.0",
30
+ "cors": "^2.8.6",
31
+ "dotenv": "^17.4.2",
32
+ "express": "^5.2.1",
33
+ "zod": "^4.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/cors": "^2.8.19",
37
+ "@types/express": "^5.0.6",
38
+ "@types/jest": "^29.0.0",
39
+ "@types/node": "^20.0.0",
40
+ "@types/supertest": "^7.2.0",
41
+ "jest": "^29.0.0",
42
+ "supertest": "^7.2.2",
43
+ "ts-jest": "^29.0.0",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }
@@ -0,0 +1,21 @@
1
+ import { createSalesflareClient } from './dist/client/salesflare-client.js';
2
+ import { createApiKeyAuth } from './dist/auth/api-key-auth.js';
3
+
4
+ const auth = createApiKeyAuth();
5
+ const client = createSalesflareClient({ authProvider: auth });
6
+
7
+ console.log('Testing tasks endpoint without pagination...\n');
8
+
9
+ try {
10
+ const response = await client.get('/tasks');
11
+ console.log('✅ Success! Response type:', typeof response);
12
+ console.log('Is array?', Array.isArray(response));
13
+ console.log('Has items?', response.items !== undefined);
14
+ if (response.items) {
15
+ console.log('Items count:', response.items.length);
16
+ }
17
+ console.log('\nFull response (first 500 chars):');
18
+ console.log(JSON.stringify(response, null, 2).substring(0, 500));
19
+ } catch (error) {
20
+ console.log('❌ Error:', error.message);
21
+ }
@@ -0,0 +1,52 @@
1
+ import { createSalesflareClient } from './dist/client/salesflare-client.js';
2
+ import { createApiKeyAuth } from './dist/auth/api-key-auth.js';
3
+
4
+ const auth = createApiKeyAuth();
5
+ const client = createSalesflareClient({ authProvider: auth });
6
+
7
+ console.log('Testing tasks endpoint with various parameters...\n');
8
+
9
+ // Test 1: No params
10
+ console.log('Test 1: No params');
11
+ try {
12
+ const response = await client.get('/tasks');
13
+ console.log('✅ Success - Got', Array.isArray(response) ? response.length : 'non-array', 'items\n');
14
+ } catch (error) {
15
+ console.log('❌ Error:', error.message, '\n');
16
+ }
17
+
18
+ // Test 2: With limit
19
+ console.log('Test 2: With limit=5');
20
+ try {
21
+ const response = await client.get('/tasks', { params: { limit: 5 } });
22
+ console.log('✅ Success - Got', Array.isArray(response) ? response.length : 'non-array', 'items\n');
23
+ } catch (error) {
24
+ console.log('❌ Error:', error.message, '\n');
25
+ }
26
+
27
+ // Test 3: With page
28
+ console.log('Test 3: With page=1');
29
+ try {
30
+ const response = await client.get('/tasks', { params: { page: 1 } });
31
+ console.log('✅ Success\n');
32
+ } catch (error) {
33
+ console.log('❌ Error:', error.message, '\n');
34
+ }
35
+
36
+ // Test 4: With status
37
+ console.log('Test 4: With status=open');
38
+ try {
39
+ const response = await client.get('/tasks', { params: { status: 'open' } });
40
+ console.log('✅ Success\n');
41
+ } catch (error) {
42
+ console.log('❌ Error:', error.message, '\n');
43
+ }
44
+
45
+ // Test 5: With completed
46
+ console.log('Test 5: With completed=false');
47
+ try {
48
+ const response = await client.get('/tasks', { params: { completed: false } });
49
+ console.log('✅ Success - Got', Array.isArray(response) ? response.length : 'non-array', 'items\n');
50
+ } catch (error) {
51
+ console.log('❌ Error:', error.message, '\n');
52
+ }
package/test-tools.js ADDED
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Systematic tool testing script
3
+ * Tests each MCP tool against the real Salesflare API and documents results
4
+ */
5
+
6
+ import { createSalesflareClient } from './dist/client/salesflare-client.js';
7
+ import { createApiKeyAuth } from './dist/auth/api-key-auth.js';
8
+ import { handleContactsTool } from './dist/tools/contacts.js';
9
+ import { handleCompaniesTool } from './dist/tools/companies.js';
10
+ import { handleDealsTool } from './dist/tools/deals.js';
11
+ import { handleTasksTool } from './dist/tools/tasks.js';
12
+ import { handlePipelineTool } from './dist/tools/pipeline.js';
13
+ import { SalesflareError } from './dist/utils/errors.js';
14
+
15
+ // Test results storage
16
+ const results = {
17
+ passed: [],
18
+ failed: [],
19
+ errors: []
20
+ };
21
+
22
+ // Helper to run a test
23
+ async function runTest(category, toolName, args, handler, client) {
24
+ console.log(`\n🧪 Testing: ${toolName}`);
25
+ console.log(` Args: ${JSON.stringify(args)}`);
26
+
27
+ try {
28
+ const result = await handler(client, toolName, args);
29
+
30
+ // Check if result has error
31
+ if (result.content[0].text.includes('Error [')) {
32
+ results.failed.push({ tool: toolName, args, error: result.content[0].text });
33
+ console.log(` ❌ FAILED: ${result.content[0].text.substring(0, 100)}...`);
34
+ } else {
35
+ results.passed.push({ tool: toolName, args, preview: result.content[0].text.substring(0, 100) });
36
+ console.log(` ✅ PASSED: ${result.content[0].text.substring(0, 100)}...`);
37
+ }
38
+ } catch (error) {
39
+ const errorMsg = error instanceof SalesflareError ? error.message : String(error);
40
+ results.failed.push({ tool: toolName, args, error: errorMsg });
41
+ console.log(` ❌ ERROR: ${errorMsg.substring(0, 100)}...`);
42
+ }
43
+ }
44
+
45
+ async function runAllTests() {
46
+ console.log('═══════════════════════════════════════════════════════');
47
+ console.log(' SALESFLARE MCP SERVER - AUTOMATED TOOL TESTING');
48
+ console.log('═══════════════════════════════════════════════════════');
49
+ console.log(`\nAPI Key: ${process.env.SALESFLARE_API_KEY ? '✓ Set' : '✗ Missing'}`);
50
+
51
+ if (!process.env.SALESFLARE_API_KEY) {
52
+ console.error('❌ SALESFLARE_API_KEY environment variable is required');
53
+ process.exit(1);
54
+ }
55
+
56
+ // Create client
57
+ const auth = createApiKeyAuth();
58
+ const client = createSalesflareClient({ authProvider: auth });
59
+
60
+ // CONTACTS TESTS
61
+ console.log('\n\n📋 CONTACTS TOOLS');
62
+ console.log('───────────────────────────────────────────────────────');
63
+
64
+ await runTest('contacts', 'salesflare_contacts_list', {}, handleContactsTool, client);
65
+ await runTest('contacts', 'salesflare_contacts_list', { limit: 5 }, handleContactsTool, client);
66
+ await runTest('contacts', 'salesflare_contacts_list', { email: 'test@example.com' }, handleContactsTool, client);
67
+
68
+ await runTest('contacts', 'salesflare_contacts_create', {
69
+ email: 'mcp-test-' + Date.now() + '@example.com',
70
+ name: 'MCP Test Contact'
71
+ }, handleContactsTool, client);
72
+
73
+ // COMPANIES TESTS
74
+ console.log('\n\n🏢 COMPANIES TOOLS');
75
+ console.log('───────────────────────────────────────────────────────');
76
+
77
+ await runTest('companies', 'salesflare_companies_list', {}, handleCompaniesTool, client);
78
+ await runTest('companies', 'salesflare_companies_list', { limit: 5 }, handleCompaniesTool, client);
79
+ await runTest('companies', 'salesflare_companies_list', { name: 'Test' }, handleCompaniesTool, client);
80
+
81
+ await runTest('companies', 'salesflare_companies_create', {
82
+ name: 'MCP Test Company ' + Date.now()
83
+ }, handleCompaniesTool, client);
84
+
85
+ // DEALS TESTS
86
+ console.log('\n\n💼 DEALS TOOLS');
87
+ console.log('───────────────────────────────────────────────────────');
88
+
89
+ await runTest('deals', 'salesflare_deals_list', {}, handleDealsTool, client);
90
+ await runTest('deals', 'salesflare_deals_list', { limit: 5 }, handleDealsTool, client);
91
+ await runTest('deals', 'salesflare_deals_list', { status: 'open' }, handleDealsTool, client);
92
+
93
+ // TASKS TESTS
94
+ console.log('\n\n✅ TASKS TOOLS');
95
+ console.log('───────────────────────────────────────────────────────');
96
+
97
+ await runTest('tasks', 'salesflare_tasks_list', {}, handleTasksTool, client);
98
+ await runTest('tasks', 'salesflare_tasks_list', { limit: 5 }, handleTasksTool, client);
99
+ await runTest('tasks', 'salesflare_tasks_list', { status: 'open' }, handleTasksTool, client);
100
+
101
+ await runTest('tasks', 'salesflare_tasks_create', {
102
+ description: 'MCP Test Task ' + Date.now()
103
+ }, handleTasksTool, client);
104
+
105
+ // PIPELINE TESTS
106
+ console.log('\n\n🔄 PIPELINE TOOLS');
107
+ console.log('───────────────────────────────────────────────────────');
108
+
109
+ await runTest('pipeline', 'salesflare_pipeline_list_stages', {}, handlePipelineTool, client);
110
+ await runTest('pipeline', 'salesflare_pipeline_get_overview', {}, handlePipelineTool, client);
111
+
112
+ // SUMMARY
113
+ console.log('\n\n═══════════════════════════════════════════════════════');
114
+ console.log(' TEST RESULTS SUMMARY');
115
+ console.log('═══════════════════════════════════════════════════════');
116
+ console.log(`\n✅ Passed: ${results.passed.length}`);
117
+ console.log(`❌ Failed: ${results.failed.length}`);
118
+ console.log(`\n📊 Success Rate: ${((results.passed.length / (results.passed.length + results.failed.length)) * 100).toFixed(1)}%`);
119
+
120
+ if (results.failed.length > 0) {
121
+ console.log('\n\n🔴 FAILED TESTS DETAILS:');
122
+ console.log('───────────────────────────────────────────────────────');
123
+ results.failed.forEach((fail, idx) => {
124
+ console.log(`\n${idx + 1}. ${fail.tool}`);
125
+ console.log(` Args: ${JSON.stringify(fail.args)}`);
126
+ console.log(` Error: ${fail.error}`);
127
+ });
128
+ }
129
+
130
+ // Generate fix plan
131
+ console.log('\n\n═══════════════════════════════════════════════════════');
132
+ console.log(' RECOMMENDED FIX PLAN');
133
+ console.log('═══════════════════════════════════════════════════════');
134
+
135
+ const errorTypes = {};
136
+ results.failed.forEach(fail => {
137
+ const errorKey = fail.error.includes('NOT_FOUND') ? 'NOT_FOUND' :
138
+ fail.error.includes('VALIDATION_ERROR') ? 'VALIDATION_ERROR' :
139
+ fail.error.includes('AUTH') ? 'AUTH_ERROR' :
140
+ fail.error.includes('API_ERROR') ? 'API_ERROR' :
141
+ 'OTHER';
142
+ if (!errorTypes[errorKey]) errorTypes[errorKey] = [];
143
+ errorTypes[errorKey].push(fail.tool);
144
+ });
145
+
146
+ Object.entries(errorTypes).forEach(([type, tools]) => {
147
+ console.log(`\n${type} (${tools.length} tools):`);
148
+ console.log(` Affected: ${tools.join(', ')}`);
149
+
150
+ switch(type) {
151
+ case 'NOT_FOUND':
152
+ console.log(` Fix: Check if endpoint URLs are correct`);
153
+ break;
154
+ case 'VALIDATION_ERROR':
155
+ console.log(` Fix: Review required fields and validation logic`);
156
+ break;
157
+ case 'AUTH_ERROR':
158
+ console.log(` Fix: Verify API key permissions`);
159
+ break;
160
+ case 'API_ERROR':
161
+ console.log(` Fix: Check API response format handling`);
162
+ break;
163
+ default:
164
+ console.log(` Fix: Review tool implementation`);
165
+ }
166
+ });
167
+
168
+ console.log('\n');
169
+ }
170
+
171
+ runAllTests().catch(console.error);