snboard-mcp 1.0.4 → 1.1.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.
package/dist/index.js CHANGED
@@ -32,52 +32,83 @@ 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();
39
46
  if (params?.folderId) searchParams.set("folderId", params.folderId);
40
- if (params?.limit) searchParams.set("limit", params.limit.toString());
47
+ searchParams.set("limit", (params?.limit || 20).toString());
41
48
  if (params?.compact) searchParams.set("compact", "true");
42
49
  const query = searchParams.toString();
43
50
  return api(`/api/projects${query ? `?${query}` : ""}`);
44
51
  },
45
52
  createProject: (data) => api("/api/projects", { method: "POST", body: JSON.stringify(data) }),
46
- getProject: (id) => api(`/api/projects/${id}`),
47
- updateProject: (id, data) => api(`/api/projects/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
53
+ getProject: (id, params) => {
54
+ const searchParams = new URLSearchParams();
55
+ if (params?.includeBoards) searchParams.set("includeBoards", "true");
56
+ if (params?.boardsCompact) searchParams.set("boardsCompact", "true");
57
+ const query = searchParams.toString();
58
+ return api(`/api/projects/${id}${query ? `?${query}` : ""}`);
59
+ },
60
+ updateProject: (id, data) => api(`/api/projects/${id}`, { method: "PUT", body: JSON.stringify(data) }),
48
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
+ }),
49
66
  // Boards
50
- listBoards: (projectId, params) => {
67
+ listBoards: (params) => {
51
68
  const searchParams = new URLSearchParams();
52
- searchParams.set("projectId", projectId);
53
- if (params?.compact) searchParams.set("compact", "true");
69
+ if (params?.projectId) searchParams.set("projectId", params.projectId);
54
70
  if (params?.limit) searchParams.set("limit", params.limit.toString());
55
- return api(`/api/boards?${searchParams.toString()}`);
71
+ if (params?.compact) searchParams.set("compact", "true");
72
+ const query = searchParams.toString();
73
+ return api(`/api/boards${query ? `?${query}` : ""}`);
56
74
  },
57
75
  createBoard: (data) => api("/api/boards", { method: "POST", body: JSON.stringify(data) }),
58
76
  getBoard: (id, params) => {
59
77
  const searchParams = new URLSearchParams();
60
78
  if (params?.columnId) searchParams.set("columnId", params.columnId);
61
- if (params?.includeCards) searchParams.set("includeCards", "true");
79
+ if (params?.includeCards) {
80
+ searchParams.set("includeCards", "true");
81
+ searchParams.set("cardLimit", (params?.cardLimit || 10).toString());
82
+ }
62
83
  if (params?.includeTags) searchParams.set("includeTags", "true");
63
84
  if (params?.includeComments) searchParams.set("includeComments", "true");
64
- if (params?.cardLimit) searchParams.set("cardLimit", params.cardLimit.toString());
65
85
  if (params?.compact) searchParams.set("compact", "true");
66
86
  if (params?.priority) searchParams.set("priority", params.priority);
67
87
  const query = searchParams.toString();
68
88
  return api(`/api/boards/${id}${query ? `?${query}` : ""}`);
69
89
  },
70
- 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) }),
71
91
  deleteBoard: (id) => api(`/api/boards/${id}`, { method: "DELETE" }),
72
92
  // Columns
73
93
  createColumn: (data) => api("/api/columns", { method: "POST", body: JSON.stringify(data) }),
74
- 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) }),
75
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
+ }),
76
100
  // Cards
101
+ getCard: (id) => api(`/api/cards/${id}`),
77
102
  createCard: (data) => api("/api/cards", { method: "POST", body: JSON.stringify(data) }),
78
- 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) }),
79
104
  deleteCard: (id) => api(`/api/cards/${id}`, { method: "DELETE" }),
80
- moveCard: (id, targetColumnId) => api("/api/cards/move", { method: "POST", body: JSON.stringify({ cardId: id, targetColumnId }) }),
105
+ archiveCard: (id) => api(`/api/cards/${id}`, { method: "PUT", body: JSON.stringify({ isArchived: true }) }),
106
+ unarchiveCard: (id) => api(`/api/cards/${id}`, { method: "PUT", body: JSON.stringify({ isArchived: false }) }),
107
+ listArchivedCards: (boardId) => api(`/api/archived?boardId=${boardId}`),
108
+ moveCard: (id, targetColumnId, newOrder) => api("/api/cards/move", {
109
+ method: "POST",
110
+ body: JSON.stringify({ cardId: id, targetColumnId, ...newOrder !== void 0 && { newOrder } })
111
+ }),
81
112
  getBranchName: (id, type) => api(`/api/cards/${id}/branch?type=${type}`),
82
113
  searchCards: (params) => {
83
114
  const searchParams = new URLSearchParams();
@@ -87,139 +118,1545 @@ var kanbanApi = {
87
118
  if (params.columnId) searchParams.set("columnId", params.columnId);
88
119
  if (params.epicId) searchParams.set("epicId", params.epicId);
89
120
  if (params.featureId) searchParams.set("featureId", params.featureId);
90
- if (params.hasEpic !== void 0) searchParams.set("hasEpic", params.hasEpic.toString());
121
+ if (params.hasEpic !== void 0)
122
+ searchParams.set("hasEpic", params.hasEpic.toString());
91
123
  if (params.status) searchParams.set("status", params.status);
92
- if (params.tagIds?.length) searchParams.set("tagIds", params.tagIds.join(","));
93
- if (params.limit) searchParams.set("limit", params.limit.toString());
124
+ if (params.tagIds?.length)
125
+ searchParams.set("tagIds", params.tagIds.join(","));
126
+ searchParams.set("limit", (params.limit || 20).toString());
94
127
  if (params.compact) searchParams.set("compact", "true");
95
128
  return api(`/api/search?${searchParams.toString()}`);
96
129
  },
130
+ // Tags - managed via card update with tagIds
131
+ addTagToCard: async (cardId, tagId) => {
132
+ const card = await api(`/api/cards/${cardId}`);
133
+ const currentTagIds = (card.tags || []).map((t) => t.id);
134
+ if (!currentTagIds.includes(tagId)) {
135
+ currentTagIds.push(tagId);
136
+ }
137
+ return api(`/api/cards/${cardId}`, {
138
+ method: "PUT",
139
+ body: JSON.stringify({ tagIds: currentTagIds })
140
+ });
141
+ },
142
+ removeTagFromCard: async (cardId, tagId) => {
143
+ const card = await api(`/api/cards/${cardId}`);
144
+ const currentTagIds = (card.tags || []).map((t) => t.id).filter((id) => id !== tagId);
145
+ return api(`/api/cards/${cardId}`, {
146
+ method: "PUT",
147
+ body: JSON.stringify({ tagIds: currentTagIds })
148
+ });
149
+ },
150
+ // Bulk Operations
151
+ bulkCreateCards: async (data) => {
152
+ const results = await Promise.all(
153
+ data.cards.map(
154
+ (card) => api("/api/cards", {
155
+ method: "POST",
156
+ body: JSON.stringify({ columnId: data.columnId, ...card })
157
+ })
158
+ )
159
+ );
160
+ return { created: results.length, cards: results };
161
+ },
162
+ bulkCreateEpicWithCards: async (data) => {
163
+ const epic = await api("/api/epics", {
164
+ method: "POST",
165
+ body: JSON.stringify(data.epic)
166
+ });
167
+ const cardResults = await Promise.all(
168
+ data.cards.map(
169
+ (card) => api("/api/cards", {
170
+ method: "POST",
171
+ body: JSON.stringify({
172
+ columnId: data.columnId,
173
+ epicId: epic.id,
174
+ ...card
175
+ })
176
+ })
177
+ )
178
+ );
179
+ return { epic, cards: cardResults, created: cardResults.length };
180
+ },
181
+ bulkCreateEpicWithFeatures: async (data) => {
182
+ const epic = await api("/api/epics", { method: "POST", body: JSON.stringify(data.epic) });
183
+ const features = await Promise.all(
184
+ data.features.map(
185
+ (f) => api("/api/features", {
186
+ method: "POST",
187
+ body: JSON.stringify({ epicId: epic.id, title: f.title, slug: f.slug, description: f.description })
188
+ })
189
+ )
190
+ );
191
+ const featureResults = await Promise.all(
192
+ features.map(async (feature, i) => {
193
+ const featureCards = data.features[i].cards;
194
+ const cards = await Promise.all(
195
+ featureCards.map(
196
+ (c) => api("/api/cards", {
197
+ method: "POST",
198
+ body: JSON.stringify({ ...c, epicId: epic.id })
199
+ })
200
+ )
201
+ );
202
+ for (const card of cards) {
203
+ await api(`/api/features/${feature.id}/cards`, {
204
+ method: "POST",
205
+ body: JSON.stringify({ cardId: card.id })
206
+ });
207
+ }
208
+ return { id: feature.id, slug: feature.slug, title: feature.title, cardIds: cards.map((c) => c.id) };
209
+ })
210
+ );
211
+ const totalCards = featureResults.reduce((sum, f) => sum + f.cardIds.length, 0);
212
+ return {
213
+ epic: { id: epic.id, slug: epic.slug, name: epic.name },
214
+ features: featureResults,
215
+ total: { features: features.length, cards: totalCards }
216
+ };
217
+ },
218
+ bulkMoveCards: async (data) => {
219
+ const results = await Promise.all(
220
+ data.cardIds.map(
221
+ (cardId) => api("/api/cards/move", {
222
+ method: "POST",
223
+ body: JSON.stringify({ cardId, targetColumnId: data.targetColumnId })
224
+ })
225
+ )
226
+ );
227
+ return { moved: results.length };
228
+ },
229
+ // Aggregated views
230
+ getWorkspace: async (projectId) => {
231
+ const project = await api(
232
+ `/api/projects/${projectId}?includeBoards=true&boardsCompact=true`
233
+ );
234
+ if (!project.boards?.length) return { project, boards: [] };
235
+ const boardsWithColumns = await Promise.all(
236
+ project.boards.map((b) => api(`/api/boards/${b.id}`))
237
+ );
238
+ return {
239
+ project: { id: project.id, name: project.name },
240
+ boards: boardsWithColumns
241
+ };
242
+ },
243
+ getBoardSummary: async (boardId) => {
244
+ const board = await api(
245
+ `/api/boards/${boardId}?includeCards=true&compact=true`
246
+ );
247
+ const summary = {
248
+ id: board.id,
249
+ name: board.name,
250
+ columns: board.columns.map((col) => ({
251
+ id: col.id,
252
+ name: col.name,
253
+ cardCount: col.cards?.length || 0,
254
+ p1Count: col.cards?.filter((c) => c.priority === "P1").length || 0,
255
+ p2Count: col.cards?.filter((c) => c.priority === "P2").length || 0,
256
+ p3Count: col.cards?.filter((c) => c.priority === "P3").length || 0
257
+ })),
258
+ totalCards: board.columns.reduce(
259
+ (sum, col) => sum + (col.cards?.length || 0),
260
+ 0
261
+ )
262
+ };
263
+ return summary;
264
+ },
265
+ getEpicSummary: async (epicId) => {
266
+ const epic = await api(`/api/epics/${epicId}`);
267
+ const cards = epic.cards || [];
268
+ const todoCards = cards.filter(
269
+ (c) => c.column?.name?.toLowerCase().includes("todo") || c.column?.name?.toLowerCase().includes("to do")
270
+ );
271
+ const inProgressCards = cards.filter(
272
+ (c) => c.column?.name?.toLowerCase().includes("progress")
273
+ );
274
+ const doneCards = cards.filter(
275
+ (c) => c.column?.name?.toLowerCase().includes("done")
276
+ );
277
+ return {
278
+ id: epic.id,
279
+ slug: epic.slug,
280
+ name: epic.name,
281
+ status: epic.status,
282
+ stats: {
283
+ total: cards.length,
284
+ todo: todoCards.length,
285
+ inProgress: inProgressCards.length,
286
+ done: doneCards.length,
287
+ progress: cards.length ? Math.round(doneCards.length / cards.length * 100) : 0
288
+ },
289
+ cards: cards.map((c) => ({
290
+ id: c.id,
291
+ title: c.title,
292
+ priority: c.priority,
293
+ status: c.column?.name
294
+ }))
295
+ };
296
+ },
297
+ quickAddCards: async (data) => {
298
+ const lines = data.text.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
299
+ const cards = [];
300
+ for (const line of lines) {
301
+ let title = line.replace(/^[-*]\s*/, "");
302
+ let priority = data.defaultPriority;
303
+ const priorityMatch = title.match(/^(?:\[?(P[123])\]?:?\s*)/i);
304
+ if (priorityMatch) {
305
+ priority = priorityMatch[1].toUpperCase();
306
+ title = title.slice(priorityMatch[0].length);
307
+ }
308
+ if (title) cards.push({ title, priority });
309
+ }
310
+ if (!cards.length) return { created: 0, cards: [] };
311
+ const results = await Promise.all(
312
+ cards.map(
313
+ (card) => api("/api/cards", {
314
+ method: "POST",
315
+ body: JSON.stringify({ columnId: data.columnId, ...card })
316
+ })
317
+ )
318
+ );
319
+ return { created: results.length, cards: results };
320
+ },
321
+ moveCardsByColumn: async (data) => {
322
+ const searchResult = await api(
323
+ `/api/search?query=*&columnId=${data.sourceColumnId}&limit=${data.limit || 50}&compact=true`
324
+ );
325
+ const cards = Array.isArray(searchResult) ? searchResult : searchResult.cards || [];
326
+ if (!cards.length) return { moved: 0 };
327
+ await Promise.all(
328
+ cards.map(
329
+ (c) => api("/api/cards/move", {
330
+ method: "POST",
331
+ body: JSON.stringify({
332
+ cardId: c.id,
333
+ targetColumnId: data.targetColumnId
334
+ })
335
+ })
336
+ )
337
+ );
338
+ return { moved: cards.length };
339
+ },
97
340
  // Comments
98
- addComment: (cardId, content) => api("/api/comments", { method: "POST", body: JSON.stringify({ cardId, content }) }),
341
+ addComment: (cardId, content) => api("/api/comments", {
342
+ method: "POST",
343
+ body: JSON.stringify({ cardId, content })
344
+ }),
345
+ deleteComment: (commentId) => api(`/api/comments?id=${commentId}`, { method: "DELETE" }),
99
346
  // Checklists
100
347
  createChecklist: (data) => api("/api/checklists", { method: "POST", body: JSON.stringify(data) }),
101
348
  updateChecklist: (id, data) => api(`/api/checklists/${id}`, { method: "PUT", body: JSON.stringify(data) }),
102
349
  deleteChecklist: (id) => api(`/api/checklists/${id}`, { method: "DELETE" }),
103
350
  // Checklist Items
104
351
  createChecklistItem: (data) => api("/api/checklist-items", { method: "POST", body: JSON.stringify(data) }),
105
- updateChecklistItem: (id, data) => api(`/api/checklist-items/${id}`, { method: "PUT", body: JSON.stringify(data) }),
352
+ updateChecklistItem: (id, data) => api(`/api/checklist-items/${id}`, {
353
+ method: "PUT",
354
+ body: JSON.stringify(data)
355
+ }),
106
356
  deleteChecklistItem: (id) => api(`/api/checklist-items/${id}`, { method: "DELETE" }),
107
357
  // Tags
108
358
  listTags: () => api("/api/tags"),
109
359
  createTag: (data) => api("/api/tags", { method: "POST", body: JSON.stringify(data) }),
110
- deleteTag: (id) => api(`/api/tags/${id}`, { method: "DELETE" }),
111
- addTagToCard: (cardId, tagId) => api(`/api/cards/${cardId}/tags`, { method: "POST", body: JSON.stringify({ tagId }) }),
112
- removeTagFromCard: (cardId, tagId) => api(`/api/cards/${cardId}/tags/${tagId}`, { method: "DELETE" }),
360
+ deleteTag: (id) => api(`/api/tags?id=${id}`, { method: "DELETE" }),
113
361
  // Epics
114
362
  listEpics: (params) => {
115
363
  const searchParams = new URLSearchParams();
116
364
  if (params?.status) searchParams.set("status", params.status);
117
- if (params?.includeProgress === false) searchParams.set("includeProgress", "false");
118
- if (params?.limit) searchParams.set("limit", params.limit.toString());
365
+ if (params?.includeProgress === false)
366
+ searchParams.set("includeProgress", "false");
367
+ searchParams.set("limit", (params?.limit || 15).toString());
119
368
  if (params?.compact) searchParams.set("compact", "true");
120
369
  const query = searchParams.toString();
121
370
  return api(`/api/epics${query ? `?${query}` : ""}`);
122
371
  },
123
372
  createEpic: (data) => api("/api/epics", { method: "POST", body: JSON.stringify(data) }),
373
+ updateEpic: (id, data) => api(`/api/epics/${id}`, { method: "PUT", body: JSON.stringify(data) }),
124
374
  getEpic: (id) => api(`/api/epics/${id}`),
125
- updateEpic: (id, data) => api(`/api/epics/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
126
375
  deleteEpic: (id) => api(`/api/epics/${id}`, { method: "DELETE" }),
127
- addCardToEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards`, { method: "POST", body: JSON.stringify({ cardId }) }),
376
+ addCardToEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards`, {
377
+ method: "POST",
378
+ body: JSON.stringify({ cardId })
379
+ }),
128
380
  removeCardFromEpic: (epicId, cardId) => api(`/api/epics/${epicId}/cards/${cardId}`, { method: "DELETE" }),
