@alanse/clickup-multi-mcp-server 1.0.0

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 (56) hide show
  1. package/Dockerfile +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +470 -0
  4. package/build/config.js +237 -0
  5. package/build/index.js +87 -0
  6. package/build/logger.js +163 -0
  7. package/build/middleware/security.js +231 -0
  8. package/build/server.js +288 -0
  9. package/build/services/clickup/base.js +432 -0
  10. package/build/services/clickup/bulk.js +180 -0
  11. package/build/services/clickup/document.js +159 -0
  12. package/build/services/clickup/folder.js +136 -0
  13. package/build/services/clickup/index.js +76 -0
  14. package/build/services/clickup/list.js +191 -0
  15. package/build/services/clickup/tag.js +239 -0
  16. package/build/services/clickup/task/index.js +32 -0
  17. package/build/services/clickup/task/task-attachments.js +105 -0
  18. package/build/services/clickup/task/task-comments.js +114 -0
  19. package/build/services/clickup/task/task-core.js +604 -0
  20. package/build/services/clickup/task/task-custom-fields.js +107 -0
  21. package/build/services/clickup/task/task-search.js +986 -0
  22. package/build/services/clickup/task/task-service.js +104 -0
  23. package/build/services/clickup/task/task-tags.js +113 -0
  24. package/build/services/clickup/time.js +244 -0
  25. package/build/services/clickup/types.js +33 -0
  26. package/build/services/clickup/workspace.js +397 -0
  27. package/build/services/shared.js +61 -0
  28. package/build/sse_server.js +277 -0
  29. package/build/tools/documents.js +489 -0
  30. package/build/tools/folder.js +331 -0
  31. package/build/tools/index.js +16 -0
  32. package/build/tools/list.js +428 -0
  33. package/build/tools/member.js +106 -0
  34. package/build/tools/tag.js +833 -0
  35. package/build/tools/task/attachments.js +357 -0
  36. package/build/tools/task/attachments.types.js +9 -0
  37. package/build/tools/task/bulk-operations.js +338 -0
  38. package/build/tools/task/handlers.js +919 -0
  39. package/build/tools/task/index.js +30 -0
  40. package/build/tools/task/main.js +233 -0
  41. package/build/tools/task/single-operations.js +469 -0
  42. package/build/tools/task/time-tracking.js +575 -0
  43. package/build/tools/task/utilities.js +310 -0
  44. package/build/tools/task/workspace-operations.js +258 -0
  45. package/build/tools/tool-enhancer.js +37 -0
  46. package/build/tools/utils.js +12 -0
  47. package/build/tools/workspace-helper.js +44 -0
  48. package/build/tools/workspace.js +73 -0
  49. package/build/utils/color-processor.js +183 -0
  50. package/build/utils/concurrency-utils.js +248 -0
  51. package/build/utils/date-utils.js +542 -0
  52. package/build/utils/resolver-utils.js +135 -0
  53. package/build/utils/sponsor-service.js +93 -0
  54. package/build/utils/token-utils.js +49 -0
  55. package/package.json +77 -0
  56. package/smithery.yaml +23 -0
