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/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
+ }