129
- getEpicTimeline: () => api("/api/epics/timeline"),
381
+ // Features
382
+ listFeatures: (epicId) => {
383
+ const query = epicId ? `?epicId=${epicId}` : "";
384
+ return api(`/api/features${query}`);
385
+ },
386
+ getFeature: (id) => api(`/api/features/${id}`),
387
+ getActiveFeatures: () => api("/api/features/active"),
388
+ createFeature: (data) => api("/api/features", { method: "POST", body: JSON.stringify(data) }),
389
+ updateFeature: (id, data) => api(`/api/features/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
390
+ deleteFeature: (id) => api(`/api/features/${id}`, { method: "DELETE" }),
391
+ addCardToFeature: (featureId, cardId) => api(`/api/features/${featureId}/cards`, { method: "POST", body: JSON.stringify({ cardId }) }),
392
+ removeCardFromFeature: (featureId, cardId) => api(`/api/features/${featureId}/cards/${cardId}`, { method: "DELETE" }),
393
+ getFeatureCards: (featureId) => api(`/api/features/${featureId}/cards`),
130
394
  // Card Links
131
- linkCards: (cardId1, cardId2, label) => api("/api/card-links", { method: "POST", body: JSON.stringify({ cardId1, cardId2, label }) }),
132
- unlinkCards: (cardId1, cardId2) => api("/api/card-links", { method: "DELETE", body: JSON.stringify({ cardId1, cardId2 }) }),
395
+ linkCards: (cardId1, cardId2, label) => api("/api/card-links", {
396
+ method: "POST",
397
+ body: JSON.stringify({ fromCardId: cardId1, toCardId: cardId2, label })
398
+ }),
399
+ unlinkCards: (linkId) => api(`/api/card-links?id=${linkId}`, { method: "DELETE" }),
133
400
  getLinkedCards: (cardId) => api(`/api/card-links?cardId=${cardId}`),
134
- getFeatureCards: (cardId) => api(`/api/features?cardId=${cardId}`),
135
- // GitHub Integration
136
- setupGithubIntegration: (data) => api("/api/github/integration", { method: "POST", body: JSON.stringify(data) }),
137
- getGithubIntegration: (projectId) => api(`/api/github/integration?projectId=${projectId}`),
138
- updateGithubIntegration: (projectId, data) => api(`/api/github/integration/${projectId}`, { method: "PATCH", body: JSON.stringify(data) }),
139
- removeGithubIntegration: (projectId) => api(`/api/github/integration/${projectId}`, { method: "DELETE" }),
140
- linkCardToBranch: (cardId, branch) => api(`/api/cards/${cardId}`, { method: "PATCH", body: JSON.stringify({ githubBranch: branch }) }),
141
- linkCardToPr: (cardId, prUrl) => api(`/api/cards/${cardId}`, { method: "PATCH", body: JSON.stringify({ githubPrUrl: prUrl }) }),
401
+ // GitHub Integration - routes at /api/projects/[id]/github
402
+ setupGithubIntegration: (data) => api(`/api/projects/${data.projectId}/github`, {
403
+ method: "POST",
404
+ body: JSON.stringify(data)
405
+ }),
406
+ getGithubIntegration: (projectId) => api(`/api/projects/${projectId}/github`),
407
+ updateGithubIntegration: (projectId, data) => api(`/api/projects/${projectId}/github`, {
408
+ method: "PUT",
409
+ body: JSON.stringify(data)
410
+ }),
411
+ removeGithubIntegration: (projectId) => api(`/api/projects/${projectId}/github`, { method: "DELETE" }),
412
+ linkCardToBranch: (cardId, branch) => api(`/api/cards/${cardId}`, {
413
+ method: "PUT",
414
+ body: JSON.stringify({ githubBranch: branch })
415
+ }),
416
+ linkCardToPr: (cardId, prUrl) => api(`/api/cards/${cardId}`, {
417
+ method: "PUT",
418
+ body: JSON.stringify({ githubPrUrl: prUrl })
419
+ }),
142
420
  // GitHub API
143
421
  githubListRepos: (userId, type) => api(`/api/github/repos?userId=${userId}${type ? `&type=${type}` : ""}`),
144
422
  githubCreateBranch: (data) => api("/api/github/branches", { method: "POST", body: JSON.stringify(data) }),
145
- githubCreatePr: (data) => api("/api/github/pull-requests", { method: "POST", body: JSON.stringify(data) }),
146
- githubAutoSetupWebhook: (data) => api("/api/github/webhooks/auto-setup", { method: "POST", body: JSON.stringify(data) })
423
+ githubCreatePr: (data) => api("/api/github/pull-requests", {
424
+ method: "POST",
425
+ body: JSON.stringify(data)
426
+ }),
427
+ // Ideas
428
+ listIdeas: (params) => {
429
+ const searchParams = new URLSearchParams();
430
+ if (params?.status) searchParams.set("status", params.status);
431
+ if (params?.filter) searchParams.set("filter", params.filter);
432
+ const query = searchParams.toString();
433
+ return api(`/api/ideas${query ? `?${query}` : ""}`);
434
+ },
435
+ getIdea: (id) => api(`/api/ideas/${id}`),
436
+ createIdea: (data) => api("/api/ideas", { method: "POST", body: JSON.stringify(data) }),
437
+ updateIdea: (id, data) => api(`/api/ideas/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
438
+ deleteIdea: (id) => api(`/api/ideas/${id}`, { method: "DELETE" }),
439
+ convertIdeaToCard: (ideaId, data) => api(`/api/ideas/${ideaId}/convert`, { method: "POST", body: JSON.stringify(data) }),
440
+ // Time Tracking
441
+ getTimeTracking: (params) => {
442
+ const searchParams = new URLSearchParams();
443
+ if (params?.startDate) searchParams.set("startDate", params.startDate);
444
+ if (params?.endDate) searchParams.set("endDate", params.endDate);
445
+ if (params?.projectId) searchParams.set("projectId", params.projectId);
446
+ const query = searchParams.toString();
447
+ return api(`/api/time-tracking${query ? `?${query}` : ""}`);
448
+ },
449
+ logActivity: (data) => api("/api/time-tracking", { method: "POST", body: JSON.stringify(data) }),
450
+ endTimeSession: () => api("/api/time-tracking", { method: "DELETE" }),
451
+ // Daily Summary
452
+ getDailySummary: () => api("/api/daily-summary"),
453
+ // Retrospective
454
+ getRetrospective: (days) => api(`/api/retrospectives/weekly${days ? `?days=${days}` : ""}`),
455
+ // Export
456
+ exportBoard: (boardId) => api(`/api/export/board/${boardId}`),
457
+ exportProject: (projectId) => api(`/api/export/project/${projectId}`)
147
458
  };
