@app-connect/core 1.7.10 → 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.
Files changed (59) hide show
  1. package/connector/developerPortal.js +43 -0
  2. package/connector/proxy/index.js +10 -3
  3. package/connector/registry.js +8 -6
  4. package/handlers/admin.js +135 -22
  5. package/handlers/auth.js +89 -67
  6. package/handlers/calldown.js +10 -4
  7. package/handlers/contact.js +4 -104
  8. package/handlers/disposition.js +7 -145
  9. package/handlers/log.js +174 -258
  10. package/handlers/user.js +19 -6
  11. package/index.js +280 -47
  12. package/lib/analytics.js +3 -1
  13. package/lib/authSession.js +68 -0
  14. package/lib/callLogComposer.js +498 -420
  15. package/lib/errorHandler.js +206 -0
  16. package/lib/jwt.js +2 -0
  17. package/lib/logger.js +190 -0
  18. package/lib/oauth.js +21 -10
  19. package/lib/ringcentral.js +2 -10
  20. package/lib/sharedSMSComposer.js +471 -0
  21. package/mcp/SupportedPlatforms.md +12 -0
  22. package/mcp/lib/validator.js +91 -0
  23. package/mcp/mcpHandler.js +166 -0
  24. package/mcp/tools/checkAuthStatus.js +110 -0
  25. package/mcp/tools/collectAuthInfo.js +91 -0
  26. package/mcp/tools/createCallLog.js +308 -0
  27. package/mcp/tools/createContact.js +117 -0
  28. package/mcp/tools/createMessageLog.js +283 -0
  29. package/mcp/tools/doAuth.js +190 -0
  30. package/mcp/tools/findContactByName.js +92 -0
  31. package/mcp/tools/findContactByPhone.js +101 -0
  32. package/mcp/tools/getCallLog.js +98 -0
  33. package/mcp/tools/getGoogleFilePicker.js +103 -0
  34. package/mcp/tools/getHelp.js +44 -0
  35. package/mcp/tools/getPublicConnectors.js +53 -0
  36. package/mcp/tools/index.js +64 -0
  37. package/mcp/tools/logout.js +68 -0
  38. package/mcp/tools/rcGetCallLogs.js +78 -0
  39. package/mcp/tools/setConnector.js +69 -0
  40. package/mcp/tools/updateCallLog.js +122 -0
  41. package/models/cacheModel.js +3 -0
  42. package/package.json +71 -70
  43. package/releaseNotes.json +24 -0
  44. package/test/handlers/log.test.js +11 -4
  45. package/test/lib/logger.test.js +206 -0
  46. package/test/lib/ringcentral.test.js +0 -6
  47. package/test/lib/sharedSMSComposer.test.js +1084 -0
  48. package/test/mcp/tools/collectAuthInfo.test.js +234 -0
  49. package/test/mcp/tools/createCallLog.test.js +425 -0
  50. package/test/mcp/tools/createMessageLog.test.js +580 -0
  51. package/test/mcp/tools/doAuth.test.js +376 -0
  52. package/test/mcp/tools/findContactByName.test.js +263 -0
  53. package/test/mcp/tools/findContactByPhone.test.js +284 -0
  54. package/test/mcp/tools/getCallLog.test.js +286 -0
  55. package/test/mcp/tools/getGoogleFilePicker.test.js +281 -0
  56. package/test/mcp/tools/getPublicConnectors.test.js +128 -0
  57. package/test/mcp/tools/logout.test.js +169 -0
  58. package/test/mcp/tools/setConnector.test.js +177 -0
  59. package/test/mcp/tools/updateCallLog.test.js +346 -0
