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/config.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DevToConfig = {
|
|
2
|
+
api_key: string;
|
|
3
|
+
api_url: string;
|
|
4
|
+
anthropic_key?: string;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function readConfig(): DevToConfig | null;
|
|
8
|
+
export declare function writeConfig(config: DevToConfig): void;
|
|
9
|
+
export declare function getApiKey(): string;
|
|
10
|
+
export declare function getApiUrl(): string;
|
|
11
|
+
export declare function getAnthropicKey(): string;
|
|
12
|
+
export declare function isVerbose(): boolean;
|
|
13
|
+
export declare function setVerbose(enabled: boolean): void;
|
|
14
|
+
export declare function setAnthropicKey(key: string): void;
|
|
15
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAMF,wBAAgB,UAAU,IAAI,WAAW,GAAG,IAAI,CAe/C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKrD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAYlC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAMxC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAGnC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAIjD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAIjD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.readConfig = readConfig;
|
|
37
|
+
exports.writeConfig = writeConfig;
|
|
38
|
+
exports.getApiKey = getApiKey;
|
|
39
|
+
exports.getApiUrl = getApiUrl;
|
|
40
|
+
exports.getAnthropicKey = getAnthropicKey;
|
|
41
|
+
exports.isVerbose = isVerbose;
|
|
42
|
+
exports.setVerbose = setVerbose;
|
|
43
|
+
exports.setAnthropicKey = setAnthropicKey;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const CONFIG_DIR = path.join(os.homedir(), ".devto");
|
|
48
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
49
|
+
const DEFAULT_API_URL = "https://api.devto.ai";
|
|
50
|
+
function readConfig() {
|
|
51
|
+
try {
|
|
52
|
+
if (!fs.existsSync(CONFIG_FILE))
|
|
53
|
+
return null;
|
|
54
|
+
const raw = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
55
|
+
const parsed = JSON.parse(raw);
|
|
56
|
+
if (!parsed.api_key)
|
|
57
|
+
return null;
|
|
58
|
+
return {
|
|
59
|
+
api_key: parsed.api_key,
|
|
60
|
+
api_url: parsed.api_url ?? DEFAULT_API_URL,
|
|
61
|
+
anthropic_key: parsed.anthropic_key,
|
|
62
|
+
verbose: parsed.verbose,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function writeConfig(config) {
|
|
70
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
71
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
72
|
+
}
|
|
73
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
74
|
+
}
|
|
75
|
+
function getApiKey() {
|
|
76
|
+
// Prefer environment variable (for MCP server launched by Claude Code)
|
|
77
|
+
const envKey = process.env.DEVTO_API_KEY;
|
|
78
|
+
if (envKey)
|
|
79
|
+
return envKey;
|
|
80
|
+
const config = readConfig();
|
|
81
|
+
if (!config) {
|
|
82
|
+
throw new Error("No DevTo API key found. Run `devto login` to authenticate, or set the DEVTO_API_KEY environment variable.");
|
|
83
|
+
}
|
|
84
|
+
return config.api_key;
|
|
85
|
+
}
|
|
86
|
+
function getApiUrl() {
|
|
87
|
+
return process.env.DEVTO_API_URL ?? readConfig()?.api_url ?? DEFAULT_API_URL;
|
|
88
|
+
}
|
|
89
|
+
function getAnthropicKey() {
|
|
90
|
+
const config = readConfig();
|
|
91
|
+
if (config?.anthropic_key)
|
|
92
|
+
return config.anthropic_key;
|
|
93
|
+
throw new Error("No Anthropic API key configured. Run: devto config set anthropic-key sk-ant-xxxx");
|
|
94
|
+
}
|
|
95
|
+
function isVerbose() {
|
|
96
|
+
const config = readConfig();
|
|
97
|
+
return config?.verbose ?? false;
|
|
98
|
+
}
|
|
99
|
+
function setVerbose(enabled) {
|
|
100
|
+
const config = readConfig() ?? { api_key: "", api_url: DEFAULT_API_URL };
|
|
101
|
+
config.verbose = enabled;
|
|
102
|
+
writeConfig(config);
|
|
103
|
+
}
|
|
104
|
+
function setAnthropicKey(key) {
|
|
105
|
+
const config = readConfig() ?? { api_key: "", api_url: DEFAULT_API_URL };
|
|
106
|
+
config.anthropic_key = key;
|
|
107
|
+
writeConfig(config);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
const client_1 = require("./client");
|
|
9
|
+
const tools_1 = require("./tools");
|
|
10
|
+
const CURRENT_VERSION = "0.1.0";
|
|
11
|
+
// Auto-update check (non-blocking)
|
|
12
|
+
(async () => {
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetch("https://registry.npmjs.org/devto-mcp/latest", {
|
|
15
|
+
signal: AbortSignal.timeout(5000),
|
|
16
|
+
});
|
|
17
|
+
if (res.ok) {
|
|
18
|
+
const data = (await res.json());
|
|
19
|
+
if (data.version && data.version !== CURRENT_VERSION) {
|
|
20
|
+
console.error(`[devto-mcp] DevTo v${data.version} is available. Run npm update -g devto-mcp to update.`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Silently ignore — don't block startup
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
// Fail fast if no API key is configured
|
|
29
|
+
try {
|
|
30
|
+
(0, config_1.getApiKey)();
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.error(`[devto-mcp] ${err instanceof Error ? err.message : String(err)}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const SYSTEM_PROMPT = `You are DevTo, an AI work manager that lives inside Claude Code. You actively manage the developer's project work alongside them as they code. The project tool (Jira, Linear, etc.) is your output mechanism — the intelligence is you.
|
|
37
|
+
|
|
38
|
+
## Session Start
|
|
39
|
+
Call get_project_summary silently when the session begins. Do not announce it. Load the project context so you can reason against it naturally.
|
|
40
|
+
|
|
41
|
+
## Tools
|
|
42
|
+
- get_project_summary — Load a lightweight snapshot of all active work. Call at session start and whenever project context may be stale.
|
|
43
|
+
- create_plan — Generate a structured plan (epic + stories + subtasks) from a feature description using the Anthropic API. Returns a preview.
|
|
44
|
+
- confirm_plan — Execute a previously previewed plan, creating all work items.
|
|
45
|
+
- create_epic — Create a single epic.
|
|
46
|
+
- create_task — Create a story or task, optionally linked to an epic.
|
|
47
|
+
- create_subtask — Create a subtask under a parent issue.
|
|
48
|
+
- get_tasks — Fetch detailed ticket data for specific epics or all open work.
|
|
49
|
+
- update_task — Update a task's status. Accepts natural language references.
|
|
50
|
+
- get_status — Get aggregate project metrics: task counts and current sprint.
|
|
51
|
+
|
|
52
|
+
## The One Rule
|
|
53
|
+
Never write to the project tool without explicit developer confirmation. Always show what you intend to do and wait for a yes. No exceptions.`;
|
|
54
|
+
const server = new index_js_1.Server({
|
|
55
|
+
name: "devto",
|
|
56
|
+
version: CURRENT_VERSION,
|
|
57
|
+
}, {
|
|
58
|
+
capabilities: {
|
|
59
|
+
tools: {},
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
// ─── Tool definitions ────────────────────────────────────────────────────────
|
|
63
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
64
|
+
tools: [
|
|
65
|
+
{
|
|
66
|
+
name: "get_project_summary",
|
|
67
|
+
description: "Load a lightweight snapshot of all open and in-progress work into context. Returns key, title, status, assignee, and parent for each issue. No descriptions or comments. Called automatically at session start for ambient project awareness. Never counts against write limits.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {},
|
|
71
|
+
required: [],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "create_plan",
|
|
76
|
+
description: "Generate an AI-powered project plan from a feature description. Returns a structured preview with epic, stories, and subtasks. Nothing is tracked until confirm_plan is called.",
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {
|
|
80
|
+
feature_description: {
|
|
81
|
+
type: "string",
|
|
82
|
+
description: "A description of the feature or work to plan",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
required: ["feature_description"],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "confirm_plan",
|
|
90
|
+
description: "Execute a previously generated plan by tracking all work items (epic, stories, subtasks). Only call this after the user has reviewed and approved the plan from create_plan.",
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
plan_id: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "The plan ID returned by create_plan",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ["plan_id"],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "create_epic",
|
|
104
|
+
description: "Create a single epic in your project",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
title: { type: "string", description: "Epic title" },
|
|
109
|
+
description: { type: "string", description: "Epic description" },
|
|
110
|
+
},
|
|
111
|
+
required: ["title", "description"],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "create_task",
|
|
116
|
+
description: "Create a single story or task, optionally linked to an epic. You can reference the epic by exact key or natural description.",
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: "object",
|
|
119
|
+
properties: {
|
|
120
|
+
title: { type: "string", description: "Task title" },
|
|
121
|
+
description: { type: "string", description: "Task description" },
|
|
122
|
+
epic_key: {
|
|
123
|
+
type: "string",
|
|
124
|
+
description: "Optional epic key (e.g. PROJ-1) or description to link this task to",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
required: ["title", "description"],
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "create_subtask",
|
|
132
|
+
description: "Create a subtask under a parent issue. You can reference the parent by exact key or natural description.",
|
|
133
|
+
inputSchema: {
|
|
134
|
+
type: "object",
|
|
135
|
+
properties: {
|
|
136
|
+
title: { type: "string", description: "Subtask title" },
|
|
137
|
+
description: { type: "string", description: "Subtask description" },
|
|
138
|
+
parent_key: {
|
|
139
|
+
type: "string",
|
|
140
|
+
description: "Parent issue key (e.g. PROJ-5) or a natural language description",
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
required: ["title", "description", "parent_key"],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "get_tasks",
|
|
148
|
+
description: "Get open tasks (To Do + In Progress) for your project. Optionally filter by epic.",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
epic_key: {
|
|
153
|
+
type: "string",
|
|
154
|
+
description: "Optional epic key to filter tasks (e.g. PROJ-1)",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
required: [],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "update_task",
|
|
162
|
+
description: "Update the status of a task. You can use an exact key (e.g. PROJ-5) or a natural description (e.g. 'the auth task'). If ambiguous, DevTo will ask which task you mean.",
|
|
163
|
+
inputSchema: {
|
|
164
|
+
type: "object",
|
|
165
|
+
properties: {
|
|
166
|
+
issue_key: {
|
|
167
|
+
type: "string",
|
|
168
|
+
description: "Issue key (e.g. PROJ-5) or a natural language description of the task",
|
|
169
|
+
},
|
|
170
|
+
status: {
|
|
171
|
+
type: "string",
|
|
172
|
+
enum: ["todo", "in_progress", "in_review", "done"],
|
|
173
|
+
description: "New status for the task",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
required: ["issue_key", "status"],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "get_status",
|
|
181
|
+
description: "Get a summary of your project: task counts and current sprint",
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {},
|
|
185
|
+
required: [],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
}));
|
|
190
|
+
// ─── Tool handler ────────────────────────────────────────────────────────────
|
|
191
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
192
|
+
const { name, arguments: args } = request.params;
|
|
193
|
+
try {
|
|
194
|
+
let result;
|
|
195
|
+
switch (name) {
|
|
196
|
+
case "get_project_summary":
|
|
197
|
+
result = await (0, tools_1.getProjectSummary)();
|
|
198
|
+
break;
|
|
199
|
+
case "create_plan":
|
|
200
|
+
result = await (0, tools_1.createPlan)(args?.feature_description);
|
|
201
|
+
break;
|
|
202
|
+
case "confirm_plan":
|
|
203
|
+
result = await (0, tools_1.confirmPlan)(args?.plan_id);
|
|
204
|
+
break;
|
|
205
|
+
case "create_epic":
|
|
206
|
+
result = await (0, tools_1.createEpic)(args?.title, args?.description);
|
|
207
|
+
break;
|
|
208
|
+
case "create_task":
|
|
209
|
+
result = await (0, tools_1.createTask)(args?.title, args?.description, args?.epic_key);
|
|
210
|
+
break;
|
|
211
|
+
case "create_subtask":
|
|
212
|
+
result = await (0, tools_1.createSubtask)(args?.title, args?.description, args?.parent_key);
|
|
213
|
+
break;
|
|
214
|
+
case "get_tasks":
|
|
215
|
+
result = await (0, tools_1.getTasks)(args?.epic_key);
|
|
216
|
+
break;
|
|
217
|
+
case "update_task":
|
|
218
|
+
result = await (0, tools_1.updateTask)(args?.issue_key, args?.status);
|
|
219
|
+
break;
|
|
220
|
+
case "get_status":
|
|
221
|
+
result = await (0, tools_1.getStatus)();
|
|
222
|
+
break;
|
|
223
|
+
default:
|
|
224
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
content: [{ type: "text", text: result }],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
if (err instanceof types_js_1.McpError)
|
|
232
|
+
throw err;
|
|
233
|
+
const message = err instanceof client_1.DevToApiError
|
|
234
|
+
? `DevTo API error: ${err.message}${err.code ? ` (${err.code})` : ""}`
|
|
235
|
+
: `Unexpected error: ${err instanceof Error ? err.message : String(err)}`;
|
|
236
|
+
return {
|
|
237
|
+
content: [{ type: "text", text: message }],
|
|
238
|
+
isError: true,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
// ─── Start server ────────────────────────────────────────────────────────────
|
|
243
|
+
async function main() {
|
|
244
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
245
|
+
await server.connect(transport);
|
|
246
|
+
console.error("[devto-mcp] Server started");
|
|
247
|
+
}
|
|
248
|
+
main().catch((err) => {
|
|
249
|
+
console.error("[devto-mcp] Fatal error:", err);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
});
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve an ambiguous reference to an issue key.
|
|
3
|
+
* If the input looks like a valid key (e.g. PROJ-5), returns it directly.
|
|
4
|
+
* Otherwise, fetches tasks and attempts semantic matching.
|
|
5
|
+
*
|
|
6
|
+
* Returns either:
|
|
7
|
+
* { resolved: true, key: string } — exact or high-confidence match
|
|
8
|
+
* { resolved: false, prompt: string } — disambiguation needed
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveIssueKey(input: string): Promise<{
|
|
11
|
+
resolved: true;
|
|
12
|
+
key: string;
|
|
13
|
+
} | {
|
|
14
|
+
resolved: false;
|
|
15
|
+
prompt: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function createPlan(featureDescription: string): Promise<string>;
|
|
18
|
+
export declare function confirmPlan(planId: string): Promise<string>;
|
|
19
|
+
export declare function createEpic(title: string, description: string): Promise<string>;
|
|
20
|
+
export declare function createTask(title: string, description: string, epicKey?: string): Promise<string>;
|
|
21
|
+
export declare function createSubtask(title: string, description: string, parentKey: string): Promise<string>;
|
|
22
|
+
export declare function getTasks(epicKey?: string): Promise<string>;
|
|
23
|
+
export declare function updateTask(issueKey: string, status: string): Promise<string>;
|
|
24
|
+
export declare function getProjectSummary(): Promise<string>;
|
|
25
|
+
export declare function getStatus(): Promise<string>;
|
|
26
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAkJA;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgEhF;AAID,wBAAsB,UAAU,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoF5E;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAajE;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpF;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAsB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmChE;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASlF;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAqBzD;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBjD"}
|