148
459
  var server = new Server(
149
- { name: "kanban-mcp", version: "1.0.0" },
460
+ { name: "kanban-mcp", version: "1.1.0" },
150
461
  { capabilities: { tools: {} } }
151
462
  );
152
463
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
153
464
  tools: [
154
465
  // FOLDERS
155
- { name: "list_folders", description: "List all folders with their projects", inputSchema: { type: "object", properties: {} } },
156
- { name: "create_folder", description: "Create a new folder to organize projects", inputSchema: { type: "object", properties: { name: { type: "string", description: "Folder name" }, icon: { type: "string", description: "Folder icon (optional)" }, color: { type: "string", description: "Folder color hex (optional)" } }, required: ["name"] } },
157
- { name: "update_folder", description: "Update a folder (name, icon, color)", inputSchema: { type: "object", properties: { folderId: { type: "string", description: "Folder ID" }, name: { type: "string" }, icon: { type: "string" }, color: { type: "string" } }, required: ["folderId"] } },
158
- { name: "delete_folder", description: "Delete a folder (projects inside become orphans, not deleted)", inputSchema: { type: "object", properties: { folderId: { type: "string", description: "Folder ID" } }, required: ["folderId"] } },
159
- { name: "move_project_to_folder", description: "Move a project to a folder (or remove from folder if folderId is null)", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, folderId: { type: "string", description: "Target folder ID (or null)" } }, required: ["projectId"] } },
466
+ {
467
+ name: "list_folders",
468
+ description: "List all folders with their projects",
469
+ inputSchema: { type: "object", properties: {} }
470
+ },
471
+ {
472
+ name: "create_folder",
473
+ description: "Create a new folder to organize projects",
474
+ inputSchema: {
475
+ type: "object",
476
+ properties: {
477
+ name: { type: "string" },
478
+ icon: { type: "string" },
479
+ color: { type: "string" }
480
+ },
481
+ required: ["name"]
482
+ }
483
+ },
484
+ {
485
+ name: "update_folder",
486
+ description: "Update a folder (name, icon, color)",
487
+ inputSchema: {
488
+ type: "object",
489
+ properties: {
490
+ folderId: { type: "string" },
491
+ name: { type: "string" },
492
+ icon: { type: "string" },
493
+ color: { type: "string" }
494
+ },
495
+ required: ["folderId"]
496
+ }
497
+ },
498
+ {
499
+ name: "delete_folder",
500
+ description: "Delete a folder (projects become orphans)",
501
+ inputSchema: {
502
+ type: "object",
503
+ properties: { folderId: { type: "string" } },
504
+ required: ["folderId"]
505
+ }
506
+ },
507
+ {
508
+ name: "move_project_to_folder",
509
+ description: "Move project to folder (null to remove)",
510
+ inputSchema: {
511
+ type: "object",
512
+ properties: {
513
+ projectId: { type: "string" },
514
+ folderId: { type: "string" }
515
+ },
516
+ required: ["projectId"]
517
+ }
518
+ },
519
+ {
520
+ name: "reorder_folders",
521
+ description: "Reorder folders by moving one before/after another",
522
+ inputSchema: {
523
+ type: "object",
524
+ properties: {
525
+ folderId: { type: "string" },
526
+ targetFolderId: { type: "string" }
527
+ },
528
+ required: ["folderId", "targetFolderId"]
529
+ }
530
+ },
160
531
  // PROJECTS
161
- { name: "list_projects", description: "List all Kanban projects with optional filters to reduce token usage", inputSchema: { type: "object", properties: { folderId: { type: "string", description: "Filter by folder ID" }, limit: { type: "number", description: "Max results" }, compact: { type: "boolean", description: "Return minimal fields" } } } },
162
- { name: "create_project", description: "Create a new Kanban project", inputSchema: { type: "object", properties: { name: { type: "string", description: "Project name" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" }, folderId: { type: "string" } }, required: ["name"] } },
163
- { name: "get_project", description: "Get a project with its boards", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" } }, required: ["projectId"] } },
164
- { name: "update_project", description: "Update a project (name, description, emoji, color)", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, name: { type: "string" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" } }, required: ["projectId"] } },
165
- { name: "delete_project", description: "Delete a project and all its boards, columns, and cards", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" } }, required: ["projectId"] } },
532
+ {
533
+ name: "list_projects",
534
+ description: "List projects (default limit:20). Use compact:true for minimal fields",
535
+ inputSchema: {
536
+ type: "object",
537
+ properties: {
538
+ folderId: { type: "string", description: 'Filter by folder. Use "none" for orphan projects' },
539
+ limit: { type: "number" },
540
+ compact: { type: "boolean" }
541
+ }
542
+ }
543
+ },
544
+ {
545
+ name: "create_project",
546
+ description: "Create a new project",
547
+ inputSchema: {
548
+ type: "object",
549
+ properties: {
550
+ name: { type: "string" },
551
+ description: { type: "string" },
552
+ emoji: { type: "string" },
553
+ color: { type: "string" },
554
+ folderId: { type: "string" }
555
+ },
556
+ required: ["name"]
557
+ }
558
+ },
559
+ {
560
+ name: "get_project",
561
+ description: "Get project. Use includeBoards:true to get boards in 1 call",
562
+ inputSchema: {
563
+ type: "object",
564
+ properties: {
565
+ projectId: { type: "string" },
566
+ includeBoards: { type: "boolean" },
567
+ boardsCompact: { type: "boolean" }
568
+ },
569
+ required: ["projectId"]
570
+ }
571
+ },
572
+ {
573
+ name: "update_project",
574
+ description: "Update project",
575
+ inputSchema: {
576
+ type: "object",
577
+ properties: {
578
+ projectId: { type: "string" },
579
+ name: { type: "string" },
580
+ description: { type: "string" },
581
+ emoji: { type: "string" },
582
+ color: { type: "string" },
583
+ folderId: { type: "string", description: "Move to folder (null to remove)" }
584
+ },
585
+ required: ["projectId"]
586
+ }
587
+ },
588
+ {
589
+ name: "delete_project",
590
+ description: "Delete project and all its content",
591
+ inputSchema: {
592
+ type: "object",
593
+ properties: { projectId: { type: "string" } },
594
+ required: ["projectId"]
595
+ }
596
+ },
597
+ {
598
+ name: "reorder_projects",
599
+ description: "Reorder projects within a folder",
600
+ inputSchema: {
601
+ type: "object",
602
+ properties: {
603
+ projectId: { type: "string" },
604
+ targetProjectId: { type: "string" },
605
+ folderId: { type: "string", description: "Folder context (null for orphans)" }
606
+ },
607
+ required: ["projectId", "targetProjectId"]
608
+ }
609
+ },
166
610
  // BOARDS
167
- { name: "list_boards", description: "List boards for a project with optional filters to reduce token usage", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, compact: { type: "boolean" }, includeColumnStats: { type: "boolean" }, limit: { type: "number" } }, required: ["projectId"] } },
168
- { name: "create_board", description: "Create a new board in a project with default columns (To Do, In Progress, Done)", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, name: { type: "string", description: "Board name" } }, required: ["projectId", "name"] } },
169
- { 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", description: "Board ID" }, 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"], description: "Filter by priority" }, compact: { type: "boolean", description: "Minimal fields (id, title, priority)" }, includeTags: { type: "boolean", description: "Include tags" }, includeComments: { type: "boolean", description: "Include comments (max 5)" } }, required: ["boardId"] } },
170
- { name: "update_board", description: "Update a board (rename)", inputSchema: { type: "object", properties: { boardId: { type: "string", description: "Board ID" }, name: { type: "string", description: "New board name" } }, required: ["boardId", "name"] } },
171
- { name: "delete_board", description: "Delete a board and all its columns and cards", inputSchema: { type: "object", properties: { boardId: { type: "string", description: "Board ID" } }, required: ["boardId"] } },
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
+ },
172
681
  // COLUMNS
