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.
- package/API.md +691 -0
- package/CHANGELOG.md +49 -0
- package/CLAUDE.md +117 -0
- package/CONTRIBUTING.md +399 -0
- package/FIX_PLAN.md +70 -0
- package/INSPECTOR.md +191 -0
- package/LICENSE +21 -0
- package/PUBLISH.md +73 -0
- package/README.md +383 -0
- package/dist/auth/api-key-auth.d.ts +75 -0
- package/dist/auth/api-key-auth.d.ts.map +1 -0
- package/dist/auth/api-key-auth.js +103 -0
- package/dist/auth/oauth-auth.d.ts +81 -0
- package/dist/auth/oauth-auth.d.ts.map +1 -0
- package/dist/auth/oauth-auth.js +123 -0
- package/dist/auth/token-manager.d.ts +105 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +87 -0
- package/dist/client/salesflare-client.d.ts +219 -0
- package/dist/client/salesflare-client.d.ts.map +1 -0
- package/dist/client/salesflare-client.js +484 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/server.d.ts +39 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +140 -0
- package/dist/tools/companies.d.ts +45 -0
- package/dist/tools/companies.d.ts.map +1 -0
- package/dist/tools/companies.js +392 -0
- package/dist/tools/contacts.d.ts +45 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +290 -0
- package/dist/tools/deals.d.ts +46 -0
- package/dist/tools/deals.d.ts.map +1 -0
- package/dist/tools/deals.js +442 -0
- package/dist/tools/pipeline.d.ts +43 -0
- package/dist/tools/pipeline.d.ts.map +1 -0
- package/dist/tools/pipeline.js +328 -0
- package/dist/tools/tasks.d.ts +44 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +406 -0
- package/dist/transport/http-transport.d.ts +36 -0
- package/dist/transport/http-transport.d.ts.map +1 -0
- package/dist/transport/http-transport.js +173 -0
- package/dist/transport/stdio-transport.d.ts +37 -0
- package/dist/transport/stdio-transport.d.ts.map +1 -0
- package/dist/transport/stdio-transport.js +129 -0
- package/dist/types/company.d.ts +223 -0
- package/dist/types/company.d.ts.map +1 -0
- package/dist/types/company.js +8 -0
- package/dist/types/contact.d.ts +166 -0
- package/dist/types/contact.d.ts.map +1 -0
- package/dist/types/contact.js +8 -0
- package/dist/types/deal.d.ts +203 -0
- package/dist/types/deal.d.ts.map +1 -0
- package/dist/types/deal.js +8 -0
- package/dist/types/pipeline.d.ts +116 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +8 -0
- package/dist/types/task.d.ts +154 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +8 -0
- package/dist/utils/errors.d.ts +128 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +205 -0
- package/dist/utils/validation.d.ts +354 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +716 -0
- package/package.json +49 -0
- package/test-tasks-debug.js +21 -0
- package/test-tasks-params.js +52 -0
- 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);
|