@taazkareem/clickup-mcp-server 0.4.16 → 0.4.18

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/build/index.js CHANGED
@@ -1,38 +1,59 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * ClickUp MCP Server
4
+ * A Model Context Protocol server implementation for ClickUp integration.
5
+ * Provides tools and resources for AI agents to interact with ClickUp tasks,
6
+ * spaces, lists, and folders through a standardized protocol.
7
+ *
8
+ * @module clickup-mcp-server
9
+ */
2
10
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
11
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
12
  import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
13
  import { ClickUpService } from "./services/clickup.js";
6
14
  import config from "./config.js";
7
- import { handleWorkspaceHierarchy, handleCreateTask } from "./handlers/tools.js";
15
+ import { handleWorkspaceHierarchy, handleCreateTask, handleCreateBulkTasks, handleCreateList, handleCreateFolder, handleCreateListInFolder, handleMoveTask, handleDuplicateTask, handleUpdateTask } from "./handlers/tools.js";
8
16
  import { handleSummarizeTasks, handleAnalyzeTaskPriorities } from "./handlers/prompts.js";
9
17
  import { getAllTasks } from "./utils/resolvers.js";
10
- console.log('Server starting up...');
11
- console.log('Config loaded:', {
18
+ import { logError, logInfo, logDebug } from "./utils/logger.js";
19
+ // Set up global error handlers
20
+ process.on('uncaughtException', (error) => {
21
+ logError('server.uncaught', error);
22
+ process.exit(1);
23
+ });
24
+ process.on('unhandledRejection', (reason) => {
25
+ logError('server.unhandled_rejection', reason);
26
+ process.exit(1);
27
+ });
28
+ logInfo('server', { status: 'starting' });
29
+ logInfo('config', {
12
30
  clickupApiKey: config.clickupApiKey ? '***' : 'missing',
13
31
  teamId: config.teamId || 'missing'
14
32
  });
15
- // Initialize ClickUp service
33
+ /**
34
+ * Initialize ClickUp service singleton
35
+ * This must be done before any other ClickUp operations
36
+ */
16
37
  let clickup;
17
38
  try {
18
- console.log('Initializing ClickUp service...');
39
+ logDebug('clickup', { status: 'initializing' });
19
40
  clickup = ClickUpService.initialize(config.clickupApiKey);
20
- console.log('ClickUp service initialized successfully');
41
+ logInfo('clickup', { status: 'initialized' });
21
42
  }
22
43
  catch (error) {
23
- console.error("Failed to initialize ClickUp service:", error);
44
+ logError('clickup.initialization', error);
24
45
  process.exit(1);
25
46
  }
26
- console.log('Creating MCP server...');
47
+ /**
48
+ * Create and configure the MCP server instance
49
+ * Sets up capabilities, tools, and error handling
50
+ */
51
+ logDebug('mcp', { status: 'creating' });
27
52
  const server = new Server({
28
53
  name: "clickup-mcp-server",
29
54
  version: "0.4.14",
30
- }, {
55
+ transport: new StdioServerTransport(),
31
56
  capabilities: {
32
- resources: {
33
- list: true,
34
- read: true,
35
- },
36
57
  tools: {
37
58
  workspace_hierarchy: {
38
59
  description: "List complete hierarchy of the ClickUp workspace",
@@ -80,17 +101,17 @@ const server = new Server({
80
101
  }
81
102
  },
82
103
  create_bulk_tasks: {
83
- description: "Create multiple tasks in a ClickUp list",
104
+ description: "Create multiple tasks simultaneously in a list",
84
105
  inputSchema: {
85
106
  type: "object",
86
107
  properties: {
87
108
  listId: {
88
109
  type: "string",
89
- description: "ID of the list to create the tasks in (optional if listName is provided)"
110
+ description: "ID of the list to create tasks in (optional if listName is provided)"
90
111
  },
91
112
  listName: {
92
113
  type: "string",
93
- description: "Name of the list to create the tasks in (optional if listId is provided)"
114
+ description: "Name of the list to create tasks in (optional if listId is provided)"
94
115
  },
95
116
  tasks: {
96
117
  type: "array",
@@ -112,18 +133,11 @@ const server = new Server({
112
133
  },
113
134
  priority: {
114
135
  type: "number",
115
- description: "Priority level (1-4)"
136
+ description: "Priority of the task (1-4)"
116
137
  },
117
138
  dueDate: {
118
139
  type: "string",
119
- description: "Due date (ISO string)"
120
- },
121
- assignees: {
122
- type: "array",
123
- items: {
124
- type: "number"
125
- },
126
- description: "Array of user IDs to assign to the task"
140
+ description: "Due date of the task (ISO string)"
127
141
  }
128
142
  },
129
143
  required: ["name"]
@@ -134,17 +148,17 @@ const server = new Server({
134
148
  }
135
149
  },
136
150
  create_list: {
137
- description: "Create a new list in a ClickUp space",
151
+ description: "Create a new list in a space",
138
152
  inputSchema: {
139
153
  type: "object",
140
154
  properties: {
141
155
  spaceId: {
142
156
  type: "string",
143
- description: "ID of the space to create the list in (optional if spaceName is provided)"
157
+ description: "ID of the space (optional if spaceName is provided)"
144
158
  },
145
159
  spaceName: {
146
160
  type: "string",
147
- description: "Name of the space to create the list in (optional if spaceId is provided)"
161
+ description: "Name of the space (optional if spaceId is provided)"
148
162
  },
149
163
  name: {
150
164
  type: "string",
@@ -152,40 +166,24 @@ const server = new Server({
152
166
  },
153
167
  content: {
154
168
  type: "string",
155
- description: "Description or content of the list"
156
- },
157
- dueDate: {
158
- type: "string",
159
- description: "Due date for the list (ISO string)"
160
- },
161
- priority: {
162
- type: "number",
163
- description: "Priority of the list (1-4)"
164
- },
165
- assignee: {
166
- type: "number",
167
- description: "User ID to assign the list to"
168
- },
169
- status: {
170
- type: "string",
171
- description: "Status of the list"
169
+ description: "List description"
172
170
  }
173
171
  },
174
172
  required: ["name"]
175
173
  }
176
174
  },
177
175
  create_folder: {
178
- description: "Create a new folder in a ClickUp space",
176
+ description: "Create a new folder in a space",
179
177
  inputSchema: {
180
178
  type: "object",
181
179
  properties: {
182
180
  spaceId: {
183
181
  type: "string",
184
- description: "ID of the space to create the folder in (optional if spaceName is provided)"
182
+ description: "ID of the space (optional if spaceName is provided)"
185
183
  },
186
184
  spaceName: {
187
185
  type: "string",
188
- description: "Name of the space to create the folder in (optional if spaceId is provided)"
186
+ description: "Name of the space (optional if spaceId is provided)"
189
187
  },
190
188
  name: {
191
189
  type: "string",
@@ -200,25 +198,25 @@ const server = new Server({
200
198
  }
201
199
  },
202
200
  create_list_in_folder: {
203
- description: "Create a new list in a ClickUp folder",
201
+ description: "Create a new list within a folder",
204
202
  inputSchema: {
205
203
  type: "object",
206
204
  properties: {
207
205
  folderId: {
208
206
  type: "string",
209
- description: "ID of the folder to create the list in (optional if folderName and spaceId/spaceName are provided)"
207
+ description: "ID of the folder (optional if using folderName)"
210
208
  },
211
209
  folderName: {
212
210
  type: "string",
213
- description: "Name of the folder to create the list in"
211
+ description: "Name of the folder"
214
212
  },
215
213
  spaceId: {
216
214
  type: "string",
217
- description: "ID of the space containing the folder (required if using folderName)"
215
+ description: "ID of the space (required if using folderName)"
218
216
  },
219
217
  spaceName: {
220
218
  type: "string",
221
- description: "Name of the space containing the folder (alternative to spaceId)"
219
+ description: "Name of the space (alternative to spaceId)"
222
220
  },
223
221
  name: {
224
222
  type: "string",
@@ -226,11 +224,7 @@ const server = new Server({
226
224
  },
227
225
  content: {
228
226
  type: "string",
229
- description: "Description or content of the list"
230
- },
231
- status: {
232
- type: "string",
233
- description: "Status of the list"
227
+ description: "List description"
234
228
  }
235
229
  },
236
230
  required: ["name"]
@@ -247,18 +241,18 @@ const server = new Server({
247
241
  },
248
242
  listId: {
249
243
  type: "string",
250
- description: "ID of the destination list (optional if listName is provided)"
244
+ description: "ID of destination list (optional if listName is provided)"
251
245
  },
252
246
  listName: {
253
247
  type: "string",
254
- description: "Name of the destination list (optional if listId is provided)"
248
+ description: "Name of destination list (optional if listId is provided)"
255
249
  }
256
250
  },
257
251
  required: ["taskId"]
258
252
  }
259
253
  },
260
254
  duplicate_task: {
261
- description: "Duplicate a task to a list",
255
+ description: "Create a copy of a task in a specified list",
262
256
  inputSchema: {
263
257
  type: "object",
264
258
  properties: {
@@ -268,18 +262,18 @@ const server = new Server({
268
262
  },
269
263
  listId: {
270
264
  type: "string",
271
- description: "ID of the destination list (optional if listName is provided)"
265
+ description: "ID of destination list (optional if listName is provided)"
272
266
  },
273
267
  listName: {
274
268
  type: "string",
275
- description: "Name of the destination list (optional if listId is provided)"
269
+ description: "Name of destination list (optional if listId is provided)"
276
270
  }
277
271
  },
278
272
  required: ["taskId"]
279
273
  }
280
274
  },
281
275
  update_task: {
282
- description: "Update an existing task in ClickUp",
276
+ description: "Update an existing task",
283
277
  inputSchema: {
284
278
  type: "object",
285
279
  properties: {
@@ -289,55 +283,106 @@ const server = new Server({
289
283
  },
290
284
  name: {
291
285
  type: "string",
292
- description: "New name of the task"
286
+ description: "New task name"
293
287
  },
294
288
  description: {
295
289
  type: "string",
296
- description: "New description of the task"
290
+ description: "New description"
297
291
  },
298
292
  status: {
299
293
  type: "string",
300
- description: "New status of the task"
294
+ description: "New status"
301
295
  },
302
296
  priority: {
303
297
  type: "number",
304
- description: "New priority of the task (1-4)"
298
+ description: "New priority level (1-4)"
305
299
  },
306
300
  dueDate: {
307
301
  type: "string",
308
- description: "New due date of the task (ISO string)"
302
+ description: "New due date (ISO string)"
309
303
  }
310
304
  },
311
305
  required: ["taskId"]
312
306
  }
313
307
  }
314
- },
315
- prompts: {
316
- summarize_tasks: {
317
- description: "Summarize tasks in the workspace",
318
- inputSchema: {
319
- type: "object",
320
- properties: {},
321
- required: []
322
- }
323
- },
324
- analyze_priorities: {
325
- description: "Analyze task priorities",
326
- inputSchema: {
327
- type: "object",
328
- properties: {},
329
- required: []
330
- }
331
- }
332
- },
308
+ }
333
309
  },
310
+ errorHandler: (error) => {
311
+ logError('mcp', error);
312
+ }
334
313
  });
335
- console.log('MCP server created');
336
314
  /**
337
- * Handler for listing available ClickUp tasks as resources.
315
+ * Register handlers for MCP tool requests
316
+ * Each tool is mapped to its corresponding handler function
317
+ */
318
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
319
+ try {
320
+ logDebug('tool.request', { name: request.params.name });
321
+ switch (request.params.name) {
322
+ case "workspace_hierarchy": {
323
+ return await handleWorkspaceHierarchy(clickup, config.teamId);
324
+ }
325
+ case "create_task": {
326
+ const args = request.params.arguments;
327
+ return await handleCreateTask(clickup, config.teamId, args);
328
+ }
329
+ case "create_bulk_tasks": {
330
+ const args = request.params.arguments;
331
+ return await handleCreateBulkTasks(clickup, config.teamId, args);
332
+ }
333
+ case "create_list": {
334
+ const args = request.params.arguments;
335
+ return await handleCreateList(clickup, config.teamId, args);
336
+ }
337
+ case "create_folder": {
338
+ const args = request.params.arguments;
339
+ return await handleCreateFolder(clickup, config.teamId, args);
340
+ }
341
+ case "create_list_in_folder": {
342
+ const args = request.params.arguments;
343
+ return await handleCreateListInFolder(clickup, config.teamId, args);
344
+ }
345
+ case "move_task": {
346
+ const args = request.params.arguments;
347
+ return await handleMoveTask(clickup, config.teamId, args);
348
+ }
349
+ case "duplicate_task": {
350
+ const args = request.params.arguments;
351
+ return await handleDuplicateTask(clickup, config.teamId, args);
352
+ }
353
+ case "update_task": {
354
+ const args = request.params.arguments;
355
+ return await handleUpdateTask(clickup, config.teamId, args);
356
+ }
357
+ default:
358
+ throw new Error(`Unknown tool: ${request.params.name}`);
359
+ }
360
+ }
361
+ catch (error) {
362
+ logError(`tool.${request.params.name}`, error);
363
+ throw error;
364
+ }
365
+ });
366
+ /**
367
+ * Initialize and start the server
368
+ * Connects to the transport and begins listening for requests
369
+ */
370
+ try {
371
+ logInfo('mcp', { status: 'connecting' });
372
+ const transport = new StdioServerTransport();
373
+ await server.connect(transport);
374
+ logInfo('mcp', { status: 'connected' });
375
+ }
376
+ catch (error) {
377
+ logError('mcp.connection', error);
378
+ process.exit(1);
379
+ }
380
+ /**
381
+ * Handler for listing available ClickUp tasks as resources
382
+ * Returns a list of all tasks across all spaces with their metadata
338
383
  */
339
384
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
340
- console.log('Handling ListResources request');
385
+ logDebug('resources', { action: 'listing' });
341
386
  try {
342
387
  const { tasks, spaces } = await getAllTasks(clickup, config.teamId);
343
388
  return {
@@ -351,17 +396,19 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
351
396
  };
352
397
  }
353
398
  catch (error) {
354
- console.error('Error in ListResources:', error);
399
+ logError('resources.list', error);
355
400
  throw error;
356
401
  }
357
402
  });
358
403
  /**
359
- * Handler for reading the contents of a specific ClickUp task.
404
+ * Handler for reading individual ClickUp task contents
405
+ * Returns detailed information about a specific task
360
406
  */
361
407
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
362
408
  try {
363
409
  const url = new URL(request.params.uri);
364
410
  const taskId = url.pathname.replace(/^\/task\//, '');
411
+ logDebug('resources.read', { taskId });
365
412
  const task = await clickup.getTask(taskId);
366
413
  return {
367
414
  contents: [{
@@ -373,259 +420,28 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
373
420
  };
374
421
  }
375
422
  catch (error) {
376
- console.error('Error reading resource:', error);
423
+ logError('resources.read', error);
377
424
  throw error;
378
425
  }
379
426
  });
380
427
  /**
381
- * Handler for listing available tools.
428
+ * Handler for listing available tools
429
+ * Returns metadata about all registered tools
382
430
  */
383
431
  server.setRequestHandler(ListToolsRequestSchema, async () => {
384
- console.log('Handling ListTools request');
432
+ logDebug('tools', { action: 'listing' });
385
433
  const toolCapabilities = server.capabilities?.tools || {};
386
- return {
387
- tools: Object.entries(toolCapabilities).map(([name, tool]) => ({
388
- name,
389
- description: tool.description,
390
- inputSchema: tool.inputSchema
391
- }))
392
- };
393
- });
394
- /**
395
- * Handler for executing tools.
396
- */
397
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
398
- try {
399
- switch (request.params.name) {
400
- case "workspace_hierarchy": {
401
- const output = await handleWorkspaceHierarchy(clickup, config.teamId);
402
- return {
403
- content: [{
404
- type: "text",
405
- text: output
406
- }]
407
- };
408
- }
409
- case "create_task": {
410
- const args = request.params.arguments;
411
- const task = await handleCreateTask(clickup, config.teamId, args);
412
- return {
413
- content: [{
414
- type: "text",
415
- text: `Created task ${task.id}: ${task.name}`
416
- }]
417
- };
418
- }
419
- case "create_bulk_tasks": {
420
- const args = request.params.arguments;
421
- let listId = args.listId;
422
- if (!listId && args.listName) {
423
- const result = await clickup.findListByNameGlobally(config.teamId, args.listName);
424
- if (!result) {
425
- throw new Error(`List with name "${args.listName}" not found`);
426
- }
427
- listId = result.list.id;
428
- }
429
- if (!listId) {
430
- throw new Error("Either listId or listName is required");
431
- }
432
- if (!args.tasks || !args.tasks.length) {
433
- throw new Error("At least one task is required");
434
- }
435
- const { listId: _, listName: __, tasks } = args;
436
- const createdTasks = await clickup.createBulkTasks(listId, { tasks });
437
- return {
438
- content: [{
439
- type: "text",
440
- text: `Created ${createdTasks.length} tasks:\n${createdTasks.map(task => `- ${task.id}: ${task.name}`).join('\n')}`
441
- }]
442
- };
443
- }
444
- case "create_list": {
445
- const args = request.params.arguments;
446
- if (!args.name) {
447
- throw new Error("name is required");
448
- }
449
- // If folder is specified, create list in folder
450
- if (args.folderName || args.folderId) {
451
- let folderId = args.folderId;
452
- if (!folderId && args.folderName) {
453
- const result = await clickup.findFolderByNameGlobally(config.teamId, args.folderName);
454
- if (!result) {
455
- throw new Error(`Folder with name "${args.folderName}" not found`);
456
- }
457
- folderId = result.folder.id;
458
- }
459
- if (!folderId) {
460
- throw new Error("Either folderId or folderName must be provided");
461
- }
462
- const { spaceId: _, spaceName: __, folderName: ___, folderId: ____, ...listData } = args;
463
- const list = await clickup.createListInFolder(folderId, listData);
464
- return {
465
- content: [{
466
- type: "text",
467
- text: `Created list ${list.id}: ${list.name} in folder`
468
- }]
469
- };
470
- }
471
- // Otherwise, create list in space
472
- let spaceId = args.spaceId;
473
- if (!spaceId && args.spaceName) {
474
- const space = await clickup.findSpaceByName(config.teamId, args.spaceName);
475
- if (!space) {
476
- throw new Error(`Space with name "${args.spaceName}" not found`);
477
- }
478
- spaceId = space.id;
479
- }
480
- if (!spaceId) {
481
- throw new Error("Either spaceId or spaceName must be provided");
482
- }
483
- const { spaceId: _, spaceName: __, folderName: ___, folderId: ____, ...listData } = args;
484
- const list = await clickup.createList(spaceId, listData);
485
- return {
486
- content: [{
487
- type: "text",
488
- text: `Created list ${list.id}: ${list.name}`
489
- }]
490
- };
491
- }
492
- case "create_folder": {
493
- const args = request.params.arguments;
494
- if (!args.name) {
495
- throw new Error("name is required");
496
- }
497
- let spaceId = args.spaceId;
498
- if (!spaceId && args.spaceName) {
499
- const space = await clickup.findSpaceByName(config.teamId, args.spaceName);
500
- if (!space) {
501
- throw new Error(`Space with name "${args.spaceName}" not found`);
502
- }
503
- spaceId = space.id;
504
- }
505
- if (!spaceId) {
506
- throw new Error("Either spaceId or spaceName must be provided");
507
- }
508
- const { spaceId: _, spaceName: __, ...folderData } = args;
509
- const folder = await clickup.createFolder(spaceId, folderData);
510
- return {
511
- content: [{
512
- type: "text",
513
- text: `Created folder ${folder.id}: ${folder.name}`
514
- }]
515
- };
516
- }
517
- case "create_list_in_folder": {
518
- const args = request.params.arguments;
519
- if (!args.name) {
520
- throw new Error("name is required");
521
- }
522
- let folderId = args.folderId;
523
- if (!folderId && args.folderName) {
524
- const result = await clickup.findFolderByNameGlobally(config.teamId, args.folderName);
525
- if (!result) {
526
- throw new Error(`Folder with name "${args.folderName}" not found`);
527
- }
528
- folderId = result.folder.id;
529
- }
530
- if (!folderId) {
531
- throw new Error("Either folderId or folderName is required");
532
- }
533
- const listData = {
534
- name: args.name,
535
- content: args.content,
536
- status: args.status
537
- };
538
- try {
539
- const list = await clickup.createListInFolder(folderId, listData);
540
- return {
541
- content: [{
542
- type: "text",
543
- text: `Created list ${list.id}: ${list.name} in folder`
544
- }]
545
- };
546
- }
547
- catch (error) {
548
- throw new Error(`Failed to create list: ${error.message}`);
549
- }
550
- }
551
- case "move_task": {
552
- const args = request.params.arguments;
553
- if (!args.taskId) {
554
- throw new Error("taskId is required");
555
- }
556
- let listId = args.listId;
557
- if (!listId && args.listName) {
558
- const result = await clickup.findListByNameGlobally(config.teamId, args.listName);
559
- if (!result) {
560
- throw new Error(`List with name "${args.listName}" not found`);
561
- }
562
- listId = result.list.id;
563
- }
564
- if (!listId) {
565
- throw new Error("Either listId or listName is required");
566
- }
567
- const task = await clickup.moveTask(args.taskId, listId);
568
- return {
569
- content: [{
570
- type: "text",
571
- text: `Moved task ${task.id} to list ${listId}`
572
- }]
573
- };
574
- }
575
- case "duplicate_task": {
576
- const args = request.params.arguments;
577
- if (!args.taskId) {
578
- throw new Error("taskId is required");
579
- }
580
- let listId = args.listId;
581
- if (!listId && args.listName) {
582
- const result = await clickup.findListByNameGlobally(config.teamId, args.listName);
583
- if (!result) {
584
- throw new Error(`List with name "${args.listName}" not found`);
585
- }
586
- listId = result.list.id;
587
- }
588
- if (!listId) {
589
- throw new Error("Either listId or listName is required");
590
- }
591
- const task = await clickup.duplicateTask(args.taskId, listId);
592
- return {
593
- content: [{
594
- type: "text",
595
- text: `Duplicated task ${args.taskId} to new task ${task.id} in list ${listId}`
596
- }]
597
- };
598
- }
599
- case "update_task": {
600
- const args = request.params.arguments;
601
- if (!args.taskId) {
602
- throw new Error("taskId is required");
603
- }
604
- const task = await clickup.updateTask(args.taskId, {
605
- name: args.name,
606
- description: args.description,
607
- status: args.status,
608
- priority: args.priority,
609
- due_date: args.due_date
610
- });
611
- return {
612
- content: [{
613
- type: "text",
614
- text: `Updated task ${task.id}: ${task.name}`
615
- }]
616
- };
617
- }
618
- default:
619
- throw new Error("Unknown tool");
620
- }
621
- }
622
- catch (error) {
623
- console.error('Error executing tool:', error);
624
- throw error;
625
- }
434
+ const tools = Object.entries(toolCapabilities).map(([name, tool]) => ({
435
+ name,
436
+ description: tool.description,
437
+ inputSchema: tool.inputSchema
438
+ }));
439
+ logDebug('tools', { count: tools.length });
440
+ return { tools };
626
441
  });
627
442
  /**
628
- * Handler for listing available prompts.
443
+ * Handler for listing available prompts
444
+ * Returns metadata about all registered prompts
629
445
  */
630
446
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
631
447
  return {
@@ -642,7 +458,8 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
642
458
  };
643
459
  });
644
460
  /**
645
- * Handler for getting a specific prompt.
461
+ * Handler for executing specific prompts
462
+ * Maps prompt names to their corresponding handler functions
646
463
  */
647
464
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
648
465
  try {
@@ -670,42 +487,61 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
670
487
  }
671
488
  }
672
489
  catch (error) {
673
- console.error('Error getting prompt:', error);
490
+ logError('prompt', error);
674
491
  throw error;
675
492
  }
676
493
  });
494
+ // Server startup logic
677
495
  if (process.argv.includes('--stdio')) {
678
- console.log('Starting server in stdio mode...');
496
+ logInfo('server', { status: 'stdio.starting' });
679
497
  // Set up stdio transport
680
498
  const transport = new StdioServerTransport();
681
499
  // Connect server with better error handling
682
500
  server.connect(transport)
683
501
  .then(() => {
684
- console.log('Server connected successfully to stdio transport');
502
+ logInfo('server', { status: 'connected' });
503
+ // Send initial handshake message with more details
504
+ const capabilities = {
505
+ tools: server.capabilities?.tools || {},
506
+ prompts: server.capabilities?.prompts || {},
507
+ resources: {
508
+ list: true,
509
+ read: true
510
+ }
511
+ };
512
+ logInfo('mcp', { status: 'handshake.preparing' });
513
+ logInfo('mcp', {
514
+ status: 'handshake',
515
+ name: "clickup-mcp-server",
516
+ version: "0.4.17", // Match package.json version
517
+ hasTools: Object.keys(capabilities.tools).length > 0,
518
+ hasPrompts: Object.keys(capabilities.prompts).length > 0
519
+ });
520
+ logInfo('server', { status: 'ready' });
685
521
  // Keep the process alive
686
522
  process.stdin.resume();
687
523
  // Handle process termination
688
524
  process.on('SIGINT', () => {
689
- console.log('Received SIGINT. Shutting down...');
525
+ logInfo('server', { status: 'shutdown.sigint' });
690
526
  transport.close();
691
527
  process.exit(0);
692
528
  });
693
529
  process.on('SIGTERM', () => {
694
- console.log('Received SIGTERM. Shutting down...');
530
+ logInfo('server', { status: 'shutdown.sigterm' });
695
531
  transport.close();
696
532
  process.exit(0);
697
533
  });
698
534
  })
699
535
  .catch(error => {
700
- console.error('Failed to connect server to transport:', error);
536
+ logError('server', error);
701
537
  process.exit(1);
702
538
  });
703
539
  }
704
540
  else {
705
- console.log('Starting server in standard mode...');
541
+ logInfo('server', { status: 'standard.starting' });
706
542
  // Add your non-stdio server initialization here if needed
707
543
  }
708
544
  // Prevent unhandled promise rejections from crashing the server
709
545
  process.on('unhandledRejection', (error) => {
710
- console.error('Unhandled promise rejection:', error);
546
+ logError('server.unhandled', error);
711
547
  });