173
- { name: "create_column", description: "Create a new column in a board", inputSchema: { type: "object", properties: { boardId: { type: "string", description: "Board ID" }, name: { type: "string", description: "Column name" }, emoji: { type: "string" } }, required: ["boardId", "name"] } },
174
- { name: "update_column", description: "Update a column (name, emoji)", inputSchema: { type: "object", properties: { columnId: { type: "string", description: "Column ID" }, name: { type: "string" }, emoji: { type: "string" } }, required: ["columnId"] } },
175
- { name: "delete_column", description: "Delete a column and all its cards", inputSchema: { type: "object", properties: { columnId: { type: "string", description: "Column ID" } }, 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
+ },
176
738
  // CARDS
177
- { name: "create_card", description: 'Create a new card in a column. Supports auto-assign to epic if title starts with [SLUG] or SLUG -. Use featureId for multi-project features (e.g., "AUTH", "PAYMENT").', inputSchema: { type: "object", properties: { columnId: { type: "string", description: "Column ID" }, title: { type: "string", description: "Card title" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, featureId: { type: "string", description: 'Shared feature ID for multi-project features (e.g., "AUTH", "PAYMENT")' }, dueDate: { type: "string" }, epicId: { type: "string" }, tagIds: { type: "array", items: { type: "string" } }, linkedCardIds: { type: "array", items: { type: "string" } }, linkLabel: { type: "string" } }, required: ["columnId", "title"] } },
178
- { name: "update_card", description: "Update an existing card (title, description, priority, featureId, dueDate)", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, title: { type: "string" }, description: { type: "string" }, priority: { type: "string", enum: ["P1", "P2", "P3"] }, featureId: { type: "string", description: 'Shared feature ID for multi-project features (e.g., "AUTH", "PAYMENT")' }, dueDate: { type: "string" } }, required: ["cardId"] } },
179
- { name: "delete_card", description: "Delete a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" } }, required: ["cardId"] } },
180
- { name: "move_card", description: "Move a card to a different column", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, targetColumnId: { type: "string", description: "Target column ID" } }, required: ["cardId", "targetColumnId"] } },
181
- { name: "add_comment", description: "Add a comment to a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, content: { type: "string", description: "Comment content" } }, 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: { type: "number", description: "Estimated time in minutes" },
762
+ cognitiveLoad: { type: "string", description: "Cognitive load level" }
763
+ },
764
+ required: ["columnId", "title"]
765
+ }
766
+ },
767
+ {
768
+ name: "update_card",
769
+ description: "Update card fields",
770
+ inputSchema: {
771
+ type: "object",
772
+ properties: {
773
+ cardId: { type: "string" },
774
+ title: { type: "string" },
775
+ description: { type: "string" },
776
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
777
+ dueDate: { type: "string" },
778
+ tagIds: { type: "array", items: { type: "string" }, description: "Replace all tags with these IDs" },
779
+ cognitiveLoad: { type: "string" },
780
+ estimatedMinutes: { type: "number" },
781
+ githubBranch: { type: "string" },
782
+ githubPrUrl: { type: "string" },
783
+ isArchived: { type: "boolean" }
784
+ },
785
+ required: ["cardId"]
786
+ }
787
+ },
788
+ {
789
+ name: "delete_card",
790
+ description: "Delete a card",
791
+ inputSchema: {
792
+ type: "object",
793
+ properties: { cardId: { type: "string" } },
794
+ required: ["cardId"]
795
+ }
796
+ },
797
+ {
798
+ name: "archive_card",
799
+ description: "Archive a card",
800
+ inputSchema: {
801
+ type: "object",
802
+ properties: { cardId: { type: "string" } },
803
+ required: ["cardId"]
804
+ }
805
+ },
806
+ {
807
+ name: "unarchive_card",
808
+ description: "Unarchive a card (restore from archive)",
809
+ inputSchema: {
810
+ type: "object",
811
+ properties: { cardId: { type: "string" } },
812
+ required: ["cardId"]
813
+ }
814
+ },
815
+ {
816
+ name: "list_archived_cards",
817
+ description: "List archived cards for a board",
818
+ inputSchema: {
819
+ type: "object",
820
+ properties: { boardId: { type: "string" } },
821
+ required: ["boardId"]
822
+ }
823
+ },
824
+ {
825
+ name: "move_card",
826
+ description: "Move card to column. Use newOrder for specific positioning.",
827
+ inputSchema: {
828
+ type: "object",
829
+ properties: {
830
+ cardId: { type: "string" },
831
+ targetColumnId: { type: "string" },
832
+ newOrder: { type: "number", description: "Position in target column (0-indexed, default: end)" }
833
+ },
834
+ required: ["cardId", "targetColumnId"]
835
+ }
836
+ },
837
+ {
838
+ name: "add_comment",
839
+ description: "Add comment to card",
840
+ inputSchema: {
841
+ type: "object",
842
+ properties: { cardId: { type: "string" }, content: { type: "string" } },
843
+ required: ["cardId", "content"]
844
+ }
845
+ },
846
+ {
847
+ name: "delete_comment",
848
+ description: "Delete a comment",
849
+ inputSchema: {
850
+ type: "object",
851
+ properties: { commentId: { type: "string" } },
852
+ required: ["commentId"]
853
+ }
854
+ },
182
855
  // CHECKLISTS
183
- { name: "create_checklist", description: "Create a new checklist on a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, title: { type: "string", description: "Checklist title" } }, required: ["cardId", "title"] } },
184
- { name: "update_checklist", description: "Update a checklist title", inputSchema: { type: "object", properties: { checklistId: { type: "string", description: "Checklist ID" }, title: { type: "string", description: "New title" } }, required: ["checklistId", "title"] } },
185
- { name: "delete_checklist", description: "Delete a checklist and all its items", inputSchema: { type: "object", properties: { checklistId: { type: "string", description: "Checklist ID" } }, required: ["checklistId"] } },
186
- { name: "create_checklist_item", description: "Add an item to a checklist", inputSchema: { type: "object", properties: { checklistId: { type: "string", description: "Checklist ID" }, content: { type: "string", description: "Item content" } }, required: ["checklistId", "content"] } },
187
- { name: "update_checklist_item", description: "Update a checklist item (content or completed status)", inputSchema: { type: "object", properties: { itemId: { type: "string", description: "Checklist item ID" }, content: { type: "string", description: "New content" }, completed: { type: "boolean", description: "Completed status" } }, required: ["itemId"] } },
188
- { name: "delete_checklist_item", description: "Delete a checklist item", inputSchema: { type: "object", properties: { itemId: { type: "string", description: "Checklist item ID" } }, required: ["itemId"] } },
189
- { name: "get_branch_name", description: "Generate a GitHub branch name for a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, type: { type: "string", enum: ["feature", "fix", "chore", "refactor", "docs"], description: "Branch type" } }, required: ["cardId"] } },
190
- { name: "search_cards", description: "Search cards by title or description with filters to reduce token usage", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query" }, projectId: { type: "string" }, boardId: { type: "string" }, columnId: { type: "string" }, epicId: { type: "string" }, featureId: { type: "string", description: "Filter by featureId (multi-project feature)" }, 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"] } },
856
+ {
857
+ name: "create_checklist",
858
+ description: "Create checklist on card",
859
+ inputSchema: {
860
+ type: "object",
861
+ properties: { cardId: { type: "string" }, title: { type: "string" } },
862
+ required: ["cardId", "title"]
863
+ }
864
+ },
865
+ {
866
+ name: "update_checklist",
867
+ description: "Update checklist title",
868
+ inputSchema: {
869
+ type: "object",
870
+ properties: {
871
+ checklistId: { type: "string" },
872
+ title: { type: "string" }
873
+ },
874
+ required: ["checklistId", "title"]
875
+ }
876
+ },
877
+ {
878
+ name: "delete_checklist",
879
+ description: "Delete checklist",
880
+ inputSchema: {
881
+ type: "object",
882
+ properties: { checklistId: { type: "string" } },
883
+ required: ["checklistId"]
884
+ }
885
+ },
886
+ {
887
+ name: "create_checklist_item",
888
+ description: "Add checklist item",
889
+ inputSchema: {
890
+ type: "object",
891
+ properties: {
892
+ checklistId: { type: "string" },
893
+ content: { type: "string" }
894
+ },
895
+ required: ["checklistId", "content"]
896
+ }
897
+ },
898
+ {
899
+ name: "update_checklist_item",
900
+ description: "Update checklist item",
901
+ inputSchema: {
902
+ type: "object",
903
+ properties: {
904
+ itemId: { type: "string" },
905
+ content: { type: "string" },
906
+ completed: { type: "boolean" }
907
+ },
908
+ required: ["itemId"]
909
+ }
910
+ },
911
+ {
912
+ name: "delete_checklist_item",
913
+ description: "Delete checklist item",
914
+ inputSchema: {
915
+ type: "object",
916
+ properties: { itemId: { type: "string" } },
917
+ required: ["itemId"]
918
+ }
919
+ },
920
+ {
921
+ name: "get_branch_name",
922
+ description: "Generate GitHub branch name",
923
+ inputSchema: {
924
+ type: "object",
925
+ properties: {
926
+ cardId: { type: "string" },
927
+ type: {
928
+ type: "string",
929
+ enum: ["feature", "fix", "chore", "refactor", "docs"]
930
+ }
931
+ },
932
+ required: ["cardId"]
933
+ }
934
+ },
935
+ {
936
+ name: "search_cards",
937
+ description: "Search cards, projects and boards (default limit:20). Use compact:true for minimal fields",
938
+ inputSchema: {
939
+ type: "object",
940
+ properties: {
941
+ query: { type: "string" },
942
+ projectId: { type: "string" },
943
+ boardId: { type: "string" },
944
+ columnId: { type: "string" },
945
+ epicId: { type: "string" },
946
+ featureId: { type: "string" },
947
+ hasEpic: { type: "boolean" },
948
+ status: { type: "string", enum: ["todo", "in_progress", "done"] },
949
+ tagIds: { type: "array", items: { type: "string" } },
950
+ limit: { type: "number" },
951
+ compact: { type: "boolean" }
952
+ },
953
+ required: ["query"]
954
+ }
955
+ },
956
+ // BULK OPERATIONS
957
+ {
958
+ name: "bulk_create_cards",
959
+ description: "Create multiple cards in 1 call",
960
+ inputSchema: {
961
+ type: "object",
962
+ properties: {
963
+ columnId: { type: "string" },
964
+ cards: {
965
+ type: "array",
966
+ items: {
967
+ type: "object",
968
+ properties: {
969
+ title: { type: "string" },
970
+ description: { type: "string" },
971
+ priority: { type: "string", enum: ["P1", "P2", "P3"] },
972
+ epicId: { type: "string" }
973
+ },
974
+ required: ["title"]
975
+ }
976
+ }
977
+ },
978
+ required: ["columnId", "cards"]
979
+ }
980
+ },
981
+ {
982
+ name: "bulk_create_epic_with_cards",
983
+ description: "Create epic + all its cards in 1 call",
984
+ inputSchema: {
985
+ type: "object",
986
+ properties: {
987
+ epic: {
988
+ type: "object",
989
+ properties: {
990
+ slug: { type: "string" },
991
+ name: { type: "string" },
992
+ description: { type: "string" },
993
+ emoji: { type: "string" },
994
+ color: { type: "string" }
995
+ },
996
+ required: ["slug", "name"]
997
+ },
998
+ columnId: { type: "string" },
999
+ cards: {
1000
+ type: "array",
1001
+ items: {
1002
+ type: "object",
1003
+ properties: {
1004
+ title: { type: "string" },
1005
+ description: { type: "string" },
1006
+ priority: { type: "string", enum: ["P1", "P2", "P3"] }
1007
+ },
1008
+ required: ["title"]
1009
+ }
1010
+ }
1011
+ },
1012
+ required: ["epic", "columnId", "cards"]
1013
+ }
1014
+ },
1015
+ {
1016
+ name: "bulk_create_epic_with_features",
1017
+ description: "Create epic + features + cards across projects in 1 call. Cards auto-prefixed with SLUG{N}-.",
1018
+ inputSchema: {
1019
+ type: "object",
1020
+ properties: {
1021
+ epic: {
1022
+ type: "object",
1023
+ properties: {
1024
+ slug: { type: "string" },
1025
+ name: { type: "string" },
1026
+ description: { type: "string" },
1027
+ emoji: { type: "string" },
1028
+ color: { type: "string" }
1029
+ },
1030
+ required: ["slug", "name"]
1031
+ },
1032
+ features: {
1033
+ type: "array",
1034
+ items: {
1035
+ type: "object",
1036
+ properties: {
1037
+ title: { type: "string" },
1038
+ slug: { type: "string", description: "UPPERCASE slug (auto-generated from title if omitted)" },
1039
+ description: { type: "string" },
1040
+ cards: {
1041
+ type: "array",
1042
+ items: {
1043
+ type: "object",
1044
+ properties: {
1045
+ columnId: { type: "string" },
1046
+ title: { type: "string" },
1047
+ description: { type: "string" },
1048
+ priority: { type: "string", enum: ["P1", "P2", "P3"] }
1049
+ },
1050
+ required: ["columnId", "title"]
1051
+ }
1052
+ }
1053
+ },
1054
+ required: ["title", "cards"]
1055
+ }
1056
+ }
1057
+ },
1058
+ required: ["epic", "features"]
1059
+ }
1060
+ },
1061
+ {
1062
+ name: "bulk_move_cards",
1063
+ description: "Move multiple cards to column in 1 call",
1064
+ inputSchema: {
1065
+ type: "object",
1066
+ properties: {
1067
+ cardIds: { type: "array", items: { type: "string" } },
1068
+ targetColumnId: { type: "string" }
1069
+ },
1070
+ required: ["cardIds", "targetColumnId"]
1071
+ }
1072
+ },
1073
+ {
1074
+ name: "quick_add_cards",
1075
+ description: 'Create cards from multiline text. Format: "- P1: task title" per line',
1076
+ inputSchema: {
1077
+ type: "object",
1078
+ properties: {
1079
+ columnId: { type: "string" },
1080
+ text: {
1081
+ type: "string",
1082
+ description: "Multiline text, 1 card per line"
1083
+ },
1084
+ defaultPriority: { type: "string", enum: ["P1", "P2", "P3"] }
1085
+ },
1086
+ required: ["columnId", "text"]
1087
+ }
1088
+ },
1089
+ {
1090
+ name: "move_cards_by_column",
1091
+ description: "Move ALL cards from one column to another",
1092
+ inputSchema: {
1093
+ type: "object",
1094
+ properties: {
1095
+ sourceColumnId: { type: "string" },
1096
+ targetColumnId: { type: "string" },
1097
+ limit: { type: "number" }
1098
+ },
1099
+ required: ["sourceColumnId", "targetColumnId"]
1100
+ }
1101
+ },
1102
+ // AGGREGATED VIEWS
1103
+ {
1104
+ name: "get_workspace",
1105
+ description: "Get project + all boards + columns in 1 call (no cards)",
1106
+ inputSchema: {
1107
+ type: "object",
1108
+ properties: { projectId: { type: "string" } },
1109
+ required: ["projectId"]
1110
+ }
1111
+ },
1112
+ {
1113
+ name: "get_board_summary",
1114
+ description: "Get board stats only: card counts per column + priority breakdown",
1115
+ inputSchema: {
1116
+ type: "object",
1117
+ properties: { boardId: { type: "string" } },
1118
+ required: ["boardId"]
1119
+ }
1120
+ },
1121
+ {
1122
+ name: "get_epic_summary",
1123
+ description: "Get epic with minimal card info: {id,title,priority,status} + progress stats",
1124
+ inputSchema: {
1125
+ type: "object",
1126
+ properties: { epicId: { type: "string" } },
1127
+ required: ["epicId"]
1128
+ }
1129
+ },
191
1130
  // TAGS
