devto-mcp 0.1.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/LICENSE +21 -0
- package/README.md +70 -0
- package/bin/devto-mcp.js +2 -0
- package/bin/devto.js +2 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +481 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +36 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +109 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +252 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +26 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +332 -0
- package/dist/tools.js.map +1 -0
- package/package.json +50 -0
package/dist/tools.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveIssueKey = resolveIssueKey;
|
|
7
|
+
exports.createPlan = createPlan;
|
|
8
|
+
exports.confirmPlan = confirmPlan;
|
|
9
|
+
exports.createEpic = createEpic;
|
|
10
|
+
exports.createTask = createTask;
|
|
11
|
+
exports.createSubtask = createSubtask;
|
|
12
|
+
exports.getTasks = getTasks;
|
|
13
|
+
exports.updateTask = updateTask;
|
|
14
|
+
exports.getProjectSummary = getProjectSummary;
|
|
15
|
+
exports.getStatus = getStatus;
|
|
16
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
17
|
+
const client_1 = require("./client");
|
|
18
|
+
const config_1 = require("./config");
|
|
19
|
+
// ─── Anthropic system prompt ────────────────────────────────────────────────
|
|
20
|
+
const PLAN_SYSTEM_PROMPT = `You are DevTo, an AI work manager for software developers. Your job is to take a feature description and break it into a structured development plan. Always return a JSON object with this exact structure and nothing else — no preamble, no markdown, just the JSON:
|
|
21
|
+
{
|
|
22
|
+
"epic": { "title": "string", "description": "string" },
|
|
23
|
+
"stories": [
|
|
24
|
+
{
|
|
25
|
+
"title": "string",
|
|
26
|
+
"description": "string",
|
|
27
|
+
"acceptance_criteria": ["string"],
|
|
28
|
+
"subtasks": [{ "title": "string", "description": "string" }]
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"clarification_needed": false,
|
|
32
|
+
"clarification_question": null
|
|
33
|
+
}
|
|
34
|
+
If the feature description is too vague to generate a meaningful plan, set clarification_needed to true and provide a specific clarifying question. Otherwise set it to false and generate the full plan. Keep story titles concise. Write descriptions in plain English. Acceptance criteria must be testable statements. Generate between 2 and 6 stories per epic. Generate between 1 and 4 subtasks per story. Never generate more work than what is described. Never invent requirements that were not mentioned.`;
|
|
35
|
+
// ─── Semantic ticket matching ────────────────────────────────────────────────
|
|
36
|
+
const ISSUE_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
|
|
37
|
+
/**
|
|
38
|
+
* Score how well a query matches a task's title and context.
|
|
39
|
+
* Returns a value between 0 and 1.
|
|
40
|
+
*/
|
|
41
|
+
function scoreMatch(query, task) {
|
|
42
|
+
const q = query.toLowerCase().trim();
|
|
43
|
+
const title = task.title.toLowerCase();
|
|
44
|
+
const parentTitle = task.parent?.title?.toLowerCase() ?? "";
|
|
45
|
+
const combinedText = `${title} ${parentTitle}`;
|
|
46
|
+
// Exact title match
|
|
47
|
+
if (title === q)
|
|
48
|
+
return 1.0;
|
|
49
|
+
// Title contains the full query
|
|
50
|
+
if (title.includes(q))
|
|
51
|
+
return 0.92;
|
|
52
|
+
// Combined text contains the full query
|
|
53
|
+
if (combinedText.includes(q))
|
|
54
|
+
return 0.85;
|
|
55
|
+
// Word-level overlap scoring
|
|
56
|
+
const queryWords = q.split(/\s+/).filter((w) => w.length > 1);
|
|
57
|
+
if (queryWords.length === 0)
|
|
58
|
+
return 0;
|
|
59
|
+
const titleWords = new Set(combinedText.split(/\s+/).filter((w) => w.length > 1));
|
|
60
|
+
let matchedWords = 0;
|
|
61
|
+
let partialScore = 0;
|
|
62
|
+
for (const qw of queryWords) {
|
|
63
|
+
if (titleWords.has(qw)) {
|
|
64
|
+
matchedWords++;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Check partial word matches (e.g. "auth" matches "authentication")
|
|
68
|
+
for (const tw of titleWords) {
|
|
69
|
+
if (tw.includes(qw) || qw.includes(tw)) {
|
|
70
|
+
partialScore += 0.5;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const wordScore = (matchedWords + partialScore) / queryWords.length;
|
|
77
|
+
return Math.min(wordScore * 0.88, 0.88);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve an ambiguous reference to an issue key.
|
|
81
|
+
* If the input looks like a valid key (e.g. PROJ-5), returns it directly.
|
|
82
|
+
* Otherwise, fetches tasks and attempts semantic matching.
|
|
83
|
+
*
|
|
84
|
+
* Returns either:
|
|
85
|
+
* { resolved: true, key: string } — exact or high-confidence match
|
|
86
|
+
* { resolved: false, prompt: string } — disambiguation needed
|
|
87
|
+
*/
|
|
88
|
+
async function resolveIssueKey(input) {
|
|
89
|
+
// If it already looks like a valid issue key, pass through
|
|
90
|
+
if (ISSUE_KEY_PATTERN.test(input.trim().toUpperCase())) {
|
|
91
|
+
return { resolved: true, key: input.trim().toUpperCase() };
|
|
92
|
+
}
|
|
93
|
+
// Fetch all open tasks for matching
|
|
94
|
+
const res = await (0, client_1.callApi)("GET", "/api/v1/tasks");
|
|
95
|
+
if (res.total === 0) {
|
|
96
|
+
return {
|
|
97
|
+
resolved: false,
|
|
98
|
+
prompt: `No open tasks found in your project. I couldn't resolve "${input}" to a ticket. Use an exact key like PROJ-5, or create the task first.`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Score all tasks against the query
|
|
102
|
+
const scored = res.tasks
|
|
103
|
+
.map((task) => ({ task, score: scoreMatch(input, task) }))
|
|
104
|
+
.filter((s) => s.score > 0.15)
|
|
105
|
+
.sort((a, b) => b.score - a.score);
|
|
106
|
+
if (scored.length === 0) {
|
|
107
|
+
// No matches — show all open tasks so the developer can pick
|
|
108
|
+
const lines = [
|
|
109
|
+
`I couldn't find a task matching "${input}". Here are your open tasks:`,
|
|
110
|
+
``,
|
|
111
|
+
];
|
|
112
|
+
res.tasks.slice(0, 5).forEach((task, i) => {
|
|
113
|
+
lines.push(`${i + 1}. **${task.key}** — ${task.title} (${task.status})`);
|
|
114
|
+
});
|
|
115
|
+
if (res.total > 5) {
|
|
116
|
+
lines.push(``, `...and ${res.total - 5} more. Use \`get_tasks\` to see all.`);
|
|
117
|
+
}
|
|
118
|
+
lines.push(``, `Which one did you mean? Reply with the key (e.g. ${res.tasks[0].key}).`);
|
|
119
|
+
return { resolved: false, prompt: lines.join("\n") };
|
|
120
|
+
}
|
|
121
|
+
const best = scored[0];
|
|
122
|
+
// High confidence (>= 90%) — state the match, ask for single confirmation
|
|
123
|
+
if (best.score >= 0.9) {
|
|
124
|
+
return {
|
|
125
|
+
resolved: false,
|
|
126
|
+
prompt: `I'm pretty sure you mean **${best.task.key}** — ${best.task.title} (${best.task.status}). Is that right? Reply **yes** or give me a different key.`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Lower confidence — show top 2-3 matches
|
|
130
|
+
const topMatches = scored.slice(0, 3);
|
|
131
|
+
const lines = [
|
|
132
|
+
`I found a few tasks that might match "${input}":`,
|
|
133
|
+
``,
|
|
134
|
+
];
|
|
135
|
+
topMatches.forEach((s, i) => {
|
|
136
|
+
lines.push(`${i + 1}. **${s.task.key}** — ${s.task.title} (${s.task.status})`);
|
|
137
|
+
});
|
|
138
|
+
lines.push(``, `Which one did you mean? Reply with the number or the key.`);
|
|
139
|
+
return { resolved: false, prompt: lines.join("\n") };
|
|
140
|
+
}
|
|
141
|
+
// ─── Tool handlers ───────────────────────────────────────────────────────────
|
|
142
|
+
async function createPlan(featureDescription) {
|
|
143
|
+
// 1. Get Anthropic key from local config
|
|
144
|
+
const anthropicKey = (0, config_1.getAnthropicKey)();
|
|
145
|
+
// 2. Call Anthropic API directly
|
|
146
|
+
const anthropic = new sdk_1.default({ apiKey: anthropicKey });
|
|
147
|
+
let plan;
|
|
148
|
+
try {
|
|
149
|
+
const message = await anthropic.messages.create({
|
|
150
|
+
model: "claude-sonnet-4-20250514",
|
|
151
|
+
max_tokens: 4096,
|
|
152
|
+
system: PLAN_SYSTEM_PROMPT,
|
|
153
|
+
messages: [
|
|
154
|
+
{
|
|
155
|
+
role: "user",
|
|
156
|
+
content: featureDescription,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
const textBlock = message.content.find((block) => block.type === "text");
|
|
161
|
+
if (!textBlock || textBlock.type !== "text") {
|
|
162
|
+
throw new Error("No text response from Anthropic API");
|
|
163
|
+
}
|
|
164
|
+
plan = JSON.parse(textBlock.text);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
// Handle Anthropic 429 rate limit errors
|
|
168
|
+
if (err &&
|
|
169
|
+
typeof err === "object" &&
|
|
170
|
+
"status" in err &&
|
|
171
|
+
err.status === 429) {
|
|
172
|
+
return "Your Anthropic API key has hit its rate limit. Please wait a few minutes or check your usage at console.anthropic.com.";
|
|
173
|
+
}
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
// 3. If clarification needed, return the question
|
|
177
|
+
if (plan.clarification_needed) {
|
|
178
|
+
return `I need a bit more detail before I can build a plan.\n\n**Question:** ${plan.clarification_question}`;
|
|
179
|
+
}
|
|
180
|
+
// 4. Save the structured plan to the backend
|
|
181
|
+
const res = await (0, client_1.callApi)("POST", "/api/v1/plan", {
|
|
182
|
+
plan,
|
|
183
|
+
});
|
|
184
|
+
const { plan_id } = res;
|
|
185
|
+
// 5. Return formatted plan preview
|
|
186
|
+
const lines = [
|
|
187
|
+
`## Plan Preview — ${plan.epic.title}`,
|
|
188
|
+
``,
|
|
189
|
+
`**Epic:** ${plan.epic.title}`,
|
|
190
|
+
`${plan.epic.description}`,
|
|
191
|
+
``,
|
|
192
|
+
`**Stories:**`,
|
|
193
|
+
];
|
|
194
|
+
plan.stories.forEach((story, i) => {
|
|
195
|
+
lines.push(``, `### ${i + 1}. ${story.title}`);
|
|
196
|
+
lines.push(story.description);
|
|
197
|
+
if (story.acceptance_criteria.length > 0) {
|
|
198
|
+
lines.push(``, `**Acceptance Criteria:**`);
|
|
199
|
+
story.acceptance_criteria.forEach((ac) => lines.push(`- ${ac}`));
|
|
200
|
+
}
|
|
201
|
+
if (story.subtasks.length > 0) {
|
|
202
|
+
lines.push(``, `**Subtasks:**`);
|
|
203
|
+
story.subtasks.forEach((st) => lines.push(`- ${st.title}`));
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
lines.push(``, `---`, `**Plan ID:** \`${plan_id}\``, ``, `This plan has NOT been tracked yet. To track this work, say: **"confirm plan ${plan_id}"**`);
|
|
207
|
+
return lines.join("\n");
|
|
208
|
+
}
|
|
209
|
+
async function confirmPlan(planId) {
|
|
210
|
+
const res = await (0, client_1.callApi)("POST", `/api/v1/confirm/${planId}`);
|
|
211
|
+
const lines = [
|
|
212
|
+
`## Done. Tracked.`,
|
|
213
|
+
``,
|
|
214
|
+
`**Epic:** ${res.epic_key}`,
|
|
215
|
+
``,
|
|
216
|
+
`**All tickets (${res.tickets.length}):**`,
|
|
217
|
+
...res.tickets.map((url) => `- ${url}`),
|
|
218
|
+
];
|
|
219
|
+
return lines.join("\n");
|
|
220
|
+
}
|
|
221
|
+
async function createEpic(title, description) {
|
|
222
|
+
const res = await (0, client_1.callApi)("POST", "/api/v1/epic", { title, description });
|
|
223
|
+
return `Done. I've tracked that as **${res.key}**.\n${res.url}`;
|
|
224
|
+
}
|
|
225
|
+
async function createTask(title, description, epicKey) {
|
|
226
|
+
let resolvedEpicKey = epicKey;
|
|
227
|
+
// Resolve ambiguous epic references
|
|
228
|
+
if (epicKey) {
|
|
229
|
+
const resolved = await resolveIssueKey(epicKey);
|
|
230
|
+
if (!resolved.resolved) {
|
|
231
|
+
return resolved.prompt;
|
|
232
|
+
}
|
|
233
|
+
resolvedEpicKey = resolved.key;
|
|
234
|
+
}
|
|
235
|
+
const res = await (0, client_1.callApi)("POST", "/api/v1/task", {
|
|
236
|
+
title,
|
|
237
|
+
description,
|
|
238
|
+
epic_key: resolvedEpicKey,
|
|
239
|
+
});
|
|
240
|
+
return `Done. I've tracked that as **${res.key}**.\n${res.url}`;
|
|
241
|
+
}
|
|
242
|
+
async function createSubtask(title, description, parentKey) {
|
|
243
|
+
// Resolve ambiguous parent references
|
|
244
|
+
const resolved = await resolveIssueKey(parentKey);
|
|
245
|
+
if (!resolved.resolved) {
|
|
246
|
+
return resolved.prompt;
|
|
247
|
+
}
|
|
248
|
+
const res = await (0, client_1.callApi)("POST", "/api/v1/subtask", {
|
|
249
|
+
title,
|
|
250
|
+
description,
|
|
251
|
+
parent_key: resolved.key,
|
|
252
|
+
});
|
|
253
|
+
return `Done. I've tracked that as **${res.key}**.\n${res.url}`;
|
|
254
|
+
}
|
|
255
|
+
async function getTasks(epicKey) {
|
|
256
|
+
let resolvedEpicKey = epicKey;
|
|
257
|
+
// Resolve ambiguous epic references
|
|
258
|
+
if (epicKey) {
|
|
259
|
+
const resolved = await resolveIssueKey(epicKey);
|
|
260
|
+
if (!resolved.resolved) {
|
|
261
|
+
return resolved.prompt;
|
|
262
|
+
}
|
|
263
|
+
resolvedEpicKey = resolved.key;
|
|
264
|
+
}
|
|
265
|
+
const path = resolvedEpicKey ? `/api/v1/tasks/${resolvedEpicKey}` : "/api/v1/tasks";
|
|
266
|
+
const res = await (0, client_1.callApi)("GET", path);
|
|
267
|
+
if (res.total === 0) {
|
|
268
|
+
return epicKey
|
|
269
|
+
? `No open tasks found under epic ${epicKey}.`
|
|
270
|
+
: "No open tasks found in the project.";
|
|
271
|
+
}
|
|
272
|
+
const lines = [
|
|
273
|
+
`## Open Tasks${epicKey ? ` — ${epicKey}` : ""} (${res.total})`,
|
|
274
|
+
``,
|
|
275
|
+
];
|
|
276
|
+
res.tasks.forEach((task) => {
|
|
277
|
+
lines.push(`**${task.key}** — ${task.title}`);
|
|
278
|
+
lines.push(` Status: ${task.status} | Type: ${task.type}${task.assignee ? ` | Assignee: ${task.assignee}` : ""}`);
|
|
279
|
+
if (task.parent)
|
|
280
|
+
lines.push(` Parent: ${task.parent.key} — ${task.parent.title}`);
|
|
281
|
+
lines.push(` ${task.url}`);
|
|
282
|
+
lines.push(``);
|
|
283
|
+
});
|
|
284
|
+
return lines.join("\n");
|
|
285
|
+
}
|
|
286
|
+
async function updateTask(issueKey, status) {
|
|
287
|
+
// Resolve ambiguous references
|
|
288
|
+
const resolved = await resolveIssueKey(issueKey);
|
|
289
|
+
if (!resolved.resolved) {
|
|
290
|
+
return resolved.prompt;
|
|
291
|
+
}
|
|
292
|
+
await (0, client_1.callApi)("PUT", `/api/v1/task/${resolved.key}`, { status });
|
|
293
|
+
return `Moved **${resolved.key}** to \`${status}\`.`;
|
|
294
|
+
}
|
|
295
|
+
async function getProjectSummary() {
|
|
296
|
+
const res = await (0, client_1.callApi)("GET", "/api/v1/project/summary");
|
|
297
|
+
if (res.total === 0) {
|
|
298
|
+
return "No open or in-progress tasks found in the project.";
|
|
299
|
+
}
|
|
300
|
+
const lines = [
|
|
301
|
+
`## Project Summary — ${res.project} (${res.total} active)`,
|
|
302
|
+
``,
|
|
303
|
+
];
|
|
304
|
+
res.issues.forEach((issue) => {
|
|
305
|
+
const parts = [`**${issue.key}** — ${issue.title} (${issue.status})`];
|
|
306
|
+
if (issue.assignee)
|
|
307
|
+
parts.push(` Assignee: ${issue.assignee}`);
|
|
308
|
+
if (issue.parent_key)
|
|
309
|
+
parts.push(` Parent: ${issue.parent_key}${issue.epic_name ? ` — ${issue.epic_name}` : ""}`);
|
|
310
|
+
lines.push(parts.join("\n"));
|
|
311
|
+
lines.push(``);
|
|
312
|
+
});
|
|
313
|
+
return lines.join("\n");
|
|
314
|
+
}
|
|
315
|
+
async function getStatus() {
|
|
316
|
+
const res = await (0, client_1.callApi)("GET", "/api/v1/status");
|
|
317
|
+
const lines = [
|
|
318
|
+
`## Project Status — ${res.project}`,
|
|
319
|
+
``,
|
|
320
|
+
`| Metric | Count |`,
|
|
321
|
+
`|--------|-------|`,
|
|
322
|
+
`| Total tasks | ${res.total_tasks} |`,
|
|
323
|
+
`| Open | ${res.open_tasks} |`,
|
|
324
|
+
`| In Progress | ${res.in_progress_tasks} |`,
|
|
325
|
+
`| Done | ${res.completed_tasks} |`,
|
|
326
|
+
];
|
|
327
|
+
if (res.current_sprint) {
|
|
328
|
+
lines.push(``, `**Current Sprint:** ${res.current_sprint}`);
|
|
329
|
+
}
|
|
330
|
+
return lines.join("\n");
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devto-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "DevTo MCP server — AI work management for Claude Code",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"devto-mcp": "./bin/devto-mcp.js",
|
|
8
|
+
"devto": "./bin/devto.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"type-check": "tsc --noEmit",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"bin"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/kelvynk01/devto-mcp.git"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://devto.ai",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/kelvynk01/devto-mcp/issues"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@anthropic-ai/sdk": "^0.27.0",
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.14.9",
|
|
34
|
+
"typescript": "^5.4.5"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"mcp",
|
|
41
|
+
"claude",
|
|
42
|
+
"claude-code",
|
|
43
|
+
"devto",
|
|
44
|
+
"project-management",
|
|
45
|
+
"ai",
|
|
46
|
+
"work-management",
|
|
47
|
+
"jira"
|
|
48
|
+
],
|
|
49
|
+
"license": "MIT"
|
|
50
|
+
}
|