@app-connect/core 1.7.37 → 1.7.38

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 (286) hide show
  1. package/README.md +17 -16
  2. package/dist/connector/developerPortal.d.ts +6 -0
  3. package/{connector → dist/connector}/developerPortal.js +29 -12
  4. package/dist/connector/mock.d.ts +1 -0
  5. package/{connector → dist/connector}/mock.js +33 -17
  6. package/dist/connector/proxy/engine.d.ts +10 -0
  7. package/dist/connector/proxy/engine.js +222 -0
  8. package/dist/connector/proxy/index.d.ts +5 -0
  9. package/dist/connector/proxy/index.js +511 -0
  10. package/dist/connector/registry.d.ts +1 -0
  11. package/dist/connector/registry.js +243 -0
  12. package/dist/handlers/admin.d.ts +1 -0
  13. package/{handlers → dist/handlers}/admin.js +137 -78
  14. package/dist/handlers/appointment.d.ts +9 -0
  15. package/{handlers → dist/handlers}/appointment.js +58 -29
  16. package/dist/handlers/auth.d.ts +9 -0
  17. package/{handlers → dist/handlers}/auth.js +68 -40
  18. package/dist/handlers/calldown.d.ts +10 -0
  19. package/dist/handlers/calldown.js +134 -0
  20. package/dist/handlers/contact.d.ts +1 -0
  21. package/{handlers → dist/handlers}/contact.js +61 -39
  22. package/dist/handlers/disposition.d.ts +1 -0
  23. package/{handlers → dist/handlers}/disposition.js +20 -10
  24. package/dist/handlers/log.d.ts +1 -0
  25. package/{handlers → dist/handlers}/log.js +91 -124
  26. package/dist/handlers/managedAuth.d.ts +1 -0
  27. package/{handlers → dist/handlers}/managedAuth.js +134 -61
  28. package/dist/handlers/managedOAuth.d.ts +13 -0
  29. package/{handlers → dist/handlers}/managedOAuth.js +102 -30
  30. package/dist/handlers/plugin.d.ts +1 -0
  31. package/{handlers → dist/handlers}/plugin.js +59 -27
  32. package/dist/handlers/user.d.ts +1 -0
  33. package/{handlers → dist/handlers}/user.js +45 -27
  34. package/dist/index.d.ts +1 -0
  35. package/{index.js → dist/index.js} +538 -449
  36. package/dist/jest.config.d.ts +1 -0
  37. package/dist/jest.config.js +65 -0
  38. package/dist/lib/analytics.d.ts +4 -0
  39. package/{lib → dist/lib}/analytics.js +8 -6
  40. package/dist/lib/authSession.d.ts +5 -0
  41. package/{lib → dist/lib}/authSession.js +15 -43
  42. package/dist/lib/cacheCleanup.d.ts +4 -0
  43. package/{lib → dist/lib}/cacheCleanup.js +5 -17
  44. package/dist/lib/callLogComposer.d.ts +109 -0
  45. package/{lib → dist/lib}/callLogComposer.js +157 -197
  46. package/dist/lib/callLogLookup.d.ts +6 -0
  47. package/{lib → dist/lib}/callLogLookup.js +12 -34
  48. package/dist/lib/constants.d.ts +6 -0
  49. package/dist/lib/constants.js +9 -0
  50. package/dist/lib/debugTracer.d.ts +17 -0
  51. package/{lib → dist/lib}/debugTracer.js +7 -83
  52. package/dist/lib/encode.d.ts +3 -0
  53. package/dist/lib/encode.js +50 -0
  54. package/dist/lib/errorHandler.d.ts +7 -0
  55. package/dist/lib/errorHandler.js +161 -0
  56. package/dist/lib/generalErrorMessage.d.ts +7 -0
  57. package/{lib → dist/lib}/generalErrorMessage.js +6 -6
  58. package/dist/lib/jwt.d.ts +4 -0
  59. package/dist/lib/jwt.js +18 -0
  60. package/dist/lib/logger.d.ts +24 -0
  61. package/dist/lib/logger.js +126 -0
  62. package/dist/lib/migrateCallLogsSchema.d.ts +32 -0
  63. package/{lib → dist/lib}/migrateCallLogsSchema.js +75 -160
  64. package/dist/lib/oauth.d.ts +4 -0
  65. package/{lib → dist/lib}/oauth.js +157 -160
  66. package/dist/lib/ringcentral.d.ts +24 -0
  67. package/dist/lib/ringcentral.js +226 -0
  68. package/dist/lib/s3ErrorLogReport.d.ts +4 -0
  69. package/{lib → dist/lib}/s3ErrorLogReport.js +11 -23
  70. package/dist/lib/sharedSMSComposer.d.ts +7 -0
  71. package/{lib → dist/lib}/sharedSMSComposer.js +21 -107
  72. package/dist/lib/util.d.ts +7 -0
  73. package/{lib → dist/lib}/util.js +9 -20
  74. package/dist/mcp/lib/oauthError.d.ts +1 -0
  75. package/dist/mcp/lib/oauthError.js +25 -0
  76. package/dist/mcp/lib/validator.d.ts +1 -0
  77. package/{mcp → dist/mcp}/lib/validator.js +16 -20
  78. package/dist/mcp/lib/widgetSessionToken.d.ts +1 -0
  79. package/dist/mcp/lib/widgetSessionToken.js +46 -0
  80. package/dist/mcp/mcpHandler.d.ts +8 -0
  81. package/{mcp → dist/mcp}/mcpHandler.js +98 -88
  82. package/dist/mcp/tools/cancelAppointment.d.ts +1 -0
  83. package/{mcp → dist/mcp}/tools/cancelAppointment.js +7 -16
  84. package/dist/mcp/tools/checkAuthStatus.d.ts +1 -0
  85. package/{mcp → dist/mcp}/tools/checkAuthStatus.js +21 -14
  86. package/dist/mcp/tools/confirmAppointment.d.ts +1 -0
  87. package/{mcp → dist/mcp}/tools/confirmAppointment.js +7 -16
  88. package/dist/mcp/tools/createAppointment.d.ts +1 -0
  89. package/{mcp → dist/mcp}/tools/createAppointment.js +7 -19
  90. package/dist/mcp/tools/createCallLog.d.ts +1 -0
  91. package/{mcp → dist/mcp}/tools/createCallLog.js +18 -29
  92. package/dist/mcp/tools/createContact.d.ts +1 -0
  93. package/{mcp → dist/mcp}/tools/createContact.js +8 -20
  94. package/dist/mcp/tools/createMessageLog.d.ts +1 -0
  95. package/{mcp → dist/mcp}/tools/createMessageLog.js +14 -26
  96. package/dist/mcp/tools/doAuth.d.ts +1 -0
  97. package/{mcp → dist/mcp}/tools/doAuth.js +17 -13
  98. package/dist/mcp/tools/findContactByName.d.ts +1 -0
  99. package/{mcp → dist/mcp}/tools/findContactByName.js +9 -15
  100. package/dist/mcp/tools/findContactByPhone.d.ts +1 -0
  101. package/{mcp → dist/mcp}/tools/findContactByPhone.js +8 -15
  102. package/dist/mcp/tools/getCallLog.d.ts +1 -0
  103. package/{mcp → dist/mcp}/tools/getCallLog.js +12 -21
  104. package/dist/mcp/tools/getGoogleFilePicker.d.ts +1 -0
  105. package/{mcp → dist/mcp}/tools/getGoogleFilePicker.js +9 -18
  106. package/dist/mcp/tools/getHelp.d.ts +1 -0
  107. package/{mcp → dist/mcp}/tools/getHelp.js +5 -6
  108. package/dist/mcp/tools/getPublicConnectors.d.ts +1 -0
  109. package/{mcp → dist/mcp}/tools/getPublicConnectors.js +19 -18
  110. package/dist/mcp/tools/getSessionInfo.d.ts +1 -0
  111. package/{mcp → dist/mcp}/tools/getSessionInfo.js +10 -16
  112. package/dist/mcp/tools/index.d.ts +8 -0
  113. package/dist/mcp/tools/index.js +50 -0
  114. package/dist/mcp/tools/listAppointments.d.ts +1 -0
  115. package/{mcp → dist/mcp}/tools/listAppointments.js +7 -19
  116. package/dist/mcp/tools/logout.d.ts +1 -0
  117. package/{mcp → dist/mcp}/tools/logout.js +16 -14
  118. package/dist/mcp/tools/rcGetCallLogs.d.ts +1 -0
  119. package/{mcp → dist/mcp}/tools/rcGetCallLogs.js +10 -8
  120. package/dist/mcp/tools/updateAppointment.d.ts +1 -0
  121. package/{mcp → dist/mcp}/tools/updateAppointment.js +17 -22
  122. package/dist/mcp/tools/updateCallLog.d.ts +1 -0
  123. package/{mcp → dist/mcp}/tools/updateCallLog.js +16 -26
  124. package/dist/models/accountDataModel.d.ts +3 -0
  125. package/dist/models/accountDataModel.js +39 -0
  126. package/dist/models/adminConfigModel.d.ts +2 -0
  127. package/dist/models/adminConfigModel.js +39 -0
  128. package/dist/models/cacheModel.d.ts +2 -0
  129. package/{models → dist/models}/cacheModel.js +7 -3
  130. package/dist/models/callDownListModel.d.ts +2 -0
  131. package/{models → dist/models}/callDownListModel.js +8 -4
  132. package/dist/models/callLogModel.d.ts +2 -0
  133. package/dist/models/callLogModel.js +43 -0
  134. package/dist/models/dynamo/connectorSchema.d.ts +2 -0
  135. package/dist/models/dynamo/connectorSchema.js +141 -0
  136. package/dist/models/dynamo/lockSchema.d.ts +2 -0
  137. package/{models → dist/models}/dynamo/lockSchema.js +5 -7
  138. package/dist/models/dynamo/noteCacheSchema.d.ts +2 -0
  139. package/{models → dist/models}/dynamo/noteCacheSchema.js +4 -6
  140. package/dist/models/llmSessionModel.d.ts +2 -0
  141. package/dist/models/llmSessionModel.js +21 -0
  142. package/dist/models/messageLogModel.d.ts +2 -0
  143. package/{models → dist/models}/messageLogModel.js +8 -4
  144. package/dist/models/sequelize.d.ts +2 -0
  145. package/dist/models/sequelize.js +68 -0
  146. package/dist/models/userModel.d.ts +2 -0
  147. package/dist/models/userModel.js +49 -0
  148. package/dist/package.json +100 -0
  149. package/dist/releaseNotes.json +1222 -0
  150. package/dist/tsconfig.json +14 -0
  151. package/dist/types/admin.d.ts +141 -0
  152. package/dist/types/analytics.d.ts +14 -0
  153. package/dist/types/appointment.d.ts +50 -0
  154. package/dist/types/auth.d.ts +137 -0
  155. package/dist/types/authSession.d.ts +35 -0
  156. package/dist/types/cacheCleanup.d.ts +12 -0
  157. package/dist/types/calldown.d.ts +54 -0
  158. package/dist/types/common.d.ts +46 -0
  159. package/dist/types/connector.d.ts +165 -0
  160. package/dist/types/contact.d.ts +125 -0
  161. package/dist/types/errorHandler.d.ts +60 -0
  162. package/dist/types/index.d.ts +76 -0
  163. package/dist/types/json.d.ts +9 -0
  164. package/dist/types/jwt.d.ts +8 -0
  165. package/dist/types/logging.d.ts +224 -0
  166. package/dist/types/managedAuth.d.ts +114 -0
  167. package/dist/types/managedOAuth.d.ts +59 -0
  168. package/dist/types/manifest.d.ts +120 -0
  169. package/dist/types/migration.d.ts +15 -0
  170. package/dist/types/plugin.d.ts +74 -0
  171. package/dist/types/ringcentral.d.ts +61 -0
  172. package/dist/types/s3ErrorLogReport.d.ts +16 -0
  173. package/dist/types/sharedSMSComposer.d.ts +105 -0
  174. package/dist/types/user.d.ts +46 -0
  175. package/dist/types/util.d.ts +7 -0
  176. package/package.json +34 -6
  177. package/releaseNotes.json +8 -0
  178. package/.env.test +0 -5
  179. package/connector/proxy/engine.js +0 -165
  180. package/connector/proxy/index.js +0 -500
  181. package/connector/registry.js +0 -252
  182. package/docs/README.md +0 -50
  183. package/docs/architecture.md +0 -94
  184. package/docs/connectors.md +0 -116
  185. package/docs/handlers.md +0 -128
  186. package/docs/libraries.md +0 -98
  187. package/docs/models.md +0 -146
  188. package/docs/routes.md +0 -119
  189. package/docs/tests.md +0 -73
  190. package/handlers/calldown.js +0 -99
  191. package/jest.config.js +0 -57
  192. package/lib/constants.js +0 -9
  193. package/lib/encode.js +0 -30
  194. package/lib/errorHandler.js +0 -218
  195. package/lib/jwt.js +0 -18
  196. package/lib/logger.js +0 -190
  197. package/lib/ringcentral.js +0 -267
  198. package/mcp/README.md +0 -420
  199. package/mcp/tools/index.js +0 -51
  200. package/mcp/ui/App/App.tsx +0 -358
  201. package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
  202. package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
  203. package/mcp/ui/App/components/ConnectorList.tsx +0 -82
  204. package/mcp/ui/App/components/DebugPanel.tsx +0 -43
  205. package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
  206. package/mcp/ui/App/lib/callTool.ts +0 -130
  207. package/mcp/ui/App/lib/debugLog.ts +0 -41
  208. package/mcp/ui/App/lib/developerPortal.ts +0 -111
  209. package/mcp/ui/App/main.css +0 -6
  210. package/mcp/ui/App/root.tsx +0 -13
  211. package/mcp/ui/dist/index.html +0 -53
  212. package/mcp/ui/vite.config.ts +0 -16
  213. package/models/accountDataModel.js +0 -34
  214. package/models/adminConfigModel.js +0 -35
  215. package/models/callLogModel.js +0 -39
  216. package/models/dynamo/connectorSchema.js +0 -146
  217. package/models/llmSessionModel.js +0 -17
  218. package/models/sequelize.js +0 -17
  219. package/models/userModel.js +0 -45
  220. package/test/connector/developerPortal.test.js +0 -166
  221. package/test/connector/mock.test.js +0 -131
  222. package/test/connector/proxy/engine.test.js +0 -211
  223. package/test/connector/proxy/index.test.js +0 -525
  224. package/test/connector/proxy/sample.json +0 -162
  225. package/test/connector/registry.test.js +0 -416
  226. package/test/handlers/admin.test.js +0 -960
  227. package/test/handlers/appointment.test.js +0 -260
  228. package/test/handlers/auth.test.js +0 -1096
  229. package/test/handlers/calldown.test.js +0 -310
  230. package/test/handlers/contact.test.js +0 -1014
  231. package/test/handlers/disposition.test.js +0 -396
  232. package/test/handlers/log.test.js +0 -1847
  233. package/test/handlers/managedAuth.test.js +0 -458
  234. package/test/handlers/managedOAuth.test.js +0 -262
  235. package/test/handlers/plugin.test.js +0 -429
  236. package/test/handlers/user.test.js +0 -381
  237. package/test/index.test.js +0 -301
  238. package/test/lib/analytics.test.js +0 -146
  239. package/test/lib/authSession.test.js +0 -173
  240. package/test/lib/cacheCleanup.test.js +0 -127
  241. package/test/lib/callLogComposer.test.js +0 -1231
  242. package/test/lib/debugTracer.test.js +0 -328
  243. package/test/lib/encode.test.js +0 -59
  244. package/test/lib/errorHandler.test.js +0 -246
  245. package/test/lib/generalErrorMessage.test.js +0 -82
  246. package/test/lib/jwt.test.js +0 -176
  247. package/test/lib/logger.test.js +0 -206
  248. package/test/lib/oauth.test.js +0 -359
  249. package/test/lib/ringcentral.test.js +0 -467
  250. package/test/lib/s3ErrorLogReport.test.js +0 -187
  251. package/test/lib/sharedSMSComposer.test.js +0 -1084
  252. package/test/lib/util.test.js +0 -329
  253. package/test/mcp/mcpHandler.test.js +0 -73
  254. package/test/mcp/mcpHandlerMore.test.js +0 -384
  255. package/test/mcp/tools/appointmentTools.test.js +0 -362
  256. package/test/mcp/tools/checkAuthStatus.test.js +0 -83
  257. package/test/mcp/tools/createCallLog.test.js +0 -436
  258. package/test/mcp/tools/createContact.test.js +0 -58
  259. package/test/mcp/tools/createMessageLog.test.js +0 -595
  260. package/test/mcp/tools/doAuth.test.js +0 -113
  261. package/test/mcp/tools/findContactByName.test.js +0 -275
  262. package/test/mcp/tools/findContactByPhone.test.js +0 -296
  263. package/test/mcp/tools/getCallLog.test.js +0 -298
  264. package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
  265. package/test/mcp/tools/getPublicConnectors.test.js +0 -107
  266. package/test/mcp/tools/getSessionInfo.test.js +0 -127
  267. package/test/mcp/tools/logout.test.js +0 -233
  268. package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
  269. package/test/mcp/tools/updateCallLog.test.js +0 -360
  270. package/test/models/accountDataModel.test.js +0 -98
  271. package/test/models/callDownListModel.test.js +0 -125
  272. package/test/models/dynamo/connectorSchema.test.js +0 -189
  273. package/test/models/dynamo/lockSchema.test.js +0 -37
  274. package/test/models/dynamo/noteCacheSchema.test.js +0 -45
  275. package/test/models/llmSessionModel.test.js +0 -91
  276. package/test/models/models.test.js +0 -660
  277. package/test/routes/calldownRoutes.test.js +0 -224
  278. package/test/routes/coreRouterBroadRoutes.test.js +0 -855
  279. package/test/routes/dispositionRoutes.test.js +0 -192
  280. package/test/routes/managedAuthRoutes.test.js +0 -386
  281. package/test/routes/pluginRoutes.test.js +0 -262
  282. package/test/setup.js +0 -178
  283. /package/{mcp → dist/mcp}/ui/index.html +0 -0
  284. /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
  285. /package/{mcp → dist/mcp}/ui/package.json +0 -0
  286. /package/{mcp → dist/mcp}/ui/tsconfig.json +0 -0