@@ -0,0 +1,159 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: © 2025 João Santana <joaosantana@gmail.com>
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Document service for ClickUp
6
+ *
7
+ * This service provides methods to manage ClickUp documents:
8
+ * - Create documents
9
+ * - Get document details
10
+ * - List documents in a container
11
+ * - List document pages
12
+ * - Get document pages content
13
+ * - Update document pages
14
+ */
15
+ import { BaseClickUpService, ClickUpServiceError, ErrorCode } from './base.js';
16
+ export class DocumentService extends BaseClickUpService {
17
+ constructor(apiKey, teamId, baseUrl) {
18
+ // Override baseUrl to use v3 API, since Docs are only available in v3
19
+ super(apiKey, teamId, baseUrl || 'https://api.clickup.com/api/v3');
20
+ }
21
+ /**
22
+ * Helper method to handle errors consistently
23
+ * @param error The error that occurred
24
+ * @param message Optional custom error message
25
+ * @returns A ClickUpServiceError
26
+ */
27
+ handleError(error, message) {
28
+ if (error instanceof ClickUpServiceError) {
29
+ return error;
30
+ }
31
+ return new ClickUpServiceError(message || `Document service error: ${error.message}`, ErrorCode.UNKNOWN, error);
32
+ }
33
+ /**
34
+ * Creates a new document in a space, folder, or list
35
+ * @param data - Document data with parent object structured as {id: string, type: number}
36
+ * @returns Created document
37
+ */
38
+ async createDocument(data) {
39
+ try {
40
+ // Log the request data for debugging
41
+ this.logOperation('Creating document with data:', { data });
42
+ const response = await this.client.post(`/workspaces/${this.teamId}/docs`, {
43
+ name: data.name,
44
+ parent: data.parent,
45
+ visibility: data.visibility || 'PRIVATE',
46
+ create_page: data.create_page !== undefined ? data.create_page : true
47
+ });
48
+ return response.data;
49
+ }
50
+ catch (error) {
51
+ throw this.handleError(error, 'Failed to create document');
52
+ }
53
+ }
54
+ /**
55
+ * Creates a new page in a document
56
+ * @param documentId - ID of the document to create the page in
57
+ * @param data - Page data
58
+ * @returns Created page
59
+ */
60
+ async createPage(documentId, data) {
61
+ try {
62
+ this.logOperation('Creating page in document with data:', { documentId, data });
63
+ const response = await this.client.post(`/workspaces/${this.teamId}/docs/${documentId}/pages`, data);
64
+ return response.data;
65
+ }
66
+ catch (error) {
67
+ throw this.handleError(error, `Failed to create page in document ${documentId}`);
68
+ }
69
+ }
70
+ /**
71
+ * Gets a document by ID
72
+ * @param documentId - ID of the document to retrieve
73
+ * @returns Document details
74
+ */
75
+ async getDocument(documentId) {
76
+ try {
77
+ this.logOperation('Getting document with ID:', { documentId });
78
+ const response = await this.client.get(`/workspaces/${this.teamId}/docs/${documentId}`);
79
+ return response.data;
80
+ }
81
+ catch (error) {
82
+ throw this.handleError(error, `Failed to get document ${documentId}`);
83
+ }
84
+ }
85
+ /**
86
+ * Lists documents in the workspace with optional filters
87
+ * @param options - Search and filter options
88
+ * @returns List of documents
89
+ */
90
+ async listDocuments(options = {}) {
91
+ try {
92
+ this.logOperation('Listing documents with options:', { options });
93
+ const response = await this.client.get(`/workspaces/${this.teamId}/docs`, {
94
+ params: options
95
+ });
96
+ return response.data;
97
+ }
98
+ catch (error) {
99
+ throw this.handleError(error, 'Failed to list documents');
100
+ }
101
+ }
102
+ /**
103
+ * Lists all pages in a document with optional depth control
104
+ * @param documentId - ID of the document
105
+ * @param options - Options for page listing
106
+ * @returns List of document pages
107
+ */
108
+ async listDocumentPages(documentId, options = {}) {
109
+ try {
110
+ this.logOperation('Listing pages for document with ID:', { documentId, options });
111
+ const response = await this.client.get(`/workspaces/${this.teamId}/docs/${documentId}/pageListing`, { params: options });
112
+ return response.data;
113
+ }
114
+ catch (error) {
115
+ throw this.handleError(error, `Failed to list pages for document ${documentId}`);
116
+ }
117
+ }
118
+ /**
119
+ * Gets the content of specific pages in a document
120
+ * @param documentId - ID of the document
121
+ * @param pageIds - Array of page IDs to retrieve
122
+ * @param options - Options for retrieving pages content
123
+ * @returns Document pages with content
124
+ */
125
+ async getDocumentPages(documentId, pageIds, options = {}) {
126
+ try {
127
+ // Get pages in parallel
128
+ this.logOperation('Getting pages for document with ID:', { documentId, pageIds, options });
129
+ const pagePromises = pageIds.map(pageId => this.client.get(`/workspaces/${this.teamId}/docs/${documentId}/pages/${pageId}`, { params: { ...options, pageIds } }));
130
+ const responses = await Promise.all(pagePromises);
131
+ const pages = responses.map(response => response.data);
132
+ return { pages };
133
+ }
134
+ catch (error) {
135
+ throw this.handleError(error, `Failed to get pages for document ${documentId}`);
136
+ }
137
+ }
138
+ /**
139
+ * Updates an existing page in a document
140
+ * @param documentId - ID of the document containing the page
141
+ * @param pageId - ID of the page to update
142
+ * @param data - Updated page data
143
+ * @returns Updated page
144
+ */
145
+ async updatePage(documentId, pageId, data) {
146
+ try {
147
+ this.logOperation('Updating page in document with ID:', { documentId, pageId, data });
148
+ const response = await this.client.put(`/workspaces/${this.teamId}/docs/${documentId}/pages/${pageId}`, {
149
+ ...data,
150
+ content_format: data.content_format || 'text/md',
151
+ content_edit_mode: data.content_edit_mode || 'append'
152
+ });
153
+ return response.data;
154
+ }
155
+ catch (error) {
156
+ throw this.handleError(error, `Failed to update page ${pageId} in document ${documentId}`);
157
+ }
158
+ }
159
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: © 2025 Talib Kareem <taazkareem@icloud.com>
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * ClickUp Folder Service
6
+ *
7
+ * Handles all operations related to folders in ClickUp, including:
8
+ * - Creating folders
9
+ * - Retrieving folders
10
+ * - Updating folders
11
+ * - Deleting folders
12
+ * - Finding folders by name
13
+ */
14
+ import { BaseClickUpService, ErrorCode, ClickUpServiceError } from './base.js';
15
+ export class FolderService extends BaseClickUpService {
16
+ /**
17
+ * Creates an instance of FolderService
18
+ * @param apiKey - ClickUp API key
19
+ * @param teamId - ClickUp team ID
20
+ * @param baseUrl - Optional custom API URL
21
+ * @param workspaceService - Optional workspace service for lookups
22
+ */
23
+ constructor(apiKey, teamId, baseUrl, workspaceService) {
24
+ super(apiKey, teamId, baseUrl);
25
+ this.workspaceService = null;
26
+ this.workspaceService = workspaceService || null;
27
+ }
28
+ /**
29
+ * Helper method to handle errors consistently
30
+ * @param error The error that occurred
31
+ * @param message Optional custom error message
32
+ * @returns A ClickUpServiceError
33
+ */
34
+ handleError(error, message) {
35
+ if (error instanceof ClickUpServiceError) {
36
+ return error;
37
+ }
38
+ return new ClickUpServiceError(message || `Folder service error: ${error.message}`, ErrorCode.UNKNOWN, error);
39
+ }
40
+ /**
41
+ * Create a new folder in a space
42
+ * @param spaceId The ID of the space to create the folder in
43
+ * @param folderData The data for the new folder
44
+ * @returns The created folder
45
+ */
46
+ async createFolder(spaceId, folderData) {
47
+ try {
48
+ this.logOperation('createFolder', { spaceId, ...folderData });
49
+ const response = await this.client.post(`/space/${spaceId}/folder`, folderData);
50
+ return response.data;
51
+ }
52
+ catch (error) {
53
+ throw this.handleError(error, `Failed to create folder in space ${spaceId}`);
54
+ }
55
+ }
56
+ /**
57
+ * Get a folder by its ID
58
+ * @param folderId The ID of the folder to retrieve
59
+ * @returns The folder details
60
+ */
61
+ async getFolder(folderId) {
62
+ try {
63
+ this.logOperation('getFolder', { folderId });
64
+ const response = await this.client.get(`/folder/${folderId}`);
65
+ return response.data;
66
+ }
67
+ catch (error) {
68
+ throw this.handleError(error, `Failed to get folder ${folderId}`);
69
+ }
70
+ }
71
+ /**
72
+ * Update an existing folder
73
+ * @param folderId The ID of the folder to update
74
+ * @param updateData The data to update on the folder
75
+ * @returns The updated folder
76
+ */
77
+ async updateFolder(folderId, updateData) {
78
+ try {
79
+ this.logOperation('updateFolder', { folderId, ...updateData });
80
+ const response = await this.client.put(`/folder/${folderId}`, updateData);
81
+ return response.data;
82
+ }
83
+ catch (error) {
84
+ throw this.handleError(error, `Failed to update folder ${folderId}`);
85
+ }
86
+ }
87
+ /**
88
+ * Delete a folder
89
+ * @param folderId The ID of the folder to delete
90
+ * @returns Success indicator
91
+ */
92
+ async deleteFolder(folderId) {
93
+ try {
94
+ this.logOperation('deleteFolder', { folderId });
95
+ await this.client.delete(`/folder/${folderId}`);
96
+ return {
97
+ success: true
98
+ };
99
+ }
100
+ catch (error) {
101
+ throw this.handleError(error, `Failed to delete folder ${folderId}`);
102
+ }
103
+ }
104
+ /**
105
+ * Get all folders in a space
106
+ * @param spaceId The ID of the space to get folders from
107
+ * @returns Array of folders in the space
108
+ */
109
+ async getFoldersInSpace(spaceId) {
110
+ this.logOperation('getFoldersInSpace', { spaceId });
111
+ try {
112
+ const response = await this.client.get(`/space/${spaceId}/folder`);
113
+ return response.data.folders;
114
+ }
115
+ catch (error) {
116
+ throw this.handleError(error, `Failed to get folders in space ${spaceId}`);
117
+ }
118
+ }
119
+ /**
120
+ * Find a folder by its name in a space
121
+ * @param spaceId The ID of the space to search in
122
+ * @param folderName The name of the folder to find
123
+ * @returns The folder if found, otherwise null
124
+ */
125
+ async findFolderByName(spaceId, folderName) {
126
+ this.logOperation('findFolderByName', { spaceId, folderName });
127
+ try {
128
+ const folders = await this.getFoldersInSpace(spaceId);
129
+ const matchingFolder = folders.find(folder => folder.name.toLowerCase() === folderName.toLowerCase());
130
+ return matchingFolder || null;
131
+ }
132
+ catch (error) {
133
+ throw this.handleError(error, `Failed to find folder by name in space ${spaceId}`);
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: © 2025 Talib Kareem <taazkareem@icloud.com>
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * ClickUp Service Entry Point
6
+ *
7
+ * This file re-exports all service modules for the ClickUp API integration.
8
+ * It also provides a convenient factory method to create instances of all services.
9
+ */
10
+ // Export base service components
11
+ export { BaseClickUpService, ClickUpServiceError, ErrorCode } from './base.js';
12
+ // Export type definitions
13
+ export * from './types.js';
14
+ // Export service modules
15
+ export { WorkspaceService } from './workspace.js';
16
+ export { TaskService } from './task/index.js';
17
+ export { ListService } from './list.js';
18
+ export { FolderService } from './folder.js';
19
+ export { ClickUpTagService } from './tag.js';
20
+ export { TimeTrackingService } from './time.js';
21
+ export { DocumentService } from './document.js';
22
+ // Import service classes for the factory function
23
+ import { WorkspaceService } from './workspace.js';
24
+ import { TaskService } from './task/index.js';
25
+ import { ListService } from './list.js';
26
+ import { FolderService } from './folder.js';
27
+ import { ClickUpTagService } from './tag.js';
28
+ import { TimeTrackingService } from './time.js';
29
+ import { Logger } from '../../logger.js';
30
+ import { DocumentService } from './document.js';
31
+ // Singleton logger for ClickUp services
32
+ const logger = new Logger('ClickUpServices');
33
+ /**
34
+ * Factory function to create instances of all ClickUp services
35
+ * @param config Configuration for the services
36
+ * @returns Object containing all service instances
37
+ */
38
+ export function createClickUpServices(config) {
39
+ const { apiKey, teamId, baseUrl } = config;
40
+ // Log start of overall initialization
41
+ logger.info('Starting ClickUp services initialization', {
42
+ teamId,
43
+ baseUrl: baseUrl || 'https://api.clickup.com/api/v2'
44
+ });
45
+ // Create workspace service first since others depend on it
46
+ logger.info('Initializing ClickUp Workspace service');
47
+ const workspaceService = new WorkspaceService(apiKey, teamId, baseUrl);
48
+ // Initialize remaining services with workspace dependency
49
+ logger.info('Initializing ClickUp Task service');
50
+ const taskService = new TaskService(apiKey, teamId, baseUrl, workspaceService);
51
+ logger.info('Initializing ClickUp List service');
52
+ const listService = new ListService(apiKey, teamId, baseUrl, workspaceService);
53
+ logger.info('Initializing ClickUp Folder service');
54
+ const folderService = new FolderService(apiKey, teamId, baseUrl, workspaceService);
55
+ logger.info('Initializing ClickUp Tag service');
56
+ const tagService = new ClickUpTagService(apiKey, teamId, baseUrl);
57
+ logger.info('Initializing ClickUp Time Tracking service');
58
+ const timeTrackingService = new TimeTrackingService(apiKey, teamId, baseUrl);
59
+ logger.info('Initializing ClickUp Document service');
60
+ const documentService = new DocumentService(apiKey, teamId, baseUrl);
61
+ const services = {
62
+ workspace: workspaceService,
63
+ task: taskService,
64
+ list: listService,
65
+ folder: folderService,
66
+ tag: tagService,
67
+ timeTracking: timeTrackingService,
68
+ document: documentService
69
+ };
70
+ // Log successful completion
71
+ logger.info('All ClickUp services initialized successfully', {
72
+ services: Object.keys(services),
73
+ baseUrl: baseUrl || 'https://api.clickup.com/api/v2'
74
+ });
75
+ return services;
76
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: © 2025 Talib Kareem <taazkareem@icloud.com>
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * ClickUp List Service
6
+ *
7
+ * Handles all operations related to lists in ClickUp, including:
8
+ * - Creating lists
9
+ * - Retrieving lists
10
+ * - Updating lists
11
+ * - Deleting lists
12
+ * - Finding lists by name
13
+ */
14
+ import { BaseClickUpService, ErrorCode, ClickUpServiceError } from './base.js';
15
+ export class ListService extends BaseClickUpService {
16
+ constructor(apiKey, teamId, baseUrl, workspaceService) {
17
+ super(apiKey, teamId, baseUrl);
18
+ this.workspaceService = null;
19
+ this.workspaceService = workspaceService || null;
20
+ }
21
+ /**
22
+ * Helper method to handle errors consistently
23
+ * @param error The error that occurred
24
+ * @param message Optional custom error message
25
+ * @returns A ClickUpServiceError
26
+ */
27
+ handleError(error, message) {
28
+ if (error instanceof ClickUpServiceError) {
29
+ return error;
30
+ }
31
+ return new ClickUpServiceError(message || `List service error: ${error.message}`, ErrorCode.UNKNOWN, error);
32
+ }
33
+ /**
34
+ * Create a new list in a space
35
+ * @param spaceId The ID of the space to create the list in
36
+ * @param listData The data for the new list
37
+ * @returns The created list
38
+ */
39
+ async createList(spaceId, listData) {
40
+ this.logOperation('createList', { spaceId, ...listData });
41
+ try {
42
+ return await this.makeRequest(async () => {
43
+ const response = await this.client.post(`/space/${spaceId}/list`, listData);
44
+ return response.data;
45
+ });
46
+ }
47
+ catch (error) {
48
+ throw this.handleError(error, `Failed to create list in space ${spaceId}`);
49
+ }
50
+ }
51
+ /**
52
+ * Create a new list in a folder
53
+ * @param folderId The ID of the folder to create the list in
54
+ * @param listData The data for the new list
55
+ * @returns The created list
56
+ */
57
+ async createListInFolder(folderId, listData) {
58
+ this.logOperation('createListInFolder', { folderId, ...listData });
59
+ try {
60
+ return await this.makeRequest(async () => {
61
+ const response = await this.client.post(`/folder/${folderId}/list`, listData);
62
+ return response.data;
63
+ });
64
+ }
65
+ catch (error) {
66
+ throw this.handleError(error, `Failed to create list in folder ${folderId}`);
67
+ }
68
+ }
69
+ /**
70
+ * Get a list by ID
71
+ * @param listId The ID of the list to retrieve
72
+ * @returns The requested list
73
+ */
74
+ async getList(listId) {
75
+ this.logOperation('getList', { listId });
76
+ try {
77
+ return await this.makeRequest(async () => {
78
+ const response = await this.client.get(`/list/${listId}`);
79
+ return response.data;
80
+ });
81
+ }
82
+ catch (error) {
83
+ throw this.handleError(error, `Failed to get list ${listId}`);
84
+ }
85
+ }
86
+ /**
87
+ * Update an existing list
88
+ * @param listId The ID of the list to update
89
+ * @param updateData The data to update on the list
90
+ * @returns The updated list
91
+ */
92
+ async updateList(listId, updateData) {
93
+ this.logOperation('updateList', { listId, ...updateData });
94
+ try {
95
+ return await this.makeRequest(async () => {
96
+ const response = await this.client.put(`/list/${listId}`, updateData);
97
+ return response.data;
98
+ });
99
+ }
100
+ catch (error) {
101
+ throw this.handleError(error, `Failed to update list ${listId}`);
102
+ }
103
+ }
104
+ /**
105
+ * Delete a list
106
+ * @param listId The ID of the list to delete
107
+ * @returns Success indicator
108
+ */
109
+ async deleteList(listId) {
110
+ this.logOperation('deleteList', { listId });
111
+ try {
112
+ await this.makeRequest(async () => {
113
+ await this.client.delete(`/list/${listId}`);
114
+ });
115
+ return {
116
+ success: true
117
+ };
118
+ }
119
+ catch (error) {
120
+ throw this.handleError(error, `Failed to delete list ${listId}`);
121
+ }
122
+ }
123
+ /**
124
+ * Get all lists in a space
125
+ * @param spaceId The ID of the space to get lists from
126
+ * @returns Array of lists in the space
127
+ */
128
+ async getListsInSpace(spaceId) {
129
+ this.logOperation('getListsInSpace', { spaceId });
130
+ try {
131
+ return await this.makeRequest(async () => {
132
+ const response = await this.client.get(`/space/${spaceId}/list`);
133
+ return response.data.lists;
134
+ });
135
+ }
136
+ catch (error) {
137
+ throw this.handleError(error, `Failed to get lists in space ${spaceId}`);
138
+ }
139
+ }
140
+ /**
141
+ * Get all lists in a folder
142
+ * @param folderId The ID of the folder to get lists from
143
+ * @returns Array of lists in the folder
144
+ */
145
+ async getListsInFolder(folderId) {
146
+ this.logOperation('getListsInFolder', { folderId });
147
+ try {
148
+ return await this.makeRequest(async () => {
149
+ const response = await this.client.get(`/folder/${folderId}/list`);
150
+ return response.data.lists;
151
+ });
152
+ }
153
+ catch (error) {
154
+ throw this.handleError(error, `Failed to get lists in folder ${folderId}`);
155
+ }
156
+ }
157
+ /**
158
+ * Find a list by its name in a space
159
+ * @param spaceId The ID of the space to search in
160
+ * @param listName The name of the list to find
161
+ * @returns The list if found, otherwise null
162
+ */
163
+ async findListByNameInSpace(spaceId, listName) {
164
+ this.logOperation('findListByNameInSpace', { spaceId, listName });
165
+ try {
166
+ const lists = await this.getListsInSpace(spaceId);
167
+ const matchingList = lists.find(list => list.name.toLowerCase() === listName.toLowerCase());
168
+ return matchingList || null;
169
+ }
170
+ catch (error) {
171
+ throw this.handleError(error, `Failed to find list by name in space ${spaceId}`);
172
+ }
173
+ }
174
+ /**
175
+ * Find a list by its name in a folder
176
+ * @param folderId The ID of the folder to search in
177
+ * @param listName The name of the list to find
178
+ * @returns The list if found, otherwise null
179
+ */
180
+ async findListByNameInFolder(folderId, listName) {
181
+ this.logOperation('findListByNameInFolder', { folderId, listName });
182
+ try {
183
+ const lists = await this.getListsInFolder(folderId);
184
+ const matchingList = lists.find(list => list.name.toLowerCase() === listName.toLowerCase());
185
+ return matchingList || null;
186
+ }
187
+ catch (error) {
188
+ throw this.handleError(error, `Failed to find list by name in folder ${folderId}`);
189
+ }
190
+ }
191
+ }