@kaneo/mcp 0.1.8 → 0.1.10
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/README.md +12 -4
- package/dist/tools/register.js +122 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
It runs over stdio, signs in with Kaneo's device flow, and then calls the Kaneo API with a bearer token. The package lives in `packages/mcp` in this monorepo and exposes the `kaneo-mcp` CLI.
|
|
6
6
|
|
|
7
|
-
> **Tip:** Every Kaneo instance also ships a built-in HTTP MCP endpoint at `/api/mcp`. If your MCP client supports Streamable HTTP transport (e.g. Claude Code), you can connect directly without this package. See the [MCP docs](https://
|
|
7
|
+
> **Tip:** Every Kaneo instance also ships a built-in HTTP MCP endpoint at `/api/mcp`. If your MCP client supports Streamable HTTP transport (e.g. Claude Code), you can connect directly without this package. See the [MCP docs](https://kaneo.app/docs/core/integrations/mcp) for details.
|
|
8
8
|
|
|
9
9
|
## Prerequisites
|
|
10
10
|
|
|
@@ -115,13 +115,21 @@ For headless or sandboxed environments where opening a browser is impractical, s
|
|
|
115
115
|
|
|
116
116
|
## Tools
|
|
117
117
|
|
|
118
|
-
- Session: `whoami`, `list_workspaces`
|
|
119
|
-
-
|
|
120
|
-
-
|
|
118
|
+
- Session: `whoami`, `list_workspaces`, `list_workspace_members`, `list_notifications`
|
|
119
|
+
- Search: `search`
|
|
120
|
+
- Projects: `list_projects`, `get_project`, `create_project`, `update_project`, `list_project_columns`
|
|
121
|
+
- Tasks: `list_tasks`, `get_task`, `create_task`, `update_task`, `delete_task`, `move_task`, `update_task_status`, `update_task_assignee`, `update_task_due_date`, `list_task_activity`
|
|
122
|
+
- Time entries: `list_task_time_entries`, `get_time_entry`, `create_time_entry`, `update_time_entry`
|
|
121
123
|
- Comments: `list_task_comments`, `create_task_comment`, `update_task_comment`, `delete_task_comment`
|
|
122
124
|
- Labels: `list_workspace_labels`, `create_label`, `attach_label_to_task`, `detach_label_from_task`, `delete_label`
|
|
123
125
|
- Task relations: `create_task_relation`, `get_task_relations`, `delete_task_relation`
|
|
124
126
|
|
|
127
|
+
Call `list_project_columns` before setting a status: the column slugs it
|
|
128
|
+
returns are the values `create_task` and `update_task_status` accept.
|
|
129
|
+
`list_workspace_members` resolves the user IDs the assignee tools expect.
|
|
130
|
+
Time entries have no delete endpoint on the API, so there is no
|
|
131
|
+
`delete_time_entry` tool.
|
|
132
|
+
|
|
125
133
|
## Releasing
|
|
126
134
|
|
|
127
135
|
Bump `version` in `packages/mcp/package.json` and merge to `main`. The [publish workflow](../../.github/workflows/publish-mcp.yml) runs the package tests, publishes the new version to npm, and creates a `mcp-v<version>` GitHub release. Nothing is published while the version stays the same, so tool changes reach npm only once the version is bumped.
|
package/dist/tools/register.js
CHANGED
|
@@ -347,4 +347,126 @@ export function registerTools(server, ctx) {
|
|
|
347
347
|
method: "DELETE",
|
|
348
348
|
});
|
|
349
349
|
}));
|
|
350
|
+
server.registerTool("list_workspace_members", {
|
|
351
|
+
description: "List the members of a workspace. Use this to resolve the user ID an assignee tool expects.",
|
|
352
|
+
inputSchema: z.object({ workspaceId: nonEmptyString }),
|
|
353
|
+
}, async (args) => run(() => client.json(`/api/workspace/${encodeURIComponent(args.workspaceId)}/members`)));
|
|
354
|
+
server.registerTool("search", {
|
|
355
|
+
description: "Search across tasks, projects, workspaces, comments, and activities.",
|
|
356
|
+
inputSchema: z.object({
|
|
357
|
+
q: nonEmptyString.describe("Search query"),
|
|
358
|
+
type: z
|
|
359
|
+
.enum([
|
|
360
|
+
"all",
|
|
361
|
+
"tasks",
|
|
362
|
+
"projects",
|
|
363
|
+
"workspaces",
|
|
364
|
+
"comments",
|
|
365
|
+
"activities",
|
|
366
|
+
])
|
|
367
|
+
.optional()
|
|
368
|
+
.describe("Restrict results to one kind. Defaults to all."),
|
|
369
|
+
workspaceId: optionalNonEmptyString.describe("Limit to one workspace"),
|
|
370
|
+
projectId: optionalNonEmptyString.describe("Limit to one project"),
|
|
371
|
+
limit: z
|
|
372
|
+
.number()
|
|
373
|
+
.int()
|
|
374
|
+
.min(1)
|
|
375
|
+
.max(50)
|
|
376
|
+
.optional()
|
|
377
|
+
.describe("Maximum results, 1 to 50. Defaults to 20."),
|
|
378
|
+
}),
|
|
379
|
+
}, async (args) => {
|
|
380
|
+
const qs = new URLSearchParams({ q: args.q });
|
|
381
|
+
if (args.type)
|
|
382
|
+
qs.set("type", args.type);
|
|
383
|
+
if (args.workspaceId)
|
|
384
|
+
qs.set("workspaceId", args.workspaceId);
|
|
385
|
+
if (args.projectId)
|
|
386
|
+
qs.set("projectId", args.projectId);
|
|
387
|
+
if (args.limit !== undefined)
|
|
388
|
+
qs.set("limit", String(args.limit));
|
|
389
|
+
return run(() => client.json(`/api/search?${qs.toString()}`));
|
|
390
|
+
});
|
|
391
|
+
server.registerTool("list_project_columns", {
|
|
392
|
+
description: "List a project's columns. Their slugs are the values update_task_status and create_task accept as a status.",
|
|
393
|
+
inputSchema: z.object({ projectId: nonEmptyString }),
|
|
394
|
+
}, async (args) => run(() => client.json(`/api/column/${encodeURIComponent(args.projectId)}`)));
|
|
395
|
+
server.registerTool("delete_task", {
|
|
396
|
+
description: "Delete a task by ID.",
|
|
397
|
+
inputSchema: z.object({ taskId: nonEmptyString }),
|
|
398
|
+
}, async (args) => run(() => client.json(`/api/task/${encodeURIComponent(args.taskId)}`, {
|
|
399
|
+
method: "DELETE",
|
|
400
|
+
})));
|
|
401
|
+
server.registerTool("update_task_assignee", {
|
|
402
|
+
description: "Assign a task to a workspace member, or pass a null userId to unassign it.",
|
|
403
|
+
inputSchema: z.object({
|
|
404
|
+
taskId: nonEmptyString,
|
|
405
|
+
userId: nonEmptyString
|
|
406
|
+
.nullable()
|
|
407
|
+
.describe("Member user ID, or null to unassign"),
|
|
408
|
+
}),
|
|
409
|
+
}, async (args) => run(() => client.json(`/api/task/assignee/${encodeURIComponent(args.taskId)}`, {
|
|
410
|
+
method: "PUT",
|
|
411
|
+
body: JSON.stringify({ userId: args.userId }),
|
|
412
|
+
})));
|
|
413
|
+
server.registerTool("update_task_due_date", {
|
|
414
|
+
description: "Set a task's due date. Omit dueDate to clear it.",
|
|
415
|
+
inputSchema: z.object({
|
|
416
|
+
taskId: nonEmptyString,
|
|
417
|
+
dueDate: optionalIsoDateTimeSchema,
|
|
418
|
+
}),
|
|
419
|
+
}, async (args) => run(() => client.json(`/api/task/due-date/${encodeURIComponent(args.taskId)}`, {
|
|
420
|
+
method: "PUT",
|
|
421
|
+
body: JSON.stringify(args.dueDate === undefined ? {} : { dueDate: args.dueDate }),
|
|
422
|
+
})));
|
|
423
|
+
server.registerTool("list_task_time_entries", {
|
|
424
|
+
description: "List the time entries logged against a task.",
|
|
425
|
+
inputSchema: z.object({ taskId: nonEmptyString }),
|
|
426
|
+
}, async (args) => run(() => client.json(`/api/time-entry/task/${encodeURIComponent(args.taskId)}`)));
|
|
427
|
+
server.registerTool("get_time_entry", {
|
|
428
|
+
description: "Get a single time entry by ID.",
|
|
429
|
+
inputSchema: z.object({ id: nonEmptyString }),
|
|
430
|
+
}, async (args) => run(() => client.json(`/api/time-entry/${encodeURIComponent(args.id)}`)));
|
|
431
|
+
server.registerTool("create_time_entry", {
|
|
432
|
+
description: "Log time against a task. Omit endTime to leave the entry running.",
|
|
433
|
+
inputSchema: z.object({
|
|
434
|
+
taskId: nonEmptyString,
|
|
435
|
+
startTime: isoDateTimeSchema,
|
|
436
|
+
endTime: optionalIsoDateTimeSchema,
|
|
437
|
+
description: optionalNonEmptyString,
|
|
438
|
+
}),
|
|
439
|
+
}, async (args) => run(() => client.json("/api/time-entry", {
|
|
440
|
+
method: "POST",
|
|
441
|
+
body: JSON.stringify({
|
|
442
|
+
taskId: args.taskId,
|
|
443
|
+
startTime: args.startTime,
|
|
444
|
+
...(args.endTime ? { endTime: args.endTime } : {}),
|
|
445
|
+
...(args.description ? { description: args.description } : {}),
|
|
446
|
+
}),
|
|
447
|
+
})));
|
|
448
|
+
server.registerTool("update_time_entry", {
|
|
449
|
+
description: "Update a time entry. startTime is required; omit endTime to reopen the entry.",
|
|
450
|
+
inputSchema: z.object({
|
|
451
|
+
id: nonEmptyString,
|
|
452
|
+
startTime: isoDateTimeSchema,
|
|
453
|
+
endTime: optionalIsoDateTimeSchema,
|
|
454
|
+
description: optionalNonEmptyString,
|
|
455
|
+
}),
|
|
456
|
+
}, async (args) => run(() => client.json(`/api/time-entry/${encodeURIComponent(args.id)}`, {
|
|
457
|
+
method: "PUT",
|
|
458
|
+
body: JSON.stringify({
|
|
459
|
+
startTime: args.startTime,
|
|
460
|
+
...(args.endTime ? { endTime: args.endTime } : {}),
|
|
461
|
+
...(args.description ? { description: args.description } : {}),
|
|
462
|
+
}),
|
|
463
|
+
})));
|
|
464
|
+
server.registerTool("list_task_activity", {
|
|
465
|
+
description: "List a task's activity history.",
|
|
466
|
+
inputSchema: z.object({ taskId: nonEmptyString }),
|
|
467
|
+
}, async (args) => run(() => client.json(`/api/activity/${encodeURIComponent(args.taskId)}`)));
|
|
468
|
+
server.registerTool("list_notifications", {
|
|
469
|
+
description: "List the signed-in user's notifications.",
|
|
470
|
+
inputSchema: z.object({}),
|
|
471
|
+
}, async () => run(() => client.json("/api/notification")));
|
|
350
472
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaneo/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"mcpName": "io.github.usekaneo/kaneo",
|
|
5
5
|
"description": "Official MCP (Model Context Protocol) server for Kaneo, the open source project management platform: manage tasks, projects, and labels from Claude, Cursor, and other MCP clients",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Kaneo (https://kaneo.app)",
|
|
8
|
-
"homepage": "https://
|
|
8
|
+
"homepage": "https://kaneo.app/docs/core/integrations/mcp",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "https://github.com/usekaneo/kaneo/",
|
|
@@ -52,17 +52,17 @@
|
|
|
52
52
|
"test:watch": "vitest --config vitest.config.ts"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
56
56
|
"open": "^11.0.0",
|
|
57
57
|
"prompts": "^2.4.2",
|
|
58
58
|
"zod": "^4.4.3"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@kaneo/typescript-config": "workspace:*",
|
|
62
|
-
"@types/node": "^
|
|
62
|
+
"@types/node": "^26.1.2",
|
|
63
63
|
"@types/prompts": "^2.4.9",
|
|
64
|
-
"tsx": "^4.23.
|
|
65
|
-
"typescript": "^
|
|
64
|
+
"tsx": "^4.23.9",
|
|
65
|
+
"typescript": "^7.0.2",
|
|
66
66
|
"vitest": "^4.1.10"
|
|
67
67
|
}
|
|
68
68
|
}
|