tana-mcp-codemode 0.2.0 → 0.2.2
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/package.json +16 -12
- package/src/api/tana.ts +41 -7
- package/src/api/types.ts +10 -0
- package/src/index.ts +0 -0
- package/src/prompts.ts +4 -2
- package/src/sandbox/executor.ts +8 -0
package/package.json
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tana-mcp-codemode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Codemode MCP server for Tana — AI writes TypeScript that executes against Tana Local API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"bin": {
|
|
8
8
|
"tana-mcp-codemode": "src/index.ts"
|
|
9
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"generate": "bun run scripts/generate.ts",
|
|
12
|
+
"list-endpoints": "bun run scripts/list-endpoints.ts",
|
|
13
|
+
"start": "bun run --env-file=.env src/index.ts",
|
|
14
|
+
"dev": "bun run --env-file=.env --watch src/index.ts",
|
|
15
|
+
"debug": "bun run --env-file=.env src/debug-server.ts",
|
|
16
|
+
"test": "bun test",
|
|
17
|
+
"typecheck": "bunx tsc --noEmit",
|
|
18
|
+
"prepublishOnly": "bun run typecheck",
|
|
19
|
+
"release:patch": "npm version patch && npm publish",
|
|
20
|
+
"release:minor": "npm version minor && npm publish",
|
|
21
|
+
"release:major": "npm version major && npm publish"
|
|
22
|
+
},
|
|
10
23
|
"files": [
|
|
11
24
|
"src/index.ts",
|
|
12
25
|
"src/prompts.ts",
|
|
@@ -41,14 +54,5 @@
|
|
|
41
54
|
"openapi-typescript": "^7.10.1",
|
|
42
55
|
"typescript": "^5.9.3"
|
|
43
56
|
},
|
|
44
|
-
"license": "MIT"
|
|
45
|
-
|
|
46
|
-
"generate": "bun run scripts/generate.ts",
|
|
47
|
-
"list-endpoints": "bun run scripts/list-endpoints.ts",
|
|
48
|
-
"start": "bun run --env-file=.env src/index.ts",
|
|
49
|
-
"dev": "bun run --env-file=.env --watch src/index.ts",
|
|
50
|
-
"debug": "bun run --env-file=.env src/debug-server.ts",
|
|
51
|
-
"test": "bun test",
|
|
52
|
-
"typecheck": "bunx tsc --noEmit"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
57
|
+
"license": "MIT"
|
|
58
|
+
}
|
package/src/api/tana.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
SearchResult,
|
|
17
17
|
Children,
|
|
18
18
|
EditNodeOptions,
|
|
19
|
+
MoveNodeOptions,
|
|
19
20
|
Tag,
|
|
20
21
|
CreateTagOptions,
|
|
21
22
|
AddFieldOptions,
|
|
@@ -54,6 +55,10 @@ export interface TanaAPI {
|
|
|
54
55
|
): Promise<Children>;
|
|
55
56
|
/** Edit a node's name/description */
|
|
56
57
|
edit(options: EditNodeOptions): Promise<{ success: boolean }>;
|
|
58
|
+
/** Move node to a new parent */
|
|
59
|
+
move(options: MoveNodeOptions): Promise<{ success: boolean }>;
|
|
60
|
+
/** Open a node in the Tana UI */
|
|
61
|
+
open(nodeId: string, openType?: "current" | "panel" | "tab"): Promise<{ success: boolean }>;
|
|
57
62
|
/** Move node to trash */
|
|
58
63
|
trash(nodeId: string): Promise<{ success: boolean }>;
|
|
59
64
|
/** Check a node's checkbox */
|
|
@@ -86,13 +91,15 @@ export interface TanaAPI {
|
|
|
86
91
|
setOption(
|
|
87
92
|
nodeId: string,
|
|
88
93
|
attributeId: string,
|
|
89
|
-
optionId: string
|
|
94
|
+
optionId: string,
|
|
95
|
+
mode?: "replace" | "append"
|
|
90
96
|
): Promise<{ success: boolean }>;
|
|
91
|
-
/** Set a field to a string value */
|
|
97
|
+
/** Set a field to a string value, or null to clear it */
|
|
92
98
|
setContent(
|
|
93
99
|
nodeId: string,
|
|
94
100
|
attributeId: string,
|
|
95
|
-
content: string
|
|
101
|
+
content: string | null,
|
|
102
|
+
mode?: "replace" | "append"
|
|
96
103
|
): Promise<{ success: boolean }>;
|
|
97
104
|
};
|
|
98
105
|
|
|
@@ -202,6 +209,31 @@ export function createTanaAPI(
|
|
|
202
209
|
return { success: !!result.nodeId };
|
|
203
210
|
},
|
|
204
211
|
|
|
212
|
+
async move(options: MoveNodeOptions): Promise<{ success: boolean }> {
|
|
213
|
+
const result = await client.post<{ nodeId: string; message: string }>(
|
|
214
|
+
`/nodes/${options.nodeId}/move`,
|
|
215
|
+
{
|
|
216
|
+
targetNodeId: options.targetNodeId,
|
|
217
|
+
keepSourceReference: options.keepSourceReference,
|
|
218
|
+
position: options.position,
|
|
219
|
+
referenceNodeId: options.referenceNodeId,
|
|
220
|
+
sourceParentId: options.sourceParentId,
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
return { success: !!result.nodeId };
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
async open(
|
|
227
|
+
nodeId: string,
|
|
228
|
+
openType: "current" | "panel" | "tab" = "current"
|
|
229
|
+
): Promise<{ success: boolean }> {
|
|
230
|
+
const result = await client.post<{ nodeId: string; message: string }>(
|
|
231
|
+
`/nodes/${nodeId}/open`,
|
|
232
|
+
{ openType }
|
|
233
|
+
);
|
|
234
|
+
return { success: !!result.nodeId };
|
|
235
|
+
},
|
|
236
|
+
|
|
205
237
|
async trash(nodeId: string): Promise<{ success: boolean }> {
|
|
206
238
|
const result = await client.post<{ nodeId: string; message: string }>(
|
|
207
239
|
`/nodes/${nodeId}/trash`,
|
|
@@ -317,11 +349,12 @@ export function createTanaAPI(
|
|
|
317
349
|
async setOption(
|
|
318
350
|
nodeId: string,
|
|
319
351
|
attributeId: string,
|
|
320
|
-
optionId: string
|
|
352
|
+
optionId: string,
|
|
353
|
+
mode?: "replace" | "append"
|
|
321
354
|
): Promise<{ success: boolean }> {
|
|
322
355
|
const result = await client.post<{ nodeId: string; message: string }>(
|
|
323
356
|
`/nodes/${nodeId}/fields/${attributeId}/option`,
|
|
324
|
-
{ optionId }
|
|
357
|
+
{ optionId, mode }
|
|
325
358
|
);
|
|
326
359
|
return { success: !!result.nodeId };
|
|
327
360
|
},
|
|
@@ -329,11 +362,12 @@ export function createTanaAPI(
|
|
|
329
362
|
async setContent(
|
|
330
363
|
nodeId: string,
|
|
331
364
|
attributeId: string,
|
|
332
|
-
content: string
|
|
365
|
+
content: string | null,
|
|
366
|
+
mode?: "replace" | "append"
|
|
333
367
|
): Promise<{ success: boolean }> {
|
|
334
368
|
const result = await client.post<{ nodeId: string; message: string }>(
|
|
335
369
|
`/nodes/${nodeId}/fields/${attributeId}/content`,
|
|
336
|
-
{ content }
|
|
370
|
+
{ content, mode }
|
|
337
371
|
);
|
|
338
372
|
return { success: !!result.nodeId };
|
|
339
373
|
},
|
package/src/api/types.ts
CHANGED
|
@@ -161,6 +161,16 @@ export interface SetCheckboxOptions {
|
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/** Options for moving a node to a new parent */
|
|
165
|
+
export interface MoveNodeOptions {
|
|
166
|
+
nodeId: string;
|
|
167
|
+
targetNodeId: string;
|
|
168
|
+
keepSourceReference?: boolean;
|
|
169
|
+
position?: "start" | "end" | "after" | "before";
|
|
170
|
+
referenceNodeId?: string;
|
|
171
|
+
sourceParentId?: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
164
174
|
/** Options for editing a node */
|
|
165
175
|
export interface EditNodeOptions {
|
|
166
176
|
nodeId: string;
|
package/src/index.ts
CHANGED
|
File without changes
|
package/src/prompts.ts
CHANGED
|
@@ -14,6 +14,8 @@ tana.nodes.search(query, options?) → SearchResult[]
|
|
|
14
14
|
tana.nodes.read(nodeId, maxDepth?) → string (markdown)
|
|
15
15
|
tana.nodes.getChildren(nodeId, { limit?, offset? }) → { children, total, hasMore }
|
|
16
16
|
tana.nodes.edit({ nodeId, name?, description? }) → { success }
|
|
17
|
+
tana.nodes.move({ nodeId, targetNodeId, keepSourceReference?, position?, referenceNodeId?, sourceParentId? }) → { success }
|
|
18
|
+
tana.nodes.open(nodeId, openType?) → { success } // openType: "current" | "panel" | "tab" (default: "current")
|
|
17
19
|
tana.nodes.trash(nodeId) → { success }
|
|
18
20
|
tana.nodes.check(nodeId) / uncheck(nodeId) → { success }
|
|
19
21
|
|
|
@@ -26,8 +28,8 @@ tana.tags.addField({ tagId, name, dataType: "plain"|"number"|"date"|"url"|"email
|
|
|
26
28
|
tana.tags.setCheckbox({ tagId, showCheckbox, doneStateMapping? })
|
|
27
29
|
|
|
28
30
|
### Fields
|
|
29
|
-
tana.fields.setOption(nodeId, attributeId, optionId)
|
|
30
|
-
tana.fields.setContent(nodeId, attributeId, content)
|
|
31
|
+
tana.fields.setOption(nodeId, attributeId, optionId, mode?) // mode: "replace" | "append" (default: "replace")
|
|
32
|
+
tana.fields.setContent(nodeId, attributeId, content, mode?) // content: string | null (null clears field), mode: "replace" | "append"
|
|
31
33
|
|
|
32
34
|
### Calendar
|
|
33
35
|
tana.calendar.getOrCreate(workspaceId, "day"|"week"|"month"|"year", date?)
|
package/src/sandbox/executor.ts
CHANGED
|
@@ -58,6 +58,14 @@ function createTrackedTanaAPI(
|
|
|
58
58
|
trackNodeId(options.nodeId);
|
|
59
59
|
return track("nodes.edit", () => tana.nodes.edit(options));
|
|
60
60
|
},
|
|
61
|
+
move: (options) => {
|
|
62
|
+
trackNodeId(options.nodeId);
|
|
63
|
+
return track("nodes.move", () => tana.nodes.move(options));
|
|
64
|
+
},
|
|
65
|
+
open: (nodeId, openType) => {
|
|
66
|
+
trackNodeId(nodeId);
|
|
67
|
+
return track("nodes.open", () => tana.nodes.open(nodeId, openType));
|
|
68
|
+
},
|
|
61
69
|
trash: (nodeId) => {
|
|
62
70
|
trackNodeId(nodeId);
|
|
63
71
|
return track("nodes.trash", () => tana.nodes.trash(nodeId));
|