192
- { name: "list_tags", description: "List all available tags", inputSchema: { type: "object", properties: {} } },
193
- { name: "create_tag", description: "Create a new tag", inputSchema: { type: "object", properties: { name: { type: "string", description: "Tag name" }, color: { type: "string", description: "Tag color hex" } }, required: ["name", "color"] } },
194
- { name: "delete_tag", description: "Delete a tag", inputSchema: { type: "object", properties: { tagId: { type: "string", description: "Tag ID" } }, required: ["tagId"] } },
195
- { name: "add_tag_to_card", description: "Add a tag to a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, tagId: { type: "string", description: "Tag ID" } }, required: ["cardId", "tagId"] } },
196
- { name: "remove_tag_from_card", description: "Remove a tag from a card", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, tagId: { type: "string", description: "Tag ID" } }, required: ["cardId", "tagId"] } },
1131
+ {
1132
+ name: "list_tags",
1133
+ description: "List all tags",
1134
+ inputSchema: { type: "object", properties: {} }
1135
+ },
1136
+ {
1137
+ name: "create_tag",
1138
+ description: "Create tag",
1139
+ inputSchema: {
1140
+ type: "object",
1141
+ properties: { name: { type: "string" }, color: { type: "string" } },
1142
+ required: ["name", "color"]
1143
+ }
1144
+ },
1145
+ {
1146
+ name: "delete_tag",
1147
+ description: "Delete tag",
1148
+ inputSchema: {
1149
+ type: "object",
1150
+ properties: { tagId: { type: "string" } },
1151
+ required: ["tagId"]
1152
+ }
1153
+ },
1154
+ {
1155
+ name: "add_tag_to_card",
1156
+ description: "Add tag to card",
1157
+ inputSchema: {
1158
+ type: "object",
1159
+ properties: { cardId: { type: "string" }, tagId: { type: "string" } },
1160
+ required: ["cardId", "tagId"]
1161
+ }
1162
+ },
1163
+ {
1164
+ name: "remove_tag_from_card",
1165
+ description: "Remove tag from card",
1166
+ inputSchema: {
1167
+ type: "object",
1168
+ properties: { cardId: { type: "string" }, tagId: { type: "string" } },
1169
+ required: ["cardId", "tagId"]
1170
+ }
1171
+ },
197
1172
  // EPICS
