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 +1733 -120
- package/package.json +1 -1
- package/{README.md → readme.md} +13 -4
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}`, {
|
|
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
|
-
|
|
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) =>
|
|
47
|
-
|
|
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: (
|
|
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
|
-
|
|
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)
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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
|
-
|
|
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)
|
|
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)
|
|
93
|
-
|
|
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", {
|
|
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}`, {
|
|
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
|
|
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)
|
|
118
|
-
|
|
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`, {
|
|
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
|
-
|
|
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", {
|
|
132
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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", {
|
|
146
|
-
|
|
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.
|
|
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
|
-
{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
{
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
{
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
{
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
{
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
{
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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(
|
|
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
|
|
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({
|
|
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, {
|
|
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({
|
|
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, {
|
|
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(
|
|
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
|
-
|
|
368
|
-
|
|
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(
|
|
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.
|
|
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
|
-
|
|
413
|
-
|
|
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
|
-
|
|
421
|
-
|
|
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";
|