@damper/mcp 0.1.1 → 0.1.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/dist/index.js +151 -8
- package/package.json +10 -3
package/dist/index.js
CHANGED
|
@@ -30,6 +30,48 @@ const server = new McpServer({
|
|
|
30
30
|
name: 'damper',
|
|
31
31
|
version: '0.1.0',
|
|
32
32
|
});
|
|
33
|
+
// Output schemas
|
|
34
|
+
const TaskSummarySchema = z.object({
|
|
35
|
+
id: z.string(),
|
|
36
|
+
title: z.string(),
|
|
37
|
+
status: z.string(),
|
|
38
|
+
priority: z.string(),
|
|
39
|
+
feedbackCount: z.number(),
|
|
40
|
+
hasImplementationPlan: z.boolean(),
|
|
41
|
+
});
|
|
42
|
+
const TaskDetailSchema = z.object({
|
|
43
|
+
id: z.string(),
|
|
44
|
+
title: z.string(),
|
|
45
|
+
description: z.string().optional(),
|
|
46
|
+
implementationPlan: z.string().optional(),
|
|
47
|
+
status: z.string(),
|
|
48
|
+
voteScore: z.number(),
|
|
49
|
+
agentNotes: z.string().optional(),
|
|
50
|
+
feedback: z.array(z.object({
|
|
51
|
+
id: z.string(),
|
|
52
|
+
title: z.string(),
|
|
53
|
+
description: z.string(),
|
|
54
|
+
voterCount: z.number(),
|
|
55
|
+
})),
|
|
56
|
+
});
|
|
57
|
+
const FeedbackSummarySchema = z.object({
|
|
58
|
+
id: z.string(),
|
|
59
|
+
title: z.string(),
|
|
60
|
+
type: z.string(),
|
|
61
|
+
voterCount: z.number(),
|
|
62
|
+
linkedTaskId: z.string().optional(),
|
|
63
|
+
});
|
|
64
|
+
const FeedbackDetailSchema = z.object({
|
|
65
|
+
id: z.string(),
|
|
66
|
+
title: z.string(),
|
|
67
|
+
description: z.string(),
|
|
68
|
+
type: z.string(),
|
|
69
|
+
status: z.string(),
|
|
70
|
+
voteScore: z.number(),
|
|
71
|
+
linkedTaskId: z.string().optional(),
|
|
72
|
+
voters: z.array(z.object({ email: z.string(), plan: z.string() })),
|
|
73
|
+
comments: z.array(z.object({ author: z.string(), body: z.string() })),
|
|
74
|
+
});
|
|
33
75
|
// Tool: List tasks
|
|
34
76
|
server.registerTool('list_tasks', {
|
|
35
77
|
title: 'List Tasks',
|
|
@@ -38,6 +80,16 @@ server.registerTool('list_tasks', {
|
|
|
38
80
|
status: z.enum(['planned', 'in_progress', 'done', 'all']).optional(),
|
|
39
81
|
limit: z.number().optional(),
|
|
40
82
|
}),
|
|
83
|
+
outputSchema: z.object({
|
|
84
|
+
project: z.string(),
|
|
85
|
+
tasks: z.array(TaskSummarySchema),
|
|
86
|
+
}),
|
|
87
|
+
annotations: {
|
|
88
|
+
readOnlyHint: true,
|
|
89
|
+
destructiveHint: false,
|
|
90
|
+
idempotentHint: true,
|
|
91
|
+
openWorldHint: false,
|
|
92
|
+
},
|
|
41
93
|
}, async ({ status, limit }) => {
|
|
42
94
|
const params = new URLSearchParams();
|
|
43
95
|
if (status)
|
|
@@ -47,7 +99,10 @@ server.registerTool('list_tasks', {
|
|
|
47
99
|
const query = params.toString();
|
|
48
100
|
const data = await api('GET', `/api/agent/tasks${query ? `?${query}` : ''}`);
|
|
49
101
|
if (!data.tasks.length) {
|
|
50
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
content: [{ type: 'text', text: `No tasks in "${data.project.name}"` }],
|
|
104
|
+
structuredContent: { project: data.project.name, tasks: [] },
|
|
105
|
+
};
|
|
51
106
|
}
|
|
52
107
|
const lines = data.tasks.map((t) => {
|
|
53
108
|
const p = t.priority === 'high' ? '🔴' : t.priority === 'medium' ? '🟡' : '⚪';
|
|
@@ -55,6 +110,7 @@ server.registerTool('list_tasks', {
|
|
|
55
110
|
});
|
|
56
111
|
return {
|
|
57
112
|
content: [{ type: 'text', text: `Tasks in "${data.project.name}":\n${lines.join('\n')}` }],
|
|
113
|
+
structuredContent: { project: data.project.name, tasks: data.tasks },
|
|
58
114
|
};
|
|
59
115
|
});
|
|
60
116
|
// Tool: Get task
|
|
@@ -64,6 +120,13 @@ server.registerTool('get_task', {
|
|
|
64
120
|
inputSchema: z.object({
|
|
65
121
|
taskId: z.string().describe('Task ID'),
|
|
66
122
|
}),
|
|
123
|
+
outputSchema: TaskDetailSchema,
|
|
124
|
+
annotations: {
|
|
125
|
+
readOnlyHint: true,
|
|
126
|
+
destructiveHint: false,
|
|
127
|
+
idempotentHint: true,
|
|
128
|
+
openWorldHint: false,
|
|
129
|
+
},
|
|
67
130
|
}, async ({ taskId }) => {
|
|
68
131
|
const t = await api('GET', `/api/agent/tasks/${taskId}`);
|
|
69
132
|
const parts = [
|
|
@@ -80,7 +143,10 @@ server.registerTool('get_task', {
|
|
|
80
143
|
parts.push(`\n## Feedback (${t.feedback.length})`);
|
|
81
144
|
t.feedback.forEach((f) => parts.push(`- ${f.title} (${f.voterCount} votes)`));
|
|
82
145
|
}
|
|
83
|
-
return {
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: 'text', text: parts.join('\n') }],
|
|
148
|
+
structuredContent: t,
|
|
149
|
+
};
|
|
84
150
|
});
|
|
85
151
|
// Tool: Create task
|
|
86
152
|
server.registerTool('create_task', {
|
|
@@ -92,10 +158,22 @@ server.registerTool('create_task', {
|
|
|
92
158
|
status: z.enum(['planned', 'in_progress']).optional(),
|
|
93
159
|
implementationPlan: z.string().optional(),
|
|
94
160
|
}),
|
|
161
|
+
outputSchema: z.object({
|
|
162
|
+
id: z.string(),
|
|
163
|
+
title: z.string(),
|
|
164
|
+
status: z.string(),
|
|
165
|
+
}),
|
|
166
|
+
annotations: {
|
|
167
|
+
readOnlyHint: false,
|
|
168
|
+
destructiveHint: false,
|
|
169
|
+
idempotentHint: false,
|
|
170
|
+
openWorldHint: false,
|
|
171
|
+
},
|
|
95
172
|
}, async (args) => {
|
|
96
173
|
const result = await api('POST', '/api/agent/tasks', args);
|
|
97
174
|
return {
|
|
98
175
|
content: [{ type: 'text', text: `Created: ${result.id} "${result.title}" [${result.status}]` }],
|
|
176
|
+
structuredContent: result,
|
|
99
177
|
};
|
|
100
178
|
});
|
|
101
179
|
// Tool: Start task
|
|
@@ -105,9 +183,23 @@ server.registerTool('start_task', {
|
|
|
105
183
|
inputSchema: z.object({
|
|
106
184
|
taskId: z.string(),
|
|
107
185
|
}),
|
|
186
|
+
outputSchema: z.object({
|
|
187
|
+
id: z.string(),
|
|
188
|
+
status: z.string(),
|
|
189
|
+
message: z.string(),
|
|
190
|
+
}),
|
|
191
|
+
annotations: {
|
|
192
|
+
readOnlyHint: false,
|
|
193
|
+
destructiveHint: false,
|
|
194
|
+
idempotentHint: true,
|
|
195
|
+
openWorldHint: false,
|
|
196
|
+
},
|
|
108
197
|
}, async ({ taskId }) => {
|
|
109
198
|
const result = await api('POST', `/api/agent/tasks/${taskId}/start`);
|
|
110
|
-
return {
|
|
199
|
+
return {
|
|
200
|
+
content: [{ type: 'text', text: `Started ${result.id}: ${result.message}` }],
|
|
201
|
+
structuredContent: result,
|
|
202
|
+
};
|
|
111
203
|
});
|
|
112
204
|
// Tool: Add note
|
|
113
205
|
server.registerTool('add_note', {
|
|
@@ -117,9 +209,22 @@ server.registerTool('add_note', {
|
|
|
117
209
|
taskId: z.string(),
|
|
118
210
|
note: z.string(),
|
|
119
211
|
}),
|
|
212
|
+
outputSchema: z.object({
|
|
213
|
+
taskId: z.string(),
|
|
214
|
+
success: z.boolean(),
|
|
215
|
+
}),
|
|
216
|
+
annotations: {
|
|
217
|
+
readOnlyHint: false,
|
|
218
|
+
destructiveHint: false,
|
|
219
|
+
idempotentHint: false,
|
|
220
|
+
openWorldHint: false,
|
|
221
|
+
},
|
|
120
222
|
}, async ({ taskId, note }) => {
|
|
121
223
|
await api('POST', `/api/agent/tasks/${taskId}/notes`, { note });
|
|
122
|
-
return {
|
|
224
|
+
return {
|
|
225
|
+
content: [{ type: 'text', text: `Note added to ${taskId}` }],
|
|
226
|
+
structuredContent: { taskId, success: true },
|
|
227
|
+
};
|
|
123
228
|
});
|
|
124
229
|
// Tool: Complete task
|
|
125
230
|
server.registerTool('complete_task', {
|
|
@@ -129,9 +234,22 @@ server.registerTool('complete_task', {
|
|
|
129
234
|
taskId: z.string(),
|
|
130
235
|
summary: z.string().describe('What was implemented'),
|
|
131
236
|
}),
|
|
237
|
+
outputSchema: z.object({
|
|
238
|
+
id: z.string(),
|
|
239
|
+
status: z.string(),
|
|
240
|
+
}),
|
|
241
|
+
annotations: {
|
|
242
|
+
readOnlyHint: false,
|
|
243
|
+
destructiveHint: false,
|
|
244
|
+
idempotentHint: true,
|
|
245
|
+
openWorldHint: false,
|
|
246
|
+
},
|
|
132
247
|
}, async ({ taskId, summary }) => {
|
|
133
248
|
const result = await api('POST', `/api/agent/tasks/${taskId}/complete`, { summary });
|
|
134
|
-
return {
|
|
249
|
+
return {
|
|
250
|
+
content: [{ type: 'text', text: `Completed ${result.id}` }],
|
|
251
|
+
structuredContent: result,
|
|
252
|
+
};
|
|
135
253
|
});
|
|
136
254
|
// Tool: List feedback
|
|
137
255
|
server.registerTool('list_feedback', {
|
|
@@ -141,6 +259,15 @@ server.registerTool('list_feedback', {
|
|
|
141
259
|
status: z.enum(['new', 'under_review', 'planned', 'in_progress', 'done', 'closed']).optional(),
|
|
142
260
|
limit: z.number().optional(),
|
|
143
261
|
}),
|
|
262
|
+
outputSchema: z.object({
|
|
263
|
+
feedback: z.array(FeedbackSummarySchema),
|
|
264
|
+
}),
|
|
265
|
+
annotations: {
|
|
266
|
+
readOnlyHint: true,
|
|
267
|
+
destructiveHint: false,
|
|
268
|
+
idempotentHint: true,
|
|
269
|
+
openWorldHint: false,
|
|
270
|
+
},
|
|
144
271
|
}, async ({ status, limit }) => {
|
|
145
272
|
const params = new URLSearchParams();
|
|
146
273
|
if (status)
|
|
@@ -150,13 +277,19 @@ server.registerTool('list_feedback', {
|
|
|
150
277
|
const query = params.toString();
|
|
151
278
|
const data = await api('GET', `/api/agent/feedback${query ? `?${query}` : ''}`);
|
|
152
279
|
if (!data.feedback.length) {
|
|
153
|
-
return {
|
|
280
|
+
return {
|
|
281
|
+
content: [{ type: 'text', text: 'No feedback found' }],
|
|
282
|
+
structuredContent: { feedback: [] },
|
|
283
|
+
};
|
|
154
284
|
}
|
|
155
285
|
const lines = data.feedback.map((f) => {
|
|
156
286
|
const link = f.linkedTaskId ? ` → ${f.linkedTaskId}` : '';
|
|
157
287
|
return `• ${f.id}: ${f.title} [${f.type}] (${f.voterCount} votes)${link}`;
|
|
158
288
|
});
|
|
159
|
-
return {
|
|
289
|
+
return {
|
|
290
|
+
content: [{ type: 'text', text: `Feedback:\n${lines.join('\n')}` }],
|
|
291
|
+
structuredContent: { feedback: data.feedback },
|
|
292
|
+
};
|
|
160
293
|
});
|
|
161
294
|
// Tool: Get feedback
|
|
162
295
|
server.registerTool('get_feedback', {
|
|
@@ -165,6 +298,13 @@ server.registerTool('get_feedback', {
|
|
|
165
298
|
inputSchema: z.object({
|
|
166
299
|
feedbackId: z.string(),
|
|
167
300
|
}),
|
|
301
|
+
outputSchema: FeedbackDetailSchema,
|
|
302
|
+
annotations: {
|
|
303
|
+
readOnlyHint: true,
|
|
304
|
+
destructiveHint: false,
|
|
305
|
+
idempotentHint: true,
|
|
306
|
+
openWorldHint: false,
|
|
307
|
+
},
|
|
168
308
|
}, async ({ feedbackId }) => {
|
|
169
309
|
const f = await api('GET', `/api/agent/feedback/${feedbackId}`);
|
|
170
310
|
const parts = [
|
|
@@ -185,7 +325,10 @@ server.registerTool('get_feedback', {
|
|
|
185
325
|
if (f.comments.length > 3)
|
|
186
326
|
parts.push(`... and ${f.comments.length - 3} more`);
|
|
187
327
|
}
|
|
188
|
-
return {
|
|
328
|
+
return {
|
|
329
|
+
content: [{ type: 'text', text: parts.join('\n') }],
|
|
330
|
+
structuredContent: f,
|
|
331
|
+
};
|
|
189
332
|
});
|
|
190
333
|
// Start
|
|
191
334
|
async function main() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@damper/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server for Damper task management",
|
|
5
5
|
"author": "Damper <hello@usedamper.com>",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
},
|
|
16
16
|
"main": "./dist/index.js",
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
|
-
"files": [
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
19
21
|
"scripts": {
|
|
20
22
|
"build": "tsc",
|
|
21
23
|
"dev": "tsx src/index.ts",
|
|
@@ -33,6 +35,11 @@
|
|
|
33
35
|
"engines": {
|
|
34
36
|
"node": ">=18"
|
|
35
37
|
},
|
|
36
|
-
"keywords": [
|
|
38
|
+
"keywords": [
|
|
39
|
+
"mcp",
|
|
40
|
+
"damper",
|
|
41
|
+
"ai",
|
|
42
|
+
"task-management"
|
|
43
|
+
],
|
|
37
44
|
"license": "MIT"
|
|
38
45
|
}
|