198
- { name: "list_epics", description: "List all epics with optional filters to reduce token usage", inputSchema: { type: "object", properties: { status: { type: "string" }, includeProgress: { type: "boolean" }, limit: { type: "number" }, compact: { type: "boolean" } } } },
199
- { name: "create_epic", description: "Create a new epic for grouping cards", inputSchema: { type: "object", properties: { slug: { type: "string", description: 'Short unique identifier (e.g., "AUTH", "PERF")' }, name: { type: "string", description: "Epic name" }, description: { type: "string" }, emoji: { type: "string" }, color: { type: "string" }, startDate: { type: "string" }, targetDate: { type: "string" } }, required: ["slug", "name"] } },
200
- { name: "get_epic", description: "Get an epic with all its cards and progress", inputSchema: { type: "object", properties: { epicId: { type: "string", description: "Epic ID or slug" } }, required: ["epicId"] } },
201
- { name: "update_epic", description: "Update an epic", inputSchema: { type: "object", properties: { epicId: { type: "string", description: "Epic ID" }, 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"] } },
202
- { name: "delete_epic", description: "Delete an epic (cards are not deleted, just unlinked)", inputSchema: { type: "object", properties: { epicId: { type: "string", description: "Epic ID" } }, required: ["epicId"] } },
203
- { name: "add_card_to_epic", description: "Add a card to an epic", inputSchema: { type: "object", properties: { epicId: { type: "string", description: "Epic ID or slug" }, cardId: { type: "string", description: "Card ID" } }, required: ["epicId", "cardId"] } },
204
- { name: "remove_card_from_epic", description: "Remove a card from an epic", inputSchema: { type: "object", properties: { epicId: { type: "string", description: "Epic ID" }, cardId: { type: "string", description: "Card ID" } }, required: ["epicId", "cardId"] } },
205
- { name: "get_epic_timeline", description: "Get timeline view of all epics with dates and progress", inputSchema: { type: "object", properties: {} } },
1173
+ {
1174
+ name: "list_epics",
1175
+ description: "List epics (default limit:15)",
1176
+ inputSchema: {
1177
+ type: "object",
1178
+ properties: {
1179
+ status: { type: "string" },
1180
+ includeProgress: { type: "boolean" },
1181
+ limit: { type: "number" },
1182
+ compact: { type: "boolean" }
1183
+ }
1184
+ }
1185
+ },
1186
+ {
1187
+ name: "create_epic",
1188
+ description: "Create epic",
1189
+ inputSchema: {
1190
+ type: "object",
1191
+ properties: {
1192
+ slug: { type: "string" },
1193
+ name: { type: "string" },
1194
+ description: { type: "string" },
1195
+ emoji: { type: "string" },
1196
+ color: { type: "string" },
1197
+ startDate: { type: "string" },
1198
+ targetDate: { type: "string" }
1199
+ },
1200
+ required: ["slug", "name"]
1201
+ }
1202
+ },
1203
+ {
1204
+ name: "get_epic",
1205
+ description: "Get an epic with all its cards, features and progress",
1206
+ inputSchema: {
1207
+ type: "object",
1208
+ properties: { epicId: { type: "string" } },
1209
+ required: ["epicId"]
1210
+ }
1211
+ },
1212
+ {
1213
+ name: "update_epic",
1214
+ description: "Update epic. Use syncDates:true to sync targetDate to all card due dates.",
1215
+ inputSchema: {
1216
+ type: "object",
1217
+ properties: {
1218
+ epicId: { type: "string" },
1219
+ slug: { type: "string" },
1220
+ name: { type: "string" },
1221
+ description: { type: "string" },
1222
+ emoji: { type: "string" },
1223
+ color: { type: "string" },
1224
+ status: { type: "string" },
1225
+ startDate: { type: "string" },
1226
+ targetDate: { type: "string" },
1227
+ syncDates: { type: "boolean", description: "Sync targetDate to all card due dates" }
1228
+ },
1229
+ required: ["epicId"]
1230
+ }
1231
+ },
1232
+ {
1233
+ name: "delete_epic",
1234
+ description: "Delete epic (cards unlinked)",
1235
+ inputSchema: {
1236
+ type: "object",
1237
+ properties: { epicId: { type: "string" } },
1238
+ required: ["epicId"]
1239
+ }
1240
+ },
1241
+ {
1242
+ name: "add_card_to_epic",
1243
+ description: "Add card to epic",
1244
+ inputSchema: {
1245
+ type: "object",
1246
+ properties: { epicId: { type: "string" }, cardId: { type: "string" } },
1247
+ required: ["epicId", "cardId"]
1248
+ }
1249
+ },
1250
+ {
1251
+ name: "remove_card_from_epic",
1252
+ description: "Remove card from epic",
1253
+ inputSchema: {
1254
+ type: "object",
1255
+ properties: { epicId: { type: "string" }, cardId: { type: "string" } },
1256
+ required: ["epicId", "cardId"]
1257
+ }
1258
+ },
1259
+ // FEATURES
1260
+ {
1261
+ name: "list_features",
1262
+ description: "List features. Filter by epicId or slug.",
1263
+ inputSchema: {
1264
+ type: "object",
1265
+ properties: {
1266
+ epicId: { type: "string" },
1267
+ slug: { type: "string", description: "Filter by feature slug (UPPERCASE)" }
1268
+ }
1269
+ }
1270
+ },
1271
+ {
1272
+ name: "get_feature",
1273
+ description: "Get a feature with cards and progress. Accepts featureId or featureSlug (UPPERCASE).",
1274
+ inputSchema: {
1275
+ type: "object",
1276
+ properties: {
1277
+ featureId: { type: "string", description: "Feature ID or slug" },
1278
+ featureSlug: { type: "string", description: "Feature slug (UPPERCASE), alternative to featureId" }
1279
+ }
1280
+ }
1281
+ },
1282
+ {
1283
+ name: "get_active_features",
1284
+ description: "Get features with cards in progress, organized by epic",
1285
+ inputSchema: { type: "object", properties: {} }
1286
+ },
1287
+ {
1288
+ name: "create_feature",
1289
+ description: "Create a new feature (optionally in an epic)",
1290
+ inputSchema: {
1291
+ type: "object",
1292
+ properties: {
1293
+ epicId: { type: "string" },
1294
+ title: { type: "string" },
1295
+ slug: { type: "string" },
1296
+ description: { type: "string" },
1297
+ status: { type: "string", enum: ["planning", "in_progress", "completed", "on_hold"] }
1298
+ },
1299
+ required: ["title"]
1300
+ }
1301
+ },
1302
+ {
1303
+ name: "update_feature",
1304
+ description: "Update a feature",
1305
+ inputSchema: {
1306
+ type: "object",
1307
+ properties: {
1308
+ featureId: { type: "string" },
1309
+ title: { type: "string" },
1310
+ slug: { type: "string" },
1311
+ description: { type: "string" },
1312
+ status: { type: "string", enum: ["planning", "in_progress", "completed", "on_hold"] },
1313
+ order: { type: "number" },
1314
+ epicId: { type: "string", description: "Move to another epic" }
1315
+ },
1316
+ required: ["featureId"]
1317
+ }
1318
+ },
1319
+ {
1320
+ name: "delete_feature",
1321
+ description: "Delete a feature (cards unlinked)",
1322
+ inputSchema: {
1323
+ type: "object",
1324
+ properties: { featureId: { type: "string" } },
1325
+ required: ["featureId"]
1326
+ }
1327
+ },
1328
+ {
1329
+ name: "add_card_to_feature",
1330
+ description: "Add a card to a feature. Accepts featureId or featureSlug.",
1331
+ inputSchema: {
1332
+ type: "object",
1333
+ properties: {
1334
+ cardId: { type: "string" },
1335
+ featureId: { type: "string", description: "Feature ID or slug" },
1336
+ featureSlug: { type: "string", description: "Feature slug (UPPERCASE), alternative to featureId" }
1337
+ },
1338
+ required: ["cardId"]
1339
+ }
1340
+ },
1341
+ {
1342
+ name: "remove_card_from_feature",
1343
+ description: "Remove a card from a feature. Accepts featureId or featureSlug.",
1344
+ inputSchema: {
1345
+ type: "object",
1346
+ properties: {
1347
+ cardId: { type: "string" },
1348
+ featureId: { type: "string", description: "Feature ID or slug" },
1349
+ featureSlug: { type: "string", description: "Feature slug (UPPERCASE), alternative to featureId" }
1350
+ },
1351
+ required: ["cardId"]
1352
+ }
1353
+ },
1354
+ {
1355
+ name: "get_feature_cards",
1356
+ description: "Get all cards in a feature. Accepts featureId or featureSlug.",
1357
+ inputSchema: {
1358
+ type: "object",
1359
+ properties: {
1360
+ featureId: { type: "string", description: "Feature ID or slug" },
1361
+ featureSlug: { type: "string", description: "Feature slug (UPPERCASE), alternative to featureId" }
1362
+ }
1363
+ }
1364
+ },
206
1365
  // CARD LINKS
207
- { name: "link_cards", description: "Create a bidirectional link between two cards (for cross-project features)", inputSchema: { type: "object", properties: { cardId1: { type: "string", description: "First card ID" }, cardId2: { type: "string", description: "Second card ID" }, label: { type: "string", description: 'Link label (e.g., "depends on")' } }, required: ["cardId1", "cardId2"] } },
208
- { name: "unlink_cards", description: "Remove a link between two cards", inputSchema: { type: "object", properties: { cardId1: { type: "string", description: "First card ID" }, cardId2: { type: "string", description: "Second card ID" } }, required: ["cardId1", "cardId2"] } },
209
- { name: "get_linked_cards", description: "Get all cards linked to a specific card (shows cross-project relationships)", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" } }, required: ["cardId"] } },
210
- { name: "get_feature_cards", description: 'Get a card and all its linked cards as a "feature bundle" with progress tracking', inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Starting card ID" } }, required: ["cardId"] } },
1366
+ {
1367
+ name: "link_cards",
1368
+ description: "Link two cards",
1369
+ inputSchema: {
1370
+ type: "object",
1371
+ properties: {
1372
+ cardId1: { type: "string" },
1373
+ cardId2: { type: "string" },
1374
+ label: { type: "string" }
1375
+ },
1376
+ required: ["cardId1", "cardId2"]
1377
+ }
1378
+ },
1379
+ {
1380
+ name: "unlink_cards",
1381
+ description: "Unlink two cards by link ID",
1382
+ inputSchema: {
1383
+ type: "object",
1384
+ properties: {
1385
+ linkId: { type: "string" }
1386
+ },
1387
+ required: ["linkId"]
1388
+ }
1389
+ },
1390
+ {
1391
+ name: "get_linked_cards",
1392
+ description: "Get linked cards",
1393
+ inputSchema: {
1394
+ type: "object",
1395
+ properties: { cardId: { type: "string" } },
1396
+ required: ["cardId"]
1397
+ }
1398
+ },
211
1399
  // GITHUB INTEGRATION
212
- { name: "setup_github_integration", description: "Configure GitHub webhook integration for a project", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, repoOwner: { type: "string", description: "GitHub repo owner" }, repoName: { type: "string", description: "GitHub repo name" }, inProgressColumnName: { type: "string" }, doneColumnName: { type: "string" } }, required: ["projectId", "repoOwner", "repoName"] } },
213
- { name: "get_github_integration", description: "Get GitHub integration settings for a project", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" } }, required: ["projectId"] } },
214
- { name: "update_github_integration", description: "Update GitHub integration settings", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" }, autoMoveOnPush: { type: "boolean" }, autoMoveOnPrMerge: { type: "boolean" }, autoLinkPr: { type: "boolean" }, inProgressColumnName: { type: "string" }, doneColumnName: { type: "string" } }, required: ["projectId"] } },
215
- { name: "remove_github_integration", description: "Remove GitHub integration from a project", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID" } }, required: ["projectId"] } },
216
- { name: "link_card_to_branch", description: "Link a card to a GitHub branch", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, branch: { type: "string", description: "GitHub branch name" } }, required: ["cardId", "branch"] } },
217
- { name: "link_card_to_pr", description: "Link a card to a GitHub Pull Request", inputSchema: { type: "object", properties: { cardId: { type: "string", description: "Card ID" }, prUrl: { type: "string", description: "GitHub PR URL" } }, required: ["cardId", "prUrl"] } },
1400
+ {
1401
+ name: "setup_github_integration",
1402
+ description: "Setup GitHub integration for a project (auto-creates webhook)",
1403
+ inputSchema: {
1404
+ type: "object",
1405
+ properties: {
1406
+ projectId: { type: "string" },
1407
+ repoOwner: { type: "string" },
1408
+ repoName: { type: "string" },
1409
+ inProgressColumnName: { type: "string" },
1410
+ doneColumnName: { type: "string" },
1411
+ autoMoveOnPush: { type: "boolean" },
1412
+ autoMoveOnPrMerge: { type: "boolean" },
1413
+ autoLinkPr: { type: "boolean" }
1414
+ },
1415
+ required: ["projectId", "repoOwner", "repoName"]
1416
+ }
1417
+ },
1418
+ {
1419
+ name: "get_github_integration",
1420
+ description: "Get GitHub integration settings",
1421
+ inputSchema: {
1422
+ type: "object",
1423
+ properties: { projectId: { type: "string" } },
1424
+ required: ["projectId"]
1425
+ }
1426
+ },
1427
+ {
1428
+ name: "update_github_integration",
1429
+ description: "Update GitHub integration settings",
1430
+ inputSchema: {
1431
+ type: "object",
1432
+ properties: {
1433
+ projectId: { type: "string" },
1434
+ repoOwner: { type: "string" },
1435
+ repoName: { type: "string" },
1436
+ autoMoveOnPush: { type: "boolean" },
1437
+ autoMoveOnPrMerge: { type: "boolean" },
1438
+ autoLinkPr: { type: "boolean" },
1439
+ inProgressColumnName: { type: "string" },
1440
+ doneColumnName: { type: "string" }
1441
+ },
1442
+ required: ["projectId"]
1443
+ }
1444
+ },
1445
+ {
1446
+ name: "remove_github_integration",
1447
+ description: "Remove GitHub integration",
1448
+ inputSchema: {
1449
+ type: "object",
1450
+ properties: { projectId: { type: "string" } },
1451
+ required: ["projectId"]
1452
+ }
1453
+ },
1454
+ {
1455
+ name: "link_card_to_branch",
1456
+ description: "Link card to branch",
1457
+ inputSchema: {
1458
+ type: "object",
1459
+ properties: { cardId: { type: "string" }, branch: { type: "string" } },
1460
+ required: ["cardId", "branch"]
1461
+ }
1462
+ },
1463
+ {
1464
+ name: "link_card_to_pr",
1465
+ description: "Link card to PR",
1466
+ inputSchema: {
1467
+ type: "object",
1468
+ properties: { cardId: { type: "string" }, prUrl: { type: "string" } },
1469
+ required: ["cardId", "prUrl"]
1470
+ }
1471
+ },
218
1472
  // GITHUB API
219
- { name: "github_list_repos", description: "List GitHub repositories accessible by the authenticated user", inputSchema: { type: "object", properties: { userId: { type: "string", description: "User ID (from session)" }, type: { type: "string", enum: ["all", "owner", "member"] } }, required: ["userId"] } },
220
- { name: "github_create_branch", description: "Create a new branch on a GitHub repository", inputSchema: { type: "object", properties: { userId: { type: "string", description: "User ID" }, owner: { type: "string", description: "Repository owner" }, repo: { type: "string", description: "Repository name" }, branchName: { type: "string", description: "New branch name" }, sourceBranch: { type: "string", description: "Source branch (default: main)" } }, required: ["userId", "owner", "repo", "branchName"] } },
221
- { name: "github_create_pr", description: "Create a pull request on a GitHub repository", inputSchema: { type: "object", properties: { userId: { type: "string", description: "User ID" }, owner: { type: "string", description: "Repository owner" }, repo: { type: "string", description: "Repository name" }, title: { type: "string", description: "PR title" }, head: { type: "string", description: "Branch containing changes" }, base: { type: "string", description: "Target branch" }, body: { type: "string", description: "PR description" } }, required: ["userId", "owner", "repo", "title", "head"] } },
222
- { name: "github_auto_setup_webhook", description: "Automatically setup GitHub webhook for a Kanban project (requires user auth)", inputSchema: { type: "object", properties: { userId: { type: "string", description: "User ID" }, projectId: { type: "string", description: "Kanban project ID" }, owner: { type: "string", description: "Repository owner" }, repo: { type: "string", description: "Repository name" } }, required: ["userId", "projectId", "owner", "repo"] } }
1473
+ {
1474
+ name: "github_list_repos",
1475
+ description: "List user repos",
1476
+ inputSchema: {
1477
+ type: "object",
1478
+ properties: {
1479
+ userId: { type: "string" },
1480
+ type: { type: "string", enum: ["all", "owner", "member"] }
1481
+ },
1482
+ required: ["userId"]
1483
+ }
1484
+ },
1485
+ {
1486
+ name: "github_create_branch",
1487
+ description: "Create branch",
1488
+ inputSchema: {
1489
+ type: "object",
1490
+ properties: {
1491
+ userId: { type: "string" },
1492
+ owner: { type: "string" },
1493
+ repo: { type: "string" },
1494
+ branchName: { type: "string" },
1495
+ sourceBranch: { type: "string" }
1496
+ },
1497
+ required: ["userId", "owner", "repo", "branchName"]
1498
+ }
1499
+ },
1500
+ {
1501
+ name: "github_create_pr",
1502
+ description: "Create PR",
1503
+ inputSchema: {
1504
+ type: "object",
1505
+ properties: {
1506
+ userId: { type: "string" },
1507
+ owner: { type: "string" },
1508
+ repo: { type: "string" },
1509
+ title: { type: "string" },
1510
+ head: { type: "string" },
1511
+ base: { type: "string" },
1512
+ body: { type: "string" }
1513
+ },
1514
+ required: ["userId", "owner", "repo", "title", "head"]
1515
+ }
1516
+ },
1517
+ // IDEAS
1518
+ {
1519
+ name: "list_ideas",
1520
+ description: "List ideas (canvas notes). Filter by status: active, archived, all",
1521
+ inputSchema: {
1522
+ type: "object",
1523
+ properties: {
1524
+ status: { type: "string", enum: ["active", "archived", "all"] },
1525
+ filter: { type: "string", enum: ["week"], description: "Filter by recent (week)" }
1526
+ }
1527
+ }
1528
+ },
1529
+ {
1530
+ name: "get_idea",
1531
+ description: "Get an idea with its tags",
1532
+ inputSchema: {
1533
+ type: "object",
1534
+ properties: { ideaId: { type: "string" } },
1535
+ required: ["ideaId"]
1536
+ }
1537
+ },
1538
+ {
1539
+ name: "create_idea",
1540
+ description: "Create a new idea (canvas note)",
1541
+ inputSchema: {
1542
+ type: "object",
1543
+ properties: {
1544
+ title: { type: "string" },
1545
+ description: { type: "string" },
1546
+ color: { type: "string" },
1547
+ posX: { type: "number" },
1548
+ posY: { type: "number" },
1549
+ tagIds: { type: "array", items: { type: "string" } }
1550
+ },
1551
+ required: ["title"]
1552
+ }
1553
+ },
1554
+ {
1555
+ name: "update_idea",
1556
+ description: "Update an idea",
1557
+ inputSchema: {
1558
+ type: "object",
1559
+ properties: {
1560
+ ideaId: { type: "string" },
1561
+ title: { type: "string" },
1562
+ description: { type: "string" },
1563
+ status: { type: "string", enum: ["active", "archived"] },
1564
+ color: { type: "string" },
1565
+ posX: { type: "number" },
1566
+ posY: { type: "number" },
1567
+ tagIds: { type: "array", items: { type: "string" } }
1568
+ },
1569
+ required: ["ideaId"]
1570
+ }
1571
+ },
1572
+ {
1573
+ name: "delete_idea",
1574
+ description: "Delete an idea",
1575
+ inputSchema: {
1576
+ type: "object",
1577
+ properties: { ideaId: { type: "string" } },
1578
+ required: ["ideaId"]
1579
+ }
1580
+ },
1581
+ {
1582
+ name: "convert_idea_to_card",
1583
+ description: "Convert an idea to a card in a specific board/column",
1584
+ inputSchema: {
1585
+ type: "object",
1586
+ properties: {
1587
+ ideaId: { type: "string" },
1588
+ boardId: { type: "string" },
1589
+ columnId: { type: "string" }
1590
+ },
1591
+ required: ["ideaId", "boardId", "columnId"]
1592
+ }
1593
+ },
1594
+ // TIME TRACKING
1595
+ {
1596
+ name: "get_time_tracking",
1597
+ description: "Get time tracking sessions with project breakdown",
1598
+ inputSchema: {
1599
+ type: "object",
1600
+ properties: {
1601
+ startDate: { type: "string", description: "ISO date (default: 7 days ago)" },
1602
+ endDate: { type: "string", description: "ISO date (default: now)" },
1603
+ projectId: { type: "string" }
1604
+ }
1605
+ }
1606
+ },
1607
+ {
1608
+ name: "log_activity",
1609
+ description: "Log activity to create/update time session",
1610
+ inputSchema: {
1611
+ type: "object",
1612
+ properties: {
1613
+ projectId: { type: "string" },
1614
+ cardId: { type: "string" },
1615
+ activityType: { type: "string" }
1616
+ }
1617
+ }
1618
+ },
1619
+ {
1620
+ name: "end_time_session",
1621
+ description: "End the current active time tracking session",
1622
+ inputSchema: { type: "object", properties: {} }
1623
+ },
1624
+ // DAILY SUMMARY
1625
+ {
1626
+ name: "get_daily_summary",
1627
+ description: "Get daily report: working on, blocked, completed today, weekly stats",
1628
+ inputSchema: { type: "object", properties: {} }
1629
+ },
1630
+ // RETROSPECTIVE
1631
+ {
1632
+ name: "get_retrospective",
1633
+ description: "Get retrospective data: completed, created, stale, blocked cards + movements",
1634
+ inputSchema: {
1635
+ type: "object",
1636
+ properties: {
1637
+ days: { type: "number", description: "Period in days (default: 7)" }
1638
+ }
1639
+ }
1640
+ },
1641
+ // EXPORT
1642
+ {
1643
+ name: "export_board",
1644
+ description: "Export a board as JSON (columns, cards, tags, comments)",
1645
+ inputSchema: {
1646
+ type: "object",
1647
+ properties: { boardId: { type: "string" } },
1648
+ required: ["boardId"]
1649
+ }
1650
+ },
1651
+ {
1652
+ name: "export_project",
1653
+ description: "Export a project as JSON (boards, columns, cards)",
1654
+ inputSchema: {
1655
+ type: "object",
1656
+ properties: { projectId: { type: "string" } },
1657
+ required: ["projectId"]
1658
+ }
1659
+ }
223
1660
  ]
224
1661
  }));
