tana-mcp-codemode 0.2.3 → 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/README.md CHANGED
@@ -1,314 +1,126 @@
1
- # Tana MCP Server
1
+ # tana-mcp-codemode
2
2
 
3
- A codemode MCP server for [Tana](https://tana.inc) knowledge management. AI writes TypeScript code that executes against the Tana Local API.
3
+ Codemode MCP server for [Tana](https://tana.inc). Instead of structured API calls, your AI writes TypeScript that executes directly against the Tana Local API.
4
4
 
5
- ## Features
5
+ ## Install
6
6
 
7
- - **Codemode Pattern** AI writes executable TypeScript, not structured API calls
8
- - **Tana Local API** — Workspaces, nodes, tags, fields, calendar, import
9
- - **Top-level Await** — `await tana.workspaces.list()` works directly
10
- - **Timeout Protection** — 10s max execution prevents infinite loops
11
- - **Script History** — SQLite persistence for debugging and replay
12
- - **Retry Logic** — Exponential backoff for transient failures
13
- - **Debug UI** — WebSocket-based dashboard for testing scripts
7
+ ### Binary (no runtime required)
14
8
 
15
- ## Requirements
9
+ Download from [GitHub Releases](https://github.com/fabiogaliano/tana-mcp-codemode/releases) for your platform:
16
10
 
17
- - [Bun](https://bun.sh) runtime
18
- - [Tana Desktop](https://tana.inc) with Local API enabled
19
- - API token from Tana (Settings → API → Generate Token)
11
+ | Platform | File |
12
+ |----------|------|
13
+ | macOS ARM | `tana-mcp-codemode-darwin-arm64` |
14
+ | macOS Intel | `tana-mcp-codemode-darwin-x64` |
15
+ | Linux x64 | `tana-mcp-codemode-linux-x64` |
16
+ | Linux ARM | `tana-mcp-codemode-linux-arm64` |
17
+ | Windows | `tana-mcp-codemode-windows-x64.exe` |
20
18
 
21
- ## Installation
19
+ ```bash
20
+ chmod +x tana-mcp-codemode-darwin-arm64
21
+ ./tana-mcp-codemode-darwin-arm64
22
+ ```
22
23
 
23
- ### Option 1: bun (recommended)
24
+ ### npm (requires Node.js ≥ 20)
24
25
 
25
26
  ```bash
26
- # Requires Bun runtime
27
- bun add -g tana-mcp-codemode
27
+ npm install -g tana-mcp-codemode
28
+ # or run without installing:
29
+ npx tana-mcp-codemode
28
30
  ```
29
31
 
30
- ### Option 2: From source
32
+ ### From source (requires Bun)
31
33
 
32
34
  ```bash
33
35
  git clone https://github.com/fabiogaliano/tana-mcp-codemode
34
36
  cd tana-mcp-codemode
35
37
  bun install
38
+ bun run src/entry-bun.ts
36
39
  ```
37
40
 
38
- ## Configuration
41
+ ## Prerequisites
39
42
 
40
- | Variable | Default | Description |
41
- | ----------------------- | ----------------------- | -------------------------------------------------------------- |
42
- | `TANA_API_TOKEN` | (required) | Bearer token from Tana Desktop |
43
- | `TANA_API_URL` | `http://127.0.0.1:8262` | Tana Local API URL |
44
- | `TANA_TIMEOUT` | `10000` | Request timeout in ms |
45
- | `TANA_HISTORY_PATH` | (platform default) | Custom path for SQLite history database |
46
- | `MAIN_TANA_WORKSPACE` | (none) | Default workspace name or ID, resolved at startup |
47
- | `TANA_SEARCH_WORKSPACES`| (none) | Comma-separated workspace names or IDs for default search scoping |
43
+ - [Tana Desktop](https://tana.inc) with **Local API enabled** (Settings → Local API → Enable)
44
+ - An API token from Tana (Settings → API → Generate Token)
48
45
 
49
- ## MCP Integration
46
+ ## MCP Configuration
50
47
 
51
- Add to your MCP client's configuration:
48
+ Add to your MCP client config (e.g. `claude_desktop_config.json`):
52
49
 
53
50
  ```json
54
51
  {
55
52
  "mcpServers": {
56
53
  "tana": {
57
- "command": "tana-mcp-codemode",
54
+ "command": "/path/to/tana-mcp-codemode-darwin-arm64",
58
55
  "env": {
59
- "TANA_API_TOKEN": "your_token_here",
60
- // Optional
61
- "MAIN_TANA_WORKSPACE": "My Workspace",
62
- "TANA_SEARCH_WORKSPACES": "My Workspace",
63
- // Optional: customize where the SQLite history database is stored
64
- "TANA_HISTORY_PATH": "/path/to/history.db"
56
+ "TANA_API_TOKEN": "your-token-here",
57
+ "MAIN_TANA_WORKSPACE": "My Workspace"
65
58
  }
66
59
  }
67
60
  }
68
61
  }
69
62
  ```
70
63
 
71
- | Client | Config Location |
72
- | ----------------- | ----------------------------------------------------------- |
73
- | Claude Desktop | `claude_desktop_config.json` |
74
- | Claude Code | `.mcp.json` (project) or `~/.claude/settings.json` (global) |
75
- | Cursor / Windsurf | IDE MCP settings |
64
+ For npm install, use `"command": "tana-mcp-codemode"`. For source, use `"command": "bun"` with `"args": ["run", "/path/to/src/entry-bun.ts"]`.
76
65
 
77
- **If installed from source**, use `bun` as the command:
66
+ ## Environment Variables
78
67
 
79
- ```json
80
- {
81
- "mcpServers": {
82
- "tana": {
83
- "command": "bun",
84
- "args": ["run", "/path/to/tana-mcp-codemode/src/index.ts"],
85
- "env": {
86
- "TANA_API_TOKEN": "your_token_here",
87
- // Optional
88
- "MAIN_TANA_WORKSPACE": "My Workspace",
89
- "TANA_SEARCH_WORKSPACES": "My Workspace",
90
- // Optional: customize where the SQLite history database is stored
91
- "TANA_HISTORY_PATH": "/path/to/history.db"
92
- }
93
- }
94
- }
95
- }
96
- ```
97
-
98
- ## Examples
99
-
100
- ### Search for nodes
68
+ | Variable | Default | Description |
69
+ |----------|---------|-------------|
70
+ | `TANA_API_TOKEN` | (required) | Bearer token from Tana Desktop |
71
+ | `TANA_API_URL` | `http://127.0.0.1:8262` | Tana Local API URL |
72
+ | `MAIN_TANA_WORKSPACE` | (none) | Default workspace name or ID |
73
+ | `TANA_SEARCH_WORKSPACES` | (none) | Comma-separated workspaces for search scope |
74
+ | `TANA_TIMEOUT` | `10000` | Request timeout in ms |
75
+ | `TANA_HISTORY_PATH` | (platform default) | Custom SQLite history path |
101
76
 
102
- ```typescript
103
- const results = await tana.nodes.search({
104
- textContains: "meeting notes"
105
- });
106
- console.log("Found:", results.length, "nodes");
107
- ```
77
+ ## Usage Examples
108
78
 
109
- ### Complex query
79
+ Search for nodes:
110
80
 
111
81
  ```typescript
112
- const tasks = await tana.nodes.search({
113
- and: [
114
- { hasType: "taskTagId" },
115
- { is: "todo" },
116
- { created: { last: 7 } }
117
- ]
82
+ const results = await tana.nodes.search("project ideas", {
83
+ workspaceIds: [tana.workspace.id]
118
84
  });
119
- console.log({ tasks });
85
+ console.log(results.map(n => n.name));
120
86
  ```
121
87
 
122
- ### Import content
88
+ Import content with tags and fields:
123
89
 
124
90
  ```typescript
125
- await tana.import(parentNodeId, `
126
- - Project Alpha #[[^projectTagId]]
127
- - [[^statusFieldId]]:: Active
128
- - [[^dueDateFieldId]]:: [[date:2024-03-15]]
91
+ await tana.import(tana.workspace.id, `
92
+ %%tana%%
93
+ - Meeting notes #meeting
94
+ - Date:: [[2024-01-15]]
95
+ - Attendees:: Alice, Bob
96
+ - Summary:: Discussed Q1 roadmap
129
97
  `);
130
98
  ```
131
99
 
132
- ## Debug UI
133
-
134
- A WebSocket-based dashboard for testing scripts:
135
-
136
- ```bash
137
- # Start debug server
138
- bun run src/debug-server.ts
139
-
140
- # Open http://localhost:3333
141
- ```
142
-
143
- **Routes:**
144
- - `http://localhost:3333/#debug` — Script execution console
145
- - `http://localhost:3333/#benchmark` — Codemode vs tana-local performance comparison
146
-
147
- **Features:**
148
- - Real-time script execution
149
- - Workflow event timeline
150
- - Error display with suggestions
151
- - Benchmark results visualization (cost, speed, token usage)
152
-
153
- ### workflow Helper (Debug UI only)
154
-
155
- Track multi-step operations with a timeline view:
156
-
157
- ```typescript
158
- workflow.start("Processing nodes");
159
- workflow.step("Fetching workspaces");
160
- workflow.progress(5, 100, "Processing");
161
- workflow.complete("Done!");
162
- // Or: workflow.abort("Error message");
163
- ```
164
-
165
- > **Note**: `workflow` is only available in the Debug UI. It's not exposed in the production MCP prompt.
166
-
167
- ### Building the React UI (optional)
168
-
169
- ```bash
170
- cd ui
171
- bun install
172
- bun run build
173
- cd ..
174
- bun run src/debug-server.ts
175
- ```
176
-
177
- ## Architecture
178
-
179
- ```
180
- src/
181
- ├── index.ts # MCP server entry
182
- ├── prompts.ts # Tool description
183
- ├── types.ts # TypeScript interfaces
184
- ├── debug-server.ts # WebSocket debug UI
185
- ├── api/
186
- │ ├── client.ts # HTTP client (auth, retry, timeouts)
187
- │ ├── tana.ts # API wrapper → `tana` object
188
- │ └── types.ts # API type definitions
189
- ├── sandbox/
190
- │ ├── executor.ts # Code execution engine
191
- │ └── workflow.ts # Progress tracking
192
- ├── storage/
193
- │ └── history.ts # SQLite script history
194
- └── generated/
195
- └── api.d.ts # Generated OpenAPI types
196
-
197
- ui/ # React debug dashboard
198
- ```
199
-
200
- ### How It Works
201
-
202
- 1. AI sends TypeScript code to the `execute` tool
203
- 2. `executor.ts` creates an AsyncFunction for top-level await
204
- 3. Code runs with injected `tana` and `console` objects
205
- 4. 10s timeout via Promise.race prevents hangs
206
- 5. `console.log()` output is captured and returned
207
- 6. Script run is saved to SQLite history
208
-
209
- ## Script History
210
-
211
- Runs are persisted to SQLite:
212
-
213
- | Platform | Location |
214
- | -------- | --------------------------------------------------- |
215
- | macOS | `~/Library/Application Support/tana-mcp/history.db` |
216
- | Windows | `%APPDATA%/tana-mcp/history.db` |
217
- | Linux | `~/.local/share/tana-mcp/history.db` |
218
-
219
- Old runs (>30 days) are automatically cleaned up on startup.
220
-
221
- ### What Gets Saved
222
-
223
- Each script run records:
100
+ ## API Reference
224
101
 
225
- | Field | Description |
226
- | ------------------- | ------------------------------------- |
227
- | `script` | The TypeScript code that was executed |
228
- | `output` | Captured `console.log()` output |
229
- | `error` | Error message if execution failed |
230
- | `api_calls` | Which Tana API methods were called |
231
- | `node_ids_affected` | Node IDs that were read/modified |
232
- | `workspace_id` | Workspace used (if detected) |
233
- | `duration_ms` | Execution time |
102
+ | Namespace | Methods |
103
+ |-----------|---------|
104
+ | `tana.workspace` | Pre-resolved default workspace |
105
+ | `tana.workspaces` | `list()` |
106
+ | `tana.nodes` | `search()`, `read()`, `getChildren()`, `edit()`, `move()`, `trash()`, `check()`, `uncheck()`, `open()` |
107
+ | `tana.tags` | `listAll()`, `getSchema()`, `create()`, `modify()`, `addField()`, `setCheckbox()` |
108
+ | `tana.fields` | `setOption()`, `setContent()`, `getFieldOptions()` |
109
+ | `tana.calendar` | `getOrCreate()` |
110
+ | `tana.import()` | Import Tana Paste content |
111
+ | `tana.health()` | API health check |
234
112
 
235
113
  ## Development
236
114
 
237
115
  ```bash
238
- # Dev mode with watch
239
- bun run dev
240
-
241
- # Type check
242
- bun run typecheck
243
-
244
- # Regenerate API types from OpenAPI spec
245
- bun run generate
246
-
247
- # Run debug server
248
- bun run debug
249
- ```
250
-
251
- ## API Reference
252
-
253
- The server exposes a single `execute` tool. AI writes TypeScript code with access to the `tana` object:
254
-
255
- ### Workspaces
256
-
257
- ```typescript
258
- const workspaces = await tana.workspaces.list();
259
- // → Workspace[] (id, name, homeNodeId)
260
- ```
261
-
262
- ### Nodes
263
-
264
- ```typescript
265
- await tana.nodes.search(query, options?) // → SearchResult[]
266
- await tana.nodes.read(nodeId, maxDepth?) // → string (markdown)
267
- await tana.nodes.getChildren(nodeId, opts?) // → { children, total, hasMore }
268
- await tana.nodes.edit({ nodeId, name?, description? })
269
- await tana.nodes.trash(nodeId)
270
- await tana.nodes.check(nodeId) // mark done
271
- await tana.nodes.uncheck(nodeId) // mark undone
272
- ```
273
-
274
- ### Tags (Supertags)
275
-
276
- ```typescript
277
- await tana.tags.listAll(workspaceId) // All workspace supertags (paginated)
278
- await tana.tags.getSchema(tagId, opts?) // opts: { includeInheritedFields? }
279
- await tana.tags.modify(nodeId, action, tagIds) // action: "add" | "remove"
280
- await tana.tags.create({ workspaceId, name, description?, extendsTagIds?, showCheckbox? })
281
- await tana.tags.addField({ tagId, name, dataType, ... })
282
- await tana.tags.setCheckbox({ tagId, showCheckbox, doneStateMapping? })
283
- ```
284
-
285
- ### Fields
286
-
287
- ```typescript
288
- await tana.fields.setOption(nodeId, attributeId, optionId) // dropdown fields
289
- await tana.fields.setContent(nodeId, attributeId, content) // text/date/url fields
290
- ```
291
-
292
- ### Calendar
293
-
294
- ```typescript
295
- await tana.calendar.getOrCreate(workspaceId, granularity, date?)
296
- // granularity: "day" | "week" | "month" | "year"
297
- ```
298
-
299
- ### Import (Tana Paste)
300
-
301
- ```typescript
302
- await tana.import(parentNodeId, tanaPasteContent)
303
- // → { success, nodeIds?, error? }
304
- ```
305
-
306
- ### Utility
307
-
308
- ```typescript
309
- tana.workspace // Pre-resolved default workspace (from MAIN_TANA_WORKSPACE) or null
310
- tana.format(data) // Compact display of any API response
311
- await tana.health() // → { status: "ok" }
116
+ bun install # Install deps
117
+ bun run start # Start MCP server
118
+ bun run dev # Dev mode with watch
119
+ bun run test # Run tests
120
+ bun run typecheck # Type check
121
+ bun run build # Build Node.js dist (tsup)
122
+ bun run build:binary # Build self-contained binary
123
+ bun run debug # Debug UI at localhost:3333
312
124
  ```
313
125
 
314
126
  ## License