@standardbeagle/dart-query 0.3.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/LICENSE +21 -0
- package/README.md +427 -0
- package/TOOLS.md +2148 -0
- package/dist/api/dartClient.d.ts +123 -0
- package/dist/api/dartClient.d.ts.map +1 -0
- package/dist/api/dartClient.js +436 -0
- package/dist/api/dartClient.js.map +1 -0
- package/dist/batch/batchOperations.d.ts +14 -0
- package/dist/batch/batchOperations.d.ts.map +1 -0
- package/dist/batch/batchOperations.js +65 -0
- package/dist/batch/batchOperations.js.map +1 -0
- package/dist/cache/configCache.d.ts +20 -0
- package/dist/cache/configCache.d.ts.map +1 -0
- package/dist/cache/configCache.js +59 -0
- package/dist/cache/configCache.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1120 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/csv.d.ts +44 -0
- package/dist/parsers/csv.d.ts.map +1 -0
- package/dist/parsers/csv.js +574 -0
- package/dist/parsers/csv.js.map +1 -0
- package/dist/parsers/dartql.d.ts +104 -0
- package/dist/parsers/dartql.d.ts.map +1 -0
- package/dist/parsers/dartql.js +889 -0
- package/dist/parsers/dartql.js.map +1 -0
- package/dist/tools/add_task_comment.d.ts +3 -0
- package/dist/tools/add_task_comment.d.ts.map +1 -0
- package/dist/tools/add_task_comment.js +43 -0
- package/dist/tools/add_task_comment.js.map +1 -0
- package/dist/tools/add_time_tracking.d.ts +3 -0
- package/dist/tools/add_time_tracking.d.ts.map +1 -0
- package/dist/tools/add_time_tracking.js +52 -0
- package/dist/tools/add_time_tracking.js.map +1 -0
- package/dist/tools/attach_url.d.ts +3 -0
- package/dist/tools/attach_url.d.ts.map +1 -0
- package/dist/tools/attach_url.js +38 -0
- package/dist/tools/attach_url.js.map +1 -0
- package/dist/tools/batch_delete_tasks.d.ts +3 -0
- package/dist/tools/batch_delete_tasks.d.ts.map +1 -0
- package/dist/tools/batch_delete_tasks.js +125 -0
- package/dist/tools/batch_delete_tasks.js.map +1 -0
- package/dist/tools/batch_update_tasks.d.ts +3 -0
- package/dist/tools/batch_update_tasks.d.ts.map +1 -0
- package/dist/tools/batch_update_tasks.js +327 -0
- package/dist/tools/batch_update_tasks.js.map +1 -0
- package/dist/tools/create_doc.d.ts +3 -0
- package/dist/tools/create_doc.d.ts.map +1 -0
- package/dist/tools/create_doc.js +65 -0
- package/dist/tools/create_doc.js.map +1 -0
- package/dist/tools/create_task.d.ts +3 -0
- package/dist/tools/create_task.d.ts.map +1 -0
- package/dist/tools/create_task.js +143 -0
- package/dist/tools/create_task.js.map +1 -0
- package/dist/tools/delete_doc.d.ts +3 -0
- package/dist/tools/delete_doc.d.ts.map +1 -0
- package/dist/tools/delete_doc.js +35 -0
- package/dist/tools/delete_doc.js.map +1 -0
- package/dist/tools/delete_task.d.ts +3 -0
- package/dist/tools/delete_task.d.ts.map +1 -0
- package/dist/tools/delete_task.js +35 -0
- package/dist/tools/delete_task.js.map +1 -0
- package/dist/tools/get_batch_status.d.ts +3 -0
- package/dist/tools/get_batch_status.d.ts.map +1 -0
- package/dist/tools/get_batch_status.js +24 -0
- package/dist/tools/get_batch_status.js.map +1 -0
- package/dist/tools/get_config.d.ts +3 -0
- package/dist/tools/get_config.d.ts.map +1 -0
- package/dist/tools/get_config.js +74 -0
- package/dist/tools/get_config.js.map +1 -0
- package/dist/tools/get_dartboard.d.ts +3 -0
- package/dist/tools/get_dartboard.d.ts.map +1 -0
- package/dist/tools/get_dartboard.js +43 -0
- package/dist/tools/get_dartboard.js.map +1 -0
- package/dist/tools/get_doc.d.ts +3 -0
- package/dist/tools/get_doc.d.ts.map +1 -0
- package/dist/tools/get_doc.js +34 -0
- package/dist/tools/get_doc.js.map +1 -0
- package/dist/tools/get_folder.d.ts +3 -0
- package/dist/tools/get_folder.d.ts.map +1 -0
- package/dist/tools/get_folder.js +45 -0
- package/dist/tools/get_folder.js.map +1 -0
- package/dist/tools/get_task.d.ts +3 -0
- package/dist/tools/get_task.d.ts.map +1 -0
- package/dist/tools/get_task.js +109 -0
- package/dist/tools/get_task.js.map +1 -0
- package/dist/tools/import_tasks_csv.d.ts +3 -0
- package/dist/tools/import_tasks_csv.d.ts.map +1 -0
- package/dist/tools/import_tasks_csv.js +218 -0
- package/dist/tools/import_tasks_csv.js.map +1 -0
- package/dist/tools/info.d.ts +3 -0
- package/dist/tools/info.d.ts.map +1 -0
- package/dist/tools/info.js +474 -0
- package/dist/tools/info.js.map +1 -0
- package/dist/tools/list_comments.d.ts +3 -0
- package/dist/tools/list_comments.d.ts.map +1 -0
- package/dist/tools/list_comments.js +46 -0
- package/dist/tools/list_comments.js.map +1 -0
- package/dist/tools/list_docs.d.ts +3 -0
- package/dist/tools/list_docs.d.ts.map +1 -0
- package/dist/tools/list_docs.js +101 -0
- package/dist/tools/list_docs.js.map +1 -0
- package/dist/tools/list_tasks.d.ts +3 -0
- package/dist/tools/list_tasks.d.ts.map +1 -0
- package/dist/tools/list_tasks.js +325 -0
- package/dist/tools/list_tasks.js.map +1 -0
- package/dist/tools/move_task.d.ts +3 -0
- package/dist/tools/move_task.d.ts.map +1 -0
- package/dist/tools/move_task.js +44 -0
- package/dist/tools/move_task.js.map +1 -0
- package/dist/tools/search_tasks.d.ts +3 -0
- package/dist/tools/search_tasks.d.ts.map +1 -0
- package/dist/tools/search_tasks.js +227 -0
- package/dist/tools/search_tasks.js.map +1 -0
- package/dist/tools/update_doc.d.ts +3 -0
- package/dist/tools/update_doc.d.ts.map +1 -0
- package/dist/tools/update_doc.js +102 -0
- package/dist/tools/update_doc.js.map +1 -0
- package/dist/tools/update_task.d.ts +3 -0
- package/dist/tools/update_task.d.ts.map +1 -0
- package/dist/tools/update_task.js +241 -0
- package/dist/tools/update_task.js.map +1 -0
- package/dist/types/index.d.ts +529 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +65 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +72 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { handleInfo } from './tools/info.js';
|
|
6
|
+
import { handleGetConfig } from './tools/get_config.js';
|
|
7
|
+
import { handleCreateTask } from './tools/create_task.js';
|
|
8
|
+
import { handleListTasks } from './tools/list_tasks.js';
|
|
9
|
+
import { handleGetTask } from './tools/get_task.js';
|
|
10
|
+
import { handleUpdateTask } from './tools/update_task.js';
|
|
11
|
+
import { handleDeleteTask } from './tools/delete_task.js';
|
|
12
|
+
import { handleBatchUpdateTasks } from './tools/batch_update_tasks.js';
|
|
13
|
+
import { handleBatchDeleteTasks } from './tools/batch_delete_tasks.js';
|
|
14
|
+
import { handleGetBatchStatus } from './tools/get_batch_status.js';
|
|
15
|
+
import { handleImportTasksCSV } from './tools/import_tasks_csv.js';
|
|
16
|
+
import { handleListDocs } from './tools/list_docs.js';
|
|
17
|
+
import { handleCreateDoc } from './tools/create_doc.js';
|
|
18
|
+
import { handleGetDoc } from './tools/get_doc.js';
|
|
19
|
+
import { handleUpdateDoc } from './tools/update_doc.js';
|
|
20
|
+
import { handleDeleteDoc } from './tools/delete_doc.js';
|
|
21
|
+
import { handleSearchTasks } from './tools/search_tasks.js';
|
|
22
|
+
import { handleAddTaskComment } from './tools/add_task_comment.js';
|
|
23
|
+
import { handleListComments } from './tools/list_comments.js';
|
|
24
|
+
import { handleMoveTask } from './tools/move_task.js';
|
|
25
|
+
import { handleAddTimeTracking } from './tools/add_time_tracking.js';
|
|
26
|
+
import { handleAttachUrl } from './tools/attach_url.js';
|
|
27
|
+
import { handleGetDartboard } from './tools/get_dartboard.js';
|
|
28
|
+
import { handleGetFolder } from './tools/get_folder.js';
|
|
29
|
+
const DART_TOKEN = process.env.DART_TOKEN;
|
|
30
|
+
if (!DART_TOKEN) {
|
|
31
|
+
console.error('Error: DART_TOKEN environment variable is required');
|
|
32
|
+
console.error('Get your token from: https://app.dartai.com/?settings=account');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (!DART_TOKEN.startsWith('dsa_')) {
|
|
36
|
+
console.error('Error: DART_TOKEN must start with "dsa_"');
|
|
37
|
+
console.error('Check your token format at: https://app.dartai.com/?settings=account');
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
class DartQueryServer {
|
|
41
|
+
server;
|
|
42
|
+
constructor() {
|
|
43
|
+
this.server = new Server({
|
|
44
|
+
name: 'dart-query',
|
|
45
|
+
version: '1.0.0',
|
|
46
|
+
}, {
|
|
47
|
+
capabilities: {
|
|
48
|
+
tools: {},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
this.setupHandlers();
|
|
52
|
+
this.setupErrorHandling();
|
|
53
|
+
}
|
|
54
|
+
setupHandlers() {
|
|
55
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
56
|
+
tools: [
|
|
57
|
+
{
|
|
58
|
+
name: 'info',
|
|
59
|
+
description: 'Progressive discovery of dart-query capabilities - start here',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
level: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
enum: ['overview', 'group', 'tool'],
|
|
66
|
+
description: 'Detail level: overview=categories, group=tools in category, tool=full documentation',
|
|
67
|
+
},
|
|
68
|
+
target: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
description: 'Group name (when level=group) or tool name (when level=tool)',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'get_config',
|
|
77
|
+
description: 'Get workspace configuration: assignees, dartboards, statuses, tags, priorities, sizes',
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
cache_bust: {
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
description: 'Force refresh cached config (default: 5-minute cache)',
|
|
84
|
+
},
|
|
85
|
+
include: {
|
|
86
|
+
type: 'array',
|
|
87
|
+
items: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
enum: ['assignees', 'dartboards', 'statuses', 'tags', 'priorities', 'sizes', 'folders'],
|
|
90
|
+
},
|
|
91
|
+
description: 'Limit response to specific config sections (default: all)',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'create_task',
|
|
98
|
+
description: 'Create a new task with title, description, status, priority, size, dates, dartboard, assignees, tags, and task relationships (subtasks, blockers, related tasks)',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
title: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: 'Task title (max 500 chars)',
|
|
105
|
+
},
|
|
106
|
+
description: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
description: 'Task description (markdown supported)',
|
|
109
|
+
},
|
|
110
|
+
dartboard: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
description: 'Dartboard dart_id (use get_config to find)',
|
|
113
|
+
},
|
|
114
|
+
status: {
|
|
115
|
+
type: 'string',
|
|
116
|
+
description: 'Status name or dart_id',
|
|
117
|
+
},
|
|
118
|
+
priority: {
|
|
119
|
+
type: 'integer',
|
|
120
|
+
description: 'Priority 1-5 (1=lowest, 5=highest)',
|
|
121
|
+
},
|
|
122
|
+
size: {
|
|
123
|
+
type: 'integer',
|
|
124
|
+
description: 'Size estimate 1-5',
|
|
125
|
+
},
|
|
126
|
+
assignees: {
|
|
127
|
+
type: 'array',
|
|
128
|
+
items: { type: 'string' },
|
|
129
|
+
description: 'Array of assignee dart_ids',
|
|
130
|
+
},
|
|
131
|
+
tags: {
|
|
132
|
+
type: 'array',
|
|
133
|
+
items: { type: 'string' },
|
|
134
|
+
description: 'Array of tag dart_ids',
|
|
135
|
+
},
|
|
136
|
+
due_at: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
description: 'Due date (ISO8601)',
|
|
139
|
+
},
|
|
140
|
+
start_at: {
|
|
141
|
+
type: 'string',
|
|
142
|
+
description: 'Start date (ISO8601)',
|
|
143
|
+
},
|
|
144
|
+
parent_task: {
|
|
145
|
+
type: 'string',
|
|
146
|
+
description: 'Parent task dart_id for subtasks',
|
|
147
|
+
},
|
|
148
|
+
subtask_ids: {
|
|
149
|
+
type: 'array',
|
|
150
|
+
items: { type: 'string' },
|
|
151
|
+
description: 'IDs of tasks that are subtasks (children) of this task. Each ID must be a valid dart_id format.',
|
|
152
|
+
},
|
|
153
|
+
blocker_ids: {
|
|
154
|
+
type: 'array',
|
|
155
|
+
items: { type: 'string' },
|
|
156
|
+
description: 'IDs of tasks that block this task from being started or completed. Each ID must be a valid dart_id format.',
|
|
157
|
+
},
|
|
158
|
+
blocking_ids: {
|
|
159
|
+
type: 'array',
|
|
160
|
+
items: { type: 'string' },
|
|
161
|
+
description: 'IDs of tasks that this task is blocking. Each ID must be a valid dart_id format.',
|
|
162
|
+
},
|
|
163
|
+
duplicate_ids: {
|
|
164
|
+
type: 'array',
|
|
165
|
+
items: { type: 'string' },
|
|
166
|
+
description: 'IDs of tasks that are duplicates of this task. Each ID must be a valid dart_id format.',
|
|
167
|
+
},
|
|
168
|
+
related_ids: {
|
|
169
|
+
type: 'array',
|
|
170
|
+
items: { type: 'string' },
|
|
171
|
+
description: 'IDs of tasks that are related to this task (loosely connected). Each ID must be a valid dart_id format.',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
required: ['title', 'dartboard'],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'list_tasks',
|
|
179
|
+
description: 'Query tasks with filters (assignee, status, dartboard, priority, tags, dates, relationships), pagination, and detail levels. Relationship filters use client-side filtering - may be slower for large task counts.',
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
properties: {
|
|
183
|
+
assignee: {
|
|
184
|
+
type: 'string',
|
|
185
|
+
description: 'Filter by assignee (dart_id, name, or email)',
|
|
186
|
+
},
|
|
187
|
+
status: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'Filter by status (dart_id or name)',
|
|
190
|
+
},
|
|
191
|
+
dartboard: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
description: 'Filter by dartboard (dart_id or name)',
|
|
194
|
+
},
|
|
195
|
+
priority: {
|
|
196
|
+
type: 'integer',
|
|
197
|
+
description: 'Filter by priority (1-5)',
|
|
198
|
+
},
|
|
199
|
+
tags: {
|
|
200
|
+
type: 'array',
|
|
201
|
+
items: { type: 'string' },
|
|
202
|
+
description: 'Filter by tags (dart_ids or names)',
|
|
203
|
+
},
|
|
204
|
+
due_before: {
|
|
205
|
+
type: 'string',
|
|
206
|
+
description: 'Filter tasks due before date (ISO8601)',
|
|
207
|
+
},
|
|
208
|
+
due_after: {
|
|
209
|
+
type: 'string',
|
|
210
|
+
description: 'Filter tasks due after date (ISO8601)',
|
|
211
|
+
},
|
|
212
|
+
has_parent: {
|
|
213
|
+
type: 'boolean',
|
|
214
|
+
description: 'Filter tasks with parent (true) or without parent (false). Client-side filter.',
|
|
215
|
+
},
|
|
216
|
+
has_subtasks: {
|
|
217
|
+
type: 'boolean',
|
|
218
|
+
description: 'Filter tasks with subtasks (true) or without subtasks (false). Client-side filter.',
|
|
219
|
+
},
|
|
220
|
+
has_blockers: {
|
|
221
|
+
type: 'boolean',
|
|
222
|
+
description: 'Filter tasks that are blocked (true) or not blocked (false). Client-side filter.',
|
|
223
|
+
},
|
|
224
|
+
is_blocking: {
|
|
225
|
+
type: 'boolean',
|
|
226
|
+
description: 'Filter tasks that block others (true) or block nothing (false). Client-side filter.',
|
|
227
|
+
},
|
|
228
|
+
blocked_by: {
|
|
229
|
+
type: 'string',
|
|
230
|
+
description: 'Filter tasks blocked by specific task (dart_id). Client-side filter.',
|
|
231
|
+
},
|
|
232
|
+
blocking: {
|
|
233
|
+
type: 'string',
|
|
234
|
+
description: 'Filter tasks that are blocking a specific task (dart_id). Client-side filter.',
|
|
235
|
+
},
|
|
236
|
+
limit: {
|
|
237
|
+
type: 'integer',
|
|
238
|
+
description: 'Max tasks to return (default: 50, max: 500)',
|
|
239
|
+
},
|
|
240
|
+
offset: {
|
|
241
|
+
type: 'integer',
|
|
242
|
+
description: 'Pagination offset (default: 0)',
|
|
243
|
+
},
|
|
244
|
+
detail_level: {
|
|
245
|
+
type: 'string',
|
|
246
|
+
enum: ['minimal', 'standard', 'full'],
|
|
247
|
+
description: 'minimal=id+title, standard=+status+assignee+priority, full=all fields including relationships',
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'get_task',
|
|
254
|
+
description: 'Get a specific task by dart_id with optional comments and relationship details. Returns task relationships (subtasks, blockers, blocking, duplicates, related) with counts and optional expanded titles.',
|
|
255
|
+
inputSchema: {
|
|
256
|
+
type: 'object',
|
|
257
|
+
properties: {
|
|
258
|
+
dart_id: {
|
|
259
|
+
type: 'string',
|
|
260
|
+
description: 'Task dart_id',
|
|
261
|
+
},
|
|
262
|
+
include_comments: {
|
|
263
|
+
type: 'boolean',
|
|
264
|
+
description: 'Include task comments in response (default: false)',
|
|
265
|
+
},
|
|
266
|
+
include_relationships: {
|
|
267
|
+
type: 'boolean',
|
|
268
|
+
description: 'Include relationship fields and counts in response (default: true). Set to false for smaller response.',
|
|
269
|
+
},
|
|
270
|
+
expand_relationships: {
|
|
271
|
+
type: 'boolean',
|
|
272
|
+
description: 'Fetch titles for all related tasks (default: false). Requires additional API calls. Only applies when include_relationships is true.',
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
required: ['dart_id'],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'update_task',
|
|
280
|
+
description: 'Update an existing task with partial field updates including task relationships (validates references, only sends changed fields). Relationship arrays use full replacement semantics - to add/remove, get current values, modify, then update with the full array.',
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
dart_id: {
|
|
285
|
+
type: 'string',
|
|
286
|
+
description: 'Task dart_id to update',
|
|
287
|
+
},
|
|
288
|
+
updates: {
|
|
289
|
+
type: 'object',
|
|
290
|
+
description: 'Fields to update (partial DartTask object)',
|
|
291
|
+
properties: {
|
|
292
|
+
title: {
|
|
293
|
+
type: 'string',
|
|
294
|
+
description: 'Task title (max 500 chars)',
|
|
295
|
+
},
|
|
296
|
+
description: {
|
|
297
|
+
type: 'string',
|
|
298
|
+
description: 'Task description (markdown supported)',
|
|
299
|
+
},
|
|
300
|
+
dartboard: {
|
|
301
|
+
type: 'string',
|
|
302
|
+
description: 'Dartboard dart_id or name',
|
|
303
|
+
},
|
|
304
|
+
status: {
|
|
305
|
+
type: 'string',
|
|
306
|
+
description: 'Status dart_id or name',
|
|
307
|
+
},
|
|
308
|
+
priority: {
|
|
309
|
+
type: 'integer',
|
|
310
|
+
description: 'Priority 1-5',
|
|
311
|
+
},
|
|
312
|
+
size: {
|
|
313
|
+
type: 'integer',
|
|
314
|
+
description: 'Size estimate 1-5',
|
|
315
|
+
},
|
|
316
|
+
assignees: {
|
|
317
|
+
type: 'array',
|
|
318
|
+
items: { type: 'string' },
|
|
319
|
+
description: 'Array of assignee dart_ids, names, or emails',
|
|
320
|
+
},
|
|
321
|
+
tags: {
|
|
322
|
+
type: 'array',
|
|
323
|
+
items: { type: 'string' },
|
|
324
|
+
description: 'Array of tag dart_ids or names',
|
|
325
|
+
},
|
|
326
|
+
due_at: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'Due date (ISO8601)',
|
|
329
|
+
},
|
|
330
|
+
start_at: {
|
|
331
|
+
type: 'string',
|
|
332
|
+
description: 'Start date (ISO8601)',
|
|
333
|
+
},
|
|
334
|
+
parent_task: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
description: 'Parent task dart_id',
|
|
337
|
+
},
|
|
338
|
+
subtask_ids: {
|
|
339
|
+
type: 'array',
|
|
340
|
+
items: { type: 'string' },
|
|
341
|
+
description: 'IDs of tasks that are subtasks (children) of this task. Full replacement: set to [] to clear all subtasks.',
|
|
342
|
+
},
|
|
343
|
+
blocker_ids: {
|
|
344
|
+
type: 'array',
|
|
345
|
+
items: { type: 'string' },
|
|
346
|
+
description: 'IDs of tasks that block this task. Full replacement: set to [] to clear all blockers.',
|
|
347
|
+
},
|
|
348
|
+
blocking_ids: {
|
|
349
|
+
type: 'array',
|
|
350
|
+
items: { type: 'string' },
|
|
351
|
+
description: 'IDs of tasks that this task is blocking. Full replacement: set to [] to clear.',
|
|
352
|
+
},
|
|
353
|
+
duplicate_ids: {
|
|
354
|
+
type: 'array',
|
|
355
|
+
items: { type: 'string' },
|
|
356
|
+
description: 'IDs of tasks that are duplicates of this task. Full replacement: set to [] to clear.',
|
|
357
|
+
},
|
|
358
|
+
related_ids: {
|
|
359
|
+
type: 'array',
|
|
360
|
+
items: { type: 'string' },
|
|
361
|
+
description: 'IDs of related tasks (loosely connected). Full replacement: set to [] to clear.',
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
required: ['dart_id', 'updates'],
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'delete_task',
|
|
371
|
+
description: 'Delete a task (moves to trash - recoverable via Dart web UI)',
|
|
372
|
+
inputSchema: {
|
|
373
|
+
type: 'object',
|
|
374
|
+
properties: {
|
|
375
|
+
dart_id: {
|
|
376
|
+
type: 'string',
|
|
377
|
+
description: 'Task dart_id to delete',
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
required: ['dart_id'],
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'batch_update_tasks',
|
|
385
|
+
description: 'Batch update multiple tasks matching a DartQL selector. Supports all task fields including relationships. CRITICAL: Always use dry_run=true first to preview changes!',
|
|
386
|
+
inputSchema: {
|
|
387
|
+
type: 'object',
|
|
388
|
+
properties: {
|
|
389
|
+
selector: {
|
|
390
|
+
type: 'string',
|
|
391
|
+
description: 'DartQL WHERE clause to select tasks (e.g., "status = \'Todo\' AND priority >= 3")',
|
|
392
|
+
},
|
|
393
|
+
updates: {
|
|
394
|
+
type: 'object',
|
|
395
|
+
description: 'Fields to update (partial DartTask object). Relationship arrays use full replacement semantics - set to [] to clear.',
|
|
396
|
+
properties: {
|
|
397
|
+
title: { type: 'string' },
|
|
398
|
+
description: { type: 'string' },
|
|
399
|
+
dartboard: { type: 'string' },
|
|
400
|
+
status: { type: 'string' },
|
|
401
|
+
priority: { type: 'integer' },
|
|
402
|
+
size: { type: 'integer' },
|
|
403
|
+
assignees: { type: 'array', items: { type: 'string' } },
|
|
404
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
405
|
+
due_at: { type: 'string' },
|
|
406
|
+
start_at: { type: 'string' },
|
|
407
|
+
parent_task: { type: 'string' },
|
|
408
|
+
subtask_ids: {
|
|
409
|
+
type: 'array',
|
|
410
|
+
items: { type: 'string' },
|
|
411
|
+
description: 'IDs of tasks that are subtasks (children) of this task. Full replacement: set to [] to clear.',
|
|
412
|
+
},
|
|
413
|
+
blocker_ids: {
|
|
414
|
+
type: 'array',
|
|
415
|
+
items: { type: 'string' },
|
|
416
|
+
description: 'IDs of tasks that block this task. Full replacement: set to [] to clear.',
|
|
417
|
+
},
|
|
418
|
+
blocking_ids: {
|
|
419
|
+
type: 'array',
|
|
420
|
+
items: { type: 'string' },
|
|
421
|
+
description: 'IDs of tasks that this task is blocking. Full replacement: set to [] to clear.',
|
|
422
|
+
},
|
|
423
|
+
duplicate_ids: {
|
|
424
|
+
type: 'array',
|
|
425
|
+
items: { type: 'string' },
|
|
426
|
+
description: 'IDs of tasks that are duplicates of this task. Full replacement: set to [] to clear.',
|
|
427
|
+
},
|
|
428
|
+
related_ids: {
|
|
429
|
+
type: 'array',
|
|
430
|
+
items: { type: 'string' },
|
|
431
|
+
description: 'IDs of related tasks (loosely connected). Full replacement: set to [] to clear.',
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
dry_run: {
|
|
436
|
+
type: 'boolean',
|
|
437
|
+
description: 'Preview mode (default: true). Set to false to execute updates.',
|
|
438
|
+
},
|
|
439
|
+
concurrency: {
|
|
440
|
+
type: 'integer',
|
|
441
|
+
description: 'Parallel updates (default: 5, range: 1-20)',
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
required: ['selector', 'updates'],
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
name: 'batch_delete_tasks',
|
|
449
|
+
description: 'Batch delete multiple tasks matching a DartQL selector. MOST DANGEROUS OPERATION! CRITICAL: dry_run defaults to true, confirm=true REQUIRED when dry_run=false. Tasks move to trash (recoverable).',
|
|
450
|
+
inputSchema: {
|
|
451
|
+
type: 'object',
|
|
452
|
+
properties: {
|
|
453
|
+
selector: {
|
|
454
|
+
type: 'string',
|
|
455
|
+
description: 'DartQL WHERE clause to select tasks (e.g., "status = \'Archived\' AND completed_at < \'2025-01-01\'")',
|
|
456
|
+
},
|
|
457
|
+
dry_run: {
|
|
458
|
+
type: 'boolean',
|
|
459
|
+
description: 'Preview mode (default: true). Set to false to execute deletions.',
|
|
460
|
+
},
|
|
461
|
+
confirm: {
|
|
462
|
+
type: 'boolean',
|
|
463
|
+
description: 'REQUIRED when dry_run=false. Safety confirmation for deletions.',
|
|
464
|
+
},
|
|
465
|
+
concurrency: {
|
|
466
|
+
type: 'integer',
|
|
467
|
+
description: 'Parallel deletions (default: 5, range: 1-20)',
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
required: ['selector'],
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
name: 'get_batch_status',
|
|
475
|
+
description: 'Retrieve status of a batch operation (update, delete, or import) by batch_operation_id. Operations are kept in memory for 1 hour.',
|
|
476
|
+
inputSchema: {
|
|
477
|
+
type: 'object',
|
|
478
|
+
properties: {
|
|
479
|
+
batch_operation_id: {
|
|
480
|
+
type: 'string',
|
|
481
|
+
description: 'Batch operation ID returned from batch_update_tasks, batch_delete_tasks, or import_tasks_csv',
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
required: ['batch_operation_id'],
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
name: 'import_tasks_csv',
|
|
489
|
+
description: 'Import tasks from CSV file with validation and parallel creation. CRITICAL: ALWAYS use validate_only=true first! Production safety: validate → fix errors → import.',
|
|
490
|
+
inputSchema: {
|
|
491
|
+
type: 'object',
|
|
492
|
+
properties: {
|
|
493
|
+
csv_data: {
|
|
494
|
+
type: 'string',
|
|
495
|
+
description: 'CSV data as string (use this OR csv_file_path)',
|
|
496
|
+
},
|
|
497
|
+
csv_file_path: {
|
|
498
|
+
type: 'string',
|
|
499
|
+
description: 'Path to CSV file (use this OR csv_data)',
|
|
500
|
+
},
|
|
501
|
+
dartboard: {
|
|
502
|
+
type: 'string',
|
|
503
|
+
description: 'Dartboard dart_id or name for all imported tasks',
|
|
504
|
+
},
|
|
505
|
+
column_mapping: {
|
|
506
|
+
type: 'object',
|
|
507
|
+
description: 'Custom column name mapping (e.g., {"Task Name": "title", "Owner": "assignee"})',
|
|
508
|
+
},
|
|
509
|
+
validate_only: {
|
|
510
|
+
type: 'boolean',
|
|
511
|
+
description: 'Preview mode (default: TRUE for production safety). Returns validation errors and preview without creating tasks.',
|
|
512
|
+
},
|
|
513
|
+
continue_on_error: {
|
|
514
|
+
type: 'boolean',
|
|
515
|
+
description: 'Continue importing valid rows even if some fail (default: true)',
|
|
516
|
+
},
|
|
517
|
+
concurrency: {
|
|
518
|
+
type: 'integer',
|
|
519
|
+
description: 'Parallel task creation (default: 5, range: 1-20)',
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
required: ['dartboard'],
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
name: 'list_docs',
|
|
527
|
+
description: 'List documents with optional filtering by folder, title_contains, text_contains. Supports pagination.',
|
|
528
|
+
inputSchema: {
|
|
529
|
+
type: 'object',
|
|
530
|
+
properties: {
|
|
531
|
+
folder: {
|
|
532
|
+
type: 'string',
|
|
533
|
+
description: 'Filter by folder (dart_id or name)',
|
|
534
|
+
},
|
|
535
|
+
title_contains: {
|
|
536
|
+
type: 'string',
|
|
537
|
+
description: 'Filter by title substring (case-insensitive)',
|
|
538
|
+
},
|
|
539
|
+
text_contains: {
|
|
540
|
+
type: 'string',
|
|
541
|
+
description: 'Filter by text content substring (case-insensitive)',
|
|
542
|
+
},
|
|
543
|
+
limit: {
|
|
544
|
+
type: 'integer',
|
|
545
|
+
description: 'Max docs to return (default: 50, max: 500)',
|
|
546
|
+
},
|
|
547
|
+
offset: {
|
|
548
|
+
type: 'integer',
|
|
549
|
+
description: 'Pagination offset (default: 0)',
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
name: 'create_doc',
|
|
556
|
+
description: 'Create a new document with title, text (markdown supported), and optional folder',
|
|
557
|
+
inputSchema: {
|
|
558
|
+
type: 'object',
|
|
559
|
+
properties: {
|
|
560
|
+
title: {
|
|
561
|
+
type: 'string',
|
|
562
|
+
description: 'Document title',
|
|
563
|
+
},
|
|
564
|
+
text: {
|
|
565
|
+
type: 'string',
|
|
566
|
+
description: 'Document text content (markdown supported)',
|
|
567
|
+
},
|
|
568
|
+
folder: {
|
|
569
|
+
type: 'string',
|
|
570
|
+
description: 'Folder dart_id or name (optional)',
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
required: ['title', 'text'],
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
name: 'get_doc',
|
|
578
|
+
description: 'Get a specific document by doc_id with full text content',
|
|
579
|
+
inputSchema: {
|
|
580
|
+
type: 'object',
|
|
581
|
+
properties: {
|
|
582
|
+
doc_id: {
|
|
583
|
+
type: 'string',
|
|
584
|
+
description: 'Document doc_id',
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
required: ['doc_id'],
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
name: 'update_doc',
|
|
592
|
+
description: 'Update an existing document (title, text, or folder). Validates references and only sends changed fields.',
|
|
593
|
+
inputSchema: {
|
|
594
|
+
type: 'object',
|
|
595
|
+
properties: {
|
|
596
|
+
doc_id: {
|
|
597
|
+
type: 'string',
|
|
598
|
+
description: 'Document doc_id to update',
|
|
599
|
+
},
|
|
600
|
+
updates: {
|
|
601
|
+
type: 'object',
|
|
602
|
+
description: 'Fields to update',
|
|
603
|
+
properties: {
|
|
604
|
+
title: {
|
|
605
|
+
type: 'string',
|
|
606
|
+
description: 'Document title',
|
|
607
|
+
},
|
|
608
|
+
text: {
|
|
609
|
+
type: 'string',
|
|
610
|
+
description: 'Document text (markdown supported)',
|
|
611
|
+
},
|
|
612
|
+
folder: {
|
|
613
|
+
type: 'string',
|
|
614
|
+
description: 'Folder dart_id or name',
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
required: ['doc_id', 'updates'],
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
name: 'delete_doc',
|
|
624
|
+
description: 'Delete a document (moves to trash - recoverable via Dart web UI)',
|
|
625
|
+
inputSchema: {
|
|
626
|
+
type: 'object',
|
|
627
|
+
properties: {
|
|
628
|
+
doc_id: {
|
|
629
|
+
type: 'string',
|
|
630
|
+
description: 'Document doc_id to delete',
|
|
631
|
+
},
|
|
632
|
+
},
|
|
633
|
+
required: ['doc_id'],
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
name: 'search_tasks',
|
|
638
|
+
description: 'Full-text search across tasks with relevance ranking. Alternative to list_tasks for text-based discovery. Supports quoted phrases and exclusions.',
|
|
639
|
+
inputSchema: {
|
|
640
|
+
type: 'object',
|
|
641
|
+
properties: {
|
|
642
|
+
query: {
|
|
643
|
+
type: 'string',
|
|
644
|
+
description: 'Search query. Supports quoted phrases ("exact match"), exclusions (-term), and regular terms.',
|
|
645
|
+
},
|
|
646
|
+
dartboard: {
|
|
647
|
+
type: 'string',
|
|
648
|
+
description: 'Optional dartboard filter (dart_id or name)',
|
|
649
|
+
},
|
|
650
|
+
include_completed: {
|
|
651
|
+
type: 'boolean',
|
|
652
|
+
description: 'Include completed tasks in results (default: false)',
|
|
653
|
+
},
|
|
654
|
+
limit: {
|
|
655
|
+
type: 'integer',
|
|
656
|
+
description: 'Max results to return (default: 50, max: 500)',
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
required: ['query'],
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
name: 'add_task_comment',
|
|
664
|
+
description: 'Add a comment to a task for status updates, AI rationale, or notes. Supports markdown formatting.',
|
|
665
|
+
inputSchema: {
|
|
666
|
+
type: 'object',
|
|
667
|
+
properties: {
|
|
668
|
+
dart_id: {
|
|
669
|
+
type: 'string',
|
|
670
|
+
description: 'Task dart_id to add comment to',
|
|
671
|
+
},
|
|
672
|
+
text: {
|
|
673
|
+
type: 'string',
|
|
674
|
+
description: 'Comment text (markdown supported)',
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
required: ['dart_id', 'text'],
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
name: 'list_comments',
|
|
682
|
+
description: 'List comments on a task with pagination. Token-efficient: returns minimal comment data.',
|
|
683
|
+
inputSchema: {
|
|
684
|
+
type: 'object',
|
|
685
|
+
properties: {
|
|
686
|
+
task_id: {
|
|
687
|
+
type: 'string',
|
|
688
|
+
description: 'Task dart_id to list comments for',
|
|
689
|
+
},
|
|
690
|
+
limit: {
|
|
691
|
+
type: 'integer',
|
|
692
|
+
description: 'Max comments to return (default: 50, max: 100)',
|
|
693
|
+
},
|
|
694
|
+
offset: {
|
|
695
|
+
type: 'integer',
|
|
696
|
+
description: 'Pagination offset (default: 0)',
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
required: ['task_id'],
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
name: 'move_task',
|
|
704
|
+
description: 'Move/reposition a task within a dartboard or to a different dartboard. Supports ordering by index or relative to another task.',
|
|
705
|
+
inputSchema: {
|
|
706
|
+
type: 'object',
|
|
707
|
+
properties: {
|
|
708
|
+
dart_id: {
|
|
709
|
+
type: 'string',
|
|
710
|
+
description: 'Task dart_id to move',
|
|
711
|
+
},
|
|
712
|
+
dartboard: {
|
|
713
|
+
type: 'string',
|
|
714
|
+
description: 'Target dartboard (dart_id or name) - moves task to different dartboard',
|
|
715
|
+
},
|
|
716
|
+
order: {
|
|
717
|
+
type: 'integer',
|
|
718
|
+
description: 'Position index in dartboard (0-based)',
|
|
719
|
+
},
|
|
720
|
+
after_id: {
|
|
721
|
+
type: 'string',
|
|
722
|
+
description: 'Place task after this task dart_id',
|
|
723
|
+
},
|
|
724
|
+
before_id: {
|
|
725
|
+
type: 'string',
|
|
726
|
+
description: 'Place task before this task dart_id',
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
required: ['dart_id'],
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
name: 'add_time_tracking',
|
|
734
|
+
description: 'Add a time tracking entry to a task. Supports started_at/finished_at or duration_minutes.',
|
|
735
|
+
inputSchema: {
|
|
736
|
+
type: 'object',
|
|
737
|
+
properties: {
|
|
738
|
+
dart_id: {
|
|
739
|
+
type: 'string',
|
|
740
|
+
description: 'Task dart_id to add time entry to',
|
|
741
|
+
},
|
|
742
|
+
started_at: {
|
|
743
|
+
type: 'string',
|
|
744
|
+
description: 'Start time in ISO8601 format (e.g., 2026-01-25T10:00:00Z)',
|
|
745
|
+
},
|
|
746
|
+
finished_at: {
|
|
747
|
+
type: 'string',
|
|
748
|
+
description: 'End time in ISO8601 format (optional if duration_minutes provided)',
|
|
749
|
+
},
|
|
750
|
+
duration_minutes: {
|
|
751
|
+
type: 'integer',
|
|
752
|
+
description: 'Duration in minutes (optional if finished_at provided)',
|
|
753
|
+
},
|
|
754
|
+
note: {
|
|
755
|
+
type: 'string',
|
|
756
|
+
description: 'Optional note about the time entry',
|
|
757
|
+
},
|
|
758
|
+
},
|
|
759
|
+
required: ['dart_id', 'started_at'],
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
name: 'attach_url',
|
|
764
|
+
description: 'Attach a file from URL to a task. URL must be publicly accessible.',
|
|
765
|
+
inputSchema: {
|
|
766
|
+
type: 'object',
|
|
767
|
+
properties: {
|
|
768
|
+
dart_id: {
|
|
769
|
+
type: 'string',
|
|
770
|
+
description: 'Task dart_id to attach file to',
|
|
771
|
+
},
|
|
772
|
+
url: {
|
|
773
|
+
type: 'string',
|
|
774
|
+
description: 'Public URL of file to attach',
|
|
775
|
+
},
|
|
776
|
+
filename: {
|
|
777
|
+
type: 'string',
|
|
778
|
+
description: 'Optional filename override',
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
required: ['dart_id', 'url'],
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
name: 'get_dartboard',
|
|
786
|
+
description: 'Get details about a dartboard including task count. Token-efficient lookup.',
|
|
787
|
+
inputSchema: {
|
|
788
|
+
type: 'object',
|
|
789
|
+
properties: {
|
|
790
|
+
dartboard_id: {
|
|
791
|
+
type: 'string',
|
|
792
|
+
description: 'Dartboard dart_id or name',
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
required: ['dartboard_id'],
|
|
796
|
+
},
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
name: 'get_folder',
|
|
800
|
+
description: 'Get details about a folder including doc count. Token-efficient lookup.',
|
|
801
|
+
inputSchema: {
|
|
802
|
+
type: 'object',
|
|
803
|
+
properties: {
|
|
804
|
+
folder_id: {
|
|
805
|
+
type: 'string',
|
|
806
|
+
description: 'Folder dart_id or name',
|
|
807
|
+
},
|
|
808
|
+
},
|
|
809
|
+
required: ['folder_id'],
|
|
810
|
+
},
|
|
811
|
+
},
|
|
812
|
+
],
|
|
813
|
+
}));
|
|
814
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
815
|
+
const { name, arguments: args } = request.params;
|
|
816
|
+
try {
|
|
817
|
+
switch (name) {
|
|
818
|
+
case 'info': {
|
|
819
|
+
const result = await handleInfo(args || {});
|
|
820
|
+
return {
|
|
821
|
+
content: [
|
|
822
|
+
{
|
|
823
|
+
type: 'text',
|
|
824
|
+
text: result.content,
|
|
825
|
+
},
|
|
826
|
+
],
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
case 'get_config': {
|
|
830
|
+
const result = await handleGetConfig(args || {});
|
|
831
|
+
return {
|
|
832
|
+
content: [
|
|
833
|
+
{
|
|
834
|
+
type: 'text',
|
|
835
|
+
text: JSON.stringify(result, null, 2),
|
|
836
|
+
},
|
|
837
|
+
],
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
case 'create_task': {
|
|
841
|
+
const result = await handleCreateTask((args || {}));
|
|
842
|
+
return {
|
|
843
|
+
content: [
|
|
844
|
+
{
|
|
845
|
+
type: 'text',
|
|
846
|
+
text: JSON.stringify(result, null, 2),
|
|
847
|
+
},
|
|
848
|
+
],
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
case 'list_tasks': {
|
|
852
|
+
const result = await handleListTasks((args || {}));
|
|
853
|
+
return {
|
|
854
|
+
content: [
|
|
855
|
+
{
|
|
856
|
+
type: 'text',
|
|
857
|
+
text: JSON.stringify(result, null, 2),
|
|
858
|
+
},
|
|
859
|
+
],
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
case 'get_task': {
|
|
863
|
+
const result = await handleGetTask((args || {}));
|
|
864
|
+
return {
|
|
865
|
+
content: [
|
|
866
|
+
{
|
|
867
|
+
type: 'text',
|
|
868
|
+
text: JSON.stringify(result, null, 2),
|
|
869
|
+
},
|
|
870
|
+
],
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
case 'update_task': {
|
|
874
|
+
const result = await handleUpdateTask((args || {}));
|
|
875
|
+
return {
|
|
876
|
+
content: [
|
|
877
|
+
{
|
|
878
|
+
type: 'text',
|
|
879
|
+
text: JSON.stringify(result, null, 2),
|
|
880
|
+
},
|
|
881
|
+
],
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
case 'delete_task': {
|
|
885
|
+
const result = await handleDeleteTask((args || {}));
|
|
886
|
+
return {
|
|
887
|
+
content: [
|
|
888
|
+
{
|
|
889
|
+
type: 'text',
|
|
890
|
+
text: JSON.stringify(result, null, 2),
|
|
891
|
+
},
|
|
892
|
+
],
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
case 'batch_update_tasks': {
|
|
896
|
+
const result = await handleBatchUpdateTasks((args || {}));
|
|
897
|
+
return {
|
|
898
|
+
content: [
|
|
899
|
+
{
|
|
900
|
+
type: 'text',
|
|
901
|
+
text: JSON.stringify(result, null, 2),
|
|
902
|
+
},
|
|
903
|
+
],
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
case 'batch_delete_tasks': {
|
|
907
|
+
const result = await handleBatchDeleteTasks((args || {}));
|
|
908
|
+
return {
|
|
909
|
+
content: [
|
|
910
|
+
{
|
|
911
|
+
type: 'text',
|
|
912
|
+
text: JSON.stringify(result, null, 2),
|
|
913
|
+
},
|
|
914
|
+
],
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
case 'get_batch_status': {
|
|
918
|
+
const result = await handleGetBatchStatus((args || {}));
|
|
919
|
+
return {
|
|
920
|
+
content: [
|
|
921
|
+
{
|
|
922
|
+
type: 'text',
|
|
923
|
+
text: JSON.stringify(result, null, 2),
|
|
924
|
+
},
|
|
925
|
+
],
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
case 'import_tasks_csv': {
|
|
929
|
+
const result = await handleImportTasksCSV((args || {}));
|
|
930
|
+
return {
|
|
931
|
+
content: [
|
|
932
|
+
{
|
|
933
|
+
type: 'text',
|
|
934
|
+
text: JSON.stringify(result, null, 2),
|
|
935
|
+
},
|
|
936
|
+
],
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
case 'list_docs': {
|
|
940
|
+
const result = await handleListDocs((args || {}));
|
|
941
|
+
return {
|
|
942
|
+
content: [
|
|
943
|
+
{
|
|
944
|
+
type: 'text',
|
|
945
|
+
text: JSON.stringify(result, null, 2),
|
|
946
|
+
},
|
|
947
|
+
],
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
case 'create_doc': {
|
|
951
|
+
const result = await handleCreateDoc((args || {}));
|
|
952
|
+
return {
|
|
953
|
+
content: [
|
|
954
|
+
{
|
|
955
|
+
type: 'text',
|
|
956
|
+
text: JSON.stringify(result, null, 2),
|
|
957
|
+
},
|
|
958
|
+
],
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
case 'get_doc': {
|
|
962
|
+
const result = await handleGetDoc((args || {}));
|
|
963
|
+
return {
|
|
964
|
+
content: [
|
|
965
|
+
{
|
|
966
|
+
type: 'text',
|
|
967
|
+
text: JSON.stringify(result, null, 2),
|
|
968
|
+
},
|
|
969
|
+
],
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
case 'update_doc': {
|
|
973
|
+
const result = await handleUpdateDoc((args || {}));
|
|
974
|
+
return {
|
|
975
|
+
content: [
|
|
976
|
+
{
|
|
977
|
+
type: 'text',
|
|
978
|
+
text: JSON.stringify(result, null, 2),
|
|
979
|
+
},
|
|
980
|
+
],
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
case 'delete_doc': {
|
|
984
|
+
const result = await handleDeleteDoc((args || {}));
|
|
985
|
+
return {
|
|
986
|
+
content: [
|
|
987
|
+
{
|
|
988
|
+
type: 'text',
|
|
989
|
+
text: JSON.stringify(result, null, 2),
|
|
990
|
+
},
|
|
991
|
+
],
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
case 'search_tasks': {
|
|
995
|
+
const result = await handleSearchTasks((args || {}));
|
|
996
|
+
return {
|
|
997
|
+
content: [
|
|
998
|
+
{
|
|
999
|
+
type: 'text',
|
|
1000
|
+
text: JSON.stringify(result, null, 2),
|
|
1001
|
+
},
|
|
1002
|
+
],
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
case 'add_task_comment': {
|
|
1006
|
+
const result = await handleAddTaskComment((args || {}));
|
|
1007
|
+
return {
|
|
1008
|
+
content: [
|
|
1009
|
+
{
|
|
1010
|
+
type: 'text',
|
|
1011
|
+
text: JSON.stringify(result, null, 2),
|
|
1012
|
+
},
|
|
1013
|
+
],
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
case 'list_comments': {
|
|
1017
|
+
const result = await handleListComments((args || {}));
|
|
1018
|
+
return {
|
|
1019
|
+
content: [
|
|
1020
|
+
{
|
|
1021
|
+
type: 'text',
|
|
1022
|
+
text: JSON.stringify(result, null, 2),
|
|
1023
|
+
},
|
|
1024
|
+
],
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
case 'move_task': {
|
|
1028
|
+
const result = await handleMoveTask((args || {}));
|
|
1029
|
+
return {
|
|
1030
|
+
content: [
|
|
1031
|
+
{
|
|
1032
|
+
type: 'text',
|
|
1033
|
+
text: JSON.stringify(result, null, 2),
|
|
1034
|
+
},
|
|
1035
|
+
],
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
case 'add_time_tracking': {
|
|
1039
|
+
const result = await handleAddTimeTracking((args || {}));
|
|
1040
|
+
return {
|
|
1041
|
+
content: [
|
|
1042
|
+
{
|
|
1043
|
+
type: 'text',
|
|
1044
|
+
text: JSON.stringify(result, null, 2),
|
|
1045
|
+
},
|
|
1046
|
+
],
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
case 'attach_url': {
|
|
1050
|
+
const result = await handleAttachUrl((args || {}));
|
|
1051
|
+
return {
|
|
1052
|
+
content: [
|
|
1053
|
+
{
|
|
1054
|
+
type: 'text',
|
|
1055
|
+
text: JSON.stringify(result, null, 2),
|
|
1056
|
+
},
|
|
1057
|
+
],
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
case 'get_dartboard': {
|
|
1061
|
+
const result = await handleGetDartboard((args || {}));
|
|
1062
|
+
return {
|
|
1063
|
+
content: [
|
|
1064
|
+
{
|
|
1065
|
+
type: 'text',
|
|
1066
|
+
text: JSON.stringify(result, null, 2),
|
|
1067
|
+
},
|
|
1068
|
+
],
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
case 'get_folder': {
|
|
1072
|
+
const result = await handleGetFolder((args || {}));
|
|
1073
|
+
return {
|
|
1074
|
+
content: [
|
|
1075
|
+
{
|
|
1076
|
+
type: 'text',
|
|
1077
|
+
text: JSON.stringify(result, null, 2),
|
|
1078
|
+
},
|
|
1079
|
+
],
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
default:
|
|
1083
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
catch (error) {
|
|
1087
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
1088
|
+
return {
|
|
1089
|
+
content: [
|
|
1090
|
+
{
|
|
1091
|
+
type: 'text',
|
|
1092
|
+
text: `Error executing ${name}: ${errorMessage}`,
|
|
1093
|
+
},
|
|
1094
|
+
],
|
|
1095
|
+
isError: true,
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
setupErrorHandling() {
|
|
1101
|
+
this.server.onerror = (error) => {
|
|
1102
|
+
console.error('[MCP Error]', error);
|
|
1103
|
+
};
|
|
1104
|
+
process.on('SIGINT', async () => {
|
|
1105
|
+
await this.server.close();
|
|
1106
|
+
process.exit(0);
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
async run() {
|
|
1110
|
+
const transport = new StdioServerTransport();
|
|
1111
|
+
await this.server.connect(transport);
|
|
1112
|
+
console.error('dart-query MCP server running on stdio');
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
const server = new DartQueryServer();
|
|
1116
|
+
server.run().catch((error) => {
|
|
1117
|
+
console.error('Failed to start server:', error);
|
|
1118
|
+
process.exit(1);
|
|
1119
|
+
});
|
|
1120
|
+
//# sourceMappingURL=index.js.map
|