225
1662
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -241,7 +1678,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
241
1678
  result = await kanbanApi.deleteFolder(args.folderId);
242
1679
  break;
243
1680
  case "move_project_to_folder":
244
- result = await kanbanApi.moveProjectToFolder(args.projectId, args.folderId);
1681
+ result = await kanbanApi.moveProjectToFolder(
1682
+ args.projectId,
1683
+ args.folderId
1684
+ );
1685
+ break;
1686
+ case "reorder_folders":
1687
+ result = await kanbanApi.reorderFolders(
1688
+ args.folderId,
1689
+ args.targetFolderId
1690
+ );
245
1691
  break;
246
1692
  // PROJECTS
247
1693
  case "list_projects":
@@ -251,7 +1697,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
251
1697
  result = await kanbanApi.createProject(args);
252
1698
  break;
253
1699
  case "get_project":
254
- result = await kanbanApi.getProject(args.projectId);
1700
+ result = await kanbanApi.getProject(args.projectId, args);
255
1701
  break;
256
1702
  case "update_project":
257
1703
  result = await kanbanApi.updateProject(args.projectId, args);
@@ -259,9 +1705,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
259
1705
  case "delete_project":
260
1706
  result = await kanbanApi.deleteProject(args.projectId);
261
1707
  break;
1708
+ case "reorder_projects":
1709
+ result = await kanbanApi.reorderProjects(
1710
+ args.projectId,
1711
+ args.targetProjectId,
1712
+ args.folderId
1713
+ );
1714
+ break;
262
1715
  // BOARDS
263
1716
  case "list_boards":
264
- result = await kanbanApi.listBoards(args.projectId, args);
1717
+ result = await kanbanApi.listBoards(args);
265
1718
  break;
266
1719
  case "create_board":
267
1720
  result = await kanbanApi.createBoard(args);
@@ -285,7 +1738,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
285
1738
  case "delete_column":
286
1739
  result = await kanbanApi.deleteColumn(args.columnId);
287
1740
  break;
1741
+ case "reorder_columns":
1742
+ result = await kanbanApi.reorderColumns(args.columns);
1743
+ break;
288
1744
  // CARDS
1745
+ case "get_card":
1746
+ result = await kanbanApi.getCard(args.cardId);
1747
+ break;
289
1748
  case "create_card":
290
1749
  result = await kanbanApi.createCard(args);
291
1750
  break;
@@ -296,36 +1755,91 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
296
1755
  result = await kanbanApi.deleteCard(args.cardId);
