@app-connect/core 1.7.11 → 1.7.12
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/handlers/admin.js +91 -1
- package/handlers/auth.js +1 -1
- package/handlers/disposition.js +3 -3
- package/handlers/log.js +2 -1
- package/index.js +67 -0
- package/lib/sharedSMSComposer.js +2 -2
- package/mcp/tools/checkAuthStatus.js +22 -2
- package/mcp/tools/collectAuthInfo.js +5 -0
- package/mcp/tools/createCallLog.js +9 -0
- package/mcp/tools/createContact.js +117 -0
- package/mcp/tools/doAuth.js +15 -10
- package/mcp/tools/findContactByName.js +5 -0
- package/mcp/tools/findContactByPhone.js +5 -0
- package/mcp/tools/getGoogleFilePicker.js +103 -0
- package/mcp/tools/getHelp.js +6 -1
- package/mcp/tools/getPublicConnectors.js +8 -1
- package/mcp/tools/index.js +14 -8
- package/mcp/tools/logout.js +5 -0
- package/mcp/tools/rcGetCallLogs.js +5 -0
- package/mcp/tools/setConnector.js +7 -2
- package/package.json +1 -1
- package/releaseNotes.json +12 -0
- package/test/handlers/log.test.js +6 -3
- package/test/lib/ringcentral.test.js +0 -6
- package/test/lib/sharedSMSComposer.test.js +1 -1
- package/test/mcp/tools/collectAuthInfo.test.js +42 -0
- package/test/mcp/tools/createCallLog.test.js +27 -14
- package/test/mcp/tools/doAuth.test.js +23 -10
- package/test/mcp/tools/getGoogleFilePicker.test.js +281 -0
- package/test/mcp/tools/getPublicConnectors.test.js +8 -8
|
@@ -13,9 +13,16 @@ const toolDefinition = {
|
|
|
13
13
|
type: 'object',
|
|
14
14
|
properties: {},
|
|
15
15
|
required: []
|
|
16
|
+
},
|
|
17
|
+
annotations: {
|
|
18
|
+
readOnlyHint: true,
|
|
19
|
+
openWorldHint: false,
|
|
20
|
+
destructiveHint: false
|
|
16
21
|
}
|
|
17
22
|
};
|
|
18
23
|
|
|
24
|
+
const supportedPlatforms = ['googleSheets','clio'];
|
|
25
|
+
|
|
19
26
|
/**
|
|
20
27
|
* Execute the getPublicConnectors tool
|
|
21
28
|
* @returns {Object} Result object with connector names
|
|
@@ -30,7 +37,7 @@ async function execute() {
|
|
|
30
37
|
}
|
|
31
38
|
return {
|
|
32
39
|
success: true,
|
|
33
|
-
data: connectorList.map(c => c.displayName)
|
|
40
|
+
data: connectorList.filter(c => supportedPlatforms.includes(c.name)).map(c => c.displayName)
|
|
34
41
|
};
|
|
35
42
|
}
|
|
36
43
|
catch (error) {
|
package/mcp/tools/index.js
CHANGED
|
@@ -19,6 +19,8 @@ const createCallLog = require('./createCallLog');
|
|
|
19
19
|
const updateCallLog = require('./updateCallLog');
|
|
20
20
|
const createMessageLog = require('./createMessageLog');
|
|
21
21
|
const rcGetCallLogs = require('./rcGetCallLogs');
|
|
22
|
+
const getGoogleFilePicker = require('./getGoogleFilePicker');
|
|
23
|
+
const createContact = require('./createContact');
|
|
22
24
|
|
|
23
25
|
// Export all tools
|
|
24
26
|
module.exports = {
|
|
@@ -31,11 +33,13 @@ module.exports = {
|
|
|
31
33
|
logout,
|
|
32
34
|
findContact,
|
|
33
35
|
findContactWithName,
|
|
34
|
-
getCallLog,
|
|
36
|
+
//getCallLog,
|
|
35
37
|
createCallLog,
|
|
36
|
-
updateCallLog,
|
|
37
|
-
createMessageLog,
|
|
38
|
-
rcGetCallLogs
|
|
38
|
+
//updateCallLog,
|
|
39
|
+
//createMessageLog,
|
|
40
|
+
rcGetCallLogs,
|
|
41
|
+
getGoogleFilePicker,
|
|
42
|
+
createContact
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
// Export tools as an array for easy iteration
|
|
@@ -49,10 +53,12 @@ module.exports.tools = [
|
|
|
49
53
|
logout,
|
|
50
54
|
findContact,
|
|
51
55
|
findContactWithName,
|
|
52
|
-
getCallLog,
|
|
56
|
+
//getCallLog,
|
|
53
57
|
createCallLog,
|
|
54
|
-
updateCallLog,
|
|
55
|
-
createMessageLog,
|
|
56
|
-
rcGetCallLogs
|
|
58
|
+
//updateCallLog,
|
|
59
|
+
//createMessageLog,
|
|
60
|
+
rcGetCallLogs,
|
|
61
|
+
getGoogleFilePicker,
|
|
62
|
+
createContact
|
|
57
63
|
];
|
|
58
64
|
|
package/mcp/tools/logout.js
CHANGED
|
@@ -19,6 +19,11 @@ const toolDefinition = {
|
|
|
19
19
|
description: 'JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.'
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
},
|
|
23
|
+
annotations: {
|
|
24
|
+
readOnlyHint: false,
|
|
25
|
+
openWorldHint: false,
|
|
26
|
+
destructiveHint: true
|
|
22
27
|
}
|
|
23
28
|
};
|
|
24
29
|
|
|
@@ -8,7 +8,7 @@ const developerPortal = require('../../connector/developerPortal');
|
|
|
8
8
|
|
|
9
9
|
const toolDefinition = {
|
|
10
10
|
name: 'setConnector',
|
|
11
|
-
description: 'Auth flow step.2. Save connectorManifest to memory if successful.
|
|
11
|
+
description: 'Auth flow step.2. Save connectorManifest to memory if successful.',
|
|
12
12
|
inputSchema: {
|
|
13
13
|
type: 'object',
|
|
14
14
|
properties: {
|
|
@@ -18,6 +18,11 @@ const toolDefinition = {
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
required: ['connectorDisplayName']
|
|
21
|
+
},
|
|
22
|
+
annotations: {
|
|
23
|
+
readOnlyHint: true,
|
|
24
|
+
openWorldHint: false,
|
|
25
|
+
destructiveHint: false
|
|
21
26
|
}
|
|
22
27
|
};
|
|
23
28
|
|
|
@@ -46,7 +51,7 @@ async function execute(args) {
|
|
|
46
51
|
connectorDisplayName,
|
|
47
52
|
connectorName,
|
|
48
53
|
// Add explicit instruction
|
|
49
|
-
message: "IMPORTANT: Use connectorManifest, connectorDisplayName, and connectorName in the next few authentication steps.",
|
|
54
|
+
message: "IMPORTANT: Use connectorManifest, connectorDisplayName, and connectorName in the next few authentication steps. Call 'collectAuthInfo' tool if the connector is oauth, unless connectorManifest.platform[0].environment.type == 'fixed'.",
|
|
50
55
|
|
|
51
56
|
}
|
|
52
57
|
};
|
package/package.json
CHANGED
package/releaseNotes.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
+
"1.7.12": {
|
|
3
|
+
"global": [
|
|
4
|
+
{
|
|
5
|
+
"type": "New",
|
|
6
|
+
"description": "A button on Developer settings page to re-initialize user mapping"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"type": "Better",
|
|
10
|
+
"description": "Click-to-SMS button is disabled if RingCentral SMS service is not activated"
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
},
|
|
2
14
|
"1.7.11": {
|
|
3
15
|
"global": [
|
|
4
16
|
{
|
|
@@ -691,10 +691,12 @@ describe('Log Handler', () => {
|
|
|
691
691
|
platformAdditionalInfo: {}
|
|
692
692
|
});
|
|
693
693
|
|
|
694
|
+
// Create existing message log with same conversationLogId
|
|
694
695
|
await MessageLogModel.create({
|
|
695
696
|
id: 'msg-1',
|
|
696
697
|
platform: 'testCRM',
|
|
697
698
|
conversationId: 'conv-123',
|
|
699
|
+
conversationLogId: 'conv-log-123',
|
|
698
700
|
thirdPartyLogId: 'existing-log',
|
|
699
701
|
userId: 'test-user-id'
|
|
700
702
|
});
|
|
@@ -720,7 +722,7 @@ describe('Log Handler', () => {
|
|
|
720
722
|
],
|
|
721
723
|
correspondents: [{ phoneNumber: '+1234567890' }],
|
|
722
724
|
conversationId: 'conv-123',
|
|
723
|
-
conversationLogId: '
|
|
725
|
+
conversationLogId: 'conv-log-123' // Same conversationLogId as existing record
|
|
724
726
|
},
|
|
725
727
|
contactId: 'contact-123',
|
|
726
728
|
contactType: 'Contact',
|
|
@@ -736,7 +738,7 @@ describe('Log Handler', () => {
|
|
|
736
738
|
|
|
737
739
|
// Assert
|
|
738
740
|
expect(result.successful).toBe(true);
|
|
739
|
-
// msg-1 is skipped (already logged), msg-2 uses updateMessageLog because same
|
|
741
|
+
// msg-1 is skipped (already logged), msg-2 uses updateMessageLog because same conversationLogId exists
|
|
740
742
|
expect(mockConnector.createMessageLog).toHaveBeenCalledTimes(0);
|
|
741
743
|
expect(mockConnector.updateMessageLog).toHaveBeenCalledTimes(1);
|
|
742
744
|
});
|
|
@@ -771,7 +773,8 @@ describe('Log Handler', () => {
|
|
|
771
773
|
|
|
772
774
|
// Assert
|
|
773
775
|
expect(result.successful).toBe(false);
|
|
774
|
-
expect(result.returnMessage).toBe('Error
|
|
776
|
+
expect(result.returnMessage.message).toBe('Error performing saveNoteCache');
|
|
777
|
+
expect(result.returnMessage.messageType).toBe('warning');
|
|
775
778
|
});
|
|
776
779
|
});
|
|
777
780
|
|
|
@@ -126,9 +126,6 @@ describe('ringcentral', () => {
|
|
|
126
126
|
expect(result.refresh_token).toBe('new-refresh-token');
|
|
127
127
|
expect(result.expire_time).toBeDefined();
|
|
128
128
|
expect(result.refresh_token_expire_time).toBeDefined();
|
|
129
|
-
// These should not be included
|
|
130
|
-
expect(result.scope).toBeUndefined();
|
|
131
|
-
expect(result.endpoint_id).toBeUndefined();
|
|
132
129
|
});
|
|
133
130
|
|
|
134
131
|
test('should throw error on failed token generation', async () => {
|
|
@@ -317,9 +314,6 @@ describe('ringcentral', () => {
|
|
|
317
314
|
}, token);
|
|
318
315
|
|
|
319
316
|
expect(result.id).toBe('sub-123');
|
|
320
|
-
// These should not be included in result
|
|
321
|
-
expect(result.uri).toBeUndefined();
|
|
322
|
-
expect(result.creationTime).toBeUndefined();
|
|
323
317
|
});
|
|
324
318
|
});
|
|
325
319
|
|
|
@@ -61,7 +61,7 @@ describe('sharedSMSComposer', () => {
|
|
|
61
61
|
timezoneOffset: '+00:00'
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
expect(result.subject).toBe('
|
|
64
|
+
expect(result.subject).toBe('SMS conversation with John Customer');
|
|
65
65
|
expect(result.body).toContain('<b>Conversation summary</b>');
|
|
66
66
|
expect(result.body).toContain('<b>Participants</b>');
|
|
67
67
|
expect(result.body).toContain('<li>');
|
|
@@ -22,6 +22,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
22
22
|
platforms: {
|
|
23
23
|
salesforce: {
|
|
24
24
|
name: 'salesforce',
|
|
25
|
+
auth: {
|
|
26
|
+
type: 'oauth',
|
|
27
|
+
oauth: {
|
|
28
|
+
authUrl: 'https://login.salesforce.com/services/oauth2/authorize',
|
|
29
|
+
clientId: 'test-client-id'
|
|
30
|
+
}
|
|
31
|
+
},
|
|
25
32
|
environment: {
|
|
26
33
|
type: 'selectable',
|
|
27
34
|
selections: [
|
|
@@ -56,6 +63,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
56
63
|
platforms: {
|
|
57
64
|
netsuite: {
|
|
58
65
|
name: 'netsuite',
|
|
66
|
+
auth: {
|
|
67
|
+
type: 'oauth',
|
|
68
|
+
oauth: {
|
|
69
|
+
authUrl: 'https://system.netsuite.com/app/login/oauth2/authorize.nl',
|
|
70
|
+
clientId: 'test-client-id'
|
|
71
|
+
}
|
|
72
|
+
},
|
|
59
73
|
environment: {
|
|
60
74
|
type: 'dynamic'
|
|
61
75
|
}
|
|
@@ -86,6 +100,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
86
100
|
platforms: {
|
|
87
101
|
salesforce: {
|
|
88
102
|
name: 'salesforce',
|
|
103
|
+
auth: {
|
|
104
|
+
type: 'oauth',
|
|
105
|
+
oauth: {
|
|
106
|
+
authUrl: 'https://login.salesforce.com/services/oauth2/authorize',
|
|
107
|
+
clientId: 'test-client-id'
|
|
108
|
+
}
|
|
109
|
+
},
|
|
89
110
|
environment: {
|
|
90
111
|
type: 'selectable',
|
|
91
112
|
selections: [
|
|
@@ -115,6 +136,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
115
136
|
platforms: {
|
|
116
137
|
netsuite: {
|
|
117
138
|
name: 'netsuite',
|
|
139
|
+
auth: {
|
|
140
|
+
type: 'oauth',
|
|
141
|
+
oauth: {
|
|
142
|
+
authUrl: 'https://system.netsuite.com/app/login/oauth2/authorize.nl',
|
|
143
|
+
clientId: 'test-client-id'
|
|
144
|
+
}
|
|
145
|
+
},
|
|
118
146
|
environment: {
|
|
119
147
|
type: 'dynamic'
|
|
120
148
|
}
|
|
@@ -141,6 +169,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
141
169
|
platforms: {
|
|
142
170
|
salesforce: {
|
|
143
171
|
name: 'salesforce',
|
|
172
|
+
auth: {
|
|
173
|
+
type: 'oauth',
|
|
174
|
+
oauth: {
|
|
175
|
+
authUrl: 'https://login.salesforce.com/services/oauth2/authorize',
|
|
176
|
+
clientId: 'test-client-id'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
144
179
|
environment: {
|
|
145
180
|
type: 'selectable',
|
|
146
181
|
selections: [
|
|
@@ -169,6 +204,13 @@ describe('MCP Tool: collectAuthInfo', () => {
|
|
|
169
204
|
platforms: {
|
|
170
205
|
netsuite: {
|
|
171
206
|
name: 'netsuite',
|
|
207
|
+
auth: {
|
|
208
|
+
type: 'oauth',
|
|
209
|
+
oauth: {
|
|
210
|
+
authUrl: 'https://system.netsuite.com/app/login/oauth2/authorize.nl',
|
|
211
|
+
clientId: 'test-client-id'
|
|
212
|
+
}
|
|
213
|
+
},
|
|
172
214
|
environment: {
|
|
173
215
|
type: 'dynamic'
|
|
174
216
|
}
|
|
@@ -2,6 +2,7 @@ const createCallLog = require('../../../mcp/tools/createCallLog');
|
|
|
2
2
|
const jwt = require('../../../lib/jwt');
|
|
3
3
|
const connectorRegistry = require('../../../connector/registry');
|
|
4
4
|
const logCore = require('../../../handlers/log');
|
|
5
|
+
const contactCore = require('../../../handlers/contact');
|
|
5
6
|
const util = require('../../../lib/util');
|
|
6
7
|
const { CallLogModel } = require('../../../models/callLogModel');
|
|
7
8
|
|
|
@@ -9,6 +10,7 @@ const { CallLogModel } = require('../../../models/callLogModel');
|
|
|
9
10
|
jest.mock('../../../lib/jwt');
|
|
10
11
|
jest.mock('../../../connector/registry');
|
|
11
12
|
jest.mock('../../../handlers/log');
|
|
13
|
+
jest.mock('../../../handlers/contact');
|
|
12
14
|
jest.mock('../../../lib/util');
|
|
13
15
|
jest.mock('../../../models/callLogModel');
|
|
14
16
|
|
|
@@ -34,10 +36,8 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
34
36
|
test('should have detailed inputSchema for incomingData', () => {
|
|
35
37
|
const incomingDataSchema = createCallLog.definition.inputSchema.properties.incomingData;
|
|
36
38
|
expect(incomingDataSchema.properties).toHaveProperty('logInfo');
|
|
37
|
-
expect(incomingDataSchema.properties).toHaveProperty('contactId');
|
|
38
39
|
expect(incomingDataSchema.properties).toHaveProperty('note');
|
|
39
40
|
expect(incomingDataSchema.required).toContain('logInfo');
|
|
40
|
-
expect(incomingDataSchema.required).toContain('contactId');
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -55,7 +55,6 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
55
55
|
to: { phoneNumber: '+0987654321', name: 'Company' },
|
|
56
56
|
accountId: 'rc-account-123'
|
|
57
57
|
},
|
|
58
|
-
contactId: 'contact-123',
|
|
59
58
|
contactName: 'John Doe',
|
|
60
59
|
contactType: 'Contact',
|
|
61
60
|
note: 'Test call note'
|
|
@@ -75,6 +74,12 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
75
74
|
|
|
76
75
|
util.getHashValue.mockReturnValue('hashed-account-id');
|
|
77
76
|
|
|
77
|
+
// Mock contactCore.findContact to return a contact
|
|
78
|
+
contactCore.findContact.mockResolvedValue({
|
|
79
|
+
successful: true,
|
|
80
|
+
contact: [{ id: 'contact-123', isNewContact: false }]
|
|
81
|
+
});
|
|
82
|
+
|
|
78
83
|
logCore.createCallLog.mockResolvedValue({
|
|
79
84
|
successful: true,
|
|
80
85
|
logId: 'crm-log-123',
|
|
@@ -99,13 +104,6 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
99
104
|
expect(CallLogModel.findOne).toHaveBeenCalledWith({
|
|
100
105
|
where: { sessionId: 'session-123' }
|
|
101
106
|
});
|
|
102
|
-
expect(logCore.createCallLog).toHaveBeenCalledWith({
|
|
103
|
-
platform: 'testCRM',
|
|
104
|
-
userId: 'user-123',
|
|
105
|
-
incomingData: mockIncomingData,
|
|
106
|
-
hashedAccountId: 'hashed-account-id',
|
|
107
|
-
isFromSSCL: false
|
|
108
|
-
});
|
|
109
107
|
});
|
|
110
108
|
|
|
111
109
|
test('should create call log with AI note and transcript', async () => {
|
|
@@ -120,7 +118,6 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
120
118
|
from: { phoneNumber: '+0987654321' },
|
|
121
119
|
to: { phoneNumber: '+1234567890' }
|
|
122
120
|
},
|
|
123
|
-
contactId: 'contact-456',
|
|
124
121
|
aiNote: 'AI generated summary of the call',
|
|
125
122
|
transcript: 'Full call transcript text'
|
|
126
123
|
};
|
|
@@ -137,6 +134,12 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
137
134
|
|
|
138
135
|
CallLogModel.findOne.mockResolvedValue(null);
|
|
139
136
|
|
|
137
|
+
// Mock contactCore.findContact to return a contact
|
|
138
|
+
contactCore.findContact.mockResolvedValue({
|
|
139
|
+
successful: true,
|
|
140
|
+
contact: [{ id: 'contact-456', isNewContact: false }]
|
|
141
|
+
});
|
|
142
|
+
|
|
140
143
|
logCore.createCallLog.mockResolvedValue({
|
|
141
144
|
successful: true,
|
|
142
145
|
logId: 'crm-log-456'
|
|
@@ -165,7 +168,6 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
165
168
|
from: { phoneNumber: '+1234567890' },
|
|
166
169
|
to: { phoneNumber: '+0987654321' }
|
|
167
170
|
},
|
|
168
|
-
contactId: 'contact-789',
|
|
169
171
|
additionalSubmission: {
|
|
170
172
|
isAssignedToUser: true,
|
|
171
173
|
adminAssignedUserToken: 'admin-jwt-token',
|
|
@@ -185,6 +187,12 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
185
187
|
|
|
186
188
|
CallLogModel.findOne.mockResolvedValue(null);
|
|
187
189
|
|
|
190
|
+
// Mock contactCore.findContact to return a contact
|
|
191
|
+
contactCore.findContact.mockResolvedValue({
|
|
192
|
+
successful: true,
|
|
193
|
+
contact: [{ id: 'contact-789', isNewContact: false }]
|
|
194
|
+
});
|
|
195
|
+
|
|
188
196
|
logCore.createCallLog.mockResolvedValue({
|
|
189
197
|
successful: true,
|
|
190
198
|
logId: 'crm-log-789'
|
|
@@ -352,8 +360,7 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
352
360
|
duration: 45,
|
|
353
361
|
from: { phoneNumber: '+1234567890' },
|
|
354
362
|
to: { phoneNumber: '+0987654321' }
|
|
355
|
-
}
|
|
356
|
-
contactId: 'contact-999'
|
|
363
|
+
}
|
|
357
364
|
};
|
|
358
365
|
|
|
359
366
|
jwt.decodeJwt.mockReturnValue({
|
|
@@ -368,6 +375,12 @@ describe('MCP Tool: createCallLog', () => {
|
|
|
368
375
|
|
|
369
376
|
CallLogModel.findOne.mockResolvedValue(null);
|
|
370
377
|
|
|
378
|
+
// Mock contactCore.findContact to return a contact
|
|
379
|
+
contactCore.findContact.mockResolvedValue({
|
|
380
|
+
successful: true,
|
|
381
|
+
contact: [{ id: 'contact-999', isNewContact: false }]
|
|
382
|
+
});
|
|
383
|
+
|
|
371
384
|
logCore.createCallLog.mockResolvedValue({
|
|
372
385
|
successful: false,
|
|
373
386
|
returnMessage: { message: 'Failed to create log in CRM' }
|
|
@@ -37,7 +37,7 @@ describe('MCP Tool: doAuth', () => {
|
|
|
37
37
|
platforms: {
|
|
38
38
|
testCRM: {
|
|
39
39
|
name: 'testCRM',
|
|
40
|
-
auth: { type: 'apiKey' },
|
|
40
|
+
auth: { type: 'apiKey', apiKey: { name: 'apiKey' } },
|
|
41
41
|
environment: { type: 'fixed' }
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -88,7 +88,7 @@ describe('MCP Tool: doAuth', () => {
|
|
|
88
88
|
platforms: {
|
|
89
89
|
testCRM: {
|
|
90
90
|
name: 'testCRM',
|
|
91
|
-
auth: { type: 'apiKey' }
|
|
91
|
+
auth: { type: 'apiKey', apiKey: { name: 'apiKey' } }
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
};
|
|
@@ -135,7 +135,7 @@ describe('MCP Tool: doAuth', () => {
|
|
|
135
135
|
platforms: {
|
|
136
136
|
testCRM: {
|
|
137
137
|
name: 'testCRM',
|
|
138
|
-
auth: { type: 'apiKey' }
|
|
138
|
+
auth: { type: 'apiKey', apiKey: { name: 'apiKey' } }
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
};
|
|
@@ -203,7 +203,10 @@ describe('MCP Tool: doAuth', () => {
|
|
|
203
203
|
name: 'salesforce',
|
|
204
204
|
auth: {
|
|
205
205
|
type: 'oauth',
|
|
206
|
-
oauth: {
|
|
206
|
+
oauth: {
|
|
207
|
+
authUrl: 'https://login.salesforce.com/services/oauth2/authorize',
|
|
208
|
+
clientId: 'test-client-id'
|
|
209
|
+
}
|
|
207
210
|
}
|
|
208
211
|
}
|
|
209
212
|
}
|
|
@@ -254,7 +257,10 @@ describe('MCP Tool: doAuth', () => {
|
|
|
254
257
|
name: 'salesforce',
|
|
255
258
|
auth: {
|
|
256
259
|
type: 'oauth',
|
|
257
|
-
oauth: {
|
|
260
|
+
oauth: {
|
|
261
|
+
authUrl: 'https://login.salesforce.com/services/oauth2/authorize',
|
|
262
|
+
clientId: 'test-client-id'
|
|
263
|
+
}
|
|
258
264
|
}
|
|
259
265
|
}
|
|
260
266
|
}
|
|
@@ -264,12 +270,12 @@ describe('MCP Tool: doAuth', () => {
|
|
|
264
270
|
userInfo: null
|
|
265
271
|
});
|
|
266
272
|
|
|
267
|
-
// Act
|
|
273
|
+
// Act - callbackUri needs code= and state= to be treated as OAuth callback
|
|
268
274
|
const result = await doAuth.execute({
|
|
269
275
|
connectorManifest: mockManifest,
|
|
270
276
|
connectorName: 'salesforce',
|
|
271
277
|
hostname: 'login.salesforce.com',
|
|
272
|
-
callbackUri: 'https://redirect.com?
|
|
278
|
+
callbackUri: 'https://redirect.com?code=invalid-code&state=test-state'
|
|
273
279
|
});
|
|
274
280
|
|
|
275
281
|
// Assert
|
|
@@ -305,9 +311,16 @@ describe('MCP Tool: doAuth', () => {
|
|
|
305
311
|
connectorName: 'customCRM'
|
|
306
312
|
});
|
|
307
313
|
|
|
308
|
-
// Assert
|
|
314
|
+
// Assert - state is now URL-encoded and includes sessionId, platform, hostname, plus customState
|
|
309
315
|
expect(result.success).toBe(true);
|
|
310
|
-
|
|
316
|
+
// The state parameter now contains session info and custom state appended
|
|
317
|
+
// Decode and verify custom state is included
|
|
318
|
+
const stateMatch = result.data.authUri.match(/state=([^&]+)/);
|
|
319
|
+
expect(stateMatch).toBeTruthy();
|
|
320
|
+
const decodedState = decodeURIComponent(stateMatch[1]);
|
|
321
|
+
expect(decodedState).toContain('custom=state&other=value');
|
|
322
|
+
expect(decodedState).toContain('sessionId=');
|
|
323
|
+
expect(decodedState).toContain('platform=customCRM');
|
|
311
324
|
});
|
|
312
325
|
});
|
|
313
326
|
|
|
@@ -318,7 +331,7 @@ describe('MCP Tool: doAuth', () => {
|
|
|
318
331
|
platforms: {
|
|
319
332
|
testCRM: {
|
|
320
333
|
name: 'testCRM',
|
|
321
|
-
auth: { type: 'apiKey' }
|
|
334
|
+
auth: { type: 'apiKey', apiKey: { name: 'apiKey' } }
|
|
322
335
|
}
|
|
323
336
|
}
|
|
324
337
|
};
|