snboard-mcp 1.0.5 → 1.1.1

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/dist/index.js CHANGED
@@ -32,7 +32,14 @@ var kanbanApi = {
32
32
  createFolder: (data) => api("/api/folders", { method: "POST", body: JSON.stringify(data) }),
33
33
  updateFolder: (id, data) => api(`/api/folders/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
34
34
  deleteFolder: (id) => api(`/api/folders/${id}`, { method: "DELETE" }),
35
- moveProjectToFolder: (projectId, folderId) => api(`/api/projects/${projectId}`, { method: "PATCH", body: JSON.stringify({ folderId }) }),
35
+ moveProjectToFolder: (projectId, folderId) => api(`/api/projects/${projectId}`, {
36
+ method: "PATCH",
37
+ body: JSON.stringify({ folderId })
38
+ }),
39
+ reorderFolders: (folderId, targetFolderId) => api("/api/folders/reorder", {
40
+ method: "POST",
41
+ body: JSON.stringify({ folderId, targetFolderId })
42
+ }),
36
43
  // Projects
37
44
  listProjects: (params) => {
38
45
  const searchParams = new URLSearchParams();
@@ -50,9 +57,21 @@ var kanbanApi = {
50
57
  const query = searchParams.toString();
51
58
  return api(`/api/projects/${id}${query ? `?${query}` : ""}`);
52
59
  },
53
- updateProject: (id, data) => api(`/api/projects/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
60
+ updateProject: (id, data) => api(`/api/projects/${id}`, { method: "PUT", body: JSON.stringify(data) }),
54
61
  deleteProject: (id) => api(`/api/projects/${id}`, { method: "DELETE" }),
62
+ reorderProjects: (projectId, targetProjectId, folderId) => api("/api/projects/reorder", {
63
+ method: "POST",
64
+ body: JSON.stringify({ projectId, targetProjectId, folderId })
65
+ }),
55
66
  // Boards
67
+ listBoards: (params) => {
68
+ const searchParams = new URLSearchParams();
69
+ if (params?.projectId) searchParams.set("projectId", params.projectId);
70
+ if (params?.limit) searchParams.set("limit", params.limit.toString());
71
+ if (params?.compact) searchParams.set("compact", "true");
72
+ const query = searchParams.toString();
73
+ return api(`/api/boards${query ? `?${query}` : ""}`);
74
+ },
56
75
  createBoard: (data) => api("/api/boards", { method: "POST", body: JSON.stringify(data) }),
57
76
  getBoard: (id, params) => {
58
77
  const searchParams = new URLSearchParams();
@@ -68,17 +87,38 @@ var kanbanApi = {
68
87
  const query = searchParams.toString();
69
88
  return api(`/api/boards/${id}${query ? `?${query}` : ""}`);
70
89
  },
71
- updateBoard: (id, data) => api(`/api/boards/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
90
+ updateBoard: (id, data) => api(`/api/boards/${id}`, { method: "PUT", body: JSON.stringify(data) }),
72
91
  deleteBoard: (id) => api(`/api/boards/${id}`, { method: "DELETE" }),
73
92
  // Columns
74
93
  createColumn: (data) => api("/api/columns", { method: "POST", body: JSON.stringify(data) }),
75
- updateColumn: (id, data) => api(`/api/columns/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
94
+ updateColumn: (id, data) => api(`/api/columns/${id}`, { method: "PUT", body: JSON.stringify(data) }),
76
95
  deleteColumn: (id) => api(`/api/columns/${id}`, { method: "DELETE" }),
96
+ reorderColumns: (columns) => api("/api/columns/reorder", {
97
+ method: "POST",
98
+ body: JSON.stringify({ columns })
99
+ }),
77
100
  // Cards
101
+ getCard: (id) => api(`/api/cards/${id}`),
78
102
  createCard: (data) => api("/api/cards", { method: "POST", body: JSON.stringify(data) }),
79
- updateCard: (id, data) => api(`/api/cards/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
103
+ updateCard: (id, data) => api(`/api/cards/${id}`, { method: "PUT", body: JSON.stringify(data) }),
80
104
  deleteCard: (id) => api(`/api/cards/${id}`, { method: "DELETE" }),
81
- moveCard: (id, targetColumnId) => api("/api/cards/move", { method: "POST", body: JSON.stringify({ cardId: id, targetColumnId }) }),
105
+ archiveCard: (id) => api(`/api/cards/${id}`, {
106
+ method: "PUT",
107
+ body: JSON.stringify({ isArchived: true })
108
+ }),
109
+ unarchiveCard: (id) => api(`/api/cards/${id}`, {
110
+ method: "PUT",
111
+ body: JSON.stringify({ isArchived: false })
112
+ }),
113
+ listArchivedCards: (boardId) => api(`/api/archived?boardId=${boardId}`),
114
+ moveCard: (id, targetColumnId, newOrder) => api("/api/cards/move", {
115
+ method: "POST",
116
+ body: JSON.stringify({
117
+ cardId: id,
118
+ targetColumnId,
119
+ ...newOrder !== void 0 && { newOrder }
120
+ })
121
+ }),
82
122
  getBranchName: (id, type) => api(`/api/cards/${id}/branch?type=${type}`),
83
123
  searchCards: (params) => {
84
124
  const searchParams = new URLSearchParams();
@@ -88,40 +128,131 @@ var kanbanApi = {
88
128
  if (params.columnId) searchParams.set("columnId", params.columnId);
89
129
  if (params.epicId) searchParams.set("epicId", params.epicId);
90
130
  if (params.featureId) searchParams.set("featureId", params.featureId);
91
- if (params.hasEpic !== void 0) searchParams.set("hasEpic", params.hasEpic.toString());
131
+ if (params.hasEpic !== void 0)
132
+ searchParams.set("hasEpic", params.hasEpic.toString());
92
133
  if (params.status) searchParams.set("status", params.status);
93
- if (params.tagIds?.length) searchParams.set("tagIds", params.tagIds.join(","));
134
+ if (params.tagIds?.length)
135
+ searchParams.set("tagIds", params.tagIds.join(","));
94
136
  searchParams.set("limit", (params.limit || 20).toString());
95
137
  if (params.compact) searchParams.set("compact", "true");
96
138
  return api(`/api/search?${searchParams.toString()}`);
97
139
  },
98
- // Bulk Operations (MCP-side aggregation for efficiency)
140
+ // Tags - managed via card update with tagIds
141
+ addTagToCard: async (cardId, tagId) => {
142
+ const card = await api(`/api/cards/${cardId}`);
143
+ const currentTagIds = (card.tags || []).map((t) => t.id);
144
+ if (!currentTagIds.includes(tagId)) {
145
+ currentTagIds.push(tagId);
146
+ }
147
+ return api(`/api/cards/${cardId}`, {
148
+ method: "PUT",
149
+ body: JSON.stringify({ tagIds: currentTagIds })
150
+ });
151
+ },
152
+ removeTagFromCard: async (cardId, tagId) => {
153
+ const card = await api(`/api/cards/${cardId}`);
154
+ const currentTagIds = (card.tags || []).map((t) => t.id).filter((id) => id !== tagId);
155
+ return api(`/api/cards/${cardId}`, {
156
+ method: "PUT",
157
+ body: JSON.stringify({ tagIds: currentTagIds })
158
+ });
159
+ },
160
+ // Bulk Operations
99
161
  bulkCreateCards: async (data) => {
100
162
  const results = await Promise.all(
101
163
  data.cards.map(
102
- (card) => api("/api/cards", { method: "POST", body: JSON.stringify({ columnId: data.columnId, ...card }) })
164
+ (card) => api("/api/cards", {
165
+ method: "POST",
166
+ body: JSON.stringify({ columnId: data.columnId, ...card })
167
+ })
103
168
  )
104
169
  );
105
170
  return { created: results.length, cards: results };
106
171
  },
107
172
  bulkCreateEpicWithCards: async (data) => {
108
- const epic = await api("/api/epics", { method: "POST", body: JSON.stringify(data.epic) });
173
+ const epic = await api("/api/epics", {
174
+ method: "POST",
175
+ body: JSON.stringify(data.epic)
176
+ });
109
177
  const cardResults = await Promise.all(
110
178
  data.cards.map(
111
- (card) => api("/api/cards", { method: "POST", body: JSON.stringify({ columnId: data.columnId, epicId: epic.id, ...card }) })
179
+ (card) => api("/api/cards", {
180
+ method: "POST",
181
+ body: JSON.stringify({
182
+ columnId: data.columnId,
183
+ epicId: epic.id,
184
+ ...card
185
+ })
186
+ })
112
187
  )
113
188
  );
114
189
  return { epic, cards: cardResults, created: cardResults.length };
115
190
  },
191
+ bulkCreateEpicWithFeatures: async (data) => {
192
+ const epic = await api("/api/epics", {
193
+ method: "POST",
194
+ body: JSON.stringify(data.epic)
195
+ });
196
+ const features = await Promise.all(
197
+ data.features.map(
198
+ (f) => api("/api/features", {
199
+ method: "POST",
200
+ body: JSON.stringify({
201
+ epicId: epic.id,
202
+ title: f.title,
203
+ slug: f.slug,
204
+ description: f.description
205
+ })
206
+ })
207
+ )
208
+ );
209
+ const featureResults = await Promise.all(
210
+ features.map(async (feature, i) => {
211
+ const featureCards = data.features[i].cards;
212
+ const cards = await Promise.all(
213
+ featureCards.map(
214
+ (c) => api("/api/cards", {
215
+ method: "POST",
216
+ body: JSON.stringify({ ...c, epicId: epic.id })
217
+ })
218
+ )
219
+ );
220
+ for (const card of cards) {
221
+ await api(`/api/features/${feature.id}/cards`, {
222
+ method: "POST",
223
+ body: JSON.stringify({ cardId: card.id })
224
+ });
225
+ }
226
+ return {
227
+ id: feature.id,
228
+ slug: feature.slug,
229
+ title: feature.title,
230
+ cardIds: cards.map((c) => c.id)
231
+ };
232
+ })
233
+ );
234
+ const totalCards = featureResults.reduce(
235
+ (sum, f) => sum + f.cardIds.length,
236
+ 0
237
+ );
238
+ return {
239
+ epic: { id: epic.id, slug: epic.slug, name: epic.name },
240
+ features: featureResults,
241
+ total: { features: features.length, cards: totalCards }
242
+ };
243
+ },
116
244
  bulkMoveCards: async (data) => {
117
245
  const results = await Promise.all(
118
246
  data.cardIds.map(
119
- (cardId) => api("/api/cards/move", { method: "POST", body: JSON.stringify({ cardId, targetColumnId: data.targetColumnId }) })
247
+ (cardId) => api("/api/cards/move", {
248
+ method: "POST",
249
+ body: JSON.stringify({ cardId, targetColumnId: data.targetColumnId })
250
+ })
120
251
  )
121
252
  );
122
253
  return { moved: results.length };
123
254
  },
124
- // Aggregated views (reduces multiple API calls to 1)
255
+ // Aggregated views
125
256
  getWorkspace: async (projectId) => {
126
257
  const project = await api(
127
258
  `/api/projects/${projectId}?includeBoards=true&boardsCompact=true`
@@ -130,10 +261,15 @@ var kanbanApi = {
130
261
  const boardsWithColumns = await Promise.all(
131
262
  project.boards.map((b) => api(`/api/boards/${b.id}`))
132
263
  );
133
- return { project: { id: project.id, name: project.name }, boards: boardsWithColumns };
264
+ return {
265
+ project: { id: project.id, name: project.name },
266
+ boards: boardsWithColumns
267
+ };
134
268
  },
135
269
  getBoardSummary: async (boardId) => {
136
- const board = await api(`/api/boards/${boardId}?includeCards=true&compact=true`);
270
+ const board = await api(
271
+ `/api/boards/${boardId}?includeCards=true&compact=true`
272
+ );
137
273
  const summary = {
138
274
  id: board.id,
139
275
  name: board.name,
@@ -145,16 +281,25 @@ var kanbanApi = {
145
281
  p2Count: col.cards?.filter((c) => c.priority === "P2").length || 0,
146
282
  p3Count: col.cards?.filter((c) => c.priority === "P3").length || 0
147
283
  })),
148
- totalCards: board.columns.reduce((sum, col) => sum + (col.cards?.length || 0), 0)
284
+ totalCards: board.columns.reduce(
285
+ (sum, col) => sum + (col.cards?.length || 0),
286
+ 0
287
+ )
149
288
  };
150
289
  return summary;
151
290
  },
152
291
  getEpicSummary: async (epicId) => {
153
292
  const epic = await api(`/api/epics/${epicId}`);
154
293
  const cards = epic.cards || [];
155
- const todoCards = cards.filter((c) => c.column?.name?.toLowerCase().includes("todo") || c.column?.name?.toLowerCase().includes("to do"));
156
- const inProgressCards = cards.filter((c) => c.column?.name?.toLowerCase().includes("progress"));
157
- const doneCards = cards.filter((c) => c.column?.name?.toLowerCase().includes("done"));
294
+ const todoCards = cards.filter(
295
+ (c) => c.column?.name?.toLowerCase().includes("todo") || c.column?.name?.toLowerCase().includes("to do")
296
+ );
297
+ const inProgressCards = cards.filter(
298
+ (c) => c.column?.name?.toLowerCase().includes("progress")
299
+ );
300
+ const doneCards = cards.filter(
301
+ (c) => c.column?.name?.toLowerCase().includes("done")
302
+ );
158
303
  return {
159
304
  id: epic.id,
160
305
  slug: epic.slug,
@@ -190,7 +335,12 @@ var kanbanApi = {
190
335
  }
191
336
  if (!cards.length) return { created: 0, cards: [] };
192
337
  const results = await Promise.all(
193
- cards.map((card) => api("/api/cards", { method: "POST", body: JSON.stringify({ columnId: data.columnId, ...card }) }))
338
+ cards.map(
339
+ (card) => api("/api/cards", {
340
+ method: "POST",
341
+ body: JSON.stringify({ columnId: data.columnId, ...card })
342
+ })
343
+ )
194
344
  );
195
345
  return { created: results.length, cards: results };
196
346
  },
@@ -201,141 +351,1164 @@ var kanbanApi = {
201
351
  const cards = Array.isArray(searchResult) ? searchResult : searchResult.cards || [];
202
352
  if (!cards.length) return { moved: 0 };
203
353
  await Promise.all(
204
- cards.map((c) => api("/api/cards/move", { method: "POST", body: JSON.stringify({ cardId: c.id, targetColumnId: data.targetColumnId }) }))
354
+ cards.map(
355
+ (c) => api("/api/cards/move", {
356
+ method: "POST",
357
+ body: JSON.stringify({
358
+ cardId: c.id,
359
+ targetColumnId: data.targetColumnId
360
+ })
361
+ })
362
+ )
205
363
  );
206
364
  return { moved: cards.length };
207
365
  },
208
366
  // Comments
209
- addComment: (cardId, content) => api("/api/comments", { method: "POST", body: JSON.stringify({ cardId, content }) }),
367
+ addComment: (cardId, content) => api("/api/comments", {
368
+ method: "POST",
369
+ body: JSON.stringify({ cardId, content })
370
+ }),
371
+ deleteComment: (commentId) => api(`/api/comments?id=${commentId}`, { method: "DELETE" }),
210
372
  // Checklists
211
373
  createChecklist: (data) => api("/api/checklists", { method: "POST", body: JSON.stringify(data) }),
212
374
  updateChecklist: (id, data) => api(`/api/checklists/${id}`, { method: "PUT", body: JSON.stringify(data) }),
213
375
  deleteChecklist: (id) => api(`/api/checklists/${id}`, { method: "DELETE" }),
214
376
  // Checklist Items
215
377
  createChecklistItem: (data) => api("/api/checklist-items", { method: "POST", body: JSON.stringify(data) }),
216
- updateChecklistItem: (id, data) => api(`/api/checklist-items/${id}`, { method: "PUT", body: JSON.stringify(data) }),
378
+ updateChecklistItem: (id, data) => api(`/api/checklist-items/${id}`, {
379
+ method: "PUT",
380
+ body: JSON.stringify(data)
381
+ }),
217
382
  deleteChecklistItem: (id) => api(`/api/checklist-items/${id}`, { method: "DELETE" }),
218
383
  // Tags
219
384
  listTags: () => api("/api/tags"),
220
385
  createTag: (data) => api("/api/tags", { method: "POST", body: JSON.stringify(data) }),
221
- deleteTag: (id) => api(`/api/tags/${id}`, { method: "DELETE" }),
222
- addTagToCard: (cardId, tagId) => api(`/api/cards/${cardId}/tags`, { method: "POST", body: JSON.stringify({ tagId }) }),
223
- removeTagFromCard: (cardId, tagId) => api(`/api/cards/${cardId}/tags/${tagId}`, { method: "DELETE" }),
386
+ deleteTag: (id) => api(`/api/tags?id=${id}`, { method: "DELETE" }),
224
387
  // Epics
225
388
  listEpics: (params) => {
226
389
  const searchParams = new URLSearchParams();
227
390
  if (params?.status) searchParams.set("status", params.status);
228
- if (params?.includeProgress === false) searchParams.set("includeProgress", "false");
391
+ if (params?.includeProgress === false)
392
+ searchParams.set("includeProgress", "false");
229
393
  searchParams.set("limit", (params?.limit || 15).toString());
230
394
  if (params?.compact) searchParams.set("compact", "true");
231
395
  const query = searchParams.toString();
232
396
  return api(`/api/epics${query ? `?${query}` : ""}`);
233
397
  },
234
398
  createEpic: (data) => api("/api/epics", { method: "POST", body: JSON.stringify(data) }),
235
- updateEpic: (id, data) => api(`/api/epics/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
399
+ updateEpic: (id, data) => api(`/api/epics/${id}`, { method: "PUT", body: JSON.stringify(data) }),
400
+ getEpic: (id) => api(`/api/epics/${id}`),
236
401
  deleteEpic: (id) => api(`/api/epics/${id}`, { method: "DELETE" }),
237
- addCardToEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards`, { method: "POST", body: JSON.stringify({ cardId }) }),
402
+ addCardToEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards`, {
403
+ method: "POST",
404
+ body: JSON.stringify({ cardId })
405
+ }),
238
406
  removeCardFromEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards/${cardId}`, { method: "DELETE" }),
239
- getEpicTimeline: () => api("/api/epics/timeline"),
407
+ // Features
408
+ listFeatures: (epicId) => {
409
+ const query = epicId ? `?epicId=${epicId}` : "";
410
+ return api(`/api/features${query}`);
411
+ },
412
+ getFeature: (id) => api(`/api/features/${id}`),
413
+ getActiveFeatures: () => api("/api/features/active"),
414
+ createFeature: (data) => api("/api/features", { method: "POST", body: JSON.stringify(data) }),
415
+ updateFeature: (id, data) => api(`/api/features/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
416
+ deleteFeature: (id) => api(`/api/features/${id}`, { method: "DELETE" }),
417
+ addCardToFeature: (featureId, cardId) => api(`/api/features/${featureId}/cards`, {
418
+ method: "POST",
419
+ body: JSON.stringify({ cardId })
420
+ }),
421
+ removeCardFromFeature: (featureId, cardId) => api(`/api/features/${featureId}/cards/${cardId}`, { method: "DELETE" }),
422
+ getFeatureCards: (featureId) => api(`/api/features/${featureId}/cards`),
240
423
  // Card Links
241
- linkCards: (cardId1, cardId2, label) => api("/api/card-links", { method: "POST", body: JSON.stringify({ cardId1, cardId2, label }) }),
242
- unlinkCards: (cardId1, cardId2) => api("/api/card-links", { method: "DELETE", body: JSON.stringify({ cardId1, cardId2 }) }),
424
+ linkCards: (cardId1, cardId2, label) => api("/api/card-links", {
425
+ method: "POST",
426
+ body: JSON.stringify({ fromCardId: cardId1, toCardId: cardId2, label })
427
+ }),
428
+ unlinkCards: (linkId) => api(`/api/card-links?id=${linkId}`, { method: "DELETE" }),
243
429
  getLinkedCards: (cardId) => api(`/api/card-links?cardId=${cardId}`),
244
- // GitHub Integration
245
- setupGithubIntegration: (data) => api("/api/github/integration", { method: "POST", body: JSON.stringify(data) }),
246
- getGithubIntegration: (projectId) => api(`/api/github/integration?projectId=${projectId}`),
247
- updateGithubIntegration: (projectId, data) => api(`/api/github/integration/${projectId}`, { method: "PATCH", body: JSON.stringify(data) }),
248
- removeGithubIntegration: (projectId) => api(`/api/github/integration/${projectId}`, { method: "DELETE" }),
249
- linkCardToBranch: (cardId, branch) => api(`/api/cards/${cardId}`, { method: "PATCH", body: JSON.stringify({ githubBranch: branch }) }),
250
- linkCardToPr: (cardId, prUrl) => api(`/api/cards/${cardId}`, { method: "PATCH", body: JSON.stringify({ githubPrUrl: prUrl }) }),
251
- // GitHub API
252
- githubListRepos: (userId, type) => api(`/api/github/repos?userId=${userId}${type ? `&type=${type}` : ""}`),
253
- githubCreateBranch: (data) => api("/api/github/branches", { method: "POST", body: JSON.stringify(data) }),
254
- githubCreatePr: (data) => api("/api/github/pull-requests", { method: "POST", body: JSON.stringify(data) }),
255
- githubAutoSetupWebhook: (data) => api("/api/github/webhooks/auto-setup", { method: "POST", body: JSON.stringify(data) })
430
+ // GitHub Integration - routes at /api/projects/[id]/github
431
+ setupGithubIntegration: (data) => api(`/api/projects/${data.projectId}/github`, {
432
+ method: "POST",
433
+ body: JSON.stringify(data)
434
+ }),
435
+ getGithubIntegration: (projectId) => api(`/api/projects/${projectId}/github`),
436
+ updateGithubIntegration: (projectId, data) => api(`/api/projects/${projectId}/github`, {
437
+ method: "PUT",
438
+ body: JSON.stringify(data)
439
+ }),
440
+ removeGithubIntegration: (projectId) => api(`/api/projects/${projectId}/github`, { method: "DELETE" }),
441
+ linkCardToBranch: (cardId, branch) => api(`/api/cards/${cardId}`, {
442
+ method: "PUT",
443
+ body: JSON.stringify({ githubBranch: branch })
444
+ }),
445
+ linkCardToPr: (cardId, prUrl) => api(`/api/cards/${cardId}`, {
446
+ method: "PUT",
447
+ body: JSON.stringify({ githubPrUrl: prUrl })
448
+ })
256
449
  };
257
450
  var server = new Server(
258
- { name: "kanban-mcp", version: "1.0.0" },
451
+ { name: "kanban-mcp", version: "1.1.0" },
259
452
  { capabilities: { tools: {} } }
260
453
  );
261
454
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
262
455
  tools: [
263
456
  // FOLDERS
264
- { name: "list_folders", description: "List all folders with their projects", inputSchema: { type: "object", properties: {} } },
265
- { name: "create_folder", description: "Create a new folder to organize projects", inputSchema: { type: "object", properties: { name: { type: "string" }, icon: { type: "string" }, color: { type: "string" } }, required: ["name"] } },
266
- { name: "update_folder", description: "Update a folder (name, icon, color)", inputSchema: { type: "object", properties: { folderId: { type: "string" }, name: { type: "string" }, icon: { type: "string" }, color: { type: "string" } }, required: ["folderId"] } },
267
- { name: "delete_folder", description: "Delete a folder (projects become orphans)", inputSchema: { type: "object", properties: { folderId: { type: "string" } }, required: ["folderId"] } },
268
- { name: "move_project_to_folder", description: "Move project to folder (null to remove)", inputSchema: { type: "object", properties: { projectId: { type: "string" }, folderId: { type: "string" } }, required: ["projectId"] } },
457
+ {
458
+ name: "list_folders",
459
+ description: "List all folders with their projects",
460
+ inputSchema: { type: "object", properties: {} }
461
+ },
462
+ {
463
+ name: "create_folder",
464
+ description: "Create a new folder to organize projects",
465
+ inputSchema: {
466
+ type: "object",
467
+ properties: {
468
+ name: { type: "string" },
469
+ icon: { type: "string" },
470
+ color: { type: "string" }
471
+ },
472
+ required: ["name"]
473
+ }
474
+ },
475
+ {
476
+ name: "update_folder",
477
+ description: "Update a folder (name, icon, color)",
478
+ inputSchema: {
479
+ type: "object",
480
+ properties: {
481
+ folderId: { type: "string" },
482
+ name: { type: "string" },
483
+ icon: { type: "string" },
484
+ color: { type: "string" }
485
+ },
486
+ required: ["folderId"]
487
+ }
488
+ },
489
+ {
490
+ name: "delete_folder",
491
+ description: "Delete a folder (projects become orphans)",
492
+ inputSchema: {
493
+ type: "object",
494
+ properties: { folderId: { type: "string" } },
495
+ required: ["folderId"]
496
+ }
497
+ },
498
+ {
499
+ name: "move_project_to_folder",
500
+ description: "Move project to folder (null to remove)",
501
+ inputSchema: {
502
+ type: "object",
503
+ properties: {
504
+ projectId: { type: "string" },
505
+ folderId: { type: "string" }
506
+ },
507
+ required: ["projectId"]
508
+ }
509
+ },
510
+ {
511
+ name: "reorder_folders",
512
+ description: "Reorder folders by moving one before/after another",
513
+ inputSchema: {
514
+ type: "object",
515
+ properties: {
516
+ folderId: { type: "string" },
517
+ targetFolderId: { type: "string" }
518
+ },
519
+ required: ["folderId", "targetFolderId"]
520
+ }
521
+ },
269
522
  // PROJECTS
270
- { name: "list_projects", description: "List projects (default limit:20). Use compact:true for minimal fields", inputSchema: { type: "object", properties: { folderId: { type: "string" }, limit: { type: "number" }, compact: { type: "boolean" } } } },
271
- { name: "create_project", description: "Create a new project", inputSchema: { type: "object", properties: { name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" }, folderId: { type: "string" } }, required: ["name"] } },
272
- { name: "get_project", description: "Get project. Use includeBoards:true to get boards in 1 call", inputSchema: { type: "object", properties: { projectId: { type: "string" }, includeBoards: { type: "boolean" }, boardsCompact: { type: "boolean" } }, required: ["projectId"] } },
273
- { name: "update_project", description: "Update project", inputSchema: { type: "object", properties: { projectId: { type: "string" }, name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" } }, required: ["projectId"] } },
274
- { name: "delete_project", description: "Delete project and all its content", inputSchema: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] } },
275
- // BOARDS (use get_workspace or get_project(includeBoards:true) to list boards)
276
- { name: "create_board", description: "Create board with default columns", inputSchema: { type: "object", properties: { projectId: { type: "string" }, name: { type: "string" } }, required: ["projectId", "name"] } },
277
- { name: "get_board", description: "Get board with columns. Cards NOT included by default. Use includeCards:true + cardLimit + columnId to get specific cards.", inputSchema: { type: "object", properties: { boardId: { type: "string" }, columnId: { type: "string", description: "Get only this column" }, includeCards: { type: "boolean", description: "Include cards (default: false)" }, cardLimit: { type: "number", description: "Max cards per column (e.g. 5)" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, compact: { type: "boolean", description: "Minimal fields (id, title, priority)" }, includeTags: { type: "boolean" }, includeComments: { type: "boolean", description: "Include comments (max 5)" } }, required: ["boardId"] } },
278
- { name: "update_board", description: "Rename a board", inputSchema: { type: "object", properties: { boardId: { type: "string" }, name: { type: "string" } }, required: ["boardId", "name"] } },
279
- { name: "delete_board", description: "Delete board and all content", inputSchema: { type: "object", properties: { boardId: { type: "string" } }, required: ["boardId"] } },
523
+ {
524
+ name: "list_projects",
525
+ description: "List projects (default limit:20). Use compact:true for minimal fields",
526
+ inputSchema: {
527
+ type: "object",
528
+ properties: {
529
+ folderId: {
530
+ type: "string",
531
+ description: 'Filter by folder. Use "none" for orphan projects'
532
+ },
533
+ limit: { type: "number" },
534
+ compact: { type: "boolean" }
535
+ }
536
+ }
537
+ },
538
+ {
539
+ name: "create_project",
540
+ description: "Create a new project",
541
+ inputSchema: {
542
+ type: "object",
543
+ properties: {
544
+ name: { type: "string" },
545
+ description: { type: "string" },
546
+ emoji: { type: "string" },
547
+ color: { type: "string" },
548
+ folderId: { type: "string" }
549
+ },
550
+ required: ["name"]
551
+ }
552
+ },
553
+ {
554
+ name: "get_project",
555
+ description: "Get project. Use includeBoards:true to get boards in 1 call",
556
+ inputSchema: {
557
+ type: "object",
558
+ properties: {
559
+ projectId: { type: "string" },
560
+ includeBoards: { type: "boolean" },
561
+ boardsCompact: { type: "boolean" }
562
+ },
563
+ required: ["projectId"]
564
+ }
565
+ },
566
+ {
567
+ name: "update_project",
568
+ description: "Update project",
569
+ inputSchema: {
570
+ type: "object",
571
+ properties: {
572
+ projectId: { type: "string" },
573
+ name: { type: "string" },
574
+ description: { type: "string" },
575
+ emoji: { type: "string" },
576
+ color: { type: "string" },
577
+ folderId: {
578
+ type: "string",
579
+ description: "Move to folder (null to remove)"
580
+ }
581
+ },
582
+ required: ["projectId"]
583
+ }
584
+ },
585
+ {
586
+ name: "delete_project",
587
+ description: "Delete project and all its content",
588
+ inputSchema: {
589
+ type: "object",
590
+ properties: { projectId: { type: "string" } },
591
+ required: ["projectId"]
592
+ }
593
+ },
594
+ {
595
+ name: "reorder_projects",
596
+ description: "Reorder projects within a folder",
597
+ inputSchema: {
598
+ type: "object",
599
+ properties: {
600
+ projectId: { type: "string" },
601
+ targetProjectId: { type: "string" },
602
+ folderId: {
603
+ type: "string",
604
+ description: "Folder context (null for orphans)"
605
+ }
606
+ },
607
+ required: ["projectId", "targetProjectId"]
608
+ }
609
+ },
610
+ // BOARDS
611
+ {
612
+ name: "list_boards",
613
+ description: "List boards for a project",
614
+ inputSchema: {
615
+ type: "object",
616
+ properties: {
617
+ projectId: { type: "string" },
618
+ limit: { type: "number" },
619
+ compact: { type: "boolean" }
620
+ },
621
+ required: ["projectId"]
622
+ }
623
+ },
624
+ {
625
+ name: "create_board",
626
+ description: "Create board with default columns",
627
+ inputSchema: {
628
+ type: "object",
629
+ properties: { projectId: { type: "string" }, name: { type: "string" } },
630
+ required: ["projectId", "name"]
631
+ }
632
+ },
633
+ {
634
+ name: "get_board",
635
+ description: "Get board with columns. Cards NOT included by default. Use includeCards:true + cardLimit + columnId to get specific cards.",
636
+ inputSchema: {
637
+ type: "object",
638
+ properties: {
639
+ boardId: { type: "string" },
640
+ columnId: { type: "string", description: "Get only this column" },
641
+ includeCards: {
642
+ type: "boolean",
643
+ description: "Include cards (default: false)"
644
+ },
645
+ cardLimit: {
646
+ type: "number",
647
+ description: "Max cards per column (e.g. 5)"
648
+ },
649
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
650
+ compact: {
651
+ type: "boolean",
652
+ description: "Minimal fields (id, title, priority)"
653
+ },
654
+ includeTags: { type: "boolean" },
655
+ includeComments: {
656
+ type: "boolean",
657
+ description: "Include comments (max 5)"
658
+ }
659
+ },
660
+ required: ["boardId"]
661
+ }
662
+ },
663
+ {
664
+ name: "update_board",
665
+ description: "Rename a board",
666
+ inputSchema: {
667
+ type: "object",
668
+ properties: { boardId: { type: "string" }, name: { type: "string" } },
669
+ required: ["boardId", "name"]
670
+ }
671
+ },
672
+ {
673
+ name: "delete_board",
674
+ description: "Delete board and all content",
675
+ inputSchema: {
676
+ type: "object",
677
+ properties: { boardId: { type: "string" } },
678
+ required: ["boardId"]
679
+ }
680
+ },
280
681
  // COLUMNS
281
- { name: "create_column", description: "Create column in board", inputSchema: { type: "object", properties: { boardId: { type: "string" }, name: { type: "string" }, emoji: { type: "string" } }, required: ["boardId", "name"] } },
282
- { name: "update_column", description: "Update column", inputSchema: { type: "object", properties: { columnId: { type: "string" }, name: { type: "string" }, emoji: { type: "string" } }, required: ["columnId"] } },
283
- { name: "delete_column", description: "Delete column and cards", inputSchema: { type: "object", properties: { columnId: { type: "string" } }, required: ["columnId"] } },
682
+ {
683
+ name: "create_column",
684
+ description: "Create column in board",
685
+ inputSchema: {
686
+ type: "object",
687
+ properties: {
688
+ boardId: { type: "string" },
689
+ name: { type: "string" },
690
+ emoji: { type: "string" }
691
+ },
692
+ required: ["boardId", "name"]
693
+ }
694
+ },
695
+ {
696
+ name: "update_column",
697
+ description: "Update column",
698
+ inputSchema: {
699
+ type: "object",
700
+ properties: {
701
+ columnId: { type: "string" },
702
+ name: { type: "string" },
703
+ emoji: { type: "string" }
704
+ },
705
+ required: ["columnId"]
706
+ }
707
+ },
708
+ {
709
+ name: "delete_column",
710
+ description: "Delete column and cards",
711
+ inputSchema: {
712
+ type: "object",
713
+ properties: { columnId: { type: "string" } },
714
+ required: ["columnId"]
715
+ }
716
+ },
717
+ {
718
+ name: "reorder_columns",
719
+ description: "Reorder columns in a board",
720
+ inputSchema: {
721
+ type: "object",
722
+ properties: {
723
+ columns: {
724
+ type: "array",
725
+ items: {
726
+ type: "object",
727
+ properties: {
728
+ id: { type: "string" },
729
+ order: { type: "number" }
730
+ },
731
+ required: ["id", "order"]
732
+ }
733
+ }
734
+ },
735
+ required: ["columns"]
736
+ }
737
+ },
284
738
  // CARDS
285
- { name: "create_card", description: "Create card. Auto-assign to epic if title starts with [SLUG]. featureId for multi-project features.", inputSchema: { type: "object", properties: { columnId: { type: "string" }, title: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, featureId: { type: "string" }, dueDate: { type: "string" }, epicId: { type: "string" }, tagIds: { type: "array", items: { type: "string" } }, linkedCardIds: { type: "array", items: { type: "string" } }, linkLabel: { type: "string" } }, required: ["columnId", "title"] } },
286
- { name: "update_card", description: "Update card", inputSchema: { type: "object", properties: { cardId: { type: "string" }, title: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, featureId: { type: "string" }, dueDate: { type: "string" } }, required: ["cardId"] } },
287
- { name: "delete_card", description: "Delete a card", inputSchema: { type: "object", properties: { cardId: { type: "string" } }, required: ["cardId"] } },
288
- { name: "move_card", description: "Move card to column", inputSchema: { type: "object", properties: { cardId: { type: "string" }, targetColumnId: { type: "string" } }, required: ["cardId", "targetColumnId"] } },
289
- { name: "add_comment", description: "Add comment to card", inputSchema: { type: "object", properties: { cardId: { type: "string" }, content: { type: "string" } }, required: ["cardId", "content"] } },
739
+ {
740
+ name: "get_card",
741
+ description: "Get a card with all details (tags, comments, checklists, epics, features)",
742
+ inputSchema: {
743
+ type: "object",
744
+ properties: { cardId: { type: "string" } },
745
+ required: ["cardId"]
746
+ }
747
+ },
748
+ {
749
+ name: "create_card",
750
+ description: "Create card. Auto-assign to epic if epicId provided.",
751
+ inputSchema: {
752
+ type: "object",
753
+ properties: {
754
+ columnId: { type: "string" },
755
+ title: { type: "string" },
756
+ description: { type: "string" },
757
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
758
+ dueDate: { type: "string" },
759
+ epicId: { type: "string" },
760
+ tagIds: { type: "array", items: { type: "string" } },
761
+ estimatedMinutes: {
762
+ type: "number",
763
+ description: "Estimated time in minutes"
764
+ },
765
+ cognitiveLoad: {
766
+ type: "string",
767
+ description: "Cognitive load level"
768
+ }
769
+ },
770
+ required: ["columnId", "title"]
771
+ }
772
+ },
773
+ {
774
+ name: "update_card",
775
+ description: "Update card fields",
776
+ inputSchema: {
777
+ type: "object",
778
+ properties: {
779
+ cardId: { type: "string" },
780
+ title: { type: "string" },
781
+ description: { type: "string" },
782
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
783
+ dueDate: { type: "string" },
784
+ tagIds: {
785
+ type: "array",
786
+ items: { type: "string" },
787
+ description: "Replace all tags with these IDs"
788
+ },
789
+ cognitiveLoad: { type: "string" },
790
+ estimatedMinutes: { type: "number" },
791
+ githubBranch: { type: "string" },
792
+ githubPrUrl: { type: "string" },
793
+ isArchived: { type: "boolean" }
794
+ },
795
+ required: ["cardId"]
796
+ }
797
+ },
798
+ {
799
+ name: "delete_card",
800
+ description: "Delete a card",
801
+ inputSchema: {
802
+ type: "object",
803
+ properties: { cardId: { type: "string" } },
804
+ required: ["cardId"]
805
+ }
806
+ },
807
+ {
808
+ name: "archive_card",
809
+ description: "Archive a card",
810
+ inputSchema: {
811
+ type: "object",
812
+ properties: { cardId: { type: "string" } },
813
+ required: ["cardId"]
814
+ }
815
+ },
816
+ {
817
+ name: "unarchive_card",
818
+ description: "Unarchive a card (restore from archive)",
819
+ inputSchema: {
820
+ type: "object",
821
+ properties: { cardId: { type: "string" } },
822
+ required: ["cardId"]
823
+ }
824
+ },
825
+ {
826
+ name: "list_archived_cards",
827
+ description: "List archived cards for a board",
828
+ inputSchema: {
829
+ type: "object",
830
+ properties: { boardId: { type: "string" } },
831
+ required: ["boardId"]
832
+ }
833
+ },
834
+ {
835
+ name: "move_card",
836
+ description: "Move card to column. Use newOrder for specific positioning.",
837
+ inputSchema: {
838
+ type: "object",
839
+ properties: {
840
+ cardId: { type: "string" },
841
+ targetColumnId: { type: "string" },
842
+ newOrder: {
843
+ type: "number",
844
+ description: "Position in target column (0-indexed, default: end)"
845
+ }
846
+ },
847
+ required: ["cardId", "targetColumnId"]
848
+ }
849
+ },
850
+ {
851
+ name: "add_comment",
852
+ description: "Add comment to card",
853
+ inputSchema: {
854
+ type: "object",
855
+ properties: { cardId: { type: "string" }, content: { type: "string" } },
856
+ required: ["cardId", "content"]
857
+ }
858
+ },
859
+ {
860
+ name: "delete_comment",
861
+ description: "Delete a comment",
862
+ inputSchema: {
863
+ type: "object",
864
+ properties: { commentId: { type: "string" } },
865
+ required: ["commentId"]
866
+ }
867
+ },
290
868
  // CHECKLISTS
291
- { name: "create_checklist", description: "Create checklist on card", inputSchema: { type: "object", properties: { cardId: { type: "string" }, title: { type: "string" } }, required: ["cardId", "title"] } },
292
- { name: "update_checklist", description: "Update checklist title", inputSchema: { type: "object", properties: { checklistId: { type: "string" }, title: { type: "string" } }, required: ["checklistId", "title"] } },
293
- { name: "delete_checklist", description: "Delete checklist", inputSchema: { type: "object", properties: { checklistId: { type: "string" } }, required: ["checklistId"] } },
294
- { name: "create_checklist_item", description: "Add checklist item", inputSchema: { type: "object", properties: { checklistId: { type: "string" }, content: { type: "string" } }, required: ["checklistId", "content"] } },
295
- { name: "update_checklist_item", description: "Update checklist item", inputSchema: { type: "object", properties: { itemId: { type: "string" }, content: { type: "string" }, completed: { type: "boolean" } }, required: ["itemId"] } },
296
- { name: "delete_checklist_item", description: "Delete checklist item", inputSchema: { type: "object", properties: { itemId: { type: "string" } }, required: ["itemId"] } },
297
- { name: "get_branch_name", description: "Generate GitHub branch name", inputSchema: { type: "object", properties: { cardId: { type: "string" }, type: { type: "string", enum: ["feature", "fix", "chore", "refactor", "docs"] } }, required: ["cardId"] } },
298
- { name: "search_cards", description: "Search cards (default limit:20). Use compact:true for minimal fields", inputSchema: { type: "object", properties: { query: { type: "string" }, projectId: { type: "string" }, boardId: { type: "string" }, columnId: { type: "string" }, epicId: { type: "string" }, featureId: { type: "string" }, hasEpic: { type: "boolean" }, status: { type: "string", enum: ["todo", "in_progress", "done"] }, tagIds: { type: "array", items: { type: "string" } }, limit: { type: "number" }, compact: { type: "boolean" } }, required: ["query"] } },
299
- // BULK OPERATIONS (reduces API calls)
300
- { name: "bulk_create_cards", description: "Create multiple cards in 1 call", inputSchema: { type: "object", properties: { columnId: { type: "string" }, cards: { type: "array", items: { type: "object", properties: { title: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, epicId: { type: "string" } }, required: ["title"] } } }, required: ["columnId", "cards"] } },
301
- { name: "bulk_create_epic_with_cards", description: "Create epic + all its cards in 1 call", inputSchema: { type: "object", properties: { epic: { type: "object", properties: { slug: { type: "string" }, name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" } }, required: ["slug", "name"] }, columnId: { type: "string" }, cards: { type: "array", items: { type: "object", properties: { title: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] } }, required: ["title"] } } }, required: ["epic", "columnId", "cards"] } },
302
- { name: "bulk_move_cards", description: "Move multiple cards to column in 1 call", inputSchema: { type: "object", properties: { cardIds: { type: "array", items: { type: "string" } }, targetColumnId: { type: "string" } }, required: ["cardIds", "targetColumnId"] } },
303
- { name: "quick_add_cards", description: 'Create cards from multiline text. Format: "- P1: task title" per line', inputSchema: { type: "object", properties: { columnId: { type: "string" }, text: { type: "string", description: "Multiline text, 1 card per line" }, defaultPriority: { type: "string", enum: ["P1", "P2", "P3"] } }, required: ["columnId", "text"] } },
304
- { name: "move_cards_by_column", description: "Move ALL cards from one column to another", inputSchema: { type: "object", properties: { sourceColumnId: { type: "string" }, targetColumnId: { type: "string" }, limit: { type: "number" } }, required: ["sourceColumnId", "targetColumnId"] } },
305
- // AGGREGATED VIEWS (1 call instead of many)
306
- { name: "get_workspace", description: "Get project + all boards + columns in 1 call (no cards)", inputSchema: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] } },
307
- { name: "get_board_summary", description: "Get board stats only: card counts per column + priority breakdown", inputSchema: { type: "object", properties: { boardId: { type: "string" } }, required: ["boardId"] } },
308
- { name: "get_epic_summary", description: "Get epic with minimal card info: {id,title,priority,status} + progress stats", inputSchema: { type: "object", properties: { epicId: { type: "string" } }, required: ["epicId"] } },
869
+ {
870
+ name: "create_checklist",
871
+ description: "Create checklist on card",
872
+ inputSchema: {
873
+ type: "object",
874
+ properties: { cardId: { type: "string" }, title: { type: "string" } },
875
+ required: ["cardId", "title"]
876
+ }
877
+ },
878
+ {
879
+ name: "update_checklist",
880
+ description: "Update checklist title",
881
+ inputSchema: {
882
+ type: "object",
883
+ properties: {
884
+ checklistId: { type: "string" },
885
+ title: { type: "string" }
886
+ },
887
+ required: ["checklistId", "title"]
888
+ }
889
+ },
890
+ {
891
+ name: "delete_checklist",
892
+ description: "Delete checklist",
893
+ inputSchema: {
894
+ type: "object",
895
+ properties: { checklistId: { type: "string" } },
896
+ required: ["checklistId"]
897
+ }
898
+ },
899
+ {
900
+ name: "create_checklist_item",
901
+ description: "Add checklist item",
902
+ inputSchema: {
903
+ type: "object",
904
+ properties: {
905
+ checklistId: { type: "string" },
906
+ content: { type: "string" }
907
+ },
908
+ required: ["checklistId", "content"]
909
+ }
910
+ },
911
+ {
912
+ name: "update_checklist_item",
913
+ description: "Update checklist item",
914
+ inputSchema: {
915
+ type: "object",
916
+ properties: {
917
+ itemId: { type: "string" },
918
+ content: { type: "string" },
919
+ completed: { type: "boolean" }
920
+ },
921
+ required: ["itemId"]
922
+ }
923
+ },
924
+ {
925
+ name: "delete_checklist_item",
926
+ description: "Delete checklist item",
927
+ inputSchema: {
928
+ type: "object",
929
+ properties: { itemId: { type: "string" } },
930
+ required: ["itemId"]
931
+ }
932
+ },
933
+ {
934
+ name: "get_branch_name",
935
+ description: "Generate GitHub branch name",
936
+ inputSchema: {
937
+ type: "object",
938
+ properties: {
939
+ cardId: { type: "string" },
940
+ type: {
941
+ type: "string",
942
+ enum: ["feature", "fix", "chore", "refactor", "docs"]
943
+ }
944
+ },
945
+ required: ["cardId"]
946
+ }
947
+ },
948
+ {
949
+ name: "search_cards",
950
+ description: "Search cards, projects and boards (default limit:20). Use compact:true for minimal fields",
951
+ inputSchema: {
952
+ type: "object",
953
+ properties: {
954
+ query: { type: "string" },
955
+ projectId: { type: "string" },
956
+ boardId: { type: "string" },
957
+ columnId: { type: "string" },
958
+ epicId: { type: "string" },
959
+ featureId: { type: "string" },
960
+ hasEpic: { type: "boolean" },
961
+ status: { type: "string", enum: ["todo", "in_progress", "done"] },
962
+ tagIds: { type: "array", items: { type: "string" } },
963
+ limit: { type: "number" },
964
+ compact: { type: "boolean" }
965
+ },
966
+ required: ["query"]
967
+ }
968
+ },
969
+ // BULK OPERATIONS
970
+ {
971
+ name: "bulk_create_cards",
972
+ description: "Create multiple cards in 1 call",
973
+ inputSchema: {
974
+ type: "object",
975
+ properties: {
976
+ columnId: { type: "string" },
977
+ cards: {
978
+ type: "array",
979
+ items: {
980
+ type: "object",
981
+ properties: {
982
+ title: { type: "string" },
983
+ description: { type: "string" },
984
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
985
+ epicId: { type: "string" }
986
+ },
987
+ required: ["title"]
988
+ }
989
+ }
990
+ },
991
+ required: ["columnId", "cards"]
992
+ }
993
+ },
994
+ {
995
+ name: "bulk_create_epic_with_cards",
996
+ description: "Create epic + all its cards in 1 call",
997
+ inputSchema: {
998
+ type: "object",
999
+ properties: {
1000
+ epic: {
1001
+ type: "object",
1002
+ properties: {
1003
+ slug: { type: "string" },
1004
+ name: { type: "string" },
1005
+ description: { type: "string" },
1006
+ emoji: { type: "string" },
1007
+ color: { type: "string" }
1008
+ },
1009
+ required: ["slug", "name"]
1010
+ },
1011
+ columnId: { type: "string" },
1012
+ cards: {
1013
+ type: "array",
1014
+ items: {
1015
+ type: "object",
1016
+ properties: {
1017
+ title: { type: "string" },
1018
+ description: { type: "string" },
1019
+ priority: { type: "string", enum: ["P1", "P2", "P3"] }
1020
+ },
1021
+ required: ["title"]
1022
+ }
1023
+ }
1024
+ },
1025
+ required: ["epic", "columnId", "cards"]
1026
+ }
1027
+ },
1028
+ {
1029
+ name: "bulk_create_epic_with_features",
1030
+ description: "Create epic + features + cards across projects in 1 call. Cards auto-prefixed with SLUG{N}-.",
1031
+ inputSchema: {
1032
+ type: "object",
1033
+ properties: {
1034
+ epic: {
1035
+ type: "object",
1036
+ properties: {
1037
+ slug: { type: "string" },
1038
+ name: { type: "string" },
1039
+ description: { type: "string" },
1040
+ emoji: { type: "string" },
1041
+ color: { type: "string" }
1042
+ },
1043
+ required: ["slug", "name"]
1044
+ },
1045
+ features: {
1046
+ type: "array",
1047
+ items: {
1048
+ type: "object",
1049
+ properties: {
1050
+ title: { type: "string" },
1051
+ slug: {
1052
+ type: "string",
1053
+ description: "UPPERCASE slug (auto-generated from title if omitted)"
1054
+ },
1055
+ description: { type: "string" },
1056
+ cards: {
1057
+ type: "array",
1058
+ items: {
1059
+ type: "object",
1060
+ properties: {
1061
+ columnId: { type: "string" },
1062
+ title: { type: "string" },
1063
+ description: { type: "string" },
1064
+ priority: { type: "string", enum: ["P1", "P2", "P3"] }
1065
+ },
1066
+ required: ["columnId", "title"]
1067
+ }
1068
+ }
1069
+ },
1070
+ required: ["title", "cards"]
1071
+ }
1072
+ }
1073
+ },
1074
+ required: ["epic", "features"]
1075
+ }
1076
+ },
1077
+ {
1078
+ name: "bulk_move_cards",
1079
+ description: "Move multiple cards to column in 1 call",
1080
+ inputSchema: {
1081
+ type: "object",
1082
+ properties: {
1083
+ cardIds: { type: "array", items: { type: "string" } },
1084
+ targetColumnId: { type: "string" }
1085
+ },
1086
+ required: ["cardIds", "targetColumnId"]
1087
+ }
1088
+ },
1089
+ {
1090
+ name: "quick_add_cards",
1091
+ description: 'Create cards from multiline text. Format: "- P1: task title" per line',
1092
+ inputSchema: {
1093
+ type: "object",
1094
+ properties: {
1095
+ columnId: { type: "string" },
1096
+ text: {
1097
+ type: "string",
1098
+ description: "Multiline text, 1 card per line"
1099
+ },
1100
+ defaultPriority: { type: "string", enum: ["P1", "P2", "P3"] }
1101
+ },
1102
+ required: ["columnId", "text"]
1103
+ }
1104
+ },
1105
+ {
1106
+ name: "move_cards_by_column",
1107
+ description: "Move ALL cards from one column to another",
1108
+ inputSchema: {
1109
+ type: "object",
1110
+ properties: {
1111
+ sourceColumnId: { type: "string" },
1112
+ targetColumnId: { type: "string" },
1113
+ limit: { type: "number" }
1114
+ },
1115
+ required: ["sourceColumnId", "targetColumnId"]
1116
+ }
1117
+ },
1118
+ // AGGREGATED VIEWS
1119
+ {
1120
+ name: "get_workspace",
1121
+ description: "Get project + all boards + columns in 1 call (no cards)",
1122
+ inputSchema: {
1123
+ type: "object",
1124
+ properties: { projectId: { type: "string" } },
1125
+ required: ["projectId"]
1126
+ }
1127
+ },
1128
+ {
1129
+ name: "get_board_summary",
1130
+ description: "Get board stats only: card counts per column + priority breakdown",
1131
+ inputSchema: {
1132
+ type: "object",
1133
+ properties: { boardId: { type: "string" } },
1134
+ required: ["boardId"]
1135
+ }
1136
+ },
1137
+ {
1138
+ name: "get_epic_summary",
1139
+ description: "Get epic with minimal card info: {id,title,priority,status} + progress stats",
1140
+ inputSchema: {
1141
+ type: "object",
1142
+ properties: { epicId: { type: "string" } },
1143
+ required: ["epicId"]
1144
+ }
1145
+ },
309
1146
  // TAGS
310
- { name: "list_tags", description: "List all tags", inputSchema: { type: "object", properties: {} } },
311
- { name: "create_tag", description: "Create tag", inputSchema: { type: "object", properties: { name: { type: "string" }, color: { type: "string" } }, required: ["name", "color"] } },
312
- { name: "delete_tag", description: "Delete tag", inputSchema: { type: "object", properties: { tagId: { type: "string" } }, required: ["tagId"] } },
313
- { name: "add_tag_to_card", description: "Add tag to card", inputSchema: { type: "object", properties: { cardId: { type: "string" }, tagId: { type: "string" } }, required: ["cardId", "tagId"] } },
314
- { name: "remove_tag_from_card", description: "Remove tag from card", inputSchema: { type: "object", properties: { cardId: { type: "string" }, tagId: { type: "string" } }, required: ["cardId", "tagId"] } },
315
- // EPICS (use get_epic_summary for optimized epic+cards view)
316
- { name: "list_epics", description: "List epics (default limit:15)", inputSchema: { type: "object", properties: { status: { type: "string" }, includeProgress: { type: "boolean" }, limit: { type: "number" }, compact: { type: "boolean" } } } },
317
- { name: "create_epic", description: "Create epic", inputSchema: { type: "object", properties: { slug: { type: "string" }, name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" }, startDate: { type: "string" }, targetDate: { type: "string" } }, required: ["slug", "name"] } },
318
- { name: "update_epic", description: "Update epic", inputSchema: { type: "object", properties: { epicId: { type: "string" }, slug: { type: "string" }, name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" }, status: { type: "string" }, startDate: { type: "string" }, targetDate: { type: "string" } }, required: ["epicId"] } },
319
- { name: "delete_epic", description: "Delete epic (cards unlinked)", inputSchema: { type: "object", properties: { epicId: { type: "string" } }, required: ["epicId"] } },
320
- { name: "add_card_to_epic", description: "Add card to epic", inputSchema: { type: "object", properties: { epicId: { type: "string" }, cardId: { type: "string" } }, required: ["epicId", "cardId"] } },
321
- { name: "remove_card_from_epic", description: "Remove card from epic", inputSchema: { type: "object", properties: { epicId: { type: "string" }, cardId: { type: "string" } }, required: ["epicId", "cardId"] } },
322
- { name: "get_epic_timeline", description: "Timeline of all epics", inputSchema: { type: "object", properties: {} } },
1147
+ {
1148
+ name: "list_tags",
1149
+ description: "List all tags",
1150
+ inputSchema: { type: "object", properties: {} }
1151
+ },
1152
+ {
1153
+ name: "create_tag",
1154
+ description: "Create tag",
1155
+ inputSchema: {
1156
+ type: "object",
1157
+ properties: { name: { type: "string" }, color: { type: "string" } },
1158
+ required: ["name", "color"]
1159
+ }
1160
+ },
1161
+ {
1162
+ name: "delete_tag",
1163
+ description: "Delete tag",
1164
+ inputSchema: {
1165
+ type: "object",
1166
+ properties: { tagId: { type: "string" } },
1167
+ required: ["tagId"]
1168
+ }
1169
+ },
1170
+ {
1171
+ name: "add_tag_to_card",
1172
+ description: "Add tag to card",
1173
+ inputSchema: {
1174
+ type: "object",
1175
+ properties: { cardId: { type: "string" }, tagId: { type: "string" } },
1176
+ required: ["cardId", "tagId"]
1177
+ }
1178
+ },
1179
+ {
1180
+ name: "remove_tag_from_card",
1181
+ description: "Remove tag from card",
1182
+ inputSchema: {
1183
+ type: "object",
1184
+ properties: { cardId: { type: "string" }, tagId: { type: "string" } },
1185
+ required: ["cardId", "tagId"]
1186
+ }
1187
+ },
1188
+ // EPICS
1189
+ {
1190
+ name: "list_epics",
1191
+ description: "List epics (default limit:15)",
1192
+ inputSchema: {
1193
+ type: "object",
1194
+ properties: {
1195
+ status: { type: "string" },
1196
+ includeProgress: { type: "boolean" },
1197
+ limit: { type: "number" },
1198
+ compact: { type: "boolean" }
1199
+ }
1200
+ }
1201
+ },
1202
+ {
1203
+ name: "create_epic",
1204
+ description: "Create epic",
1205
+ inputSchema: {
1206
+ type: "object",
1207
+ properties: {
1208
+ slug: { type: "string" },
1209
+ name: { type: "string" },
1210
+ description: { type: "string" },
1211
+ emoji: { type: "string" },
1212
+ color: { type: "string" },
1213
+ startDate: { type: "string" },
1214
+ targetDate: { type: "string" }
1215
+ },
1216
+ required: ["slug", "name"]
1217
+ }
1218
+ },
1219
+ {
1220
+ name: "get_epic",
1221
+ description: "Get an epic with all its cards, features and progress",
1222
+ inputSchema: {
1223
+ type: "object",
1224
+ properties: { epicId: { type: "string" } },
1225
+ required: ["epicId"]
1226
+ }
1227
+ },
1228
+ {
1229
+ name: "update_epic",
1230
+ description: "Update epic. Use syncDates:true to sync targetDate to all card due dates.",
1231
+ inputSchema: {
1232
+ type: "object",
1233
+ properties: {
1234
+ epicId: { type: "string" },
1235
+ slug: { type: "string" },
1236
+ name: { type: "string" },
1237
+ description: { type: "string" },
1238
+ emoji: { type: "string" },
1239
+ color: { type: "string" },
1240
+ status: { type: "string" },
1241
+ startDate: { type: "string" },
1242
+ targetDate: { type: "string" },
1243
+ syncDates: {
1244
+ type: "boolean",
1245
+ description: "Sync targetDate to all card due dates"
1246
+ }
1247
+ },
1248
+ required: ["epicId"]
1249
+ }
1250
+ },
1251
+ {
1252
+ name: "delete_epic",
1253
+ description: "Delete epic (cards unlinked)",
1254
+ inputSchema: {
1255
+ type: "object",
1256
+ properties: { epicId: { type: "string" } },
1257
+ required: ["epicId"]
1258
+ }
1259
+ },
1260
+ {
1261
+ name: "add_card_to_epic",
1262
+ description: "Add card to epic",
1263
+ inputSchema: {
1264
+ type: "object",
1265
+ properties: { epicId: { type: "string" }, cardId: { type: "string" } },
1266
+ required: ["epicId", "cardId"]
1267
+ }
1268
+ },
1269
+ {
1270
+ name: "remove_card_from_epic",
1271
+ description: "Remove card from epic",
1272
+ inputSchema: {
1273
+ type: "object",
1274
+ properties: { epicId: { type: "string" }, cardId: { type: "string" } },
1275
+ required: ["epicId", "cardId"]
1276
+ }
1277
+ },
1278
+ // FEATURES
1279
+ {
1280
+ name: "list_features",
1281
+ description: "List features. Filter by epicId or slug.",
1282
+ inputSchema: {
1283
+ type: "object",
1284
+ properties: {
1285
+ epicId: { type: "string" },
1286
+ slug: {
1287
+ type: "string",
1288
+ description: "Filter by feature slug (UPPERCASE)"
1289
+ }
1290
+ }
1291
+ }
1292
+ },
1293
+ {
1294
+ name: "get_feature",
1295
+ description: "Get a feature with cards and progress. Accepts featureId or featureSlug (UPPERCASE).",
1296
+ inputSchema: {
1297
+ type: "object",
1298
+ properties: {
1299
+ featureId: { type: "string", description: "Feature ID or slug" },
1300
+ featureSlug: {
1301
+ type: "string",
1302
+ description: "Feature slug (UPPERCASE), alternative to featureId"
1303
+ }
1304
+ }
1305
+ }
1306
+ },
1307
+ {
1308
+ name: "get_active_features",
1309
+ description: "Get features with cards in progress, organized by epic",
1310
+ inputSchema: { type: "object", properties: {} }
1311
+ },
1312
+ {
1313
+ name: "create_feature",
1314
+ description: "Create a new feature (optionally in an epic)",
1315
+ inputSchema: {
1316
+ type: "object",
1317
+ properties: {
1318
+ epicId: { type: "string" },
1319
+ title: { type: "string" },
1320
+ slug: { type: "string" },
1321
+ description: { type: "string" },
1322
+ status: {
1323
+ type: "string",
1324
+ enum: ["planning", "in_progress", "completed", "on_hold"]
1325
+ }
1326
+ },
1327
+ required: ["title"]
1328
+ }
1329
+ },
1330
+ {
1331
+ name: "update_feature",
1332
+ description: "Update a feature",
1333
+ inputSchema: {
1334
+ type: "object",
1335
+ properties: {
1336
+ featureId: { type: "string" },
1337
+ title: { type: "string" },
1338
+ slug: { type: "string" },
1339
+ description: { type: "string" },
1340
+ status: {
1341
+ type: "string",
1342
+ enum: ["planning", "in_progress", "completed", "on_hold"]
1343
+ },
1344
+ order: { type: "number" },
1345
+ epicId: { type: "string", description: "Move to another epic" }
1346
+ },
1347
+ required: ["featureId"]
1348
+ }
1349
+ },
1350
+ {
1351
+ name: "delete_feature",
1352
+ description: "Delete a feature (cards unlinked)",
1353
+ inputSchema: {
1354
+ type: "object",
1355
+ properties: { featureId: { type: "string" } },
1356
+ required: ["featureId"]
1357
+ }
1358
+ },
1359
+ {
1360
+ name: "add_card_to_feature",
1361
+ description: "Add a card to a feature. Accepts featureId or featureSlug.",
1362
+ inputSchema: {
1363
+ type: "object",
1364
+ properties: {
1365
+ cardId: { type: "string" },
1366
+ featureId: { type: "string", description: "Feature ID or slug" },
1367
+ featureSlug: {
1368
+ type: "string",
1369
+ description: "Feature slug (UPPERCASE), alternative to featureId"
1370
+ }
1371
+ },
1372
+ required: ["cardId"]
1373
+ }
1374
+ },
1375
+ {
1376
+ name: "remove_card_from_feature",
1377
+ description: "Remove a card from a feature. Accepts featureId or featureSlug.",
1378
+ inputSchema: {
1379
+ type: "object",
1380
+ properties: {
1381
+ cardId: { type: "string" },
1382
+ featureId: { type: "string", description: "Feature ID or slug" },
1383
+ featureSlug: {
1384
+ type: "string",
1385
+ description: "Feature slug (UPPERCASE), alternative to featureId"
1386
+ }
1387
+ },
1388
+ required: ["cardId"]
1389
+ }
1390
+ },
1391
+ {
1392
+ name: "get_feature_cards",
1393
+ description: "Get all cards in a feature. Accepts featureId or featureSlug.",
1394
+ inputSchema: {
1395
+ type: "object",
1396
+ properties: {
1397
+ featureId: { type: "string", description: "Feature ID or slug" },
1398
+ featureSlug: {
1399
+ type: "string",
1400
+ description: "Feature slug (UPPERCASE), alternative to featureId"
1401
+ }
1402
+ }
1403
+ }
1404
+ },
323
1405
  // CARD LINKS
324
- { name: "link_cards", description: "Link two cards", inputSchema: { type: "object", properties: { cardId1: { type: "string" }, cardId2: { type: "string" }, label: { type: "string" } }, required: ["cardId1", "cardId2"] } },
325
- { name: "unlink_cards", description: "Unlink two cards", inputSchema: { type: "object", properties: { cardId1: { type: "string" }, cardId2: { type: "string" } }, required: ["cardId1", "cardId2"] } },
326
- { name: "get_linked_cards", description: "Get linked cards", inputSchema: { type: "object", properties: { cardId: { type: "string" } }, required: ["cardId"] } },
1406
+ {
1407
+ name: "link_cards",
1408
+ description: "Link two cards",
1409
+ inputSchema: {
1410
+ type: "object",
1411
+ properties: {
1412
+ cardId1: { type: "string" },
1413
+ cardId2: { type: "string" },
1414
+ label: { type: "string" }
1415
+ },
1416
+ required: ["cardId1", "cardId2"]
1417
+ }
1418
+ },
1419
+ {
1420
+ name: "unlink_cards",
1421
+ description: "Unlink two cards by link ID",
1422
+ inputSchema: {
1423
+ type: "object",
1424
+ properties: {
1425
+ linkId: { type: "string" }
1426
+ },
1427
+ required: ["linkId"]
1428
+ }
1429
+ },
1430
+ {
1431
+ name: "get_linked_cards",
1432
+ description: "Get linked cards",
1433
+ inputSchema: {
1434
+ type: "object",
1435
+ properties: { cardId: { type: "string" } },
1436
+ required: ["cardId"]
1437
+ }
1438
+ },
327
1439
  // GITHUB INTEGRATION
328
- { name: "setup_github_integration", description: "Setup GitHub webhook", inputSchema: { type: "object", properties: { projectId: { type: "string" }, repoOwner: { type: "string" }, repoName: { type: "string" }, inProgressColumnName: { type: "string" }, doneColumnName: { type: "string" } }, required: ["projectId", "repoOwner", "repoName"] } },
329
- { name: "get_github_integration", description: "Get GitHub integration", inputSchema: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] } },
330
- { name: "update_github_integration", description: "Update GitHub integration", inputSchema: { type: "object", properties: { projectId: { type: "string" }, autoMoveOnPush: { type: "boolean" }, autoMoveOnPrMerge: { type: "boolean" }, autoLinkPr: { type: "boolean" }, inProgressColumnName: { type: "string" }, doneColumnName: { type: "string" } }, required: ["projectId"] } },
331
- { name: "remove_github_integration", description: "Remove GitHub integration", inputSchema: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] } },
332
- { name: "link_card_to_branch", description: "Link card to branch", inputSchema: { type: "object", properties: { cardId: { type: "string" }, branch: { type: "string" } }, required: ["cardId", "branch"] } },
333
- { name: "link_card_to_pr", description: "Link card to PR", inputSchema: { type: "object", properties: { cardId: { type: "string" }, prUrl: { type: "string" } }, required: ["cardId", "prUrl"] } },
334
- // GITHUB API
335
- { name: "github_list_repos", description: "List user repos", inputSchema: { type: "object", properties: { userId: { type: "string" }, type: { type: "string", enum: ["all", "owner", "member"] } }, required: ["userId"] } },
336
- { name: "github_create_branch", description: "Create branch", inputSchema: { type: "object", properties: { userId: { type: "string" }, owner: { type: "string" }, repo: { type: "string" }, branchName: { type: "string" }, sourceBranch: { type: "string" } }, required: ["userId", "owner", "repo", "branchName"] } },
337
- { name: "github_create_pr", description: "Create PR", inputSchema: { type: "object", properties: { userId: { type: "string" }, owner: { type: "string" }, repo: { type: "string" }, title: { type: "string" }, head: { type: "string" }, base: { type: "string" }, body: { type: "string" } }, required: ["userId", "owner", "repo", "title", "head"] } },
338
- { name: "github_auto_setup_webhook", description: "Auto-setup webhook", inputSchema: { type: "object", properties: { userId: { type: "string" }, projectId: { type: "string" }, owner: { type: "string" }, repo: { type: "string" } }, required: ["userId", "projectId", "owner", "repo"] } }
1440
+ {
1441
+ name: "setup_github_integration",
1442
+ description: "Setup GitHub integration for a project (auto-creates webhook)",
1443
+ inputSchema: {
1444
+ type: "object",
1445
+ properties: {
1446
+ projectId: { type: "string" },
1447
+ repoOwner: { type: "string" },
1448
+ repoName: { type: "string" },
1449
+ inProgressColumnName: { type: "string" },
1450
+ doneColumnName: { type: "string" },
1451
+ autoMoveOnPush: { type: "boolean" },
1452
+ autoMoveOnPrMerge: { type: "boolean" },
1453
+ autoLinkPr: { type: "boolean" }
1454
+ },
1455
+ required: ["projectId", "repoOwner", "repoName"]
1456
+ }
1457
+ },
1458
+ {
1459
+ name: "get_github_integration",
1460
+ description: "Get GitHub integration settings",
1461
+ inputSchema: {
1462
+ type: "object",
1463
+ properties: { projectId: { type: "string" } },
1464
+ required: ["projectId"]
1465
+ }
1466
+ },
1467
+ {
1468
+ name: "update_github_integration",
1469
+ description: "Update GitHub integration settings",
1470
+ inputSchema: {
1471
+ type: "object",
1472
+ properties: {
1473
+ projectId: { type: "string" },
1474
+ repoOwner: { type: "string" },
1475
+ repoName: { type: "string" },
1476
+ autoMoveOnPush: { type: "boolean" },
1477
+ autoMoveOnPrMerge: { type: "boolean" },
1478
+ autoLinkPr: { type: "boolean" },
1479
+ inProgressColumnName: { type: "string" },
1480
+ doneColumnName: { type: "string" }
1481
+ },
1482
+ required: ["projectId"]
1483
+ }
1484
+ },
1485
+ {
1486
+ name: "remove_github_integration",
1487
+ description: "Remove GitHub integration",
1488
+ inputSchema: {
1489
+ type: "object",
1490
+ properties: { projectId: { type: "string" } },
1491
+ required: ["projectId"]
1492
+ }
1493
+ },
1494
+ {
1495
+ name: "link_card_to_branch",
1496
+ description: "Link card to branch",
1497
+ inputSchema: {
1498
+ type: "object",
1499
+ properties: { cardId: { type: "string" }, branch: { type: "string" } },
1500
+ required: ["cardId", "branch"]
1501
+ }
1502
+ },
1503
+ {
1504
+ name: "link_card_to_pr",
1505
+ description: "Link card to PR",
1506
+ inputSchema: {
1507
+ type: "object",
1508
+ properties: { cardId: { type: "string" }, prUrl: { type: "string" } },
1509
+ required: ["cardId", "prUrl"]
1510
+ }
1511
+ }
339
1512
  ]
340
1513
  }));
341
1514
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -351,13 +1524,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
351
1524
  result = await kanbanApi.createFolder(args);
352
1525
  break;
353
1526
  case "update_folder":
354
- result = await kanbanApi.updateFolder(args.folderId, args);
1527
+ result = await kanbanApi.updateFolder(
1528
+ args.folderId,
1529
+ args
1530
+ );
355
1531
  break;
356
1532
  case "delete_folder":
357
1533
  result = await kanbanApi.deleteFolder(args.folderId);
358
1534
  break;
359
1535
  case "move_project_to_folder":
360
- result = await kanbanApi.moveProjectToFolder(args.projectId, args.folderId);
1536
+ result = await kanbanApi.moveProjectToFolder(
1537
+ args.projectId,
1538
+ args.folderId
1539
+ );
1540
+ break;
1541
+ case "reorder_folders":
1542
+ result = await kanbanApi.reorderFolders(
1543
+ args.folderId,
1544
+ args.targetFolderId
1545
+ );
361
1546
  break;
362
1547
  // PROJECTS
363
1548
  case "list_projects":
@@ -367,15 +1552,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
367
1552
  result = await kanbanApi.createProject(args);
368
1553
  break;
369
1554
  case "get_project":
370
- result = await kanbanApi.getProject(args.projectId, args);
1555
+ result = await kanbanApi.getProject(
1556
+ args.projectId,
1557
+ args
1558
+ );
371
1559
  break;
372
1560
  case "update_project":
373
- result = await kanbanApi.updateProject(args.projectId, args);
1561
+ result = await kanbanApi.updateProject(
1562
+ args.projectId,
1563
+ args
1564
+ );
374
1565
  break;
375
1566
  case "delete_project":
376
1567
  result = await kanbanApi.deleteProject(args.projectId);
377
1568
  break;
1569
+ case "reorder_projects":
1570
+ result = await kanbanApi.reorderProjects(
1571
+ args.projectId,
1572
+ args.targetProjectId,
1573
+ args.folderId
1574
+ );
1575
+ break;
378
1576
  // BOARDS
1577
+ case "list_boards":
1578
+ result = await kanbanApi.listBoards(args);
1579
+ break;
379
1580
  case "create_board":
380
1581
  result = await kanbanApi.createBoard(args);
381
1582
  break;
@@ -383,7 +1584,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
383
1584
  result = await kanbanApi.getBoard(args.boardId, args);
384
1585
  break;
385
1586
  case "update_board":
386
- result = await kanbanApi.updateBoard(args.boardId, { name: args.name });
1587
+ result = await kanbanApi.updateBoard(args.boardId, {
1588
+ name: args.name
1589
+ });
387
1590
  break;
388
1591
  case "delete_board":
389
1592
  result = await kanbanApi.deleteBoard(args.boardId);
@@ -393,12 +1596,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
393
1596
  result = await kanbanApi.createColumn(args);
394
1597
  break;
395
1598
  case "update_column":
396
- result = await kanbanApi.updateColumn(args.columnId, args);
1599
+ result = await kanbanApi.updateColumn(
1600
+ args.columnId,
1601
+ args
1602
+ );
397
1603
  break;
398
1604
  case "delete_column":
399
1605
  result = await kanbanApi.deleteColumn(args.columnId);
400
1606
  break;
1607
+ case "reorder_columns":
1608
+ result = await kanbanApi.reorderColumns(args.columns);
1609
+ break;
401
1610
  // CARDS
1611
+ case "get_card":
1612
+ result = await kanbanApi.getCard(args.cardId);
1613
+ break;
402
1614
  case "create_card":
403
1615
  result = await kanbanApi.createCard(args);
404
1616
  break;
@@ -409,32 +1621,65 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
409
1621
  result = await kanbanApi.deleteCard(args.cardId);
410
1622
  break;
411
1623
  case "move_card":
412
- result = await kanbanApi.moveCard(args.cardId, args.targetColumnId);
1624
+ result = await kanbanApi.moveCard(
1625
+ args.cardId,
1626
+ args.targetColumnId,
1627
+ args.newOrder
1628
+ );
1629
+ break;
1630
+ case "archive_card":
1631
+ result = await kanbanApi.archiveCard(args.cardId);
1632
+ break;
1633
+ case "unarchive_card":
1634
+ result = await kanbanApi.unarchiveCard(args.cardId);
1635
+ break;
1636
+ case "list_archived_cards":
1637
+ result = await kanbanApi.listArchivedCards(args.boardId);
413
1638
  break;
414
1639
  case "add_comment":
415
- result = await kanbanApi.addComment(args.cardId, args.content);
1640
+ result = await kanbanApi.addComment(
1641
+ args.cardId,
1642
+ args.content
1643
+ );
1644
+ break;
1645
+ case "delete_comment":
1646
+ result = await kanbanApi.deleteComment(args.commentId);
416
1647
  break;
417
1648
  // CHECKLISTS
418
1649
  case "create_checklist":
419
- result = await kanbanApi.createChecklist({ cardId: args.cardId, title: args.title });
1650
+ result = await kanbanApi.createChecklist({
1651
+ cardId: args.cardId,
1652
+ title: args.title
1653
+ });
420
1654
  break;
421
1655
  case "update_checklist":
422
- result = await kanbanApi.updateChecklist(args.checklistId, { title: args.title });
1656
+ result = await kanbanApi.updateChecklist(args.checklistId, {
1657
+ title: args.title
1658
+ });
423
1659
  break;
424
1660
  case "delete_checklist":
425
1661
  result = await kanbanApi.deleteChecklist(args.checklistId);
426
1662
  break;
427
1663
  case "create_checklist_item":
428
- result = await kanbanApi.createChecklistItem({ checklistId: args.checklistId, content: args.content });
1664
+ result = await kanbanApi.createChecklistItem({
1665
+ checklistId: args.checklistId,
1666
+ content: args.content
1667
+ });
429
1668
  break;
430
1669
  case "update_checklist_item":
431
- result = await kanbanApi.updateChecklistItem(args.itemId, { content: args.content, completed: args.completed });
1670
+ result = await kanbanApi.updateChecklistItem(args.itemId, {
1671
+ content: args.content,
1672
+ completed: args.completed
1673
+ });
432
1674
  break;
433
1675
  case "delete_checklist_item":
434
1676
  result = await kanbanApi.deleteChecklistItem(args.itemId);
435
1677
  break;
436
1678
  case "get_branch_name":
437
- result = await kanbanApi.getBranchName(args.cardId, args.type || "feature");
1679
+ result = await kanbanApi.getBranchName(
1680
+ args.cardId,
1681
+ args.type || "feature"
1682
+ );
438
1683
  break;
439
1684
  case "search_cards":
440
1685
  result = await kanbanApi.searchCards(args);
@@ -446,6 +1691,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
446
1691
  case "bulk_create_epic_with_cards":
447
1692
  result = await kanbanApi.bulkCreateEpicWithCards(args);
448
1693
  break;
1694
+ case "bulk_create_epic_with_features":
1695
+ result = await kanbanApi.bulkCreateEpicWithFeatures(args);
1696
+ break;
449
1697
  case "bulk_move_cards":
450
1698
  result = await kanbanApi.bulkMoveCards(args);
451
1699
  break;
@@ -476,10 +1724,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
476
1724
  result = await kanbanApi.deleteTag(args.tagId);
477
1725
  break;
478
1726
  case "add_tag_to_card":
479
- result = await kanbanApi.addTagToCard(args.cardId, args.tagId);
1727
+ result = await kanbanApi.addTagToCard(
1728
+ args.cardId,
1729
+ args.tagId
1730
+ );
480
1731
  break;
481
1732
  case "remove_tag_from_card":
482
- result = await kanbanApi.removeTagFromCard(args.cardId, args.tagId);
1733
+ result = await kanbanApi.removeTagFromCard(
1734
+ args.cardId,
1735
+ args.tagId
1736
+ );
483
1737
  break;
484
1738
  // EPICS
485
1739
  case "list_epics":
@@ -488,6 +1742,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
488
1742
  case "create_epic":
489
1743
  result = await kanbanApi.createEpic(args);
490
1744
  break;
1745
+ case "get_epic":
1746
+ result = await kanbanApi.getEpic(args.epicId);
1747
+ break;
491
1748
  case "update_epic":
492
1749
  result = await kanbanApi.updateEpic(args.epicId, args);
493
1750
  break;
@@ -495,20 +1752,97 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
495
1752
  result = await kanbanApi.deleteEpic(args.epicId);
496
1753
  break;
497
1754
  case "add_card_to_epic":
498
- result = await kanbanApi.addCardToEpic(args.epicId, args.cardId);
1755
+ result = await kanbanApi.addCardToEpic(
1756
+ args.epicId,
1757
+ args.cardId
1758
+ );
499
1759
  break;
500
1760
  case "remove_card_from_epic":
501
- result = await kanbanApi.removeCardFromEpic(args.epicId, args.cardId);
1761
+ result = await kanbanApi.removeCardFromEpic(
1762
+ args.epicId,
1763
+ args.cardId
1764
+ );
1765
+ break;
1766
+ // FEATURES
1767
+ case "list_features": {
1768
+ const features = await kanbanApi.listFeatures(args.epicId);
1769
+ const slugFilter = args.slug;
1770
+ result = slugFilter ? (Array.isArray(features) ? features : []).filter(
1771
+ (f) => f.slug === slugFilter.toUpperCase()
1772
+ ) : features;
502
1773
  break;
503
- case "get_epic_timeline":
504
- result = await kanbanApi.getEpicTimeline();
1774
+ }
1775
+ case "get_feature": {
1776
+ const fId = args.featureId || args.featureSlug;
1777
+ if (!fId)
1778
+ throw new Error("Either featureId or featureSlug is required");
1779
+ result = await kanbanApi.getFeature(fId);
1780
+ break;
1781
+ }
1782
+ case "get_active_features":
1783
+ result = await kanbanApi.getActiveFeatures();
1784
+ break;
1785
+ case "create_feature":
1786
+ result = await kanbanApi.createFeature(args);
1787
+ break;
1788
+ case "update_feature":
1789
+ result = await kanbanApi.updateFeature(
1790
+ args.featureId,
1791
+ args
1792
+ );
1793
+ break;
1794
+ case "delete_feature":
1795
+ result = await kanbanApi.deleteFeature(args.featureId);
1796
+ break;
1797
+ case "add_card_to_feature": {
1798
+ let addFeatureId = args.featureId || args.featureSlug;
1799
+ if (!addFeatureId)
1800
+ throw new Error("Either featureId or featureSlug is required");
1801
+ if (args.featureSlug && !args.featureId) {
1802
+ const resolved = await kanbanApi.getFeature(addFeatureId);
1803
+ addFeatureId = resolved.id;
1804
+ }
1805
+ result = await kanbanApi.addCardToFeature(
1806
+ addFeatureId,
1807
+ args.cardId
1808
+ );
1809
+ break;
1810
+ }
1811
+ case "remove_card_from_feature": {
1812
+ let removeFeatureId = args.featureId || args.featureSlug;
1813
+ if (!removeFeatureId)
1814
+ throw new Error("Either featureId or featureSlug is required");
1815
+ if (args.featureSlug && !args.featureId) {
1816
+ const resolved = await kanbanApi.getFeature(removeFeatureId);
1817
+ removeFeatureId = resolved.id;
1818
+ }
1819
+ result = await kanbanApi.removeCardFromFeature(
1820
+ removeFeatureId,
1821
+ args.cardId
1822
+ );
1823
+ break;
1824
+ }
1825
+ case "get_feature_cards": {
1826
+ let cardsFeatureId = args.featureId || args.featureSlug;
1827
+ if (!cardsFeatureId)
1828
+ throw new Error("Either featureId or featureSlug is required");
1829
+ if (args.featureSlug && !args.featureId) {
1830
+ const resolved = await kanbanApi.getFeature(cardsFeatureId);
1831
+ cardsFeatureId = resolved.id;
1832
+ }
1833
+ result = await kanbanApi.getFeatureCards(cardsFeatureId);
505
1834
  break;
1835
+ }
506
1836
  // CARD LINKS
507
1837
  case "link_cards":
508
- result = await kanbanApi.linkCards(args.cardId1, args.cardId2, args.label);
1838
+ result = await kanbanApi.linkCards(
1839
+ args.cardId1,
1840
+ args.cardId2,
1841
+ args.label
1842
+ );
509
1843
  break;
510
1844
  case "unlink_cards":
511
- result = await kanbanApi.unlinkCards(args.cardId1, args.cardId2);
1845
+ result = await kanbanApi.unlinkCards(args.linkId);
512
1846
  break;
513
1847
  case "get_linked_cards":
514
1848
  result = await kanbanApi.getLinkedCards(args.cardId);
@@ -521,38 +1855,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
521
1855
  result = await kanbanApi.getGithubIntegration(args.projectId);
522
1856
  break;
523
1857
  case "update_github_integration":
524
- result = await kanbanApi.updateGithubIntegration(args.projectId, args);
1858
+ result = await kanbanApi.updateGithubIntegration(
1859
+ args.projectId,
1860
+ args
1861
+ );
525
1862
  break;
526
1863
  case "remove_github_integration":
527
- result = await kanbanApi.removeGithubIntegration(args.projectId);
1864
+ result = await kanbanApi.removeGithubIntegration(
1865
+ args.projectId
1866
+ );
528
1867
  break;
529
1868
  case "link_card_to_branch":
530
- result = await kanbanApi.linkCardToBranch(args.cardId, args.branch);
1869
+ result = await kanbanApi.linkCardToBranch(
1870
+ args.cardId,
1871
+ args.branch
1872
+ );
531
1873
  break;
532
1874
  case "link_card_to_pr":
533
- result = await kanbanApi.linkCardToPr(args.cardId, args.prUrl);
534
- break;
535
- // GITHUB API
536
- case "github_list_repos":
537
- result = await kanbanApi.githubListRepos(args.userId, args.type);
538
- break;
539
- case "github_create_branch":
540
- result = await kanbanApi.githubCreateBranch(args);
541
- break;
542
- case "github_create_pr":
543
- result = await kanbanApi.githubCreatePr(args);
544
- break;
545
- case "github_auto_setup_webhook":
546
- result = await kanbanApi.githubAutoSetupWebhook(args);
1875
+ result = await kanbanApi.linkCardToPr(
1876
+ args.cardId,
1877
+ args.prUrl
1878
+ );
547
1879
  break;
548
1880
  default:
549
1881
  throw new Error(`Unknown tool: ${name}`);
550
1882
  }
551
1883
  return {
552
- content: [{
553
- type: "text",
554
- text: typeof result === "string" ? result : JSON.stringify(result)
555
- }]
1884
+ content: [
1885
+ {
1886
+ type: "text",
1887
+ text: typeof result === "string" ? result : JSON.stringify(result)
1888
+ }
1889
+ ]
556
1890
  };
557
1891
  } catch (error) {
558
1892
  const message = error instanceof Error ? error.message : "Unknown error";