cowork-os 0.3.21 → 0.3.23

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 (170) hide show
  1. package/README.md +293 -6
  2. package/connectors/README.md +20 -0
  3. package/connectors/asana-mcp/README.md +24 -0
  4. package/connectors/asana-mcp/dist/index.js +427 -0
  5. package/connectors/asana-mcp/package.json +15 -0
  6. package/connectors/asana-mcp/src/index.ts +553 -0
  7. package/connectors/asana-mcp/tsconfig.json +13 -0
  8. package/connectors/hubspot-mcp/README.md +35 -0
  9. package/connectors/hubspot-mcp/dist/index.js +454 -0
  10. package/connectors/hubspot-mcp/package.json +15 -0
  11. package/connectors/hubspot-mcp/src/index.ts +562 -0
  12. package/connectors/hubspot-mcp/tsconfig.json +13 -0
  13. package/connectors/jira-mcp/README.md +49 -0
  14. package/connectors/jira-mcp/dist/index.js +588 -0
  15. package/connectors/jira-mcp/package.json +15 -0
  16. package/connectors/jira-mcp/src/index.ts +711 -0
  17. package/connectors/jira-mcp/tsconfig.json +13 -0
  18. package/connectors/linear-mcp/README.md +22 -0
  19. package/connectors/linear-mcp/dist/index.js +402 -0
  20. package/connectors/linear-mcp/package.json +15 -0
  21. package/connectors/linear-mcp/src/index.ts +522 -0
  22. package/connectors/linear-mcp/tsconfig.json +13 -0
  23. package/connectors/okta-mcp/README.md +24 -0
  24. package/connectors/okta-mcp/dist/index.js +411 -0
  25. package/connectors/okta-mcp/package.json +15 -0
  26. package/connectors/okta-mcp/src/index.ts +520 -0
  27. package/connectors/okta-mcp/tsconfig.json +13 -0
  28. package/connectors/salesforce-mcp/README.md +47 -0
  29. package/connectors/salesforce-mcp/dist/index.js +584 -0
  30. package/connectors/salesforce-mcp/package.json +15 -0
  31. package/connectors/salesforce-mcp/src/index.ts +722 -0
  32. package/connectors/salesforce-mcp/tsconfig.json +13 -0
  33. package/connectors/servicenow-mcp/README.md +26 -0
  34. package/connectors/servicenow-mcp/dist/index.js +400 -0
  35. package/connectors/servicenow-mcp/package.json +15 -0
  36. package/connectors/servicenow-mcp/src/index.ts +500 -0
  37. package/connectors/servicenow-mcp/tsconfig.json +13 -0
  38. package/connectors/templates/mcp-connector/README.md +31 -0
  39. package/connectors/templates/mcp-connector/package.json +15 -0
  40. package/connectors/templates/mcp-connector/src/index.ts +330 -0
  41. package/connectors/templates/mcp-connector/tsconfig.json +13 -0
  42. package/connectors/zendesk-mcp/README.md +40 -0
  43. package/connectors/zendesk-mcp/dist/index.js +431 -0
  44. package/connectors/zendesk-mcp/package.json +15 -0
  45. package/connectors/zendesk-mcp/src/index.ts +543 -0
  46. package/connectors/zendesk-mcp/tsconfig.json +13 -0
  47. package/dist/electron/electron/agent/daemon.js +25 -0
  48. package/dist/electron/electron/agent/executor.js +181 -26
  49. package/dist/electron/electron/agent/llm/anthropic-compatible-provider.js +177 -0
  50. package/dist/electron/electron/agent/llm/github-copilot-provider.js +97 -0
  51. package/dist/electron/electron/agent/llm/groq-provider.js +33 -0
  52. package/dist/electron/electron/agent/llm/index.js +11 -1
  53. package/dist/electron/electron/agent/llm/kimi-provider.js +33 -0
  54. package/dist/electron/electron/agent/llm/openai-compatible-provider.js +116 -0
  55. package/dist/electron/electron/agent/llm/openai-compatible.js +111 -0
  56. package/dist/electron/electron/agent/llm/openai-oauth.js +2 -1
  57. package/dist/electron/electron/agent/llm/openrouter-provider.js +1 -1
  58. package/dist/electron/electron/agent/llm/provider-factory.js +318 -4
  59. package/dist/electron/electron/agent/llm/types.js +66 -1
  60. package/dist/electron/electron/agent/llm/xai-provider.js +33 -0
  61. package/dist/electron/electron/agent/tools/box-tools.js +231 -0
  62. package/dist/electron/electron/agent/tools/builtin-settings.js +28 -0
  63. package/dist/electron/electron/agent/tools/dropbox-tools.js +237 -0
  64. package/dist/electron/electron/agent/tools/google-drive-tools.js +227 -0
  65. package/dist/electron/electron/agent/tools/notion-tools.js +312 -0
  66. package/dist/electron/electron/agent/tools/onedrive-tools.js +217 -0
  67. package/dist/electron/electron/agent/tools/registry.js +541 -0
  68. package/dist/electron/electron/agent/tools/sharepoint-tools.js +243 -0
  69. package/dist/electron/electron/agent/tools/shell-tools.js +12 -3
  70. package/dist/electron/electron/agent/tools/x-tools.js +1 -1
  71. package/dist/electron/electron/gateway/index.js +1 -0
  72. package/dist/electron/electron/gateway/router.js +123 -143
  73. package/dist/electron/electron/ipc/canvas-handlers.js +5 -0
  74. package/dist/electron/electron/ipc/handlers.js +627 -158
  75. package/dist/electron/electron/main.js +63 -0
  76. package/dist/electron/electron/mcp/oauth/connector-oauth.js +333 -0
  77. package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +503 -154
  78. package/dist/electron/electron/memory/MemoryService.js +1 -1
  79. package/dist/electron/electron/preload.js +74 -1
  80. package/dist/electron/electron/settings/box-manager.js +54 -0
  81. package/dist/electron/electron/settings/dropbox-manager.js +54 -0
  82. package/dist/electron/electron/settings/google-drive-manager.js +54 -0
  83. package/dist/electron/electron/settings/notion-manager.js +56 -0
  84. package/dist/electron/electron/settings/onedrive-manager.js +54 -0
  85. package/dist/electron/electron/settings/sharepoint-manager.js +54 -0
  86. package/dist/electron/electron/utils/box-api.js +153 -0
  87. package/dist/electron/electron/utils/dropbox-api.js +144 -0
  88. package/dist/electron/electron/utils/env-migration.js +19 -0
  89. package/dist/electron/electron/utils/google-drive-api.js +152 -0
  90. package/dist/electron/electron/utils/notion-api.js +103 -0
  91. package/dist/electron/electron/utils/onedrive-api.js +113 -0
  92. package/dist/electron/electron/utils/sharepoint-api.js +109 -0
  93. package/dist/electron/electron/utils/validation.js +82 -3
  94. package/dist/electron/electron/utils/x-cli.js +1 -1
  95. package/dist/electron/shared/channelMessages.js +284 -3
  96. package/dist/electron/shared/llm-provider-catalog.js +198 -0
  97. package/dist/electron/shared/types.js +88 -1
  98. package/package.json +12 -2
  99. package/src/electron/agent/executor.ts +205 -28
  100. package/src/electron/agent/llm/anthropic-compatible-provider.ts +214 -0
  101. package/src/electron/agent/llm/github-copilot-provider.ts +117 -0
  102. package/src/electron/agent/llm/groq-provider.ts +39 -0
  103. package/src/electron/agent/llm/index.ts +5 -0
  104. package/src/electron/agent/llm/kimi-provider.ts +39 -0
  105. package/src/electron/agent/llm/openai-compatible-provider.ts +153 -0
  106. package/src/electron/agent/llm/openai-compatible.ts +133 -0
  107. package/src/electron/agent/llm/openai-oauth.ts +2 -1
  108. package/src/electron/agent/llm/openrouter-provider.ts +2 -1
  109. package/src/electron/agent/llm/provider-factory.ts +414 -6
  110. package/src/electron/agent/llm/types.ts +90 -1
  111. package/src/electron/agent/llm/xai-provider.ts +39 -0
  112. package/src/electron/agent/tools/box-tools.ts +239 -0
  113. package/src/electron/agent/tools/builtin-settings.ts +34 -0
  114. package/src/electron/agent/tools/dropbox-tools.ts +237 -0
  115. package/src/electron/agent/tools/google-drive-tools.ts +228 -0
  116. package/src/electron/agent/tools/notion-tools.ts +330 -0
  117. package/src/electron/agent/tools/onedrive-tools.ts +217 -0
  118. package/src/electron/agent/tools/registry.ts +565 -0
  119. package/src/electron/agent/tools/sharepoint-tools.ts +247 -0
  120. package/src/electron/agent/tools/shell-tools.ts +11 -3
  121. package/src/electron/agent/tools/x-tools.ts +1 -1
  122. package/src/electron/database/SecureSettingsRepository.ts +7 -1
  123. package/src/electron/gateway/index.ts +1 -0
  124. package/src/electron/gateway/router.ts +134 -149
  125. package/src/electron/ipc/canvas-handlers.ts +10 -0
  126. package/src/electron/ipc/handlers.ts +673 -153
  127. package/src/electron/main.ts +35 -0
  128. package/src/electron/mcp/oauth/connector-oauth.ts +448 -0
  129. package/src/electron/mcp/registry/MCPRegistryManager.ts +343 -12
  130. package/src/electron/memory/MemoryService.ts +5 -1
  131. package/src/electron/preload.ts +167 -4
  132. package/src/electron/settings/box-manager.ts +58 -0
  133. package/src/electron/settings/dropbox-manager.ts +58 -0
  134. package/src/electron/settings/google-drive-manager.ts +58 -0
  135. package/src/electron/settings/notion-manager.ts +60 -0
  136. package/src/electron/settings/onedrive-manager.ts +58 -0
  137. package/src/electron/settings/sharepoint-manager.ts +58 -0
  138. package/src/electron/utils/box-api.ts +184 -0
  139. package/src/electron/utils/dropbox-api.ts +171 -0
  140. package/src/electron/utils/env-migration.ts +22 -0
  141. package/src/electron/utils/google-drive-api.ts +183 -0
  142. package/src/electron/utils/notion-api.ts +126 -0
  143. package/src/electron/utils/onedrive-api.ts +137 -0
  144. package/src/electron/utils/sharepoint-api.ts +132 -0
  145. package/src/electron/utils/validation.ts +102 -1
  146. package/src/electron/utils/x-cli.ts +1 -1
  147. package/src/renderer/App.tsx +20 -2
  148. package/src/renderer/components/BoxSettings.tsx +203 -0
  149. package/src/renderer/components/BrowserView.tsx +101 -0
  150. package/src/renderer/components/BuiltinToolsSettings.tsx +105 -0
  151. package/src/renderer/components/CanvasPreview.tsx +68 -1
  152. package/src/renderer/components/ConnectorEnvModal.tsx +116 -0
  153. package/src/renderer/components/ConnectorSetupModal.tsx +566 -0
  154. package/src/renderer/components/ConnectorsSettings.tsx +397 -0
  155. package/src/renderer/components/DropboxSettings.tsx +202 -0
  156. package/src/renderer/components/GoogleDriveSettings.tsx +201 -0
  157. package/src/renderer/components/MCPSettings.tsx +56 -0
  158. package/src/renderer/components/MainContent.tsx +270 -34
  159. package/src/renderer/components/NotionSettings.tsx +231 -0
  160. package/src/renderer/components/Onboarding/Onboarding.tsx +13 -1
  161. package/src/renderer/components/OnboardingModal.tsx +70 -1
  162. package/src/renderer/components/OneDriveSettings.tsx +212 -0
  163. package/src/renderer/components/Settings.tsx +611 -8
  164. package/src/renderer/components/SharePointSettings.tsx +224 -0
  165. package/src/renderer/components/Sidebar.tsx +25 -9
  166. package/src/renderer/hooks/useOnboardingFlow.ts +21 -0
  167. package/src/renderer/styles/index.css +438 -25
  168. package/src/shared/channelMessages.ts +367 -4
  169. package/src/shared/llm-provider-catalog.ts +217 -0
  170. package/src/shared/types.ts +226 -1