package/mcp/README.md DELETED
@@ -1,420 +0,0 @@
1
- # MCP Module Documentation
2
-
3
- ## Overview
4
-
5
- The MCP (Model Context Protocol) module provides an AI assistant interface for the RingCentral Unified CRM Extension. It enables AI assistants like ChatGPT to interact with the CRM integration through a standardized protocol, allowing users to authenticate, manage contacts, and log calls via conversational AI.
6
-
7
- ## Architecture
8
-
9
- ```
10
- packages/core/mcp/
11
- ├── mcpHandler.js # Main MCP server handler + WIDGET_VERSION constant
12
- ├── lib/
13
- │ └── validator.js # Connector manifest validation
14
- ├── tools/ # MCP tool implementations
15
- │ ├── index.js # Tool registry (tools + widgetTools)
16
- │ ├── getHelp.js # Help/onboarding tool
17
- │ ├── getPublicConnectors.js # Triggers widget, resolves RC account ID + rcExtensionId + openaiSessionId
18
- │ ├── doAuth.js # OAuth session creation (widget-only)
19
- │ ├── checkAuthStatus.js # Poll OAuth status (widget-only)
20
- │ ├── logout.js # Logout from CRM
21
- │ ├── findContactByPhone.js # Search contact by phone
22
- │ ├── findContactByName.js # Search contact by name
23
- │ ├── createContact.js # Create new contact
24
- │ ├── createCallLog.js # Create call log entry
25
- │ ├── rcGetCallLogs.js # Fetch RingCentral call logs
26
- │ ├── listAppointments.js # List appointments (upcoming/today/past/all/custom)
27
- │ ├── createAppointment.js # Create a new appointment/event
28
- │ ├── updateAppointment.js # Update/reschedule an appointment/event
29
- │ ├── confirmAppointment.js # Confirm an appointment/event
30
- │ ├── cancelAppointment.js # Cancel an appointment/event
31
- │ ├── getGoogleFilePicker.js # Google Sheets picker (disabled)
32
- │ ├── getCallLog.js # Get call log (disabled)
33
- │ ├── updateCallLog.js # Update call log (disabled)
34
- │ └── createMessageLog.js # Create message log (disabled)
35
- └── ui/ # ChatGPT Widget UI
36
- ├── index.html # Entry HTML
37
- ├── package.json # UI dependencies
38
- ├── vite.config.ts # Vite build config
39
- ├── App/
40
- │ ├── root.tsx # React entry point
41
- │ ├── App.tsx # Multi-step auth flow orchestrator
42
- │ ├── main.css # Tailwind + OpenAI styles
43
- │ ├── lib/
44
- │ │ ├── callTool.ts # Direct fetch to /mcp/widget-tool-call
45
- │ │ ├── developerPortal.ts # Client-side developer portal API calls
46
- │ │ └── debugLog.ts # Debug logger
47
- │ └── components/
48
- │ ├── ConnectorList.tsx # Connector selection widget
49
- │ ├── AuthInfoForm.tsx # Hostname/environment input form
50
- │ ├── OAuthConnect.tsx # OAuth link + status polling
51
- │ ├── AuthSuccess.tsx # Success banner
52
- │ └── DebugPanel.tsx # Collapsible debug log panel
53
- └── dist/ # Built widget output
54
- ```
55
-
56
- ## Core Components
57
-
58
- ### MCP Handler (`mcpHandler.js`)
59
-
60
- A stateless, hand-rolled JSON-RPC handler — no `@modelcontextprotocol/sdk`, no SSE, no in-memory sessions. Each POST request is handled independently, making it fully compatible with stateless deployments like AWS Lambda.
61
-
62
- **Key Features:**
63
- - Defines `WIDGET_VERSION` — the **single source of truth** for the widget cache-busting URI
64
- - Handles `initialize`, `tools/list`, `tools/call`, `resources/list`, `resources/read`, and `ping` methods
65
- - Defines `outputSchema` (JSON Schema) for AI-visible tools so clients can understand and validate structured results
66
- - Defines `inputSchema` (JSON Schema) for every tool that takes parameters — required so ChatGPT forwards arguments
67
- - Injects `rcAccessToken`, `openaiSessionId`, and `rcExtensionId` into every `tools/call` request
68
- - Verifies the RC access token against the RC API and caches `rcExtensionId` in `CacheModel` keyed by `openaiSessionId` (24h TTL) — subsequent requests hit the cache instead of the RC API
69
- - Automatically looks up and injects `jwtToken` from `LlmSessionModel` using `rcExtensionId` (or `openaiSessionId` as a fallback), only when the linked `User` row still has a CRM `accessToken`
70
- - Stamps `WIDGET_URI` into `getPublicConnectors`'s `_meta['openai/outputTemplate']` at response time
71
- - Returns `structuredContent` for schema-bearing tool calls and includes serialized JSON text content for backwards compatibility
72
- - Serves the widget HTML via `resources/read`
73
- - Exposes `handleWidgetToolCall` which searches both `tools.tools` and `tools.widgetTools`
74
-
75
- **Request Flow:**
76
- 1. Receives `POST /mcp` with a JSON-RPC body
77
- 2. Extracts `rcAccessToken` from `Authorization` header and `openaiSessionId` from `params._meta['openai/session']`
78
- 3. On `tools/call`: checks `CacheModel` for a cached `rcExtensionId`; if missing, verifies via RC API and persists to cache
79
- 4. Injects server-side context (`rcAccessToken`, `openaiSessionId`, `rcExtensionId`, `jwtToken`) into tool args
80
- 5. Routes to the appropriate tool handler via a `switch` on `method`
81
- 6. Returns a JSON-RPC response immediately — no streaming, no SSE
82
-
83
- ### Widget Version Management
84
-
85
- `WIDGET_VERSION` in `mcpHandler.js` is the **only place** that needs to change when bumping the widget version:
86
-
87
- ```js
88
- // mcpHandler.js
89
- const WIDGET_VERSION = 6;
90
- const WIDGET_URI = `ui://widget/ConnectorList-v${WIDGET_VERSION}.html`;
91
- ```
92
-
93
- At registration time, `mcpHandler.js` stamps `WIDGET_URI` into `getPublicConnectors`'s `_meta['openai/outputTemplate']`. `getPublicConnectors.js` itself does **not** contain a version number.
94
-
95
- **To deploy a new widget build:**
96
- 1. Rebuild the widget: `cd packages/core/mcp/ui && npm run build`
97
- 2. Increment `WIDGET_VERSION` in `mcpHandler.js`
98
- 3. Restart the server
99
-
100
- ### Manifest Validator (`lib/validator.js`)
101
-
102
- Validates connector manifest structures before authentication operations.
103
-
104
- ## MCP Tools
105
-
106
- ### Tool Registry
107
-
108
- Tools are split into two registries in `tools/index.js`:
109
-
110
- | Registry | Purpose |
111
- |----------|---------|
112
- | `tools` | Registered in the MCP server — visible to and callable by the AI model |
113
- | `widgetTools` | Accessible only via `POST /mcp/widget-tool-call` — hidden from the AI model |
114
-
115
- ### Argument Handling
116
-
117
- `mcpHandler.js` automatically injects server-side values into every tool's args before calling `execute()`:
118
-
119
- | Injected arg | Source | Purpose |
120
- |---|---|---|
121
- | `rcAccessToken` | `Authorization` request header | RingCentral API calls |
122
- | `openaiSessionId` | `params._meta['openai/session']` | Stable ChatGPT conversation ID |
123
- | `rcExtensionId` | RC API (`/extension/~`), verified once and cached in `sessionContext` | Cryptographically verified RC identity; used as `LlmSessionModel` key |
124
- | `jwtToken` | `LlmSessionModel.findByPk(rcExtensionId)` (fallback: `findByPk(openaiSessionId)`) | CRM auth token (after OAuth) |
125
-
126
- Tools do **not** need ChatGPT to pass `jwtToken` explicitly — it is resolved from the session automatically. The `rcExtensionId` is verified via the RC API on the **first tool call** of each session and cached for all subsequent calls within the same conversation (0 additional API calls after that). If the user has logged out or the CRM token was cleared, `jwtToken` is not injected even when a stale row exists in `LlmSessionModel`.
127
-
128
- New or refreshed LLM session JWTs are written only when the user record has an `accessToken`, so disconnected users are not issued a new tool JWT.
129
-
130
- Note: `widgetTools` are called via `POST /mcp/widget-tool-call` which bypasses the MCP session layer entirely. No server-side injection occurs for widget tool calls — all required values must be passed explicitly by the widget in the request body.
131
-
132
- ### Output Handling
133
-
134
- `tools/list` includes an `outputSchema` for every AI-visible MCP tool. For `tools/call`, `mcpHandler.js` converts each tool's returned object into MCP `structuredContent` and also returns the same payload as serialized JSON in a text content block for clients that still read only `content`.
135
-
136
- Tools that return `{ success: false, ... }` are surfaced as regular MCP tool results with `isError: true`, so the model can see the error payload and self-correct.
137
-
138
- ### AI-Visible Tools (`tools`)
139
-
140
- #### `getHelp`
141
- Provides onboarding guidance for new users.
142
-
143
- | Property | Value |
144
- |----------|-------|
145
- | Read-only | Yes |
146
- | Parameters | None |
147
- | Returns | Overview, steps |
148
-
149
- #### `getPublicConnectors`
150
- Triggers the interactive connector selection widget. The widget fetches the connector list and manifests directly from the developer portal on the client side.
151
-
152
- | Property | Value |
153
- |----------|-------|
154
- | Read-only | Yes |
155
- | Parameters | None (server injects `rcAccessToken` and `openaiSessionId`) |
156
- | Returns | `structuredContent` with `serverUrl`, `rcAccountId`, `rcExtensionId`, and `openaiSessionId` |
157
- | Widget | `ui://widget/ConnectorList-v{WIDGET_VERSION}.html` (versioned by `mcpHandler.js`) |
158
-
159
- #### `logout`
160
- Logs out user from the CRM platform.
161
-
162
- | Property | Value |
163
- |----------|-------|
164
- | Destructive | Yes |
165
- | Parameters | `jwtToken` (optional — injected from session if not passed) |
166
- | Action | Clears user credentials |
167
- | Note | Local session cleanup always runs. Failures from the connector `unAuthorize` call are logged; the tool still returns success so the client can clear context. |
168
-
169
- #### Contact & Call Log Tools
170
-
171
- `jwtToken` is injected automatically from the session — ChatGPT does not need to pass it:
172
-
173
- | Tool | Parameters | Description |
174
- |------|-----------|-------------|
175
- | `findContactByPhone` | `phoneNumber` (E.164) | Search contact by phone |
176
- | `findContactByName` | `name` | Search contact by name |
177
- | `createContact` | `phoneNumber`, `newContactName?` | Create new CRM contact |
178
- | `rcGetCallLogs` | `timeFrom`, `timeTo` (ISO 8601) | Fetch RingCentral call logs. Each `records[i]` item can be passed directly as `incomingData.logInfo` to `createCallLog`. |
179
- | `createCallLog` | `incomingData` (with `logInfo` = single `rcGetCallLogs` record), `contactId?`, `note?` | Create call log in CRM. Pass a `records[i]` item from `rcGetCallLogs` directly as `incomingData.logInfo`. |
180
-
181
- #### Appointment / Event Tools
182
-
183
- `jwtToken` is injected automatically from the session — ChatGPT does not need to pass it:
184
-
185
- | Tool | Parameters | Description |
186
- |------|-----------|-------------|
187
- | `listAppointments` | `filter?` (`upcoming`/`today`/`past`/`all`/`custom`), `startDate?`, `endDate?` (YYYY-MM-DD), `mineOnly?` | List appointments from the CRM. Named filters auto-compute date windows (±90 days). Use `custom` with `startDate`/`endDate` for a specific range. |
188
- | `createAppointment` | `title`, `startTimeUtc` (ISO 8601), `durationMinutes`, `summary?`, `contacts?` | Create a new appointment or event in the CRM. `contacts` is an array of CRM contact IDs to invite as attendees. |
189
- | `updateAppointment` | `appointmentId`, `title?`, `summary?`, `startTimeUtc?`, `durationMinutes?`, `contacts?` | Update or reschedule an existing appointment. Only the supplied fields are changed. `contacts` replaces the entire attendee list when provided. |
190
- | `confirmAppointment` | `appointmentId` | Mark an existing appointment as confirmed. |
191
- | `cancelAppointment` | `appointmentId` | Cancel (delete) an existing appointment. Destructive — cannot be undone. |
192
-
193
- ### Widget-Only Tools (`widgetTools`)
194
-
195
- Not registered in the MCP server; only callable by the widget iframe via `POST /mcp/widget-tool-call`. No server-side arg injection — the widget passes all required values directly.
196
-
197
- #### `doAuth`
198
- Creates a server-side OAuth session for the given `sessionId`.
199
-
200
- | Property | Value |
201
- |----------|-------|
202
- | Parameters | `sessionId`, `connectorName`, `hostname` |
203
- | Returns | `{ success: true }` |
204
- | Note | The widget generates `sessionId` and the OAuth URL client-side; `doAuth` just registers the session in the DB so the callback can resolve it |
205
-
206
- #### `checkAuthStatus`
207
- Polls the OAuth session status. Called exclusively by the widget during the OAuth flow — the AI model never calls this directly.
208
-
209
- | Property | Value |
210
- |----------|-------|
211
- | Parameters | `sessionId`, `rcExtensionId?` (passed by widget from `getPublicConnectors` structuredContent) |
212
- | Returns | `{ data: { status, ... } }` for all states |
213
- | On Success | `data.jwtToken` and `data.userInfo` included; JWT stored in `LlmSessionModel` keyed by `rcExtensionId` |
214
- | Statuses | `pending` · `completed` · `failed` — all return consistent `{ data: { status } }` for reliable widget parsing |
215
-
216
- ## ChatGPT Widget UI
217
-
218
- The UI module provides a single interactive widget that drives the full authentication flow inside a ChatGPT iframe. Users select a connector, provide any required environment info, authorize via OAuth (opened in a new tab), and see a success confirmation — all without leaving the widget.
219
-
220
- ### Technology Stack
221
- - **React 18** with TypeScript
222
- - **Vite** with `vite-plugin-singlefile` for self-contained HTML
223
- - **Tailwind CSS 4** with `@openai/apps-sdk-ui` components
224
- - **OpenAI Apps SDK UI** for consistent ChatGPT styling
225
-
226
- ### Widget Communication
227
-
228
- **1. Receiving the initial server context** — via four mechanisms (whichever fires first):
229
-
230
- | Mechanism | Description |
231
- |-----------|-------------|
232
- | `window.openai.toolOutput` | Synchronous read on mount |
233
- | `openai:set_globals` event | ChatGPT pushes globals into the iframe |
234
- | `ui/notifications/tool-result` postMessage | MCP Apps bridge notification |
235
- | Polling `window.openai.toolOutput` | Fallback for async population |
236
-
237
- The initial payload is `{ serverUrl, rcAccountId, rcExtensionId, openaiSessionId }`.
238
-
239
- **2. Fetching connectors and manifests** — via direct `fetch()` to `appconnect.labs.ringcentral.com`:
240
-
241
- ```typescript
242
- import { fetchConnectors, fetchManifest } from './lib/developerPortal'
243
-
244
- const connectors = await fetchConnectors(rcAccountId) // list with id, name, displayName
245
- const manifest = await fetchManifest(connector.id, isPrivate, rcAccountId)
246
- ```
247
-
248
- **3. Calling widget tools** — via direct `fetch()` to `POST /mcp/widget-tool-call`:
249
-
250
- ```typescript
251
- import { callTool } from './lib/callTool'
252
-
253
- const result = await callTool('doAuth', { sessionId, connectorName, hostname })
254
- const status = await callTool('checkAuthStatus', { sessionId, rcExtensionId })
255
- ```
256
-
257
- `window.openai.callTool()` is **intentionally not used** for widget tool calls. Direct `fetch()` to `/mcp/widget-tool-call` forwards all arguments correctly and works for both `doAuth` and `checkAuthStatus`.
258
-
259
- ### Widget Auth Flow
260
-
261
- The widget (`App.tsx`) acts as a multi-step wizard:
262
-
263
- ```
264
- loadingConnectors → select → loading → authInfo (if dynamic/selectable env) → oauth → success
265
- → oauth (if fixed env) → error
266
- ```
267
-
268
- | Step | Component | Description |
269
- |------|-----------|-------------|
270
- | `loadingConnectors` | (spinner) | Widget fetches connector list from developer portal |
271
- | `select` | `ConnectorList` | Displays available connectors |
272
- | `loading` | (spinner) | Shown while manifest is being fetched |
273
- | `authInfo` | `AuthInfoForm` | Collects hostname (dynamic) or environment (selectable). Resolved locally — no server call |
274
- | `oauth` | `OAuthConnect` | Uses `openaiSessionId` as the OAuth session ID (falls back to `crypto.randomUUID()`). Generates the OAuth URL client-side, calls `doAuth` in background to register the session in the DB, then shows "Authorize" button. After click, polls `checkAuthStatus` every 5 seconds via direct fetch |
275
- | `success` | `AuthSuccess` | Shows connected CRM name and user info |
276
- | `error` | (inline) | Shows error with "Back to connector list" link |
277
-
278
- ### Components
279
-
280
- #### ConnectorList
281
- Displays available CRM connectors with public/private badges. On selection, delegates to `App.tsx` which fetches the manifest directly.
282
-
283
- #### AuthInfoForm
284
- Form for environment info collection. Handles `dynamic` (text input) and `selectable` (button list) environment types. Hostname resolution happens inline in `App.tsx`.
285
-
286
- #### OAuthConnect
287
- Handles the full OAuth step. Uses `openaiSessionId` (from the initial tool output) as the session ID so the OAuth callback can be correlated with the ChatGPT conversation — falls back to `crypto.randomUUID()` when running outside ChatGPT. Calls `doAuth` in the background, shows an "Authorize in [CRM]" button (disabled until session is created), then polls `checkAuthStatus` every 5 seconds via `callTool()` (direct fetch). On success, fires `updateModelContext` to push the jwtToken into ChatGPT's context, then calls `onSuccess`.
288
-
289
- #### AuthSuccess
290
- Success banner showing the connected CRM name and optional user info.
291
-
292
- ### Developer Portal Client (`lib/developerPortal.ts`)
293
-
294
- Calls `appconnect.labs.ringcentral.com/public-api` directly from the browser:
295
-
296
- | Function | Description |
297
- |----------|-------------|
298
- | `fetchConnectors(rcAccountId?)` | Fetches public + private connectors, filters to `SUPPORTED_PLATFORMS` |
299
- | `fetchManifest(connectorId, isPrivate, rcAccountId?)` | Fetches connector manifest by ID |
300
-
301
- `SUPPORTED_PLATFORMS` is defined in this file: `['clio']`.
302
-
303
- ### Building the Widget
304
-
305
- **Production build** (generates `dist/index.html` with all JS, CSS, and assets inlined):
306
-
307
- ```bash
308
- cd packages/core/mcp/ui
309
- npm install
310
- npm run build # Output: dist/index.html (single file)
311
- ```
312
-
313
- **Development server** (hot reload for local testing):
314
-
315
- ```bash
316
- cd packages/core/mcp/ui
317
- npm run dev
318
- ```
319
-
320
- **Cache busting after a build:** Increment `WIDGET_VERSION` in `mcpHandler.js` and restart the server. That is the only file that needs to change — `getPublicConnectors.js` and the README do not contain a version number.
321
-
322
- ## API Integration
323
-
324
- ### Endpoints
325
-
326
- | Endpoint | Purpose |
327
- |----------|---------|
328
- | `POST /mcp` | Full MCP protocol endpoint for AI assistants (ChatGPT, etc.) |
329
- | `POST /mcp/widget-tool-call` | Lightweight direct tool call for the widget iframe (bypasses MCP session protocol) |
330
-
331
- #### `POST /mcp/widget-tool-call`
332
-
333
- Called by the widget via `fetch()` to invoke `doAuth` and `checkAuthStatus` with full argument support.
334
-
335
- **`doAuth` request:**
336
- ```json
337
- {
338
- "tool": "doAuth",
339
- "toolArgs": {
340
- "sessionId": "<openaiSessionId or random UUID>",
341
- "connectorName": "clio",
342
- "hostname": "app.clio.com"
343
- }
344
- }
345
- ```
346
-
347
- **`checkAuthStatus` request:**
348
- ```json
349
- {
350
- "tool": "checkAuthStatus",
351
- "toolArgs": {
352
- "sessionId": "<same sessionId used in doAuth>",
353
- "rcExtensionId": "<from getPublicConnectors structuredContent>"
354
- }
355
- }
356
- ```
357
-
358
- **Response:** The raw result from `tool.execute()` — shape varies by tool.
359
-
360
- ### Headers (for `/mcp`)
361
-
362
- | Header | Value |
363
- |--------|-------|
364
- | `Content-Type` | `application/json` |
365
- | `Authorization` | `Bearer <RC_ACCESS_TOKEN>` (optional, for RingCentral API calls) |
366
-
367
- ## Supported Platforms
368
-
369
- Currently supported for MCP integration:
370
- - **Clio** - Legal practice management
371
-
372
- ## Security Considerations
373
-
374
- 1. **JWT Tokens**: Stored server-side in `LlmSessionModel`, **keyed by `rcExtensionId`** (a cryptographically verified RingCentral identity). Tools receive the JWT via server injection — it is never sent back to ChatGPT as a visible parameter.
375
- 2. **RC Identity Verification**: On the first tool call of each session, `mcpHandler.js` calls `GET /restapi/v1.0/extension/~` with the Bearer token from the request. If the RC token is invalid, the call throws and `rcExtensionId` remains `null`. The result is cached in `sessionContext` so at most **one RC API call** is made per conversation.
376
- 3. **Session key binding**: The sessions Map is keyed on the stable `openai/session` ID so the same `sessionContext` (and its verified `rcExtensionId`) is reused for all tool calls within a ChatGPT conversation. A session can only access credentials stored under its own verified `rcExtensionId`.
377
- 4. **Session Management**: MCP sessions are server-side and automatically cleaned up on transport close.
378
- 5. **OAuth Flows**: Uses secure OAuth 2.0 with server-side callback handling.
379
- 6. **RC Account ID**: Resolved server-side via RC API and passed to the widget — never requires exposing secrets to the browser.
380
- 7. **CORS**: Widget calls `appconnect.labs.ringcentral.com` directly; the developer portal public API supports browser fetch.
381
-
382
- | | Before | After |
383
- |---|---|---|
384
- | Identity proof | `openai/session` (unverified, from request body) | `rcExtensionId` (verified via RC API) |
385
- | RC token verified? | No | Yes — first tool call per conversation |
386
- | API calls per session | 0 (no verify) | 1 (cached after first call) |
387
- | `LlmSessionModel` key | arbitrary session ID | stable, verified RC extension ID |
388
-
389
- ## Error Handling
390
-
391
- All tools return standardized response objects:
392
-
393
- **Success:**
394
- ```json
395
- { "success": true, "data": { ... } }
396
- ```
397
-
398
- **Failure:**
399
- ```json
400
- { "success": false, "error": "Error message" }
401
- ```
402
-
403
- ## Usage Example
404
-
405
- A typical conversation flow:
406
-
407
- 1. **User**: "Connect me to my CRM"
408
- 2. **AI**: Calls `getPublicConnectors` → server verifies RC token, resolves `rcExtensionId` + RC account ID + `openaiSessionId` → shows widget
409
- 3. **Widget**: Fetches connector list from developer portal → displays connector cards
410
- 4. **User**: Clicks "Clio" in the widget
411
- 5. **Widget**: Fetches Clio manifest → shows environment selector (US/EU/AU/CA)
412
- 6. **User**: Selects region → widget calls `doAuth` with `openaiSessionId` as OAuth session key → shows "Authorize in Clio" button
413
- 7. **User**: Clicks button → Clio OAuth page opens in new tab → user authorizes
414
- 8. **Widget**: Polls `checkAuthStatus` every 5 seconds via direct fetch (passes `sessionId` + `rcExtensionId`) → "Waiting for authorization..."
415
- 9. **Widget**: Auth completes → jwtToken stored in `LlmSessionModel[rcExtensionId]` → widget fires `updateModelContext` with jwtToken → shows success banner
416
- 10. **AI**: "You're now connected! What would you like to do?"
417
- 11. **User**: "Find contacts named Test"
418
- 12. **AI**: Calls `findContactByName(name="Test")` — server injects jwtToken automatically using cached `rcExtensionId` as lookup key → returns results
419
-
420
- Steps 3–9 happen entirely within the widget iframe. The AI assistant is not involved until authentication is complete.
@@ -1,51 +0,0 @@
1
- /**
2
- * MCP Tools Index
3
- *
4
- * Two separate registries:
5
- * - tools: Registered in the MCP server — visible to and callable by the AI model
6
- * - widgetTools: Only accessible via POST /mcp/widget-tool-call — hidden from the AI model
7
- */
8
-
9
- const getHelp = require('./getHelp');
10
- const getPublicConnectors = require('./getPublicConnectors');
11
- const getSessionInfo = require('./getSessionInfo');
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 createCallLog = require('./createCallLog');
18
- const rcGetCallLogs = require('./rcGetCallLogs');
19
- // const getGoogleFilePicker = require('./getGoogleFilePicker');
20
- const createContact = require('./createContact');
21
- const createAppointment = require('./createAppointment');
22
- const updateAppointment = require('./updateAppointment');
23
- const confirmAppointment = require('./confirmAppointment');
24
- const cancelAppointment = require('./cancelAppointment');
25
- const listAppointments = require('./listAppointments');
26
-
27
- // AI-visible MCP tools — registered in the MCP server
28
- module.exports.tools = [
29
- getHelp,
30
- getPublicConnectors,
31
- getSessionInfo,
32
- logout,
33
- findContact,
34
- findContactWithName,
35
- createCallLog,
36
- rcGetCallLogs,
37
- // getGoogleFilePicker,
38
- createContact,
39
- listAppointments,
40
- createAppointment,
41
- updateAppointment,
42
- confirmAppointment,
43
- cancelAppointment,
44
- ];
45
-
46
- // Widget-only tools — callable via /mcp/widget-tool-call, NOT registered as MCP tools
47
- module.exports.widgetTools = [
48
- doAuth,
49
- checkAuthStatus,
50
- ];
51
-