@omnicoreos/planka-mcp 0.2.0 → 0.3.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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +26 -0
- package/.claude-plugin/plugin.json +45 -0
- package/.codex-plugin/mcp.json +16 -0
- package/.codex-plugin/plugin.json +27 -0
- package/.mcp.json +17 -0
- package/CHANGELOG.md +510 -0
- package/README.es.md +294 -55
- package/README.md +293 -55
- package/dist/cli/init.d.ts +101 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +481 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/client.d.ts +32 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +106 -32
- package/dist/client.js.map +1 -1
- package/dist/config/policy.d.ts +82 -0
- package/dist/config/policy.d.ts.map +1 -0
- package/dist/config/policy.js +226 -0
- package/dist/config/policy.js.map +1 -0
- package/dist/errors.d.ts +5 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +62 -5
- package/dist/errors.js.map +1 -1
- package/dist/identity.generated.d.ts +2 -1
- package/dist/identity.generated.d.ts.map +1 -1
- package/dist/identity.generated.js +2 -1
- package/dist/identity.generated.js.map +1 -1
- package/dist/index.js +85 -10
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +21 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +37 -0
- package/dist/instructions.js.map +1 -0
- package/dist/operations/actions.d.ts +654 -0
- package/dist/operations/actions.d.ts.map +1 -0
- package/dist/operations/actions.js +154 -0
- package/dist/operations/actions.js.map +1 -0
- package/dist/operations/archive.d.ts +28 -0
- package/dist/operations/archive.d.ts.map +1 -0
- package/dist/operations/archive.js +74 -0
- package/dist/operations/archive.js.map +1 -0
- package/dist/operations/attachments.d.ts +1 -1
- package/dist/operations/attachments.d.ts.map +1 -1
- package/dist/operations/attachments.js +3 -1
- package/dist/operations/attachments.js.map +1 -1
- package/dist/operations/board-id.d.ts +1 -1
- package/dist/operations/board-id.d.ts.map +1 -1
- package/dist/operations/board-id.js +13 -7
- package/dist/operations/board-id.js.map +1 -1
- package/dist/operations/boards.d.ts +96 -19
- package/dist/operations/boards.d.ts.map +1 -1
- package/dist/operations/boards.js +377 -93
- package/dist/operations/boards.js.map +1 -1
- package/dist/operations/card-brief.d.ts +91 -0
- package/dist/operations/card-brief.d.ts.map +1 -0
- package/dist/operations/card-brief.js +79 -0
- package/dist/operations/card-brief.js.map +1 -0
- package/dist/operations/cards.d.ts +34 -9
- package/dist/operations/cards.d.ts.map +1 -1
- package/dist/operations/cards.js +60 -14
- package/dist/operations/cards.js.map +1 -1
- package/dist/operations/comments.d.ts +61 -4
- package/dist/operations/comments.d.ts.map +1 -1
- package/dist/operations/comments.js +91 -8
- package/dist/operations/comments.js.map +1 -1
- package/dist/operations/duplicate.d.ts +16 -0
- package/dist/operations/duplicate.d.ts.map +1 -0
- package/dist/operations/duplicate.js +43 -0
- package/dist/operations/duplicate.js.map +1 -0
- package/dist/operations/labels.d.ts +1 -1
- package/dist/operations/labels.d.ts.map +1 -1
- package/dist/operations/labels.js +7 -4
- package/dist/operations/labels.js.map +1 -1
- package/dist/operations/lists.d.ts +63 -1
- package/dist/operations/lists.d.ts.map +1 -1
- package/dist/operations/lists.js +97 -2
- package/dist/operations/lists.js.map +1 -1
- package/dist/operations/members.d.ts +39 -0
- package/dist/operations/members.d.ts.map +1 -0
- package/dist/operations/members.js +107 -0
- package/dist/operations/members.js.map +1 -0
- package/dist/operations/projects.d.ts +16 -0
- package/dist/operations/projects.d.ts.map +1 -1
- package/dist/operations/projects.js +54 -9
- package/dist/operations/projects.js.map +1 -1
- package/dist/operations/tasks.d.ts +1 -1
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/operations/tasks.js +5 -3
- package/dist/operations/tasks.js.map +1 -1
- package/dist/operations/users.d.ts +123 -0
- package/dist/operations/users.d.ts.map +1 -0
- package/dist/operations/users.js +180 -0
- package/dist/operations/users.js.map +1 -0
- package/dist/operations/verify.d.ts +84 -0
- package/dist/operations/verify.d.ts.map +1 -0
- package/dist/operations/verify.js +124 -0
- package/dist/operations/verify.js.map +1 -0
- package/dist/prompts.d.ts +48 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +155 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +38 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +127 -0
- package/dist/resources.js.map +1 -0
- package/dist/schemas/entities.d.ts +115 -24
- package/dist/schemas/entities.d.ts.map +1 -1
- package/dist/schemas/entities.js +48 -0
- package/dist/schemas/entities.js.map +1 -1
- package/dist/schemas/requests.d.ts +121 -46
- package/dist/schemas/requests.d.ts.map +1 -1
- package/dist/schemas/requests.js +57 -12
- package/dist/schemas/requests.js.map +1 -1
- package/dist/schemas/responses.d.ts +541 -186
- package/dist/schemas/responses.d.ts.map +1 -1
- package/dist/schemas/responses.js +13 -2
- package/dist/schemas/responses.js.map +1 -1
- package/dist/tools/activity.d.ts +150 -0
- package/dist/tools/activity.d.ts.map +1 -0
- package/dist/tools/activity.js +198 -0
- package/dist/tools/activity.js.map +1 -0
- package/dist/tools/annotations.d.ts +52 -0
- package/dist/tools/annotations.d.ts.map +1 -0
- package/dist/tools/annotations.js +214 -0
- package/dist/tools/annotations.js.map +1 -0
- package/dist/tools/attachments.d.ts +28 -4
- package/dist/tools/attachments.d.ts.map +1 -1
- package/dist/tools/attachments.js +53 -34
- package/dist/tools/attachments.js.map +1 -1
- package/dist/tools/card-ops.d.ts +232 -0
- package/dist/tools/card-ops.d.ts.map +1 -0
- package/dist/tools/card-ops.js +333 -0
- package/dist/tools/card-ops.js.map +1 -0
- package/dist/tools/cards.d.ts +90 -8
- package/dist/tools/cards.d.ts.map +1 -1
- package/dist/tools/cards.js +411 -128
- package/dist/tools/cards.js.map +1 -1
- package/dist/tools/comments.d.ts +226 -22
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +163 -134
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/dispatch.d.ts +47 -0
- package/dist/tools/dispatch.d.ts.map +1 -0
- package/dist/tools/dispatch.js +63 -0
- package/dist/tools/dispatch.js.map +1 -0
- package/dist/tools/guard.d.ts +9 -0
- package/dist/tools/guard.d.ts.map +1 -0
- package/dist/tools/guard.js +20 -0
- package/dist/tools/guard.js.map +1 -0
- package/dist/tools/index.d.ts +748 -450
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +136 -17
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/labels.d.ts +213 -18
- package/dist/tools/labels.d.ts.map +1 -1
- package/dist/tools/labels.js +218 -203
- package/dist/tools/labels.js.map +1 -1
- package/dist/tools/lists.d.ts +222 -15
- package/dist/tools/lists.d.ts.map +1 -1
- package/dist/tools/lists.js +175 -156
- package/dist/tools/lists.js.map +1 -1
- package/dist/tools/members.d.ts +128 -0
- package/dist/tools/members.d.ts.map +1 -0
- package/dist/tools/members.js +150 -0
- package/dist/tools/members.js.map +1 -0
- package/dist/tools/navigation.d.ts +22 -2
- package/dist/tools/navigation.d.ts.map +1 -1
- package/dist/tools/navigation.js +60 -15
- package/dist/tools/navigation.js.map +1 -1
- package/dist/tools/queries.d.ts +196 -166
- package/dist/tools/queries.d.ts.map +1 -1
- package/dist/tools/queries.js +125 -155
- package/dist/tools/queries.js.map +1 -1
- package/dist/tools/tasks.d.ts +26 -6
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +110 -55
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/users.d.ts +130 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +165 -0
- package/dist/tools/users.js.map +1 -0
- package/docs/planka-2x-gotchas.md +121 -5
- package/docs/tools.md +771 -187
- package/docs/troubleshooting.md +137 -5
- package/hooks/hooks.json +15 -0
- package/hooks/preflight.mjs +100 -0
- package/package.json +6 -1
- package/scripts/setup.sh +8 -26
- package/scripts/sync-identity.mjs +55 -1
- package/server.json +87 -6
- package/tests/smoke/planka-smoke.mjs +512 -72
- package/workflow/skills/planka-close-card/SKILL.md +18 -5
- package/workflow/skills/planka-orchestrator/SKILL.md +36 -7
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified writes — the one place that decides whether a write LANDED.
|
|
3
|
+
*
|
|
4
|
+
* A 200 from Planka proves that the request was accepted, not that the change
|
|
5
|
+
* is in the database: `PATCH /api/cards/:id {isSubscribed:true}` answers 200
|
|
6
|
+
* with `isSubscribed: null`, and a `DELETE` that returns the deleted item is
|
|
7
|
+
* still worth re-reading. So every write in this server writes, re-reads, and
|
|
8
|
+
* reports what the re-read says — never what was asked for.
|
|
9
|
+
*
|
|
10
|
+
* The pattern was written twice by hand (setCardLabels, add_attachment); this
|
|
11
|
+
* module is that pattern, once.
|
|
12
|
+
*/
|
|
13
|
+
import { PlankaError } from "../errors.js";
|
|
14
|
+
function describe(error) {
|
|
15
|
+
return error instanceof Error ? error.message : String(error);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run a write, re-read the entity, and report whether the change is really there.
|
|
19
|
+
*
|
|
20
|
+
* `landed` gets the re-read state and the write's own result; it answers the
|
|
21
|
+
* only question that matters: is what we asked for true now?
|
|
22
|
+
*/
|
|
23
|
+
export async function verifiedWrite(opts) {
|
|
24
|
+
const result = await opts.write();
|
|
25
|
+
let after;
|
|
26
|
+
try {
|
|
27
|
+
after = await opts.reread(result);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return {
|
|
31
|
+
result,
|
|
32
|
+
verified: false,
|
|
33
|
+
verificationError: `the write was sent but could not be re-read: ${describe(error)}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return { result, verified: opts.landed(after, result), after };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Run a delete and confirm the entity is really gone.
|
|
40
|
+
*
|
|
41
|
+
* `confirmGone` returns true (gone), false (still there) or null (could not
|
|
42
|
+
* check — e.g. the parent id needed for the re-read is unknown).
|
|
43
|
+
*/
|
|
44
|
+
export async function verifiedDelete(opts) {
|
|
45
|
+
const result = await opts.del();
|
|
46
|
+
let gone;
|
|
47
|
+
try {
|
|
48
|
+
gone = await opts.confirmGone(result);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
result,
|
|
53
|
+
verified: false,
|
|
54
|
+
verificationError: `the delete was sent but could not be confirmed: ${describe(error)}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (gone === null) {
|
|
58
|
+
return {
|
|
59
|
+
result,
|
|
60
|
+
verified: false,
|
|
61
|
+
verificationUnavailable: opts.unknownReason ?? "the entity's parent is unknown, so the delete could not be confirmed",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return { result, verified: gone };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Confirmation helper for entities that have their own GET: a 404 on re-read
|
|
68
|
+
* is the proof of deletion. Any other failure propagates.
|
|
69
|
+
*/
|
|
70
|
+
export async function goneOn404(reread) {
|
|
71
|
+
try {
|
|
72
|
+
await reread();
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error instanceof PlankaError && error.status === 404)
|
|
77
|
+
return true;
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Standard tool payload for a write.
|
|
83
|
+
*
|
|
84
|
+
* `success` mirrors `verified` and nothing else. "I could not check" is not a
|
|
85
|
+
* success: a payload that says `success: true` next to `verified: false` and
|
|
86
|
+
* "delete not confirmed" is read by the model as done, and the model moves on.
|
|
87
|
+
*
|
|
88
|
+
* - verified → success, no isError
|
|
89
|
+
* - unavailable → success:false, verified:false, isError, and a
|
|
90
|
+
* `verificationUnavailable` that names the parameter
|
|
91
|
+
* which would have made the check possible
|
|
92
|
+
* - anything else → isError, because the write cannot be claimed
|
|
93
|
+
*/
|
|
94
|
+
export function writeResult(payload, v) {
|
|
95
|
+
const body = {
|
|
96
|
+
success: v.verified,
|
|
97
|
+
verified: v.verified,
|
|
98
|
+
...(v.verificationError ? { verificationError: v.verificationError } : {}),
|
|
99
|
+
...(v.verificationUnavailable && !v.verificationError
|
|
100
|
+
? { verificationUnavailable: v.verificationUnavailable }
|
|
101
|
+
: {}),
|
|
102
|
+
...payload,
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: JSON.stringify(body) }],
|
|
106
|
+
...(v.verified ? {} : { isError: true }),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The "nothing to do" guard shared by the update tools: a PATCH with only an
|
|
111
|
+
* id is a no-op that Planka happily answers 200 to.
|
|
112
|
+
*/
|
|
113
|
+
export function nothingToDo(fields, extra) {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: `Error: nothing to do — pass at least one field to change (${fields}).${extra ? ` ${extra}` : ""}`,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
isError: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/operations/verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP prompts: three ways to start, all of them cheap.
|
|
3
|
+
*
|
|
4
|
+
* A prompt costs nothing until it is invoked — Claude Code surfaces them as
|
|
5
|
+
* `/mcp__planka__<name>`, Cursor from its prompt picker — so this is where the
|
|
6
|
+
* "how do I open / close / triage" procedures live instead of in `instructions`.
|
|
7
|
+
* They deliberately do NOT restate what tool descriptions already say; they
|
|
8
|
+
* order the calls and say what to look at in the answers.
|
|
9
|
+
*
|
|
10
|
+
* Codex supports neither prompts nor resources, so nothing here is required for
|
|
11
|
+
* correct use of the server.
|
|
12
|
+
*
|
|
13
|
+
* The three overlap with the workflow skills on purpose: the skills are the long
|
|
14
|
+
* form for a repo that adopted the board workflow, these are the short form for
|
|
15
|
+
* everyone else.
|
|
16
|
+
*/
|
|
17
|
+
export interface PromptArgument {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
required: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface PromptDefinition {
|
|
23
|
+
name: string;
|
|
24
|
+
title: string;
|
|
25
|
+
description: string;
|
|
26
|
+
arguments: PromptArgument[];
|
|
27
|
+
render: (args: Record<string, string>) => string;
|
|
28
|
+
}
|
|
29
|
+
export declare const PROMPTS: readonly PromptDefinition[];
|
|
30
|
+
/** What `prompts/list` answers. Deterministic order, cacheable by the client. */
|
|
31
|
+
export declare function listPrompts(): {
|
|
32
|
+
name: string;
|
|
33
|
+
title: string;
|
|
34
|
+
description: string;
|
|
35
|
+
arguments: PromptArgument[];
|
|
36
|
+
}[];
|
|
37
|
+
/** What `prompts/get` answers. Unknown name throws; a missing required argument too. */
|
|
38
|
+
export declare function getPrompt(name: string, args?: Record<string, string>): {
|
|
39
|
+
description: string;
|
|
40
|
+
messages: {
|
|
41
|
+
role: "user";
|
|
42
|
+
content: {
|
|
43
|
+
type: "text";
|
|
44
|
+
text: string;
|
|
45
|
+
};
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC;CAClD;AAqBD,eAAO,MAAM,OAAO,EAAE,SAAS,gBAAgB,EA+F9C,CAAC;AAIF,iFAAiF;AACjF,wBAAgB,WAAW;;;;;IAO1B;AAED,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;;;;;;;;;EA2BxE"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP prompts: three ways to start, all of them cheap.
|
|
3
|
+
*
|
|
4
|
+
* A prompt costs nothing until it is invoked — Claude Code surfaces them as
|
|
5
|
+
* `/mcp__planka__<name>`, Cursor from its prompt picker — so this is where the
|
|
6
|
+
* "how do I open / close / triage" procedures live instead of in `instructions`.
|
|
7
|
+
* They deliberately do NOT restate what tool descriptions already say; they
|
|
8
|
+
* order the calls and say what to look at in the answers.
|
|
9
|
+
*
|
|
10
|
+
* Codex supports neither prompts nor resources, so nothing here is required for
|
|
11
|
+
* correct use of the server.
|
|
12
|
+
*
|
|
13
|
+
* The three overlap with the workflow skills on purpose: the skills are the long
|
|
14
|
+
* form for a repo that adopted the board workflow, these are the short form for
|
|
15
|
+
* everyone else.
|
|
16
|
+
*/
|
|
17
|
+
const boardArgument = {
|
|
18
|
+
name: "boardId",
|
|
19
|
+
description: "Board to work on. Optional: omit it when PLANKA_DEFAULT_BOARD_ID is configured, or let the summary resolve it.",
|
|
20
|
+
required: false,
|
|
21
|
+
};
|
|
22
|
+
/** "on board <id>" or "" — keeps the rendered text readable either way. */
|
|
23
|
+
function onBoard(args) {
|
|
24
|
+
const boardId = args.boardId?.trim();
|
|
25
|
+
return boardId ? ` on board ${boardId}` : "";
|
|
26
|
+
}
|
|
27
|
+
function boardIdNote(args) {
|
|
28
|
+
return args.boardId?.trim()
|
|
29
|
+
? ""
|
|
30
|
+
: " If no board is configured as the default, call planka_get_structure once to get its ID and say which board you picked.";
|
|
31
|
+
}
|
|
32
|
+
export const PROMPTS = [
|
|
33
|
+
{
|
|
34
|
+
name: "planka-open-session",
|
|
35
|
+
title: "Open a Planka session",
|
|
36
|
+
description: "Read the board the cheap way and report where it stands: columns, counts, what moved recently, what is waiting on a human.",
|
|
37
|
+
arguments: [
|
|
38
|
+
boardArgument,
|
|
39
|
+
{
|
|
40
|
+
name: "since",
|
|
41
|
+
description: "ISO date to measure recent movement from (defaults to the last 24 hours).",
|
|
42
|
+
required: false,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
render: (args) => {
|
|
46
|
+
const since = args.since?.trim();
|
|
47
|
+
return [
|
|
48
|
+
`Open the Planka board${onBoard(args)} and tell me where it stands.${boardIdNote(args)}`,
|
|
49
|
+
"",
|
|
50
|
+
"1. planka_board_summary first: it returns every column with its card count and every label with its ID in one call. Do not call planka_get_board.",
|
|
51
|
+
`2. planka_board_activity ${since ? `since ${since}` : "for the last 24 hours"}: what moved and who moved it. Planka logs card creation, moves, member changes and task completion only — comments and edits do not appear there.`,
|
|
52
|
+
"3. planka_find_cards with the listId of any column that looks decisive (blocked, waiting on a decision, ready to review): with a listId it reads a whole column in one request, nothing clipped.",
|
|
53
|
+
"",
|
|
54
|
+
"Then report, in this order: the shape of the board (columns and counts), what moved since the cutoff, the cards waiting on a human, and anything that looks stale or contradictory. Do not open individual cards yet — say which ones you would open and why.",
|
|
55
|
+
].join("\n");
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "planka-close-card",
|
|
60
|
+
title: "Close a Planka card",
|
|
61
|
+
description: "Record a closing comment with real evidence, move the card, and prove both landed.",
|
|
62
|
+
arguments: [
|
|
63
|
+
{
|
|
64
|
+
name: "cardId",
|
|
65
|
+
description: "Card to close.",
|
|
66
|
+
required: true,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "listId",
|
|
70
|
+
description: "Column to move the card to. Optional: without it, propose the destination and ask before moving.",
|
|
71
|
+
required: false,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
render: (args) => {
|
|
75
|
+
const cardId = args.cardId?.trim() || "<cardId>";
|
|
76
|
+
const listId = args.listId?.trim();
|
|
77
|
+
return [
|
|
78
|
+
`Close Planka card ${cardId}.`,
|
|
79
|
+
"",
|
|
80
|
+
`1. Read it whole first: planka_get_card ${cardId} with withComments, and keep paging planka_get_comments while hasMore is true. The description says how the card was born; the comments say where it stands today, and the last one usually wins. Never act on a card you have not read to the end.`,
|
|
81
|
+
"2. State the evidence you actually have: what changed, where to check it, the one step that proves it, what could regress nearby, and what you could NOT verify. If a claim has no evidence, say so instead of implying it.",
|
|
82
|
+
"3. planka_add_comment with that closing note.",
|
|
83
|
+
listId
|
|
84
|
+
? `4. planka_move_card to list ${listId}.`
|
|
85
|
+
: "4. Propose the destination column (from planka_board_summary) and ask me before moving the card.",
|
|
86
|
+
"5. Check the `verified` field of both writes. A write that comes back without it confirmed nothing — re-read the card before telling me it is closed.",
|
|
87
|
+
"",
|
|
88
|
+
"Do not apply a human-only label (decided, tested-ok or the equivalent on this board) on my behalf.",
|
|
89
|
+
].join("\n");
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "planka-board-triage",
|
|
94
|
+
title: "Triage the decision columns",
|
|
95
|
+
description: "Walk the columns that are waiting on a person and turn each card into one concrete question or next step.",
|
|
96
|
+
arguments: [
|
|
97
|
+
boardArgument,
|
|
98
|
+
{
|
|
99
|
+
name: "lists",
|
|
100
|
+
description: "Comma-separated names of the columns to walk. Defaults to whatever the summary shows as waiting on a human.",
|
|
101
|
+
required: false,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
render: (args) => {
|
|
105
|
+
const lists = args.lists?.trim();
|
|
106
|
+
return [
|
|
107
|
+
`Triage the Planka cards that are waiting on a person${onBoard(args)}.${boardIdNote(args)}`,
|
|
108
|
+
"",
|
|
109
|
+
"1. planka_board_summary to get the columns and their label IDs.",
|
|
110
|
+
lists
|
|
111
|
+
? `2. Walk these columns, in order: ${lists}. Use planka_find_cards with each listId — one request per column, nothing clipped.`
|
|
112
|
+
: "2. Pick the columns that are waiting on a human (a decision queue, a review queue, anything blocked) and walk them with planka_find_cards by listId — one request per column, nothing clipped.",
|
|
113
|
+
"3. For each card, read every comment (planka_get_card with withComments, paging planka_get_comments while hasMore). A card whose thread you did not finish is a card you cannot triage.",
|
|
114
|
+
"",
|
|
115
|
+
"For every card report one line: what it is waiting for, who owes the next move, and how long it has been sitting there. Then rank them: what is blocking other work first, what is stale and probably dead last. Flag any card whose comments contradict its description or its column, and say which side you believe.",
|
|
116
|
+
"",
|
|
117
|
+
"Do not move cards or apply labels during triage. Propose; I decide.",
|
|
118
|
+
].join("\n");
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
const byName = new Map(PROMPTS.map((prompt) => [prompt.name, prompt]));
|
|
123
|
+
/** What `prompts/list` answers. Deterministic order, cacheable by the client. */
|
|
124
|
+
export function listPrompts() {
|
|
125
|
+
return PROMPTS.map(({ name, title, description, arguments: args }) => ({
|
|
126
|
+
name,
|
|
127
|
+
title,
|
|
128
|
+
description,
|
|
129
|
+
arguments: args,
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
/** What `prompts/get` answers. Unknown name throws; a missing required argument too. */
|
|
133
|
+
export function getPrompt(name, args = {}) {
|
|
134
|
+
const prompt = byName.get(name);
|
|
135
|
+
if (!prompt) {
|
|
136
|
+
throw new Error(`Unknown prompt: ${name}. Available: ${PROMPTS.map((p) => p.name).join(", ")}`);
|
|
137
|
+
}
|
|
138
|
+
const missing = prompt.arguments
|
|
139
|
+
.filter((argument) => argument.required)
|
|
140
|
+
.filter((argument) => !args[argument.name]?.trim())
|
|
141
|
+
.map((argument) => argument.name);
|
|
142
|
+
if (missing.length > 0) {
|
|
143
|
+
throw new Error(`Prompt ${name} needs: ${missing.join(", ")}.`);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
description: prompt.description,
|
|
147
|
+
messages: [
|
|
148
|
+
{
|
|
149
|
+
role: "user",
|
|
150
|
+
content: { type: "text", text: prompt.render(args) },
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface ResourceDefinition {
|
|
2
|
+
uri: string;
|
|
3
|
+
name: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
/** Path inside the package, relative to its root. Absent = generated. */
|
|
8
|
+
file?: string;
|
|
9
|
+
/** Generated resources build their own body. */
|
|
10
|
+
generate?: () => string;
|
|
11
|
+
}
|
|
12
|
+
/** The valid Planka label colors, straight from the schema the tools validate with. */
|
|
13
|
+
export declare function labelColorsDocument(): string;
|
|
14
|
+
/**
|
|
15
|
+
* The catalogue. Order is fixed on purpose: `resources/list` should be
|
|
16
|
+
* deterministic so clients can cache it and prompt caches keep hitting.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RESOURCES: readonly ResourceDefinition[];
|
|
19
|
+
/** Everything `resources/list` answers. Shape matches the MCP `Resource` type. */
|
|
20
|
+
export declare function listResources(): {
|
|
21
|
+
uri: string;
|
|
22
|
+
name: string;
|
|
23
|
+
title: string;
|
|
24
|
+
description: string;
|
|
25
|
+
mimeType: string;
|
|
26
|
+
}[];
|
|
27
|
+
/**
|
|
28
|
+
* Body of one resource. Unknown URIs throw: a resource read that silently
|
|
29
|
+
* answers empty is the same false green as a write that never re-reads.
|
|
30
|
+
*/
|
|
31
|
+
export declare function readResource(uri: string): Promise<{
|
|
32
|
+
contents: {
|
|
33
|
+
uri: string;
|
|
34
|
+
mimeType: string;
|
|
35
|
+
text: string;
|
|
36
|
+
}[];
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;CACzB;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,kBAAkB,EAuDlD,CAAC;AAgBF,kFAAkF;AAClF,wBAAgB,aAAa;;;;;;IAQ5B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvD,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7D,CAAC,CAsBD"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources: the guides that travel in the tarball, served over the wire.
|
|
3
|
+
*
|
|
4
|
+
* Why resources and not more `instructions`: a resource costs nothing until
|
|
5
|
+
* someone reads it. `instructions` is a fixed per-session cost paid on top of
|
|
6
|
+
* `tools/list`, so it holds only what every session needs; everything longer —
|
|
7
|
+
* the workflow guide, the board template, the two skills, the Planka 2.x
|
|
8
|
+
* gotchas — lives here and is pulled on demand (Claude Code by `@`-mention,
|
|
9
|
+
* Cursor from its resource picker). Codex does not support resources; that is
|
|
10
|
+
* why nothing here is load-bearing for correctness.
|
|
11
|
+
*
|
|
12
|
+
* Files are read from the published package at runtime, resolved from
|
|
13
|
+
* `import.meta.url`, so `dist/resources.js` and `src/resources.ts` both sit one
|
|
14
|
+
* level under the package root and find `workflow/` and `docs/` the same way.
|
|
15
|
+
* A missing file is not an error: an install that trimmed the tarball gets a
|
|
16
|
+
* short note pointing at the repository instead of a broken read.
|
|
17
|
+
*/
|
|
18
|
+
import { readFile } from "node:fs/promises";
|
|
19
|
+
import { LabelColorSchema } from "./schemas/entities.js";
|
|
20
|
+
const REPO_URL = "https://github.com/omnicoreos/planka-mcp";
|
|
21
|
+
/** The valid Planka label colors, straight from the schema the tools validate with. */
|
|
22
|
+
export function labelColorsDocument() {
|
|
23
|
+
return JSON.stringify({
|
|
24
|
+
description: "Valid values for the `color` field of planka_create_label and planka_update_label. Planka rejects anything else with a validation error.",
|
|
25
|
+
colors: LabelColorSchema.options,
|
|
26
|
+
count: LabelColorSchema.options.length,
|
|
27
|
+
}, null, 2);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The catalogue. Order is fixed on purpose: `resources/list` should be
|
|
31
|
+
* deterministic so clients can cache it and prompt caches keep hitting.
|
|
32
|
+
*/
|
|
33
|
+
export const RESOURCES = [
|
|
34
|
+
{
|
|
35
|
+
uri: "planka://workflow/readme",
|
|
36
|
+
name: "workflow-readme",
|
|
37
|
+
title: "Planka agent workflow",
|
|
38
|
+
description: "The optional board workflow: columns, labels, who moves what, and the director/worker split. Read it before running cards in parallel.",
|
|
39
|
+
mimeType: "text/markdown",
|
|
40
|
+
file: "workflow/README.md",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
uri: "planka://workflow/board-template",
|
|
44
|
+
name: "workflow-board-template",
|
|
45
|
+
title: "Workflow board template",
|
|
46
|
+
description: "The columns and labels the workflow expects, ready to create on a fresh board.",
|
|
47
|
+
mimeType: "text/markdown",
|
|
48
|
+
file: "workflow/board-template.md",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
uri: "planka://workflow/skills/orchestrator",
|
|
52
|
+
name: "skill-orchestrator",
|
|
53
|
+
title: "Skill: planka-orchestrator",
|
|
54
|
+
description: "Director role: select cards, dispatch one worker per card, audit evidence, merge. Same text the plugin installs as a skill.",
|
|
55
|
+
mimeType: "text/markdown",
|
|
56
|
+
file: "workflow/skills/planka-orchestrator/SKILL.md",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
uri: "planka://workflow/skills/close-card",
|
|
60
|
+
name: "skill-close-card",
|
|
61
|
+
title: "Skill: planka-close-card",
|
|
62
|
+
description: "Closing a card honestly: required evidence, the closing comment template, and which transition each role owns.",
|
|
63
|
+
mimeType: "text/markdown",
|
|
64
|
+
file: "workflow/skills/planka-close-card/SKILL.md",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
uri: "planka://gotchas/planka-2x",
|
|
68
|
+
name: "planka-2x-gotchas",
|
|
69
|
+
title: "Planka 2.x gotchas",
|
|
70
|
+
description: "How Planka 2.x actually behaves: HTML-with-200 on unknown GETs, 404 that means 403, fixed page sizes, archive lists. Read this when a call answers something that makes no sense.",
|
|
71
|
+
mimeType: "text/markdown",
|
|
72
|
+
file: "docs/planka-2x-gotchas.md",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
uri: "planka://labels/colors",
|
|
76
|
+
name: "label-colors",
|
|
77
|
+
title: "Valid label colors",
|
|
78
|
+
description: "Every color planka_create_label and planka_update_label accept, as JSON. Generated from the schema, so it can never drift from what the server validates.",
|
|
79
|
+
mimeType: "application/json",
|
|
80
|
+
generate: labelColorsDocument,
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
const byUri = new Map(RESOURCES.map((resource) => [resource.uri, resource]));
|
|
84
|
+
/** Package root: this module lives one level under it in both src/ and dist/. */
|
|
85
|
+
function packageRoot() {
|
|
86
|
+
return new URL("../", import.meta.url);
|
|
87
|
+
}
|
|
88
|
+
function missingFileNote(resource) {
|
|
89
|
+
return (`${resource.title} is not present in this installation ` +
|
|
90
|
+
`(expected ${resource.file}). Read it at ${REPO_URL}/blob/main/${resource.file}.`);
|
|
91
|
+
}
|
|
92
|
+
/** Everything `resources/list` answers. Shape matches the MCP `Resource` type. */
|
|
93
|
+
export function listResources() {
|
|
94
|
+
return RESOURCES.map(({ uri, name, title, description, mimeType }) => ({
|
|
95
|
+
uri,
|
|
96
|
+
name,
|
|
97
|
+
title,
|
|
98
|
+
description,
|
|
99
|
+
mimeType,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Body of one resource. Unknown URIs throw: a resource read that silently
|
|
104
|
+
* answers empty is the same false green as a write that never re-reads.
|
|
105
|
+
*/
|
|
106
|
+
export async function readResource(uri) {
|
|
107
|
+
const resource = byUri.get(uri);
|
|
108
|
+
if (!resource) {
|
|
109
|
+
throw new Error(`Unknown resource: ${uri}. Available: ${RESOURCES.map((r) => r.uri).join(", ")}`);
|
|
110
|
+
}
|
|
111
|
+
let text;
|
|
112
|
+
if (resource.generate) {
|
|
113
|
+
text = resource.generate();
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
try {
|
|
117
|
+
text = await readFile(new URL(resource.file, packageRoot()), "utf8");
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
text = missingFileNote(resource);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
contents: [{ uri: resource.uri, mimeType: resource.mimeType, text }],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|