@@ -0,0 +1,431 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const readline = __importStar(require("readline"));
37
+ const PROTOCOL_VERSION = '2024-11-05';
38
+ const MCP_METHODS = {
39
+ INITIALIZE: 'initialize',
40
+ INITIALIZED: 'notifications/initialized',
41
+ SHUTDOWN: 'shutdown',
42
+ TOOLS_LIST: 'tools/list',
43
+ TOOLS_CALL: 'tools/call',
44
+ };
45
+ const MCP_ERROR_CODES = {
46
+ PARSE_ERROR: -32700,
47
+ INVALID_REQUEST: -32600,
48
+ METHOD_NOT_FOUND: -32601,
49
+ INVALID_PARAMS: -32602,
50
+ INTERNAL_ERROR: -32603,
51
+ SERVER_NOT_INITIALIZED: -32002,
52
+ };
53
+ class ZendeskClient {
54
+ constructor(config) {
55
+ this.config = config;
56
+ }
57
+ async health() {
58
+ return this.requestJson('GET', 'api/v2/users/me.json');
59
+ }
60
+ async searchTickets(query) {
61
+ const params = new URLSearchParams({ query });
62
+ return this.requestJson('GET', `api/v2/search.json?${params.toString()}`);
63
+ }
64
+ async getTicket(ticketId) {
65
+ return this.requestJson('GET', `api/v2/tickets/${encodeURIComponent(ticketId)}.json`);
66
+ }
67
+ async createTicket(payload) {
68
+ return this.requestJson('POST', 'api/v2/tickets.json', payload);
69
+ }
70
+ async updateTicket(ticketId, payload) {
71
+ return this.requestJson('PUT', `api/v2/tickets/${encodeURIComponent(ticketId)}.json`, payload);
72
+ }
73
+ getBaseUrl() {
74
+ if (!this.config.baseUrl) {
75
+ throw new Error('ZENDESK_BASE_URL or ZENDESK_SUBDOMAIN is required');
76
+ }
77
+ return this.config.baseUrl.replace(/\/$/, '');
78
+ }
79
+ canRefresh() {
80
+ return Boolean(this.config.clientId && this.config.clientSecret && this.config.refreshToken);
81
+ }
82
+ async ensureAccessToken() {
83
+ if (this.config.accessToken) {
84
+ return this.config.accessToken;
85
+ }
86
+ if (!this.canRefresh()) {
87
+ throw new Error('Missing Zendesk credentials (ZENDESK_ACCESS_TOKEN or ZENDESK_EMAIL + ZENDESK_API_TOKEN)');
88
+ }
89
+ await this.refreshAccessToken();
90
+ if (!this.config.accessToken) {
91
+ throw new Error('Failed to refresh Zendesk access token');
92
+ }
93
+ return this.config.accessToken;
94
+ }
95
+ async getAuthHeader() {
96
+ if (this.config.accessToken || this.canRefresh()) {
97
+ const token = await this.ensureAccessToken();
98
+ return `Bearer ${token}`;
99
+ }
100
+ if (this.config.email && this.config.apiToken) {
101
+ const basic = Buffer.from(`${this.config.email}/token:${this.config.apiToken}`).toString('base64');
102
+ return `Basic ${basic}`;
103
+ }
104
+ throw new Error('Missing Zendesk credentials (ZENDESK_ACCESS_TOKEN or ZENDESK_EMAIL + ZENDESK_API_TOKEN)');
105
+ }
106
+ async requestJson(method, path, body) {
107
+ const start = Date.now();
108
+ const url = `${this.getBaseUrl()}/${path.replace(/^\//, '')}`;
109
+ const res = await fetch(url, {
110
+ method,
111
+ headers: {
112
+ Authorization: await this.getAuthHeader(),
113
+ 'Content-Type': 'application/json',
114
+ 'User-Agent': 'CoWork-Zendesk-Connector/0.1.0',
115
+ },
116
+ body: body ? JSON.stringify(body) : undefined,
117
+ });
118
+ const durationMs = Date.now() - start;
119
+ const vendorRequestId = res.headers.get('x-request-id') || undefined;
120
+ if (res.status === 401 && this.canRefresh()) {
121
+ await this.refreshAccessToken();
122
+ return this.requestJson(method, path, body);
123
+ }
124
+ if (!res.ok) {
125
+ const message = await res.text();
126
+ throw new Error(message || `Zendesk API error (${res.status})`);
127
+ }
128
+ let data = null;
129
+ if (res.status !== 204) {
130
+ data = await res.json();
131
+ }
132
+ return {
133
+ data,
134
+ meta: {
135
+ durationMs,
136
+ vendorRequestId,
137
+ baseUrl: this.config.baseUrl,
138
+ },
139
+ };
140
+ }
141
+ async refreshAccessToken() {
142
+ if (!this.canRefresh()) {
143
+ throw new Error('Missing Zendesk refresh credentials');
144
+ }
145
+ const res = await fetch(`${this.getBaseUrl()}/oauth/tokens`, {
146
+ method: 'POST',
147
+ headers: { 'Content-Type': 'application/json' },
148
+ body: JSON.stringify({
149
+ grant_type: 'refresh_token',
150
+ client_id: this.config.clientId,
151
+ client_secret: this.config.clientSecret,
152
+ refresh_token: this.config.refreshToken,
153
+ }),
154
+ });
155
+ if (!res.ok) {
156
+ const text = await res.text();
157
+ throw new Error(`Zendesk OAuth refresh failed: ${text}`);
158
+ }
159
+ const data = await res.json();
160
+ if (!data.access_token) {
161
+ throw new Error('Zendesk OAuth refresh returned no access_token');
162
+ }
163
+ this.config.accessToken = data.access_token;
164
+ if (data.refresh_token) {
165
+ this.config.refreshToken = data.refresh_token;
166
+ }
167
+ }
168
+ }
169
+ class StdioMCPServer {
170
+ constructor(toolProvider, serverInfo) {
171
+ this.toolProvider = toolProvider;
172
+ this.serverInfo = serverInfo;
173
+ this.initialized = false;
174
+ this.rl = null;
175
+ }
176
+ start() {
177
+ this.rl = readline.createInterface({
178
+ input: process.stdin,
179
+ output: process.stdout,
180
+ terminal: false,
181
+ });
182
+ this.rl.on('line', (line) => this.handleLine(line));
183
+ this.rl.on('close', () => this.stop());
184
+ process.on('SIGINT', () => this.stop());
185
+ process.on('SIGTERM', () => this.stop());
186
+ }
187
+ stop() {
188
+ if (this.rl) {
189
+ this.rl.close();
190
+ this.rl = null;
191
+ }
192
+ process.exit(0);
193
+ }
194
+ handleLine(line) {
195
+ const trimmed = line.trim();
196
+ if (!trimmed)
197
+ return;
198
+ try {
199
+ const message = JSON.parse(trimmed);
200
+ this.handleMessage(message);
201
+ }
202
+ catch {
203
+ this.sendError(0, MCP_ERROR_CODES.PARSE_ERROR, 'Parse error');
204
+ }
205
+ }
206
+ async handleMessage(message) {
207
+ if ('id' in message && message.id !== null) {
208
+ await this.handleRequest(message);
209
+ return;
210
+ }
211
+ if ('method' in message) {
212
+ await this.handleNotification(message);
213
+ }
214
+ }
215
+ async handleRequest(request) {
216
+ const { id, method, params } = request;
217
+ try {
218
+ let result;
219
+ switch (method) {
220
+ case MCP_METHODS.INITIALIZE:
221
+ result = this.handleInitialize(params);
222
+ break;
223
+ case MCP_METHODS.TOOLS_LIST:
224
+ this.requireInitialized();
225
+ result = this.handleToolsList();
226
+ break;
227
+ case MCP_METHODS.TOOLS_CALL:
228
+ this.requireInitialized();
229
+ result = await this.handleToolsCall(params);
230
+ break;
231
+ case MCP_METHODS.SHUTDOWN:
232
+ result = this.handleShutdown();
233
+ break;
234
+ default:
235
+ throw this.createError(MCP_ERROR_CODES.METHOD_NOT_FOUND, `Method not found: ${method}`);
236
+ }
237
+ this.sendResult(id, result);
238
+ }
239
+ catch (error) {
240
+ if (error.code !== undefined) {
241
+ this.sendError(id, error.code, error.message, error.data);
242
+ }
243
+ else {
244
+ this.sendError(id, MCP_ERROR_CODES.INTERNAL_ERROR, error?.message || 'Internal error');
245
+ }
246
+ }
247
+ }
248
+ async handleNotification(notification) {
249
+ const { method } = notification;
250
+ if (method === MCP_METHODS.INITIALIZED) {
251
+ this.initialized = true;
252
+ }
253
+ }
254
+ handleInitialize(_params) {
255
+ if (this.initialized) {
256
+ throw this.createError(MCP_ERROR_CODES.INVALID_REQUEST, 'Already initialized');
257
+ }
258
+ return {
259
+ protocolVersion: PROTOCOL_VERSION,
260
+ capabilities: this.serverInfo.capabilities,
261
+ serverInfo: this.serverInfo,
262
+ };
263
+ }
264
+ handleToolsList() {
265
+ return { tools: this.toolProvider.getTools() };
266
+ }
267
+ async handleToolsCall(params) {
268
+ const { name, arguments: args } = params || {};
269
+ if (!name) {
270
+ throw this.createError(MCP_ERROR_CODES.INVALID_PARAMS, 'Tool name is required');
271
+ }
272
+ try {
273
+ const result = await this.toolProvider.executeTool(name, args || {});
274
+ if (typeof result === 'string') {
275
+ return { content: [{ type: 'text', text: result }] };
276
+ }
277
+ if (result && typeof result === 'object') {
278
+ if (result.content && Array.isArray(result.content)) {
279
+ return result;
280
+ }
281
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
282
+ }
283
+ return { content: [{ type: 'text', text: String(result) }] };
284
+ }
285
+ catch (error) {
286
+ return {
287
+ content: [{ type: 'text', text: `Error: ${error?.message || 'Tool failed'}` }],
288
+ isError: true,
289
+ };
290
+ }
291
+ }
292
+ handleShutdown() {
293
+ setImmediate(() => this.stop());
294
+ return {};
295
+ }
296
+ sendResult(id, result) {
297
+ const response = { jsonrpc: '2.0', id, result };
298
+ this.sendMessage(response);
299
+ }
300
+ sendError(id, code, message, data) {
301
+ const response = {
302
+ jsonrpc: '2.0',
303
+ id,
304
+ error: { code, message, data },
305
+ };
306
+ this.sendMessage(response);
307
+ }
308
+ sendMessage(message) {
309
+ process.stdout.write(JSON.stringify(message) + '\n');
310
+ }
311
+ requireInitialized() {
312
+ if (!this.initialized) {
313
+ throw this.createError(MCP_ERROR_CODES.SERVER_NOT_INITIALIZED, 'Server not initialized');
314
+ }
315
+ }
316
+ createError(code, message, data) {
317
+ return { code, message, data };
318
+ }
319
+ }
320
+ // ==================== Tool Definitions ====================
321
+ const CONNECTOR_PREFIX = 'zendesk';
322
+ const baseUrl = process.env.ZENDESK_BASE_URL
323
+ ? process.env.ZENDESK_BASE_URL
324
+ : process.env.ZENDESK_SUBDOMAIN
325
+ ? `https://${process.env.ZENDESK_SUBDOMAIN}.zendesk.com`
326
+ : '';
327
+ const config = {
328
+ baseUrl,
329
+ accessToken: process.env.ZENDESK_ACCESS_TOKEN,
330
+ email: process.env.ZENDESK_EMAIL,
331
+ apiToken: process.env.ZENDESK_API_TOKEN,
332
+ clientId: process.env.ZENDESK_CLIENT_ID,
333
+ clientSecret: process.env.ZENDESK_CLIENT_SECRET,
334
+ refreshToken: process.env.ZENDESK_REFRESH_TOKEN,
335
+ };
336
+ const client = new ZendeskClient(config);
337
+ const tools = [
338
+ {
339
+ name: `${CONNECTOR_PREFIX}.health`,
340
+ description: 'Check connector health and authentication status',
341
+ inputSchema: { type: 'object', properties: {}, additionalProperties: false },
342
+ },
343
+ {
344
+ name: `${CONNECTOR_PREFIX}.search_tickets`,
345
+ description: 'Search Zendesk tickets with a query string',
346
+ inputSchema: {
347
+ type: 'object',
348
+ properties: {
349
+ query: { type: 'string', description: 'Search query (Zendesk search syntax)' },
350
+ },
351
+ required: ['query'],
352
+ additionalProperties: false,
353
+ },
354
+ },
355
+ {
356
+ name: `${CONNECTOR_PREFIX}.get_ticket`,
357
+ description: 'Fetch a ticket by ID',
358
+ inputSchema: {
359
+ type: 'object',
360
+ properties: {
361
+ id: { type: 'string', description: 'Ticket ID' },
362
+ },
363
+ required: ['id'],
364
+ additionalProperties: false,
365
+ },
366
+ },
367
+ {
368
+ name: `${CONNECTOR_PREFIX}.create_ticket`,
369
+ description: 'Create a new ticket',
370
+ inputSchema: {
371
+ type: 'object',
372
+ properties: {
373
+ ticket: { type: 'object', description: 'Zendesk ticket payload (ticket object)' },
374
+ },
375
+ required: ['ticket'],
376
+ additionalProperties: false,
377
+ },
378
+ },
379
+ {
380
+ name: `${CONNECTOR_PREFIX}.update_ticket`,
381
+ description: 'Update a ticket',
382
+ inputSchema: {
383
+ type: 'object',
384
+ properties: {
385
+ id: { type: 'string', description: 'Ticket ID' },
386
+ ticket: { type: 'object', description: 'Zendesk ticket payload (ticket object)' },
387
+ },
388
+ required: ['id', 'ticket'],
389
+ additionalProperties: false,
390
+ },
391
+ },
392
+ ];
393
+ const handlers = {
394
+ [`${CONNECTOR_PREFIX}.health`]: async () => buildEnvelope(await client.health()),
395
+ [`${CONNECTOR_PREFIX}.search_tickets`]: async (args) => buildEnvelope(await client.searchTickets(args.query)),
396
+ [`${CONNECTOR_PREFIX}.get_ticket`]: async (args) => buildEnvelope(await client.getTicket(args.id)),
397
+ [`${CONNECTOR_PREFIX}.create_ticket`]: async (args) => buildEnvelope(await client.createTicket({ ticket: args.ticket })),
398
+ [`${CONNECTOR_PREFIX}.update_ticket`]: async (args) => buildEnvelope(await client.updateTicket(args.id, { ticket: args.ticket })),
399
+ };
400
+ const toolProvider = {
401
+ getTools: () => tools,
402
+ executeTool: async (name, args) => {
403
+ const handler = handlers[name];
404
+ if (!handler) {
405
+ throw new Error(`Unknown tool: ${name}`);
406
+ }
407
+ return handler(args);
408
+ },
409
+ };
410
+ const serverInfo = {
411
+ name: 'Zendesk Connector',
412
+ version: '0.1.0',
413
+ protocolVersion: PROTOCOL_VERSION,
414
+ capabilities: {
415
+ tools: { listChanged: false },
416
+ },
417
+ };
418
+ const server = new StdioMCPServer(toolProvider, serverInfo);
419
+ server.start();
420
+ function buildEnvelope(result) {
421
+ return {
422
+ ok: true,
423
+ data: result.data,
424
+ meta: {
425
+ durationMs: result.meta.durationMs,
426
+ vendorRequestId: result.meta.vendorRequestId,
427
+ baseUrl: result.meta.baseUrl,
428
+ },
429
+ warnings: [],
430
+ };
431
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "cowork-zendesk-mcp",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "commonjs",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.json",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "devDependencies": {
12
+ "@types/node": "^20.11.30",
13
+ "typescript": "^5.7.3"
14
+ }
15
+ }