kaneo-mcp 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kaneo-mcp.js +2 -0
- package/dist/index.js +1625 -0
- package/package.json +33 -0
- package/src/client.ts +443 -0
- package/src/index.ts +1350 -0
- package/src/types.ts +104 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +7 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1625 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import {
|
|
5
|
+
CallToolRequestSchema,
|
|
6
|
+
ListToolsRequestSchema
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
|
|
9
|
+
// src/client.ts
|
|
10
|
+
var KaneoClient = class {
|
|
11
|
+
baseUrl;
|
|
12
|
+
token;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
15
|
+
if (!this.baseUrl.endsWith("/api")) {
|
|
16
|
+
this.baseUrl = `${this.baseUrl}/api`;
|
|
17
|
+
}
|
|
18
|
+
this.token = config.token;
|
|
19
|
+
}
|
|
20
|
+
async request(path, options = {}) {
|
|
21
|
+
const url = `${this.baseUrl}${path}`;
|
|
22
|
+
const headers = {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
Authorization: `Bearer ${this.token}`,
|
|
25
|
+
...options.headers
|
|
26
|
+
};
|
|
27
|
+
const response = await fetch(url, {
|
|
28
|
+
...options,
|
|
29
|
+
headers
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const error = await response.text();
|
|
33
|
+
throw new Error(`Kaneo API error: ${response.status} ${error}`);
|
|
34
|
+
}
|
|
35
|
+
return response.json();
|
|
36
|
+
}
|
|
37
|
+
// Health
|
|
38
|
+
async health() {
|
|
39
|
+
return this.request("/health");
|
|
40
|
+
}
|
|
41
|
+
// Config
|
|
42
|
+
async getConfig() {
|
|
43
|
+
return this.request("/config");
|
|
44
|
+
}
|
|
45
|
+
// Projects
|
|
46
|
+
async listProjects(workspaceId) {
|
|
47
|
+
return this.request(
|
|
48
|
+
`/project?workspaceId=${encodeURIComponent(workspaceId)}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
async createProject(data) {
|
|
52
|
+
return this.request("/project", {
|
|
53
|
+
method: "POST",
|
|
54
|
+
body: JSON.stringify(data)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async getProject(id) {
|
|
58
|
+
return this.request(`/project/${id}`);
|
|
59
|
+
}
|
|
60
|
+
async updateProject(id, data) {
|
|
61
|
+
return this.request(`/project/${id}`, {
|
|
62
|
+
method: "PUT",
|
|
63
|
+
body: JSON.stringify(data)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async deleteProject(id) {
|
|
67
|
+
return this.request(`/project/${id}`, {
|
|
68
|
+
method: "DELETE"
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async archiveProject(id) {
|
|
72
|
+
return this.request(`/project/${id}/archive`, {
|
|
73
|
+
method: "PUT"
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async unarchiveProject(id) {
|
|
77
|
+
return this.request(`/project/${id}/unarchive`, {
|
|
78
|
+
method: "PUT"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Tasks
|
|
82
|
+
async listTasks(projectId, params) {
|
|
83
|
+
const query = new URLSearchParams();
|
|
84
|
+
if (params?.status) query.set("status", params.status);
|
|
85
|
+
if (params?.priority) query.set("priority", params.priority);
|
|
86
|
+
if (params?.assigneeId) query.set("assigneeId", params.assigneeId);
|
|
87
|
+
const queryString = query.toString();
|
|
88
|
+
return this.request(
|
|
89
|
+
`/task/tasks/${projectId}${queryString ? `?${queryString}` : ""}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
async createTask(projectId, data) {
|
|
93
|
+
return this.request(`/task/${projectId}`, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
body: JSON.stringify(data)
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async getTask(id) {
|
|
99
|
+
return this.request(`/task/${id}`);
|
|
100
|
+
}
|
|
101
|
+
async updateTask(id, data) {
|
|
102
|
+
return this.request(`/task/${id}`, {
|
|
103
|
+
method: "PUT",
|
|
104
|
+
body: JSON.stringify(data)
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async deleteTask(id) {
|
|
108
|
+
return this.request(`/task/${id}`, {
|
|
109
|
+
method: "DELETE"
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async updateTaskStatus(id, status) {
|
|
113
|
+
return this.request(`/task/status/${id}`, {
|
|
114
|
+
method: "PUT",
|
|
115
|
+
body: JSON.stringify({ status })
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async updateTaskPriority(id, priority) {
|
|
119
|
+
return this.request(`/task/priority/${id}`, {
|
|
120
|
+
method: "PUT",
|
|
121
|
+
body: JSON.stringify({ priority })
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async updateTaskAssignee(id, userId) {
|
|
125
|
+
return this.request(`/task/assignee/${id}`, {
|
|
126
|
+
method: "PUT",
|
|
127
|
+
body: JSON.stringify({ userId })
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
async updateTaskDueDate(id, dueDate) {
|
|
131
|
+
return this.request(`/task/due-date/${id}`, {
|
|
132
|
+
method: "PUT",
|
|
133
|
+
body: JSON.stringify({ dueDate })
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
async updateTaskTitle(id, title) {
|
|
137
|
+
return this.request(`/task/title/${id}`, {
|
|
138
|
+
method: "PUT",
|
|
139
|
+
body: JSON.stringify({ title })
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
async updateTaskDescription(id, description) {
|
|
143
|
+
return this.request(`/task/description/${id}`, {
|
|
144
|
+
method: "PUT",
|
|
145
|
+
body: JSON.stringify({ description })
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async moveTask(id, projectId) {
|
|
149
|
+
return this.request(`/task/move/${id}`, {
|
|
150
|
+
method: "PUT",
|
|
151
|
+
body: JSON.stringify({ projectId })
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Columns
|
|
155
|
+
async listColumns(projectId) {
|
|
156
|
+
return this.request(`/column/${projectId}`);
|
|
157
|
+
}
|
|
158
|
+
async createColumn(projectId, data) {
|
|
159
|
+
return this.request(`/column/${projectId}`, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
body: JSON.stringify(data)
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
async updateColumn(id, data) {
|
|
165
|
+
return this.request(`/column/${id}`, {
|
|
166
|
+
method: "PUT",
|
|
167
|
+
body: JSON.stringify(data)
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async deleteColumn(id) {
|
|
171
|
+
return this.request(`/column/${id}`, {
|
|
172
|
+
method: "DELETE"
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async reorderColumns(projectId, columnIds) {
|
|
176
|
+
return this.request(
|
|
177
|
+
`/column/reorder/${projectId}`,
|
|
178
|
+
{
|
|
179
|
+
method: "PUT",
|
|
180
|
+
body: JSON.stringify({ columnIds })
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
// Comments
|
|
185
|
+
async listComments(taskId) {
|
|
186
|
+
return this.request(`/comment/${taskId}`);
|
|
187
|
+
}
|
|
188
|
+
async createComment(taskId, content) {
|
|
189
|
+
return this.request(`/comment/${taskId}`, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
body: JSON.stringify({ content })
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
async updateComment(id, content) {
|
|
195
|
+
return this.request(`/comment/${id}`, {
|
|
196
|
+
method: "PUT",
|
|
197
|
+
body: JSON.stringify({ content })
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
async deleteComment(id) {
|
|
201
|
+
return this.request(`/comment/${id}`, {
|
|
202
|
+
method: "DELETE"
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// Labels
|
|
206
|
+
async listLabelsForTask(taskId) {
|
|
207
|
+
return this.request(`/label/task/${taskId}`);
|
|
208
|
+
}
|
|
209
|
+
async listWorkspaceLabels(workspaceId) {
|
|
210
|
+
return this.request(
|
|
211
|
+
`/label/workspace/${workspaceId}`
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
async createLabel(data) {
|
|
215
|
+
return this.request("/label", {
|
|
216
|
+
method: "POST",
|
|
217
|
+
body: JSON.stringify(data)
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
async getLabel(id) {
|
|
221
|
+
return this.request(`/label/${id}`);
|
|
222
|
+
}
|
|
223
|
+
async updateLabel(id, data) {
|
|
224
|
+
return this.request(`/label/${id}`, {
|
|
225
|
+
method: "PUT",
|
|
226
|
+
body: JSON.stringify(data)
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
async deleteLabel(id) {
|
|
230
|
+
return this.request(`/label/${id}`, {
|
|
231
|
+
method: "DELETE"
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
async attachLabelToTask(labelId, taskId) {
|
|
235
|
+
return this.request(`/label/${labelId}/task`, {
|
|
236
|
+
method: "PUT",
|
|
237
|
+
body: JSON.stringify({ taskId })
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
async detachLabelFromTask(labelId, taskId) {
|
|
241
|
+
return this.request(`/label/${labelId}/task`, {
|
|
242
|
+
method: "DELETE",
|
|
243
|
+
body: JSON.stringify({ taskId })
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// Time Entries
|
|
247
|
+
async listTimeEntries(taskId) {
|
|
248
|
+
return this.request(
|
|
249
|
+
`/time-entry/task/${taskId}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
async getTimeEntry(id) {
|
|
253
|
+
return this.request(`/time-entry/${id}`);
|
|
254
|
+
}
|
|
255
|
+
async createTimeEntry(data) {
|
|
256
|
+
return this.request("/time-entry", {
|
|
257
|
+
method: "POST",
|
|
258
|
+
body: JSON.stringify(data)
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
async updateTimeEntry(id, data) {
|
|
262
|
+
return this.request(`/time-entry/${id}`, {
|
|
263
|
+
method: "PUT",
|
|
264
|
+
body: JSON.stringify(data)
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// Task Relations
|
|
268
|
+
async listTaskRelations(taskId) {
|
|
269
|
+
return this.request(`/task-relation/${taskId}`);
|
|
270
|
+
}
|
|
271
|
+
async createTaskRelation(data) {
|
|
272
|
+
return this.request("/task-relation", {
|
|
273
|
+
method: "POST",
|
|
274
|
+
body: JSON.stringify(data)
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
async deleteTaskRelation(id) {
|
|
278
|
+
return this.request(`/task-relation/${id}`, {
|
|
279
|
+
method: "DELETE"
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Notifications
|
|
283
|
+
async listNotifications() {
|
|
284
|
+
return this.request("/notification");
|
|
285
|
+
}
|
|
286
|
+
async markNotificationRead(id) {
|
|
287
|
+
return this.request(`/notification/${id}/read`, {
|
|
288
|
+
method: "PATCH"
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
async markAllNotificationsRead() {
|
|
292
|
+
return this.request("/notification/read-all", {
|
|
293
|
+
method: "PATCH"
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async clearAllNotifications() {
|
|
297
|
+
return this.request("/notification/clear-all", {
|
|
298
|
+
method: "DELETE"
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
// Workspace
|
|
302
|
+
async listWorkspaceMembers(workspaceId) {
|
|
303
|
+
return this.request(
|
|
304
|
+
`/workspace/${workspaceId}/members`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
// Search
|
|
308
|
+
async search(query, type) {
|
|
309
|
+
const params = new URLSearchParams({ q: query });
|
|
310
|
+
if (type) params.set("type", type);
|
|
311
|
+
return this.request(`/search?${params.toString()}`);
|
|
312
|
+
}
|
|
313
|
+
// Activity
|
|
314
|
+
async listActivities(taskId) {
|
|
315
|
+
return this.request(`/activity/${taskId}`);
|
|
316
|
+
}
|
|
317
|
+
// Invitations
|
|
318
|
+
async listPendingInvitations() {
|
|
319
|
+
return this.request("/invitation/pending");
|
|
320
|
+
}
|
|
321
|
+
async getInvitation(id) {
|
|
322
|
+
return this.request(`/invitation/${id}`);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// src/index.ts
|
|
327
|
+
var KaneoMCPServer = class {
|
|
328
|
+
server;
|
|
329
|
+
client;
|
|
330
|
+
constructor(config) {
|
|
331
|
+
this.client = new KaneoClient(config);
|
|
332
|
+
this.server = new Server(
|
|
333
|
+
{
|
|
334
|
+
name: "kaneo-mcp-server",
|
|
335
|
+
version: "1.0.0"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
capabilities: {
|
|
339
|
+
tools: {}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
this.setupToolHandlers();
|
|
344
|
+
}
|
|
345
|
+
setupToolHandlers() {
|
|
346
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
347
|
+
return { tools: this.getTools() };
|
|
348
|
+
});
|
|
349
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
350
|
+
const { name, arguments: args } = request.params;
|
|
351
|
+
try {
|
|
352
|
+
switch (name) {
|
|
353
|
+
// Health & Config
|
|
354
|
+
case "health":
|
|
355
|
+
return {
|
|
356
|
+
content: [
|
|
357
|
+
{
|
|
358
|
+
type: "text",
|
|
359
|
+
text: JSON.stringify(await this.client.health())
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
};
|
|
363
|
+
case "get_config":
|
|
364
|
+
return {
|
|
365
|
+
content: [
|
|
366
|
+
{
|
|
367
|
+
type: "text",
|
|
368
|
+
text: JSON.stringify(await this.client.getConfig())
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
};
|
|
372
|
+
// Projects
|
|
373
|
+
case "list_projects":
|
|
374
|
+
return {
|
|
375
|
+
content: [
|
|
376
|
+
{
|
|
377
|
+
type: "text",
|
|
378
|
+
text: JSON.stringify(
|
|
379
|
+
await this.client.listProjects(args.workspaceId)
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
};
|
|
384
|
+
case "create_project":
|
|
385
|
+
return {
|
|
386
|
+
content: [
|
|
387
|
+
{
|
|
388
|
+
type: "text",
|
|
389
|
+
text: JSON.stringify(await this.client.createProject(args))
|
|
390
|
+
}
|
|
391
|
+
]
|
|
392
|
+
};
|
|
393
|
+
case "get_project":
|
|
394
|
+
return {
|
|
395
|
+
content: [
|
|
396
|
+
{
|
|
397
|
+
type: "text",
|
|
398
|
+
text: JSON.stringify(await this.client.getProject(args.id))
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
};
|
|
402
|
+
case "update_project":
|
|
403
|
+
return {
|
|
404
|
+
content: [
|
|
405
|
+
{
|
|
406
|
+
type: "text",
|
|
407
|
+
text: JSON.stringify(
|
|
408
|
+
await this.client.updateProject(args.id, args)
|
|
409
|
+
)
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
};
|
|
413
|
+
case "delete_project":
|
|
414
|
+
return {
|
|
415
|
+
content: [
|
|
416
|
+
{
|
|
417
|
+
type: "text",
|
|
418
|
+
text: JSON.stringify(
|
|
419
|
+
await this.client.deleteProject(args.id)
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
};
|
|
424
|
+
case "archive_project":
|
|
425
|
+
return {
|
|
426
|
+
content: [
|
|
427
|
+
{
|
|
428
|
+
type: "text",
|
|
429
|
+
text: JSON.stringify(
|
|
430
|
+
await this.client.archiveProject(args.id)
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
]
|
|
434
|
+
};
|
|
435
|
+
case "unarchive_project":
|
|
436
|
+
return {
|
|
437
|
+
content: [
|
|
438
|
+
{
|
|
439
|
+
type: "text",
|
|
440
|
+
text: JSON.stringify(
|
|
441
|
+
await this.client.unarchiveProject(args.id)
|
|
442
|
+
)
|
|
443
|
+
}
|
|
444
|
+
]
|
|
445
|
+
};
|
|
446
|
+
// Tasks
|
|
447
|
+
case "list_tasks":
|
|
448
|
+
return {
|
|
449
|
+
content: [
|
|
450
|
+
{
|
|
451
|
+
type: "text",
|
|
452
|
+
text: JSON.stringify(
|
|
453
|
+
await this.client.listTasks(args.projectId, args)
|
|
454
|
+
)
|
|
455
|
+
}
|
|
456
|
+
]
|
|
457
|
+
};
|
|
458
|
+
case "create_task":
|
|
459
|
+
return {
|
|
460
|
+
content: [
|
|
461
|
+
{
|
|
462
|
+
type: "text",
|
|
463
|
+
text: JSON.stringify(
|
|
464
|
+
await this.client.createTask(args.projectId, args)
|
|
465
|
+
)
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
};
|
|
469
|
+
case "get_task":
|
|
470
|
+
return {
|
|
471
|
+
content: [
|
|
472
|
+
{
|
|
473
|
+
type: "text",
|
|
474
|
+
text: JSON.stringify(await this.client.getTask(args.id))
|
|
475
|
+
}
|
|
476
|
+
]
|
|
477
|
+
};
|
|
478
|
+
case "update_task":
|
|
479
|
+
return {
|
|
480
|
+
content: [
|
|
481
|
+
{
|
|
482
|
+
type: "text",
|
|
483
|
+
text: JSON.stringify(
|
|
484
|
+
await this.client.updateTask(args.id, args)
|
|
485
|
+
)
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
};
|
|
489
|
+
case "delete_task":
|
|
490
|
+
return {
|
|
491
|
+
content: [
|
|
492
|
+
{
|
|
493
|
+
type: "text",
|
|
494
|
+
text: JSON.stringify(await this.client.deleteTask(args.id))
|
|
495
|
+
}
|
|
496
|
+
]
|
|
497
|
+
};
|
|
498
|
+
case "update_task_status":
|
|
499
|
+
return {
|
|
500
|
+
content: [
|
|
501
|
+
{
|
|
502
|
+
type: "text",
|
|
503
|
+
text: JSON.stringify(
|
|
504
|
+
await this.client.updateTaskStatus(args.id, args.status)
|
|
505
|
+
)
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
};
|
|
509
|
+
case "update_task_priority":
|
|
510
|
+
return {
|
|
511
|
+
content: [
|
|
512
|
+
{
|
|
513
|
+
type: "text",
|
|
514
|
+
text: JSON.stringify(
|
|
515
|
+
await this.client.updateTaskPriority(
|
|
516
|
+
args.id,
|
|
517
|
+
args.priority
|
|
518
|
+
)
|
|
519
|
+
)
|
|
520
|
+
}
|
|
521
|
+
]
|
|
522
|
+
};
|
|
523
|
+
case "update_task_assignee":
|
|
524
|
+
return {
|
|
525
|
+
content: [
|
|
526
|
+
{
|
|
527
|
+
type: "text",
|
|
528
|
+
text: JSON.stringify(
|
|
529
|
+
await this.client.updateTaskAssignee(args.id, args.userId)
|
|
530
|
+
)
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
};
|
|
534
|
+
case "update_task_due_date":
|
|
535
|
+
return {
|
|
536
|
+
content: [
|
|
537
|
+
{
|
|
538
|
+
type: "text",
|
|
539
|
+
text: JSON.stringify(
|
|
540
|
+
await this.client.updateTaskDueDate(args.id, args.dueDate)
|
|
541
|
+
)
|
|
542
|
+
}
|
|
543
|
+
]
|
|
544
|
+
};
|
|
545
|
+
case "update_task_title":
|
|
546
|
+
return {
|
|
547
|
+
content: [
|
|
548
|
+
{
|
|
549
|
+
type: "text",
|
|
550
|
+
text: JSON.stringify(
|
|
551
|
+
await this.client.updateTaskTitle(args.id, args.title)
|
|
552
|
+
)
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
};
|
|
556
|
+
case "update_task_description":
|
|
557
|
+
return {
|
|
558
|
+
content: [
|
|
559
|
+
{
|
|
560
|
+
type: "text",
|
|
561
|
+
text: JSON.stringify(
|
|
562
|
+
await this.client.updateTaskDescription(
|
|
563
|
+
args.id,
|
|
564
|
+
args.description
|
|
565
|
+
)
|
|
566
|
+
)
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
};
|
|
570
|
+
case "move_task":
|
|
571
|
+
return {
|
|
572
|
+
content: [
|
|
573
|
+
{
|
|
574
|
+
type: "text",
|
|
575
|
+
text: JSON.stringify(
|
|
576
|
+
await this.client.moveTask(args.id, args.projectId)
|
|
577
|
+
)
|
|
578
|
+
}
|
|
579
|
+
]
|
|
580
|
+
};
|
|
581
|
+
// Columns
|
|
582
|
+
case "list_columns":
|
|
583
|
+
return {
|
|
584
|
+
content: [
|
|
585
|
+
{
|
|
586
|
+
type: "text",
|
|
587
|
+
text: JSON.stringify(
|
|
588
|
+
await this.client.listColumns(args.projectId)
|
|
589
|
+
)
|
|
590
|
+
}
|
|
591
|
+
]
|
|
592
|
+
};
|
|
593
|
+
case "create_column":
|
|
594
|
+
return {
|
|
595
|
+
content: [
|
|
596
|
+
{
|
|
597
|
+
type: "text",
|
|
598
|
+
text: JSON.stringify(
|
|
599
|
+
await this.client.createColumn(args.projectId, args)
|
|
600
|
+
)
|
|
601
|
+
}
|
|
602
|
+
]
|
|
603
|
+
};
|
|
604
|
+
case "update_column":
|
|
605
|
+
return {
|
|
606
|
+
content: [
|
|
607
|
+
{
|
|
608
|
+
type: "text",
|
|
609
|
+
text: JSON.stringify(
|
|
610
|
+
await this.client.updateColumn(args.id, args)
|
|
611
|
+
)
|
|
612
|
+
}
|
|
613
|
+
]
|
|
614
|
+
};
|
|
615
|
+
case "delete_column":
|
|
616
|
+
return {
|
|
617
|
+
content: [
|
|
618
|
+
{
|
|
619
|
+
type: "text",
|
|
620
|
+
text: JSON.stringify(await this.client.deleteColumn(args.id))
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
};
|
|
624
|
+
case "reorder_columns":
|
|
625
|
+
return {
|
|
626
|
+
content: [
|
|
627
|
+
{
|
|
628
|
+
type: "text",
|
|
629
|
+
text: JSON.stringify(
|
|
630
|
+
await this.client.reorderColumns(
|
|
631
|
+
args.projectId,
|
|
632
|
+
args.columnIds
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
}
|
|
636
|
+
]
|
|
637
|
+
};
|
|
638
|
+
// Comments
|
|
639
|
+
case "list_comments":
|
|
640
|
+
return {
|
|
641
|
+
content: [
|
|
642
|
+
{
|
|
643
|
+
type: "text",
|
|
644
|
+
text: JSON.stringify(
|
|
645
|
+
await this.client.listComments(args.taskId)
|
|
646
|
+
)
|
|
647
|
+
}
|
|
648
|
+
]
|
|
649
|
+
};
|
|
650
|
+
case "create_comment":
|
|
651
|
+
return {
|
|
652
|
+
content: [
|
|
653
|
+
{
|
|
654
|
+
type: "text",
|
|
655
|
+
text: JSON.stringify(
|
|
656
|
+
await this.client.createComment(args.taskId, args.content)
|
|
657
|
+
)
|
|
658
|
+
}
|
|
659
|
+
]
|
|
660
|
+
};
|
|
661
|
+
case "update_comment":
|
|
662
|
+
return {
|
|
663
|
+
content: [
|
|
664
|
+
{
|
|
665
|
+
type: "text",
|
|
666
|
+
text: JSON.stringify(
|
|
667
|
+
await this.client.updateComment(args.id, args.content)
|
|
668
|
+
)
|
|
669
|
+
}
|
|
670
|
+
]
|
|
671
|
+
};
|
|
672
|
+
case "delete_comment":
|
|
673
|
+
return {
|
|
674
|
+
content: [
|
|
675
|
+
{
|
|
676
|
+
type: "text",
|
|
677
|
+
text: JSON.stringify(
|
|
678
|
+
await this.client.deleteComment(args.id)
|
|
679
|
+
)
|
|
680
|
+
}
|
|
681
|
+
]
|
|
682
|
+
};
|
|
683
|
+
// Labels
|
|
684
|
+
case "list_labels_for_task":
|
|
685
|
+
return {
|
|
686
|
+
content: [
|
|
687
|
+
{
|
|
688
|
+
type: "text",
|
|
689
|
+
text: JSON.stringify(
|
|
690
|
+
await this.client.listLabelsForTask(args.taskId)
|
|
691
|
+
)
|
|
692
|
+
}
|
|
693
|
+
]
|
|
694
|
+
};
|
|
695
|
+
case "list_workspace_labels":
|
|
696
|
+
return {
|
|
697
|
+
content: [
|
|
698
|
+
{
|
|
699
|
+
type: "text",
|
|
700
|
+
text: JSON.stringify(
|
|
701
|
+
await this.client.listWorkspaceLabels(args.workspaceId)
|
|
702
|
+
)
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
};
|
|
706
|
+
case "create_label":
|
|
707
|
+
return {
|
|
708
|
+
content: [
|
|
709
|
+
{
|
|
710
|
+
type: "text",
|
|
711
|
+
text: JSON.stringify(await this.client.createLabel(args))
|
|
712
|
+
}
|
|
713
|
+
]
|
|
714
|
+
};
|
|
715
|
+
case "get_label":
|
|
716
|
+
return {
|
|
717
|
+
content: [
|
|
718
|
+
{
|
|
719
|
+
type: "text",
|
|
720
|
+
text: JSON.stringify(await this.client.getLabel(args.id))
|
|
721
|
+
}
|
|
722
|
+
]
|
|
723
|
+
};
|
|
724
|
+
case "update_label":
|
|
725
|
+
return {
|
|
726
|
+
content: [
|
|
727
|
+
{
|
|
728
|
+
type: "text",
|
|
729
|
+
text: JSON.stringify(
|
|
730
|
+
await this.client.updateLabel(args.id, args)
|
|
731
|
+
)
|
|
732
|
+
}
|
|
733
|
+
]
|
|
734
|
+
};
|
|
735
|
+
case "delete_label":
|
|
736
|
+
return {
|
|
737
|
+
content: [
|
|
738
|
+
{
|
|
739
|
+
type: "text",
|
|
740
|
+
text: JSON.stringify(await this.client.deleteLabel(args.id))
|
|
741
|
+
}
|
|
742
|
+
]
|
|
743
|
+
};
|
|
744
|
+
case "attach_label_to_task":
|
|
745
|
+
return {
|
|
746
|
+
content: [
|
|
747
|
+
{
|
|
748
|
+
type: "text",
|
|
749
|
+
text: JSON.stringify(
|
|
750
|
+
await this.client.attachLabelToTask(
|
|
751
|
+
args.labelId,
|
|
752
|
+
args.taskId
|
|
753
|
+
)
|
|
754
|
+
)
|
|
755
|
+
}
|
|
756
|
+
]
|
|
757
|
+
};
|
|
758
|
+
case "detach_label_from_task":
|
|
759
|
+
return {
|
|
760
|
+
content: [
|
|
761
|
+
{
|
|
762
|
+
type: "text",
|
|
763
|
+
text: JSON.stringify(
|
|
764
|
+
await this.client.detachLabelFromTask(
|
|
765
|
+
args.labelId,
|
|
766
|
+
args.taskId
|
|
767
|
+
)
|
|
768
|
+
)
|
|
769
|
+
}
|
|
770
|
+
]
|
|
771
|
+
};
|
|
772
|
+
// Time Entries
|
|
773
|
+
case "list_time_entries":
|
|
774
|
+
return {
|
|
775
|
+
content: [
|
|
776
|
+
{
|
|
777
|
+
type: "text",
|
|
778
|
+
text: JSON.stringify(
|
|
779
|
+
await this.client.listTimeEntries(args.taskId)
|
|
780
|
+
)
|
|
781
|
+
}
|
|
782
|
+
]
|
|
783
|
+
};
|
|
784
|
+
case "get_time_entry":
|
|
785
|
+
return {
|
|
786
|
+
content: [
|
|
787
|
+
{
|
|
788
|
+
type: "text",
|
|
789
|
+
text: JSON.stringify(await this.client.getTimeEntry(args.id))
|
|
790
|
+
}
|
|
791
|
+
]
|
|
792
|
+
};
|
|
793
|
+
case "create_time_entry":
|
|
794
|
+
return {
|
|
795
|
+
content: [
|
|
796
|
+
{
|
|
797
|
+
type: "text",
|
|
798
|
+
text: JSON.stringify(await this.client.createTimeEntry(args))
|
|
799
|
+
}
|
|
800
|
+
]
|
|
801
|
+
};
|
|
802
|
+
case "update_time_entry":
|
|
803
|
+
return {
|
|
804
|
+
content: [
|
|
805
|
+
{
|
|
806
|
+
type: "text",
|
|
807
|
+
text: JSON.stringify(
|
|
808
|
+
await this.client.updateTimeEntry(args.id, args)
|
|
809
|
+
)
|
|
810
|
+
}
|
|
811
|
+
]
|
|
812
|
+
};
|
|
813
|
+
// Task Relations
|
|
814
|
+
case "list_task_relations":
|
|
815
|
+
return {
|
|
816
|
+
content: [
|
|
817
|
+
{
|
|
818
|
+
type: "text",
|
|
819
|
+
text: JSON.stringify(
|
|
820
|
+
await this.client.listTaskRelations(args.taskId)
|
|
821
|
+
)
|
|
822
|
+
}
|
|
823
|
+
]
|
|
824
|
+
};
|
|
825
|
+
case "create_task_relation":
|
|
826
|
+
return {
|
|
827
|
+
content: [
|
|
828
|
+
{
|
|
829
|
+
type: "text",
|
|
830
|
+
text: JSON.stringify(
|
|
831
|
+
await this.client.createTaskRelation(args)
|
|
832
|
+
)
|
|
833
|
+
}
|
|
834
|
+
]
|
|
835
|
+
};
|
|
836
|
+
case "delete_task_relation":
|
|
837
|
+
return {
|
|
838
|
+
content: [
|
|
839
|
+
{
|
|
840
|
+
type: "text",
|
|
841
|
+
text: JSON.stringify(
|
|
842
|
+
await this.client.deleteTaskRelation(args.id)
|
|
843
|
+
)
|
|
844
|
+
}
|
|
845
|
+
]
|
|
846
|
+
};
|
|
847
|
+
// Notifications
|
|
848
|
+
case "list_notifications":
|
|
849
|
+
return {
|
|
850
|
+
content: [
|
|
851
|
+
{
|
|
852
|
+
type: "text",
|
|
853
|
+
text: JSON.stringify(await this.client.listNotifications())
|
|
854
|
+
}
|
|
855
|
+
]
|
|
856
|
+
};
|
|
857
|
+
case "mark_notification_read":
|
|
858
|
+
return {
|
|
859
|
+
content: [
|
|
860
|
+
{
|
|
861
|
+
type: "text",
|
|
862
|
+
text: JSON.stringify(
|
|
863
|
+
await this.client.markNotificationRead(args.id)
|
|
864
|
+
)
|
|
865
|
+
}
|
|
866
|
+
]
|
|
867
|
+
};
|
|
868
|
+
case "mark_all_notifications_read":
|
|
869
|
+
return {
|
|
870
|
+
content: [
|
|
871
|
+
{
|
|
872
|
+
type: "text",
|
|
873
|
+
text: JSON.stringify(
|
|
874
|
+
await this.client.markAllNotificationsRead()
|
|
875
|
+
)
|
|
876
|
+
}
|
|
877
|
+
]
|
|
878
|
+
};
|
|
879
|
+
case "clear_all_notifications":
|
|
880
|
+
return {
|
|
881
|
+
content: [
|
|
882
|
+
{
|
|
883
|
+
type: "text",
|
|
884
|
+
text: JSON.stringify(
|
|
885
|
+
await this.client.clearAllNotifications()
|
|
886
|
+
)
|
|
887
|
+
}
|
|
888
|
+
]
|
|
889
|
+
};
|
|
890
|
+
// Workspace
|
|
891
|
+
case "list_workspace_members":
|
|
892
|
+
return {
|
|
893
|
+
content: [
|
|
894
|
+
{
|
|
895
|
+
type: "text",
|
|
896
|
+
text: JSON.stringify(
|
|
897
|
+
await this.client.listWorkspaceMembers(args.workspaceId)
|
|
898
|
+
)
|
|
899
|
+
}
|
|
900
|
+
]
|
|
901
|
+
};
|
|
902
|
+
// Search
|
|
903
|
+
case "search":
|
|
904
|
+
return {
|
|
905
|
+
content: [
|
|
906
|
+
{
|
|
907
|
+
type: "text",
|
|
908
|
+
text: JSON.stringify(
|
|
909
|
+
await this.client.search(args.q, args.type)
|
|
910
|
+
)
|
|
911
|
+
}
|
|
912
|
+
]
|
|
913
|
+
};
|
|
914
|
+
// Activity
|
|
915
|
+
case "list_activities":
|
|
916
|
+
return {
|
|
917
|
+
content: [
|
|
918
|
+
{
|
|
919
|
+
type: "text",
|
|
920
|
+
text: JSON.stringify(
|
|
921
|
+
await this.client.listActivities(args.taskId)
|
|
922
|
+
)
|
|
923
|
+
}
|
|
924
|
+
]
|
|
925
|
+
};
|
|
926
|
+
// Invitations
|
|
927
|
+
case "list_pending_invitations":
|
|
928
|
+
return {
|
|
929
|
+
content: [
|
|
930
|
+
{
|
|
931
|
+
type: "text",
|
|
932
|
+
text: JSON.stringify(
|
|
933
|
+
await this.client.listPendingInvitations()
|
|
934
|
+
)
|
|
935
|
+
}
|
|
936
|
+
]
|
|
937
|
+
};
|
|
938
|
+
case "get_invitation":
|
|
939
|
+
return {
|
|
940
|
+
content: [
|
|
941
|
+
{
|
|
942
|
+
type: "text",
|
|
943
|
+
text: JSON.stringify(
|
|
944
|
+
await this.client.getInvitation(args.id)
|
|
945
|
+
)
|
|
946
|
+
}
|
|
947
|
+
]
|
|
948
|
+
};
|
|
949
|
+
default:
|
|
950
|
+
return {
|
|
951
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
952
|
+
isError: true
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
} catch (error) {
|
|
956
|
+
return {
|
|
957
|
+
content: [
|
|
958
|
+
{
|
|
959
|
+
type: "text",
|
|
960
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
961
|
+
}
|
|
962
|
+
],
|
|
963
|
+
isError: true
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
getTools() {
|
|
969
|
+
return [
|
|
970
|
+
// Health & Config
|
|
971
|
+
{
|
|
972
|
+
name: "health",
|
|
973
|
+
description: "Check if the Kaneo API server is healthy",
|
|
974
|
+
inputSchema: { type: "object", properties: {} }
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
name: "get_config",
|
|
978
|
+
description: "Get public configuration from the Kaneo API server",
|
|
979
|
+
inputSchema: { type: "object", properties: {} }
|
|
980
|
+
},
|
|
981
|
+
// Projects
|
|
982
|
+
{
|
|
983
|
+
name: "list_projects",
|
|
984
|
+
description: "List all projects in a workspace",
|
|
985
|
+
inputSchema: {
|
|
986
|
+
type: "object",
|
|
987
|
+
properties: {
|
|
988
|
+
workspaceId: { type: "string", description: "The workspace ID" }
|
|
989
|
+
},
|
|
990
|
+
required: ["workspaceId"]
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
name: "create_project",
|
|
995
|
+
description: "Create a new project in a workspace",
|
|
996
|
+
inputSchema: {
|
|
997
|
+
type: "object",
|
|
998
|
+
properties: {
|
|
999
|
+
name: { type: "string", description: "Project name" },
|
|
1000
|
+
description: { type: "string", description: "Project description" },
|
|
1001
|
+
workspaceId: { type: "string", description: "Workspace ID" }
|
|
1002
|
+
},
|
|
1003
|
+
required: ["name", "workspaceId"]
|
|
1004
|
+
}
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
name: "get_project",
|
|
1008
|
+
description: "Get a project by ID",
|
|
1009
|
+
inputSchema: {
|
|
1010
|
+
type: "object",
|
|
1011
|
+
properties: { id: { type: "string", description: "Project ID" } },
|
|
1012
|
+
required: ["id"]
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: "update_project",
|
|
1017
|
+
description: "Update a project",
|
|
1018
|
+
inputSchema: {
|
|
1019
|
+
type: "object",
|
|
1020
|
+
properties: {
|
|
1021
|
+
id: { type: "string", description: "Project ID" },
|
|
1022
|
+
name: { type: "string", description: "Project name" },
|
|
1023
|
+
description: { type: "string", description: "Project description" }
|
|
1024
|
+
},
|
|
1025
|
+
required: ["id"]
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
name: "delete_project",
|
|
1030
|
+
description: "Delete a project",
|
|
1031
|
+
inputSchema: {
|
|
1032
|
+
type: "object",
|
|
1033
|
+
properties: { id: { type: "string", description: "Project ID" } },
|
|
1034
|
+
required: ["id"]
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
{
|
|
1038
|
+
name: "archive_project",
|
|
1039
|
+
description: "Archive a project",
|
|
1040
|
+
inputSchema: {
|
|
1041
|
+
type: "object",
|
|
1042
|
+
properties: { id: { type: "string", description: "Project ID" } },
|
|
1043
|
+
required: ["id"]
|
|
1044
|
+
}
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
name: "unarchive_project",
|
|
1048
|
+
description: "Unarchive a project",
|
|
1049
|
+
inputSchema: {
|
|
1050
|
+
type: "object",
|
|
1051
|
+
properties: { id: { type: "string", description: "Project ID" } },
|
|
1052
|
+
required: ["id"]
|
|
1053
|
+
}
|
|
1054
|
+
},
|
|
1055
|
+
// Tasks
|
|
1056
|
+
{
|
|
1057
|
+
name: "list_tasks",
|
|
1058
|
+
description: "List tasks in a project with optional filters",
|
|
1059
|
+
inputSchema: {
|
|
1060
|
+
type: "object",
|
|
1061
|
+
properties: {
|
|
1062
|
+
projectId: { type: "string", description: "Project ID" },
|
|
1063
|
+
status: {
|
|
1064
|
+
type: "string",
|
|
1065
|
+
description: "Filter by status (todo, in_progress, done, canceled)"
|
|
1066
|
+
},
|
|
1067
|
+
priority: {
|
|
1068
|
+
type: "string",
|
|
1069
|
+
description: "Filter by priority (low, medium, high, urgent)"
|
|
1070
|
+
},
|
|
1071
|
+
assigneeId: {
|
|
1072
|
+
type: "string",
|
|
1073
|
+
description: "Filter by assignee ID"
|
|
1074
|
+
}
|
|
1075
|
+
},
|
|
1076
|
+
required: ["projectId"]
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
name: "create_task",
|
|
1081
|
+
description: "Create a new task in a project",
|
|
1082
|
+
inputSchema: {
|
|
1083
|
+
type: "object",
|
|
1084
|
+
properties: {
|
|
1085
|
+
projectId: { type: "string", description: "Project ID" },
|
|
1086
|
+
title: { type: "string", description: "Task title" },
|
|
1087
|
+
description: { type: "string", description: "Task description" },
|
|
1088
|
+
status: {
|
|
1089
|
+
type: "string",
|
|
1090
|
+
description: "Task status (todo, in_progress, done, canceled)"
|
|
1091
|
+
},
|
|
1092
|
+
priority: {
|
|
1093
|
+
type: "string",
|
|
1094
|
+
description: "Task priority (low, medium, high, urgent)"
|
|
1095
|
+
},
|
|
1096
|
+
assigneeId: { type: "string", description: "Assignee user ID" },
|
|
1097
|
+
startDate: { type: "string", description: "Start date (ISO 8601)" },
|
|
1098
|
+
dueDate: { type: "string", description: "Due date (ISO 8601)" }
|
|
1099
|
+
},
|
|
1100
|
+
required: ["projectId", "title"]
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
name: "get_task",
|
|
1105
|
+
description: "Get a task by ID",
|
|
1106
|
+
inputSchema: {
|
|
1107
|
+
type: "object",
|
|
1108
|
+
properties: { id: { type: "string", description: "Task ID" } },
|
|
1109
|
+
required: ["id"]
|
|
1110
|
+
}
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
name: "update_task",
|
|
1114
|
+
description: "Update a task",
|
|
1115
|
+
inputSchema: {
|
|
1116
|
+
type: "object",
|
|
1117
|
+
properties: {
|
|
1118
|
+
id: { type: "string", description: "Task ID" },
|
|
1119
|
+
title: { type: "string", description: "Task title" },
|
|
1120
|
+
description: { type: "string", description: "Task description" },
|
|
1121
|
+
status: { type: "string", description: "Task status" },
|
|
1122
|
+
priority: { type: "string", description: "Task priority" },
|
|
1123
|
+
assigneeId: { type: "string", description: "Assignee user ID" },
|
|
1124
|
+
startDate: { type: "string", description: "Start date" },
|
|
1125
|
+
dueDate: { type: "string", description: "Due date" }
|
|
1126
|
+
},
|
|
1127
|
+
required: ["id"]
|
|
1128
|
+
}
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
name: "delete_task",
|
|
1132
|
+
description: "Delete a task",
|
|
1133
|
+
inputSchema: {
|
|
1134
|
+
type: "object",
|
|
1135
|
+
properties: { id: { type: "string", description: "Task ID" } },
|
|
1136
|
+
required: ["id"]
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
name: "update_task_status",
|
|
1141
|
+
description: "Update only the status of a task",
|
|
1142
|
+
inputSchema: {
|
|
1143
|
+
type: "object",
|
|
1144
|
+
properties: {
|
|
1145
|
+
id: { type: "string", description: "Task ID" },
|
|
1146
|
+
status: {
|
|
1147
|
+
type: "string",
|
|
1148
|
+
description: "New status (todo, in_progress, done, canceled)"
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1151
|
+
required: ["id", "status"]
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
name: "update_task_priority",
|
|
1156
|
+
description: "Update only the priority of a task",
|
|
1157
|
+
inputSchema: {
|
|
1158
|
+
type: "object",
|
|
1159
|
+
properties: {
|
|
1160
|
+
id: { type: "string", description: "Task ID" },
|
|
1161
|
+
priority: {
|
|
1162
|
+
type: "string",
|
|
1163
|
+
description: "New priority (low, medium, high, urgent)"
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
required: ["id", "priority"]
|
|
1167
|
+
}
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
name: "update_task_assignee",
|
|
1171
|
+
description: "Update the assignee of a task",
|
|
1172
|
+
inputSchema: {
|
|
1173
|
+
type: "object",
|
|
1174
|
+
properties: {
|
|
1175
|
+
id: { type: "string", description: "Task ID" },
|
|
1176
|
+
userId: {
|
|
1177
|
+
type: "string",
|
|
1178
|
+
description: "User ID to assign (null to unassign)"
|
|
1179
|
+
}
|
|
1180
|
+
},
|
|
1181
|
+
required: ["id"]
|
|
1182
|
+
}
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
name: "update_task_due_date",
|
|
1186
|
+
description: "Update the due date of a task",
|
|
1187
|
+
inputSchema: {
|
|
1188
|
+
type: "object",
|
|
1189
|
+
properties: {
|
|
1190
|
+
id: { type: "string", description: "Task ID" },
|
|
1191
|
+
dueDate: {
|
|
1192
|
+
type: "string",
|
|
1193
|
+
description: "Due date ISO string (null to remove)"
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
required: ["id"]
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
name: "update_task_title",
|
|
1201
|
+
description: "Update only the title of a task",
|
|
1202
|
+
inputSchema: {
|
|
1203
|
+
type: "object",
|
|
1204
|
+
properties: {
|
|
1205
|
+
id: { type: "string", description: "Task ID" },
|
|
1206
|
+
title: { type: "string", description: "New title" }
|
|
1207
|
+
},
|
|
1208
|
+
required: ["id", "title"]
|
|
1209
|
+
}
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
name: "update_task_description",
|
|
1213
|
+
description: "Update only the description of a task",
|
|
1214
|
+
inputSchema: {
|
|
1215
|
+
type: "object",
|
|
1216
|
+
properties: {
|
|
1217
|
+
id: { type: "string", description: "Task ID" },
|
|
1218
|
+
description: { type: "string", description: "New description" }
|
|
1219
|
+
},
|
|
1220
|
+
required: ["id", "description"]
|
|
1221
|
+
}
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
name: "move_task",
|
|
1225
|
+
description: "Move a task to another project",
|
|
1226
|
+
inputSchema: {
|
|
1227
|
+
type: "object",
|
|
1228
|
+
properties: {
|
|
1229
|
+
id: { type: "string", description: "Task ID" },
|
|
1230
|
+
projectId: { type: "string", description: "Target project ID" }
|
|
1231
|
+
},
|
|
1232
|
+
required: ["id", "projectId"]
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
// Columns
|
|
1236
|
+
{
|
|
1237
|
+
name: "list_columns",
|
|
1238
|
+
description: "List all columns in a project",
|
|
1239
|
+
inputSchema: {
|
|
1240
|
+
type: "object",
|
|
1241
|
+
properties: {
|
|
1242
|
+
projectId: { type: "string", description: "Project ID" }
|
|
1243
|
+
},
|
|
1244
|
+
required: ["projectId"]
|
|
1245
|
+
}
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
name: "create_column",
|
|
1249
|
+
description: "Create a new column in a project",
|
|
1250
|
+
inputSchema: {
|
|
1251
|
+
type: "object",
|
|
1252
|
+
properties: {
|
|
1253
|
+
projectId: { type: "string", description: "Project ID" },
|
|
1254
|
+
name: { type: "string", description: "Column name" },
|
|
1255
|
+
order: { type: "number", description: "Column order" }
|
|
1256
|
+
},
|
|
1257
|
+
required: ["projectId", "name"]
|
|
1258
|
+
}
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
name: "update_column",
|
|
1262
|
+
description: "Update a column",
|
|
1263
|
+
inputSchema: {
|
|
1264
|
+
type: "object",
|
|
1265
|
+
properties: {
|
|
1266
|
+
id: { type: "string", description: "Column ID" },
|
|
1267
|
+
name: { type: "string", description: "Column name" },
|
|
1268
|
+
order: { type: "number", description: "Column order" }
|
|
1269
|
+
},
|
|
1270
|
+
required: ["id"]
|
|
1271
|
+
}
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
name: "delete_column",
|
|
1275
|
+
description: "Delete a column",
|
|
1276
|
+
inputSchema: {
|
|
1277
|
+
type: "object",
|
|
1278
|
+
properties: { id: { type: "string", description: "Column ID" } },
|
|
1279
|
+
required: ["id"]
|
|
1280
|
+
}
|
|
1281
|
+
},
|
|
1282
|
+
{
|
|
1283
|
+
name: "reorder_columns",
|
|
1284
|
+
description: "Reorder columns in a project",
|
|
1285
|
+
inputSchema: {
|
|
1286
|
+
type: "object",
|
|
1287
|
+
properties: {
|
|
1288
|
+
projectId: { type: "string", description: "Project ID" },
|
|
1289
|
+
columnIds: {
|
|
1290
|
+
type: "array",
|
|
1291
|
+
items: { type: "string" },
|
|
1292
|
+
description: "Array of column IDs in new order"
|
|
1293
|
+
}
|
|
1294
|
+
},
|
|
1295
|
+
required: ["projectId", "columnIds"]
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
// Comments
|
|
1299
|
+
{
|
|
1300
|
+
name: "list_comments",
|
|
1301
|
+
description: "List all comments on a task",
|
|
1302
|
+
inputSchema: {
|
|
1303
|
+
type: "object",
|
|
1304
|
+
properties: { taskId: { type: "string", description: "Task ID" } },
|
|
1305
|
+
required: ["taskId"]
|
|
1306
|
+
}
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
name: "create_comment",
|
|
1310
|
+
description: "Add a comment to a task",
|
|
1311
|
+
inputSchema: {
|
|
1312
|
+
type: "object",
|
|
1313
|
+
properties: {
|
|
1314
|
+
taskId: { type: "string", description: "Task ID" },
|
|
1315
|
+
content: { type: "string", description: "Comment content" }
|
|
1316
|
+
},
|
|
1317
|
+
required: ["taskId", "content"]
|
|
1318
|
+
}
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
name: "update_comment",
|
|
1322
|
+
description: "Update a comment (author only)",
|
|
1323
|
+
inputSchema: {
|
|
1324
|
+
type: "object",
|
|
1325
|
+
properties: {
|
|
1326
|
+
id: { type: "string", description: "Comment ID" },
|
|
1327
|
+
content: { type: "string", description: "New content" }
|
|
1328
|
+
},
|
|
1329
|
+
required: ["id", "content"]
|
|
1330
|
+
}
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
name: "delete_comment",
|
|
1334
|
+
description: "Delete a comment (author only)",
|
|
1335
|
+
inputSchema: {
|
|
1336
|
+
type: "object",
|
|
1337
|
+
properties: { id: { type: "string", description: "Comment ID" } },
|
|
1338
|
+
required: ["id"]
|
|
1339
|
+
}
|
|
1340
|
+
},
|
|
1341
|
+
// Labels
|
|
1342
|
+
{
|
|
1343
|
+
name: "list_labels_for_task",
|
|
1344
|
+
description: "List all labels attached to a task",
|
|
1345
|
+
inputSchema: {
|
|
1346
|
+
type: "object",
|
|
1347
|
+
properties: { taskId: { type: "string", description: "Task ID" } },
|
|
1348
|
+
required: ["taskId"]
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
{
|
|
1352
|
+
name: "list_workspace_labels",
|
|
1353
|
+
description: "List all labels in a workspace",
|
|
1354
|
+
inputSchema: {
|
|
1355
|
+
type: "object",
|
|
1356
|
+
properties: {
|
|
1357
|
+
workspaceId: { type: "string", description: "Workspace ID" }
|
|
1358
|
+
},
|
|
1359
|
+
required: ["workspaceId"]
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
name: "create_label",
|
|
1364
|
+
description: "Create a new label in a workspace",
|
|
1365
|
+
inputSchema: {
|
|
1366
|
+
type: "object",
|
|
1367
|
+
properties: {
|
|
1368
|
+
name: { type: "string", description: "Label name" },
|
|
1369
|
+
color: { type: "string", description: "Label color (hex code)" },
|
|
1370
|
+
workspaceId: { type: "string", description: "Workspace ID" }
|
|
1371
|
+
},
|
|
1372
|
+
required: ["name", "color", "workspaceId"]
|
|
1373
|
+
}
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
name: "get_label",
|
|
1377
|
+
description: "Get a label by ID",
|
|
1378
|
+
inputSchema: {
|
|
1379
|
+
type: "object",
|
|
1380
|
+
properties: { id: { type: "string", description: "Label ID" } },
|
|
1381
|
+
required: ["id"]
|
|
1382
|
+
}
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
name: "update_label",
|
|
1386
|
+
description: "Update a label",
|
|
1387
|
+
inputSchema: {
|
|
1388
|
+
type: "object",
|
|
1389
|
+
properties: {
|
|
1390
|
+
id: { type: "string", description: "Label ID" },
|
|
1391
|
+
name: { type: "string", description: "Label name" },
|
|
1392
|
+
color: { type: "string", description: "Label color" }
|
|
1393
|
+
},
|
|
1394
|
+
required: ["id"]
|
|
1395
|
+
}
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
name: "delete_label",
|
|
1399
|
+
description: "Delete a label",
|
|
1400
|
+
inputSchema: {
|
|
1401
|
+
type: "object",
|
|
1402
|
+
properties: { id: { type: "string", description: "Label ID" } },
|
|
1403
|
+
required: ["id"]
|
|
1404
|
+
}
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
name: "attach_label_to_task",
|
|
1408
|
+
description: "Attach a label to a task",
|
|
1409
|
+
inputSchema: {
|
|
1410
|
+
type: "object",
|
|
1411
|
+
properties: {
|
|
1412
|
+
labelId: { type: "string", description: "Label ID" },
|
|
1413
|
+
taskId: { type: "string", description: "Task ID" }
|
|
1414
|
+
},
|
|
1415
|
+
required: ["labelId", "taskId"]
|
|
1416
|
+
}
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
name: "detach_label_from_task",
|
|
1420
|
+
description: "Detach a label from a task",
|
|
1421
|
+
inputSchema: {
|
|
1422
|
+
type: "object",
|
|
1423
|
+
properties: {
|
|
1424
|
+
labelId: { type: "string", description: "Label ID" },
|
|
1425
|
+
taskId: { type: "string", description: "Task ID" }
|
|
1426
|
+
},
|
|
1427
|
+
required: ["labelId", "taskId"]
|
|
1428
|
+
}
|
|
1429
|
+
},
|
|
1430
|
+
// Time Entries
|
|
1431
|
+
{
|
|
1432
|
+
name: "list_time_entries",
|
|
1433
|
+
description: "List time entries for a task",
|
|
1434
|
+
inputSchema: {
|
|
1435
|
+
type: "object",
|
|
1436
|
+
properties: { taskId: { type: "string", description: "Task ID" } },
|
|
1437
|
+
required: ["taskId"]
|
|
1438
|
+
}
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
name: "get_time_entry",
|
|
1442
|
+
description: "Get a time entry by ID",
|
|
1443
|
+
inputSchema: {
|
|
1444
|
+
type: "object",
|
|
1445
|
+
properties: { id: { type: "string", description: "Time entry ID" } },
|
|
1446
|
+
required: ["id"]
|
|
1447
|
+
}
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
name: "create_time_entry",
|
|
1451
|
+
description: "Create a time entry for a task",
|
|
1452
|
+
inputSchema: {
|
|
1453
|
+
type: "object",
|
|
1454
|
+
properties: {
|
|
1455
|
+
taskId: { type: "string", description: "Task ID" },
|
|
1456
|
+
duration: { type: "number", description: "Duration in seconds" },
|
|
1457
|
+
description: {
|
|
1458
|
+
type: "string",
|
|
1459
|
+
description: "Time entry description"
|
|
1460
|
+
}
|
|
1461
|
+
},
|
|
1462
|
+
required: ["taskId", "duration"]
|
|
1463
|
+
}
|
|
1464
|
+
},
|
|
1465
|
+
{
|
|
1466
|
+
name: "update_time_entry",
|
|
1467
|
+
description: "Update a time entry",
|
|
1468
|
+
inputSchema: {
|
|
1469
|
+
type: "object",
|
|
1470
|
+
properties: {
|
|
1471
|
+
id: { type: "string", description: "Time entry ID" },
|
|
1472
|
+
duration: { type: "number", description: "Duration in seconds" },
|
|
1473
|
+
description: {
|
|
1474
|
+
type: "string",
|
|
1475
|
+
description: "Time entry description"
|
|
1476
|
+
}
|
|
1477
|
+
},
|
|
1478
|
+
required: ["id"]
|
|
1479
|
+
}
|
|
1480
|
+
},
|
|
1481
|
+
// Task Relations
|
|
1482
|
+
{
|
|
1483
|
+
name: "list_task_relations",
|
|
1484
|
+
description: "List all relations for a task",
|
|
1485
|
+
inputSchema: {
|
|
1486
|
+
type: "object",
|
|
1487
|
+
properties: { taskId: { type: "string", description: "Task ID" } },
|
|
1488
|
+
required: ["taskId"]
|
|
1489
|
+
}
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
name: "create_task_relation",
|
|
1493
|
+
description: "Create a relation between tasks",
|
|
1494
|
+
inputSchema: {
|
|
1495
|
+
type: "object",
|
|
1496
|
+
properties: {
|
|
1497
|
+
taskId: { type: "string", description: "Source task ID" },
|
|
1498
|
+
relatedTaskId: { type: "string", description: "Related task ID" },
|
|
1499
|
+
type: {
|
|
1500
|
+
type: "string",
|
|
1501
|
+
enum: ["subtask", "blocks", "related"],
|
|
1502
|
+
description: "Relation type"
|
|
1503
|
+
}
|
|
1504
|
+
},
|
|
1505
|
+
required: ["taskId", "relatedTaskId", "type"]
|
|
1506
|
+
}
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
name: "delete_task_relation",
|
|
1510
|
+
description: "Delete a task relation",
|
|
1511
|
+
inputSchema: {
|
|
1512
|
+
type: "object",
|
|
1513
|
+
properties: { id: { type: "string", description: "Relation ID" } },
|
|
1514
|
+
required: ["id"]
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
// Notifications
|
|
1518
|
+
{
|
|
1519
|
+
name: "list_notifications",
|
|
1520
|
+
description: "List all notifications for the current user",
|
|
1521
|
+
inputSchema: { type: "object", properties: {} }
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
name: "mark_notification_read",
|
|
1525
|
+
description: "Mark a notification as read",
|
|
1526
|
+
inputSchema: {
|
|
1527
|
+
type: "object",
|
|
1528
|
+
properties: {
|
|
1529
|
+
id: { type: "string", description: "Notification ID" }
|
|
1530
|
+
},
|
|
1531
|
+
required: ["id"]
|
|
1532
|
+
}
|
|
1533
|
+
},
|
|
1534
|
+
{
|
|
1535
|
+
name: "mark_all_notifications_read",
|
|
1536
|
+
description: "Mark all notifications as read",
|
|
1537
|
+
inputSchema: { type: "object", properties: {} }
|
|
1538
|
+
},
|
|
1539
|
+
{
|
|
1540
|
+
name: "clear_all_notifications",
|
|
1541
|
+
description: "Clear all notifications",
|
|
1542
|
+
inputSchema: { type: "object", properties: {} }
|
|
1543
|
+
},
|
|
1544
|
+
// Workspace
|
|
1545
|
+
{
|
|
1546
|
+
name: "list_workspace_members",
|
|
1547
|
+
description: "List all members in a workspace",
|
|
1548
|
+
inputSchema: {
|
|
1549
|
+
type: "object",
|
|
1550
|
+
properties: {
|
|
1551
|
+
workspaceId: { type: "string", description: "Workspace ID" }
|
|
1552
|
+
},
|
|
1553
|
+
required: ["workspaceId"]
|
|
1554
|
+
}
|
|
1555
|
+
},
|
|
1556
|
+
// Search
|
|
1557
|
+
{
|
|
1558
|
+
name: "search",
|
|
1559
|
+
description: "Search across projects, tasks, comments, and activities",
|
|
1560
|
+
inputSchema: {
|
|
1561
|
+
type: "object",
|
|
1562
|
+
properties: {
|
|
1563
|
+
q: { type: "string", description: "Search query" },
|
|
1564
|
+
type: {
|
|
1565
|
+
type: "string",
|
|
1566
|
+
enum: [
|
|
1567
|
+
"all",
|
|
1568
|
+
"tasks",
|
|
1569
|
+
"projects",
|
|
1570
|
+
"workspaces",
|
|
1571
|
+
"comments",
|
|
1572
|
+
"activities"
|
|
1573
|
+
],
|
|
1574
|
+
description: "Search type"
|
|
1575
|
+
}
|
|
1576
|
+
},
|
|
1577
|
+
required: ["q"]
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
// Activity
|
|
1581
|
+
{
|
|
1582
|
+
name: "list_activities",
|
|
1583
|
+
description: "List all activities for a task",
|
|
1584
|
+
inputSchema: {
|
|
1585
|
+
type: "object",
|
|
1586
|
+
properties: { taskId: { type: "string", description: "Task ID" } },
|
|
1587
|
+
required: ["taskId"]
|
|
1588
|
+
}
|
|
1589
|
+
},
|
|
1590
|
+
// Invitations
|
|
1591
|
+
{
|
|
1592
|
+
name: "list_pending_invitations",
|
|
1593
|
+
description: "List pending invitations for the current user",
|
|
1594
|
+
inputSchema: { type: "object", properties: {} }
|
|
1595
|
+
},
|
|
1596
|
+
{
|
|
1597
|
+
name: "get_invitation",
|
|
1598
|
+
description: "Get an invitation by ID",
|
|
1599
|
+
inputSchema: {
|
|
1600
|
+
type: "object",
|
|
1601
|
+
properties: { id: { type: "string", description: "Invitation ID" } },
|
|
1602
|
+
required: ["id"]
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
];
|
|
1606
|
+
}
|
|
1607
|
+
async start() {
|
|
1608
|
+
const transport = new StdioServerTransport();
|
|
1609
|
+
await this.server.connect(transport);
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
async function main() {
|
|
1613
|
+
const baseUrl = process.env.KANEO_BASE_URL || "http://localhost:1337";
|
|
1614
|
+
const token = process.env.KANEO_TOKEN;
|
|
1615
|
+
if (!token) {
|
|
1616
|
+
console.error("Error: KANEO_TOKEN environment variable is required");
|
|
1617
|
+
process.exit(1);
|
|
1618
|
+
}
|
|
1619
|
+
const server = new KaneoMCPServer({ baseUrl, token });
|
|
1620
|
+
await server.start();
|
|
1621
|
+
}
|
|
1622
|
+
main().catch(console.error);
|
|
1623
|
+
export {
|
|
1624
|
+
KaneoMCPServer
|
|
1625
|
+
};
|