@@ -0,0 +1,101 @@
1
+ const jwt = require('../../lib/jwt');
2
+ const connectorRegistry = require('../../connector/registry');
3
+ const contactCore = require('../../handlers/contact');
4
+
5
+ /**
6
+ * MCP Tool: Find Contact
7
+ *
8
+ * This tool searches for a contact in the CRM platform by phone number.
9
+ * It uses the platform-specific connector to find matching contacts.
10
+ */
11
+
12
+ const toolDefinition = {
13
+ name: 'findContactByPhone',
14
+ description: '⚠️ REQUIRES AUTHENTICATION: User must first authenticate using the "auth" tool to obtain a JWT token before using this tool. | Search for a contact in the CRM platform by phone number. Returns contact details if found.',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ jwtToken: {
19
+ type: 'string',
20
+ description: 'JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.'
21
+ },
22
+ phoneNumber: {
23
+ type: 'string',
24
+ description: 'Phone number to search for, if not in E.164 format, convert it to E.164 format'
25
+ },
26
+ overridingFormat: {
27
+ type: 'string',
28
+ description: 'Overriding format to search for'
29
+ },
30
+ isExtension: {
31
+ type: 'boolean',
32
+ description: 'Whether the request is from an extension'
33
+ }
34
+ },
35
+ required: ['jwtToken', 'phoneNumber']
36
+ },
37
+ annotations: {
38
+ readOnlyHint: true,
39
+ openWorldHint: true,
40
+ destructiveHint: false
41
+ }
42
+ };
43
+
44
+ /**
45
+ * Execute the findContactByPhone tool
46
+ * @param {Object} args - The tool arguments
47
+ * @param {string} args.jwtToken - JWT token with user and platform info
48
+ * @param {string} [args.phoneNumber] - Phone number to search for
49
+ * @param {string} [args.overridingFormat] - Overriding format to search for
50
+ * @param {string} [args.isExtension] - Whether the request is from an extension
51
+ * @returns {Object} Result object with contact information
52
+ */
53
+ async function execute(args) {
54
+ try {
55
+ const { jwtToken, phoneNumber, overridingFormat, isExtension } = args;
56
+
57
+ // Decode JWT to get userId and platform
58
+ const { id: userId, platform } = jwt.decodeJwt(jwtToken);
59
+
60
+ if (!userId) {
61
+ throw new Error('Invalid JWT token: userId not found');
62
+ }
63
+
64
+ // Get the platform connector module
65
+ const platformModule = connectorRegistry.getConnector(platform);
66
+
67
+ if (!platformModule) {
68
+ throw new Error(`Platform connector not found for: ${platform}`);
69
+ }
70
+
71
+ // Check if findContactByPhone is implemented
72
+ if (!platformModule.findContact) {
73
+ throw new Error(`findContactByPhone is not implemented for platform: ${platform}`);
74
+ }
75
+
76
+ // Call the findContactByPhone method
77
+ const { successful, returnMessage, contact } = await contactCore.findContact({ platform, userId, phoneNumber, overridingFormat: overridingFormat ?? '', isExtension: isExtension ?? false });
78
+ if (successful) {
79
+ return {
80
+ success: true,
81
+ data: contact,
82
+ };
83
+ }
84
+ else {
85
+ return {
86
+ success: false,
87
+ error: returnMessage.message,
88
+ };
89
+ }
90
+ }
91
+ catch (error) {
92
+ return {
93
+ success: false,
94
+ error: error.message || 'Unknown error occurred',
95
+ errorDetails: error.stack
96
+ };
97
+ }
98
+ }
99
+
100
+ exports.definition = toolDefinition;
101
+ exports.execute = execute;
@@ -0,0 +1,98 @@
1
+ const jwt = require('../../lib/jwt');
2
+ const connectorRegistry = require('../../connector/registry');
3
+ const logCore = require('../../handlers/log');
4
+
5
+ /**
6
+ * MCP Tool: Get Call Log
7
+ *
8
+ * This tool retrieves call logs from the CRM platform by session IDs.
9
+ */
10
+
11
+ const toolDefinition = {
12
+ name: 'getCallLog',
13
+ description: '⚠️ REQUIRES AUTHENTICATION: User must first authenticate using the "auth" tool to obtain a JWT token before using this tool. | Get call logs from the CRM platform by session IDs. Returns log details if found.',
14
+ inputSchema: {
15
+ type: 'object',
16
+ properties: {
17
+ jwtToken: {
18
+ type: 'string',
19
+ description: 'JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.'
20
+ },
21
+ sessionIds: {
22
+ type: 'string',
23
+ description: 'Session IDs to retrieve, seprated by commas'
24
+ },
25
+ requireDetails: {
26
+ type: 'boolean',
27
+ description: 'Whether to require detailed log information. If true, will call CRM API. Otherwise will just query in our own database',
28
+ default: false
29
+ }
30
+ },
31
+ required: ['jwtToken', 'sessionIds']
32
+ }
33
+ };
34
+
35
+ /**
36
+ * Execute the getCallLog tool
37
+ * @param {Object} args - The tool arguments
38
+ * @param {string} args.jwtToken - JWT token with user and platform info
39
+ * @param {string} args.sessionIds - Session IDs to retrieve, seprated by commas
40
+ * @param {boolean} [args.requireDetails] - Whether to require detailed log information. If true, will call CRM API. Otherwise will just query in our own database.
41
+ * @returns {Object} Result object with call log information
42
+ */
43
+ async function execute(args) {
44
+ try {
45
+ const { jwtToken, sessionIds, requireDetails = false } = args;
46
+
47
+ // Decode JWT to get userId and platform
48
+ const { id: userId, platform } = jwt.decodeJwt(jwtToken);
49
+
50
+ if (!userId) {
51
+ throw new Error('Invalid JWT token: userId not found');
52
+ }
53
+
54
+ // Get the platform connector module
55
+ const platformModule = connectorRegistry.getConnector(platform);
56
+
57
+ if (!platformModule) {
58
+ throw new Error(`Platform connector not found for: ${platform}`);
59
+ }
60
+
61
+ // Check if getCallLog is implemented
62
+ if (!platformModule.getCallLog) {
63
+ throw new Error(`getCallLog is not implemented for platform: ${platform}`);
64
+ }
65
+
66
+ // Call the getCallLog method
67
+ const { successful, logs, returnMessage } = await logCore.getCallLog({
68
+ userId,
69
+ sessionIds,
70
+ platform,
71
+ requireDetails
72
+ });
73
+
74
+ if (successful) {
75
+ return {
76
+ success: true,
77
+ data: logs,
78
+ };
79
+ }
80
+ else {
81
+ return {
82
+ success: false,
83
+ error: returnMessage.message,
84
+ };
85
+ }
86
+ }
87
+ catch (error) {
88
+ return {
89
+ success: false,
90
+ error: error.message || 'Unknown error occurred',
91
+ errorDetails: error.stack
92
+ };
93
+ }
94
+ }
95
+
96
+ exports.definition = toolDefinition;
97
+ exports.execute = execute;
98
+
@@ -0,0 +1,103 @@
1
+ const jwt = require('../../lib/jwt');
2
+ const { UserModel } = require('../../models/userModel');
3
+ const axios = require('axios');
4
+
5
+ /**
6
+ * MCP Tool: Get Google File Picker
7
+ *
8
+ * Returns the URL for the Google Sheets file picker.
9
+ * The user must visit this URL in a browser to select a Google Sheet.
10
+ */
11
+
12
+ const toolDefinition = {
13
+ name: 'getGoogleFilePicker',
14
+ description: '⚠️ REQUIRES AUTHENTICATION: User must first authenticate with googleSheets platform. | Returns a URL for the Google Sheets file picker (1st preference) OR create a new sheet with input sheet name (2nd preference). The user should open this URL in their browser to select a Google Sheet for logging.',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ jwtToken: {
19
+ type: 'string',
20
+ description: 'JWT token obtained from authentication. If user does not have this, direct them to use the "doAuth" tool first with googleSheets platform.'
21
+ },
22
+ sheetName: {
23
+ type: 'string',
24
+ description: 'OPTIONAL. Name of the new sheet to create.'
25
+ }
26
+ },
27
+ required: ['jwtToken']
28
+ },
29
+ annotations: {
30
+ readOnlyHint: false,
31
+ openWorldHint: true,
32
+ destructiveHint: false
33
+ }
34
+ };
35
+
36
+ /**
37
+ * Execute the getGoogleFilePicker tool
38
+ * @param {Object} args - The tool arguments
39
+ * @param {string} args.jwtToken - JWT token containing userId
40
+ * @param {string} args.sheetName - Name of the new sheet to create
41
+ * @returns {Object} Result object with file picker URL
42
+ */
43
+ async function execute(args) {
44
+ try {
45
+ const { jwtToken, sheetName } = args;
46
+
47
+ if (!jwtToken) {
48
+ return {
49
+ success: false,
50
+ error: 'JWT token is required. Please authenticate with googleSheets platform first using the doAuth tool.'
51
+ };
52
+ }
53
+
54
+ // Decode JWT to get userId
55
+ const unAuthData = jwt.decodeJwt(jwtToken);
56
+
57
+ if (!unAuthData?.id) {
58
+ return {
59
+ success: false,
60
+ error: 'Invalid JWT token: userId not found'
61
+ };
62
+ }
63
+
64
+ // Find the user
65
+ const user = await UserModel.findByPk(unAuthData.id);
66
+
67
+ if (!user) {
68
+ return {
69
+ success: false,
70
+ error: 'User not found. Please authenticate with googleSheets platform first.'
71
+ };
72
+ }
73
+
74
+
75
+ if (sheetName) {
76
+ const createSheetResponse = await axios.post(`${process.env.APP_SERVER}/googleSheets/sheet?jwtToken=${jwtToken}`, { name: sheetName });
77
+ return createSheetResponse.data;
78
+ }
79
+ else {
80
+ // Generate the file picker URL
81
+ const filePickerUrl = `${process.env.APP_SERVER}/googleSheets/filePicker?token=${jwtToken}}`;
82
+
83
+ return {
84
+ success: true,
85
+ data: {
86
+ filePickerUrl,
87
+ message: 'Please open this URL in a browser to select a Google Sheet. After selecting a sheet, it will be configured for logging your calls and messages.'
88
+ }
89
+ };
90
+ }
91
+ }
92
+ catch (error) {
93
+ return {
94
+ success: false,
95
+ error: error.message || 'Unknown error occurred',
96
+ errorDetails: error.stack
97
+ };
98
+ }
99
+ }
100
+
101
+ exports.definition = toolDefinition;
102
+ exports.execute = execute;
103
+
@@ -0,0 +1,44 @@
1
+ /**
2
+ * MCP Tool: Get Help
3
+ *
4
+ * This tool provides users with a friendly guide to available capabilities
5
+ * and how to get started with the RingCentral CRM integration.
6
+ */
7
+
8
+ const toolDefinition = {
9
+ name: 'getHelp',
10
+ description: 'Get a quick guide on what this integration can do and how to get started.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {},
14
+ required: []
15
+ },
16
+ annotations: {
17
+ readOnlyHint: true,
18
+ openWorldHint: false,
19
+ destructiveHint: false
20
+ }
21
+ };
22
+
23
+ /**
24
+ * Execute the getHelp tool
25
+ * @returns {Object} Result object with help information
26
+ */
27
+ async function execute() {
28
+ return {
29
+ success: true,
30
+ data: {
31
+ overview: "I help you connect RingCentral with your CRM to log calls.",
32
+ steps:[
33
+ '1. Tell me to show all connectors and let me connect you to your CRM',
34
+ '2. Follow authorization flow to authorize your CRM',
35
+ '3. Once authorized, I can help find contacts and log your calls'
36
+ ],
37
+ supportedCRMs: ["Clio", "Google Sheets"],
38
+ }
39
+ };
40
+ }
41
+
42
+ exports.definition = toolDefinition;
43
+ exports.execute = execute;
44
+
@@ -0,0 +1,53 @@
1
+ const developerPortal = require('../../connector/developerPortal');
2
+
3
+ /**
4
+ * MCP Tool: Get Public Connectors
5
+ *
6
+ * This tool retrieves a list of public connectors from the developer portal.
7
+ */
8
+
9
+ const toolDefinition = {
10
+ name: 'getPublicConnectors',
11
+ description: 'Auth flow step.1. Get a list of all available connectors from the developer portal. Returns a list of connector names for users to choose. Next step is calling step.2 "setConnector" tool.',
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {},
15
+ required: []
16
+ },
17
+ annotations: {
18
+ readOnlyHint: true,
19
+ openWorldHint: false,
20
+ destructiveHint: false
21
+ }
22
+ };
23
+
24
+ const supportedPlatforms = ['googleSheets','clio'];
25
+
26
+ /**
27
+ * Execute the getPublicConnectors tool
28
+ * @returns {Object} Result object with connector names
29
+ */
30
+ async function execute() {
31
+ try {
32
+ const { connectors: publicConnectorList } = await developerPortal.getPublicConnectorList();
33
+ const connectorList = publicConnectorList;
34
+ if(process.env.RC_ACCOUNT_ID) {
35
+ const { privateConnectors } = await developerPortal.getPrivateConnectorList();
36
+ connectorList.push(...privateConnectors);
37
+ }
38
+ return {
39
+ success: true,
40
+ data: connectorList.filter(c => supportedPlatforms.includes(c.name)).map(c => c.displayName)
41
+ };
42
+ }
43
+ catch (error) {
44
+ return {
45
+ success: false,
46
+ error: error.message || 'Unknown error occurred',
47
+ errorDetails: error.stack
48
+ };
49
+ }
50
+ }
51
+
52
+ exports.definition = toolDefinition;
53
+ exports.execute = execute;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MCP Tools Index
3
+ *
4
+ * This file exports all available MCP tools for the RC Unified CRM Extension.
5
+ */
6
+
7
+ // const auth = require('./auth');
8
+ const getHelp = require('./getHelp');
9
+ const getPublicConnectors = require('./getPublicConnectors');
10
+ const setConnector = require('./setConnector');
11
+ const collectAuthInfo = require('./collectAuthInfo');
12
+ const doAuth = require('./doAuth');
13
+ const checkAuthStatus = require('./checkAuthStatus');
14
+ const logout = require('./logout');
15
+ const findContact = require('./findContactByPhone');
16
+ const findContactWithName = require('./findContactByName');
17
+ const getCallLog = require('./getCallLog');
18
+ const createCallLog = require('./createCallLog');
19
+ const updateCallLog = require('./updateCallLog');
20
+ const createMessageLog = require('./createMessageLog');
21
+ const rcGetCallLogs = require('./rcGetCallLogs');
22
+ const getGoogleFilePicker = require('./getGoogleFilePicker');
23
+ const createContact = require('./createContact');
24
+
25
+ // Export all tools
26
+ module.exports = {
27
+ getHelp,
28
+ getPublicConnectors,
29
+ setConnector,
30
+ collectAuthInfo,
31
+ doAuth,
32
+ checkAuthStatus,
33
+ logout,
34
+ findContact,
35
+ findContactWithName,
36
+ //getCallLog,
37
+ createCallLog,
38
+ //updateCallLog,
39
+ //createMessageLog,
40
+ rcGetCallLogs,
41
+ getGoogleFilePicker,
42
+ createContact
43
+ };
44
+
45
+ // Export tools as an array for easy iteration
46
+ module.exports.tools = [
47
+ getHelp,
48
+ getPublicConnectors,
49
+ setConnector,
50
+ collectAuthInfo,
51
+ doAuth,
52
+ checkAuthStatus,
53
+ logout,
54
+ findContact,
55
+ findContactWithName,
56
+ //getCallLog,
57
+ createCallLog,
58
+ //updateCallLog,
59
+ //createMessageLog,
60
+ rcGetCallLogs,
61
+ getGoogleFilePicker,
62
+ createContact
63
+ ];
64
+
@@ -0,0 +1,68 @@
1
+ const jwt = require('../../lib/jwt');
2
+ const { UserModel } = require('../../models/userModel');
3
+ const connectorRegistry = require('../../connector/registry');
4
+
5
+ /**
6
+ * MCP Tool: Logout
7
+ *
8
+ * This tool logs out the user from the CRM platform.
9
+ */
10
+
11
+ const toolDefinition = {
12
+ name: 'logout',
13
+ description: 'Logout the user from the CRM platform.',
14
+ inputSchema: {
15
+ type: 'object',
16
+ properties: {
17
+ jwtToken: {
18
+ type: 'string',
19
+ description: 'JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.'
20
+ }
21
+ }
22
+ },
23
+ annotations: {
24
+ readOnlyHint: false,
25
+ openWorldHint: false,
26
+ destructiveHint: true
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Execute the logout tool
32
+ * @param {Object} args - The tool arguments
33
+ * @param {string} args.jwtToken - JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.
34
+ * @returns {Object} Result object with logout information
35
+ */
36
+ async function execute(args) {
37
+ try {
38
+ const { jwtToken } = args;
39
+ const { platform, id } = jwt.decodeJwt(jwtToken);
40
+
41
+ const userToLogout = await UserModel.findByPk(id);
42
+ if (!userToLogout) {
43
+ return {
44
+ success: false,
45
+ error: "User not found",
46
+ errorDetails: "User not found",
47
+ };
48
+ }
49
+ const platformModule = connectorRegistry.getConnector(platform);
50
+ await platformModule.unAuthorize({ user: userToLogout });
51
+ return {
52
+ success: true,
53
+ data: {
54
+ message: "IMPORTANT: Logout successful. Clear jwtToken, connectorManifest, connectorDisplayName, hostname and connectorName in memory. User is logged out from the CRM platform.",
55
+ }
56
+ }
57
+ }
58
+ catch (error) {
59
+ return {
60
+ success: false,
61
+ error: error.message || 'Unknown error occurred',
62
+ errorDetails: error.stack
63
+ };
64
+ }
65
+ }
66
+
67
+ exports.definition = toolDefinition;
68
+ exports.execute = execute;
@@ -0,0 +1,78 @@
1
+ const { RingCentral } = require('../../lib/ringcentral');
2
+ const jwt = require('../../lib/jwt');
3
+ const { CallLogModel } = require('../../models/callLogModel');
4
+
5
+ const toolDefinition = {
6
+ name: 'rcGetCallLogs',
7
+ description: '⚠️ REQUIRES AUTHENTICATION: User must first authenticate using the "auth" tool to obtain a JWT token before using this tool. | Get call logs from RingCentral',
8
+ inputSchema: {
9
+ type: 'object',
10
+ properties: {
11
+ jwtToken: {
12
+ type: 'string',
13
+ description: 'JWT token containing userId and platform information. If user does not have this, direct them to use the "auth" tool first.'
14
+ },
15
+ timeFrom: {
16
+ type: 'string',
17
+ description: 'MUST be ISO string. Default is 24 hours ago.'
18
+ },
19
+ timeTo: {
20
+ type: 'string',
21
+ description: 'MUST be ISO string. Default is now.'
22
+ }
23
+ },
24
+ required: ['jwtToken', 'timeFrom', 'timeTo']
25
+ },
26
+ annotations: {
27
+ readOnlyHint: true,
28
+ openWorldHint: false,
29
+ destructiveHint: false
30
+ }
31
+ }
32
+
33
+ async function execute(args) {
34
+ try {
35
+ const { jwtToken, rcAccessToken, timeFrom, timeTo } = args;
36
+ if (!rcAccessToken) {
37
+ throw new Error('RingCentral access token not found');
38
+ }
39
+ const { id: userId } = jwt.decodeJwt(jwtToken);
40
+ if (!userId) {
41
+ throw new Error('Invalid JWT token: userId not found');
42
+ }
43
+ const rcSDK = new RingCentral({
44
+ server: process.env.RINGCENTRAL_SERVER,
45
+ clientId: process.env.RINGCENTRAL_CLIENT_ID,
46
+ clientSecret: process.env.RINGCENTRAL_CLIENT_SECRET,
47
+ redirectUri: `${process.env.APP_SERVER}/ringcentral/oauth/callback`
48
+ });
49
+ const callLogData = await rcSDK.getCallLogData({
50
+ token: { access_token: rcAccessToken, token_type: 'Bearer' },
51
+ timeFrom: timeFrom ?? new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
52
+ timeTo: timeTo ?? new Date().toISOString(),
53
+ });
54
+ // hack: remove already logged calls
55
+ const existingCalls = [];
56
+ for (const call of callLogData.records) {
57
+ const existingCallLog = await CallLogModel.findOne({
58
+ where: {
59
+ sessionId: call.sessionId
60
+ }
61
+ });
62
+ if (existingCallLog) {
63
+ existingCalls.push(existingCallLog.sessionId);
64
+ }
65
+ }
66
+ callLogData.records = callLogData.records.filter(call => !existingCalls.includes(call.sessionId));
67
+ return callLogData;
68
+ }
69
+ catch (e) {
70
+ return {
71
+ success: false,
72
+ error: e.message
73
+ }
74
+ }
75
+ }
76
+
77
+ exports.definition = toolDefinition;
78
+ exports.execute = execute;
@@ -0,0 +1,69 @@
1
+ const developerPortal = require('../../connector/developerPortal');
2
+
3
+ /**
4
+ * MCP Tool: Set Connector
5
+ *
6
+ * This tool helps the user set the connector.
7
+ */
8
+
9
+ const toolDefinition = {
10
+ name: 'setConnector',
11
+ description: 'Auth flow step.2. Save connectorManifest to memory if successful.',
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ connectorDisplayName: {
16
+ type: 'string',
17
+ description: 'Connector displayname to set'
18
+ }
19
+ },
20
+ required: ['connectorDisplayName']
21
+ },
22
+ annotations: {
23
+ readOnlyHint: true,
24
+ openWorldHint: false,
25
+ destructiveHint: false
26
+ }
27
+ };
28
+
29
+ /**
30
+ * Execute the setConnector tool
31
+ * @param {Object} args - The tool arguments
32
+ * @param {string} args.connectorDisplayName - Connector display name to set
33
+ * @returns {Object} Result object with connector information
34
+ */
35
+ async function execute(args) {
36
+ try {
37
+ const { connectorDisplayName } = args;
38
+ const { connectors: publicConnectorList } = await developerPortal.getPublicConnectorList();
39
+ const { privateConnectors } = await developerPortal.getPrivateConnectorList();
40
+ const connectorList = [...publicConnectorList, ...privateConnectors];
41
+ const connector = connectorList.find(c => c.displayName === connectorDisplayName);
42
+ const connectorName = connector.name;
43
+ const connectorManifest = await developerPortal.getConnectorManifest({ connectorId: connector.id, isPrivate: connector.status === 'private' });
44
+ if (!connectorManifest) {
45
+ throw new Error(`Connector manifest not found: ${connectorDisplayName}`);
46
+ }
47
+ return {
48
+ success: true,
49
+ data: {
50
+ connectorManifest,
51
+ connectorDisplayName,
52
+ connectorName,
53
+ // Add explicit instruction
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'.",
55
+
56
+ }
57
+ };
58
+ }
59
+ catch (error) {
60
+ return {
61
+ success: false,
62
+ error: error.message || 'Unknown error occurred',
63
+ errorDetails: error.stack
64
+ };
65
+ }
66
+ }
67
+
68
+ exports.definition = toolDefinition;
69
+ exports.execute = execute;