297
1756
  break;
298
1757
  case "move_card":
299
- result = await kanbanApi.moveCard(args.cardId, args.targetColumnId);
1758
+ result = await kanbanApi.moveCard(args.cardId, args.targetColumnId, args.newOrder);
1759
+ break;
1760
+ case "archive_card":
1761
+ result = await kanbanApi.archiveCard(args.cardId);
1762
+ break;
1763
+ case "unarchive_card":
1764
+ result = await kanbanApi.unarchiveCard(args.cardId);
1765
+ break;
1766
+ case "list_archived_cards":
1767
+ result = await kanbanApi.listArchivedCards(args.boardId);
300
1768
  break;
301
1769
  case "add_comment":
302
1770
  result = await kanbanApi.addComment(args.cardId, args.content);
303
1771
  break;
1772
+ case "delete_comment":
1773
+ result = await kanbanApi.deleteComment(args.commentId);
1774
+ break;
304
1775
  // CHECKLISTS
305
1776
  case "create_checklist":
306
- result = await kanbanApi.createChecklist({ cardId: args.cardId, title: args.title });
1777
+ result = await kanbanApi.createChecklist({
1778
+ cardId: args.cardId,
1779
+ title: args.title
1780
+ });
307
1781
  break;
308
1782
  case "update_checklist":
309
- result = await kanbanApi.updateChecklist(args.checklistId, { title: args.title });
1783
+ result = await kanbanApi.updateChecklist(args.checklistId, {
1784
+ title: args.title
1785
+ });
310
1786
  break;
311
1787
  case "delete_checklist":
312
1788
  result = await kanbanApi.deleteChecklist(args.checklistId);
313
1789
  break;
314
1790
  case "create_checklist_item":
315
- result = await kanbanApi.createChecklistItem({ checklistId: args.checklistId, content: args.content });
1791
+ result = await kanbanApi.createChecklistItem({
1792
+ checklistId: args.checklistId,
1793
+ content: args.content
1794
+ });
316
1795
  break;
317
1796
  case "update_checklist_item":
318
- result = await kanbanApi.updateChecklistItem(args.itemId, { content: args.content, completed: args.completed });
1797
+ result = await kanbanApi.updateChecklistItem(args.itemId, {
1798
+ content: args.content,
1799
+ completed: args.completed
1800
+ });
319
1801
  break;
320
1802
  case "delete_checklist_item":
321
1803
  result = await kanbanApi.deleteChecklistItem(args.itemId);
322
1804
  break;
323
1805
  case "get_branch_name":
324
- result = await kanbanApi.getBranchName(args.cardId, args.type || "feature");
1806
+ result = await kanbanApi.getBranchName(
1807
+ args.cardId,
1808
+ args.type || "feature"
1809
+ );
325
1810
  break;
326
1811
  case "search_cards":
327
1812
  result = await kanbanApi.searchCards(args);
328
1813
  break;
1814
+ // BULK OPERATIONS
1815
+ case "bulk_create_cards":
1816
+ result = await kanbanApi.bulkCreateCards(args);
1817
+ break;
1818
+ case "bulk_create_epic_with_cards":
1819
+ result = await kanbanApi.bulkCreateEpicWithCards(args);
1820
+ break;
1821
+ case "bulk_create_epic_with_features":
1822
+ result = await kanbanApi.bulkCreateEpicWithFeatures(args);
1823
+ break;
1824
+ case "bulk_move_cards":
1825
+ result = await kanbanApi.bulkMoveCards(args);
1826
+ break;
1827
+ case "quick_add_cards":
1828
+ result = await kanbanApi.quickAddCards(args);
1829
+ break;
1830
+ case "move_cards_by_column":
1831
+ result = await kanbanApi.moveCardsByColumn(args);
1832
+ break;
1833
+ // AGGREGATED VIEWS
1834
+ case "get_workspace":
1835
+ result = await kanbanApi.getWorkspace(args.projectId);
1836
+ break;
1837
+ case "get_board_summary":
1838
+ result = await kanbanApi.getBoardSummary(args.boardId);
1839
+ break;
1840
+ case "get_epic_summary":
1841
+ result = await kanbanApi.getEpicSummary(args.epicId);
1842
+ break;
329
1843
  // TAGS
330
1844
  case "list_tags":
331
1845
  result = await kanbanApi.listTags();
@@ -364,22 +1878,75 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
364
1878
  case "remove_card_from_epic":
365
1879
  result = await kanbanApi.removeCardFromEpic(args.epicId, args.cardId);
366
1880
  break;
367
- case "get_epic_timeline":
368
- result = await kanbanApi.getEpicTimeline();
1881
+ // FEATURES
1882
+ case "list_features": {
1883
+ const features = await kanbanApi.listFeatures(args.epicId);
1884
+ const slugFilter = args.slug;
1885
+ result = slugFilter ? (Array.isArray(features) ? features : []).filter((f) => f.slug === slugFilter.toUpperCase()) : features;
1886
+ break;
1887
+ }
1888
+ case "get_feature": {
1889
+ const fId = args.featureId || args.featureSlug;
1890
+ if (!fId) throw new Error("Either featureId or featureSlug is required");
1891
+ result = await kanbanApi.getFeature(fId);
1892
+ break;
1893
+ }
1894
+ case "get_active_features":
1895
+ result = await kanbanApi.getActiveFeatures();
369
1896
  break;
1897
+ case "create_feature":
1898
+ result = await kanbanApi.createFeature(args);
1899
+ break;
1900
+ case "update_feature":
1901
+ result = await kanbanApi.updateFeature(args.featureId, args);
1902
+ break;
1903
+ case "delete_feature":
1904
+ result = await kanbanApi.deleteFeature(args.featureId);
1905
+ break;
1906
+ case "add_card_to_feature": {
1907
+ let addFeatureId = args.featureId || args.featureSlug;
1908
+ if (!addFeatureId) throw new Error("Either featureId or featureSlug is required");
1909
+ if (args.featureSlug && !args.featureId) {
1910
+ const resolved = await kanbanApi.getFeature(addFeatureId);
1911
+ addFeatureId = resolved.id;
1912
+ }
1913
+ result = await kanbanApi.addCardToFeature(addFeatureId, args.cardId);
1914
+ break;
1915
+ }
1916
+ case "remove_card_from_feature": {
1917
+ let removeFeatureId = args.featureId || args.featureSlug;
1918
+ if (!removeFeatureId) throw new Error("Either featureId or featureSlug is required");
1919
+ if (args.featureSlug && !args.featureId) {
1920
+ const resolved = await kanbanApi.getFeature(removeFeatureId);
1921
+ removeFeatureId = resolved.id;
1922
+ }
1923
+ result = await kanbanApi.removeCardFromFeature(removeFeatureId, args.cardId);
1924
+ break;
1925
+ }
1926
+ case "get_feature_cards": {
1927
+ let cardsFeatureId = args.featureId || args.featureSlug;
1928
+ if (!cardsFeatureId) throw new Error("Either featureId or featureSlug is required");
1929
+ if (args.featureSlug && !args.featureId) {
1930
+ const resolved = await kanbanApi.getFeature(cardsFeatureId);
1931
+ cardsFeatureId = resolved.id;
1932
+ }
1933
+ result = await kanbanApi.getFeatureCards(cardsFeatureId);
1934
+ break;
1935
+ }
370
1936
  // CARD LINKS
371
1937
  case "link_cards":
372
- result = await kanbanApi.linkCards(args.cardId1, args.cardId2, args.label);
1938
+ result = await kanbanApi.linkCards(
1939
+ args.cardId1,
1940
+ args.cardId2,
1941
+ args.label
1942
+ );
373
1943
  break;
374
1944
  case "unlink_cards":
375
- result = await kanbanApi.unlinkCards(args.cardId1, args.cardId2);
1945
+ result = await kanbanApi.unlinkCards(args.linkId);
376
1946
  break;
377
1947
  case "get_linked_cards":
378
1948
  result = await kanbanApi.getLinkedCards(args.cardId);
379
1949
  break;
380
- case "get_feature_cards":
381
- result = await kanbanApi.getFeatureCards(args.cardId);
382
- break;
383
1950
  // GITHUB INTEGRATION
384
1951
  case "setup_github_integration":
385
1952
  result = await kanbanApi.setupGithubIntegration(args);
@@ -409,17 +1976,63 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
409
1976
  case "github_create_pr":
410
1977
  result = await kanbanApi.githubCreatePr(args);
411
1978
  break;
412
- case "github_auto_setup_webhook":
413
- result = await kanbanApi.githubAutoSetupWebhook(args);
1979
+ // IDEAS
1980
+ case "list_ideas":
1981
+ result = await kanbanApi.listIdeas(args);
1982
+ break;
1983
+ case "get_idea":
1984
+ result = await kanbanApi.getIdea(args.ideaId);
1985
+ break;
1986
+ case "create_idea":
1987
+ result = await kanbanApi.createIdea(args);
1988
+ break;
1989
+ case "update_idea":
1990
+ result = await kanbanApi.updateIdea(args.ideaId, args);
1991
+ break;
1992
+ case "delete_idea":
1993
+ result = await kanbanApi.deleteIdea(args.ideaId);
1994
+ break;
1995
+ case "convert_idea_to_card":
1996
+ result = await kanbanApi.convertIdeaToCard(args.ideaId, {
1997
+ boardId: args.boardId,
1998
+ columnId: args.columnId
1999
+ });
2000
+ break;
2001
+ // TIME TRACKING
2002
+ case "get_time_tracking":
2003
+ result = await kanbanApi.getTimeTracking(args);
2004
+ break;
2005
+ case "log_activity":
2006
+ result = await kanbanApi.logActivity(args);
2007
+ break;
2008
+ case "end_time_session":
2009
+ result = await kanbanApi.endTimeSession();
2010
+ break;
2011
+ // DAILY SUMMARY
2012
+ case "get_daily_summary":
2013
+ result = await kanbanApi.getDailySummary();
2014
+ break;
2015
+ // RETROSPECTIVE
2016
+ case "get_retrospective":
2017
+ result = await kanbanApi.getRetrospective(args.days);
2018
+ break;
2019
+ // EXPORT
2020
+ case "export_board":
2021
+ result = await kanbanApi.exportBoard(args.boardId);
2022
+ break;
2023
+ case "export_project":
2024
+ result = await kanbanApi.exportProject(args.projectId);
414
2025
  break;
415
2026
  default:
416
2027
  throw new Error(`Unknown tool: ${name}`);
417
2028
  }
418
2029
  return {
419
- content: [{
420
- type: "text",
421
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
422
- }]
2030
+ content: [
2031
+ {
2032
+ type: "text",
2033
+ text: typeof result === "string" ? result : JSON.stringify(result)
2034
+ }
2035
+ ]
423
2036
  };
424
2037
  } catch (error) {
425
2038
  const message = error instanceof Error ? error.message : "Unknown error";