@k-system/tickr-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/CHANGELOG.md +12 -0
- package/README.md +87 -0
- package/dist/api-client.d.ts +29 -0
- package/dist/api-client.js +65 -0
- package/dist/auth.d.ts +18 -0
- package/dist/auth.js +60 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +33 -0
- package/dist/formatters.d.ts +10 -0
- package/dist/formatters.js +58 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +67 -0
- package/dist/resources/project-resource.d.ts +4 -0
- package/dist/resources/project-resource.js +18 -0
- package/dist/resources/ticket-resource.d.ts +4 -0
- package/dist/resources/ticket-resource.js +17 -0
- package/dist/tools/add-comment.d.ts +4 -0
- package/dist/tools/add-comment.js +25 -0
- package/dist/tools/add-label.d.ts +4 -0
- package/dist/tools/add-label.js +21 -0
- package/dist/tools/assign-cycle.d.ts +4 -0
- package/dist/tools/assign-cycle.js +22 -0
- package/dist/tools/assign-epic.d.ts +4 -0
- package/dist/tools/assign-epic.js +22 -0
- package/dist/tools/complete-dev-task.d.ts +4 -0
- package/dist/tools/complete-dev-task.js +37 -0
- package/dist/tools/create-ticket.d.ts +4 -0
- package/dist/tools/create-ticket.js +38 -0
- package/dist/tools/get-ticket.d.ts +4 -0
- package/dist/tools/get-ticket.js +20 -0
- package/dist/tools/list-cycles.d.ts +4 -0
- package/dist/tools/list-cycles.js +23 -0
- package/dist/tools/list-epics.d.ts +4 -0
- package/dist/tools/list-epics.js +23 -0
- package/dist/tools/list-labels.d.ts +4 -0
- package/dist/tools/list-labels.js +23 -0
- package/dist/tools/list-tickets.d.ts +4 -0
- package/dist/tools/list-tickets.js +39 -0
- package/dist/tools/poll-dev-queue.d.ts +4 -0
- package/dist/tools/poll-dev-queue.js +37 -0
- package/dist/tools/remove-label.d.ts +4 -0
- package/dist/tools/remove-label.js +21 -0
- package/dist/tools/search-tickets.d.ts +4 -0
- package/dist/tools/search-tickets.js +30 -0
- package/dist/tools/triage-accept.d.ts +4 -0
- package/dist/tools/triage-accept.js +30 -0
- package/dist/tools/triage-list.d.ts +4 -0
- package/dist/tools/triage-list.js +23 -0
- package/dist/tools/triage-reject.d.ts +4 -0
- package/dist/tools/triage-reject.js +28 -0
- package/dist/tools/update-implementation-item.d.ts +4 -0
- package/dist/tools/update-implementation-item.js +33 -0
- package/dist/tools/update-ticket.d.ts +4 -0
- package/dist/tools/update-ticket.js +32 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.js +3 -0
- package/package.json +55 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerCompleteDevTask(server, api) {
|
|
3
|
+
server.tool("complete_dev_task", "Mark a dev agent task as completed with summary, branch name, and commit hash", {
|
|
4
|
+
assignment_id: z.string().describe("UUID of the dev agent assignment"),
|
|
5
|
+
summary: z.string().describe("Summary of what was done"),
|
|
6
|
+
branch: z.string().optional().describe("Git branch name"),
|
|
7
|
+
commit_hash: z.string().optional().describe("Last commit SHA"),
|
|
8
|
+
}, async (params) => {
|
|
9
|
+
try {
|
|
10
|
+
await api.post(`/api/dev-queue/complete/${params.assignment_id}`, {
|
|
11
|
+
resultSummary: params.summary,
|
|
12
|
+
branchName: params.branch ?? null,
|
|
13
|
+
commitHash: params.commit_hash ?? null,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: "text",
|
|
19
|
+
text: `Task ${params.assignment_id} marked as completed.`,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: "text",
|
|
29
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=complete-dev-task.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerCreateTicket(server, api) {
|
|
3
|
+
server.tool("create_ticket", "Create a new ticket in a project", {
|
|
4
|
+
project: z.string().describe("Project slug, e.g. 'veliox'"),
|
|
5
|
+
type: z.enum(["task", "bug", "feature", "adr"]),
|
|
6
|
+
title: z.string(),
|
|
7
|
+
scope: z.string().optional().describe("Scope tag, e.g. 'api', 'frontend'"),
|
|
8
|
+
priority: z.enum(["P0", "P1", "P2", "P3"]).default("P2"),
|
|
9
|
+
content: z.string().optional().describe("Markdown content (analysis, solution)"),
|
|
10
|
+
affected_parts: z.array(z.string()).optional(),
|
|
11
|
+
}, async (params) => {
|
|
12
|
+
try {
|
|
13
|
+
const ticket = await api.post(`/api/projects/${params.project}/tickets`, {
|
|
14
|
+
type: params.type,
|
|
15
|
+
title: params.title,
|
|
16
|
+
scope: params.scope,
|
|
17
|
+
priority: params.priority,
|
|
18
|
+
content: params.content,
|
|
19
|
+
affectedParts: params.affected_parts,
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
type: "text",
|
|
25
|
+
text: `Created ${ticket.displayNumber}: ${ticket.title}`,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
33
|
+
isError: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=create-ticket.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatTicketMarkdown } from "../formatters.js";
|
|
3
|
+
export function registerGetTicket(server, api) {
|
|
4
|
+
server.tool("get_ticket", "Get full ticket detail by display number", {
|
|
5
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
const ticket = await api.get(`/api/tickets/${params.number}`);
|
|
9
|
+
const md = formatTicketMarkdown(ticket);
|
|
10
|
+
return { content: [{ type: "text", text: md }] };
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=get-ticket.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListCycles(server, api) {
|
|
3
|
+
server.tool("list_cycles", "List cycles (sprints) for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const cycles = await api.get(`/api/projects/${params.project}/cycles`);
|
|
8
|
+
const text = cycles
|
|
9
|
+
.map((c) => `#${c.number}${c.name ? ` ${c.name}` : ""} [${c.status}] ${c.startDate}–${c.endDate} (${c.completedTickets}/${c.totalTickets})`)
|
|
10
|
+
.join("\n");
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text: text || "No cycles found." }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
18
|
+
isError: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=list-cycles.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListEpics(server, api) {
|
|
3
|
+
server.tool("list_epics", "List epics for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const epics = await api.get(`/api/projects/${params.project}/epics`);
|
|
8
|
+
const text = epics
|
|
9
|
+
.map((e) => `${e.name} [${e.status}] (${e.completedTickets}/${e.totalTickets})${e.targetDate ? ` target: ${e.targetDate}` : ""}`)
|
|
10
|
+
.join("\n");
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text: text || "No epics found." }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
18
|
+
isError: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=list-epics.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListLabels(server, api) {
|
|
3
|
+
server.tool("list_labels", "List labels for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const labels = await api.get(`/api/projects/${params.project}/labels`);
|
|
8
|
+
const text = labels
|
|
9
|
+
.map((l) => `${l.name} (${l.color})`)
|
|
10
|
+
.join("\n");
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text: text || "No labels configured." }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
18
|
+
isError: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=list-labels.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListTickets(server, api) {
|
|
3
|
+
server.tool("list_tickets", "List tickets with optional filters", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
status: z.string().optional().describe("Status slug: planning, in-progress, done..."),
|
|
6
|
+
type: z.string().optional(),
|
|
7
|
+
assignee: z.string().optional().describe("Username"),
|
|
8
|
+
scope: z.string().optional(),
|
|
9
|
+
limit: z.number().default(20),
|
|
10
|
+
}, async (params) => {
|
|
11
|
+
try {
|
|
12
|
+
const qs = new URLSearchParams();
|
|
13
|
+
if (params.status)
|
|
14
|
+
qs.set("status", params.status);
|
|
15
|
+
if (params.type)
|
|
16
|
+
qs.set("type", params.type);
|
|
17
|
+
if (params.assignee)
|
|
18
|
+
qs.set("assignee", params.assignee);
|
|
19
|
+
if (params.scope)
|
|
20
|
+
qs.set("scope", params.scope);
|
|
21
|
+
qs.set("limit", String(params.limit));
|
|
22
|
+
const path = `/api/projects/${params.project}/tickets?${qs}`;
|
|
23
|
+
const tickets = await api.get(path);
|
|
24
|
+
const text = tickets
|
|
25
|
+
.map((t) => `${t.displayNumber} [${t.status}] ${t.title} (${t.priority}, ${t.scope || "-"})`)
|
|
26
|
+
.join("\n");
|
|
27
|
+
return {
|
|
28
|
+
content: [{ type: "text", text: text || "No tickets found." }],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
34
|
+
isError: true,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=list-tickets.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function registerPollDevQueue(server, api) {
|
|
2
|
+
server.tool("poll_dev_queue", "Poll for next dev task in the agent queue. Returns ticket details and assigned skills/instructions.", {}, async () => {
|
|
3
|
+
try {
|
|
4
|
+
const result = await api.get("/api/dev-queue/poll");
|
|
5
|
+
if (!result) {
|
|
6
|
+
return {
|
|
7
|
+
content: [{ type: "text", text: "No tasks in queue." }],
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const { assignmentId, ticket, skills } = result;
|
|
11
|
+
let text = `## New task: ${ticket.displayNumber} — ${ticket.title}\n` +
|
|
12
|
+
`**Assignment ID:** ${assignmentId}\n` +
|
|
13
|
+
`**Type:** ${ticket.type} | **Priority:** ${ticket.priority} | **Scope:** ${ticket.scope || "any"}\n` +
|
|
14
|
+
`**Project:** ${ticket.projectSlug}\n\n` +
|
|
15
|
+
`### Description\n${ticket.description || "(no description)"}\n`;
|
|
16
|
+
if (skills.length > 0) {
|
|
17
|
+
text += `\n---\n### Instructions\n`;
|
|
18
|
+
for (const skill of skills) {
|
|
19
|
+
text += `\n#### ${skill.name}\n${skill.instructions}\n`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { content: [{ type: "text", text }] };
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: "text",
|
|
29
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=poll-dev-queue.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerRemoveLabel(server, api) {
|
|
3
|
+
server.tool("remove_label", "Remove a label from a ticket", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
label_id: z.string().describe("UUID of the label to remove"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
await api.delete(`/api/tickets/${params.number}/labels/${params.label_id}`);
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: `Label removed from ${params.number}` }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
return {
|
|
15
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
16
|
+
isError: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=remove-label.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerSearchTickets(server, api) {
|
|
3
|
+
server.tool("search_tickets", "Fulltext search in ticket titles and content", {
|
|
4
|
+
query: z.string().describe("Fulltext search query"),
|
|
5
|
+
project: z.string().optional().describe("Limit to project slug"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
const q = encodeURIComponent(params.query);
|
|
9
|
+
let path = `/api/search?q=${q}`;
|
|
10
|
+
if (params.project)
|
|
11
|
+
path += `&project=${encodeURIComponent(params.project)}`;
|
|
12
|
+
const results = await api.get(path);
|
|
13
|
+
const text = results
|
|
14
|
+
.map((t) => `${t.displayNumber} [${t.status}] ${t.title} (${t.priority})`)
|
|
15
|
+
.join("\n");
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{ type: "text", text: text || "No results found." },
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
25
|
+
isError: true,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=search-tickets.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerTriageAccept(server, api) {
|
|
3
|
+
server.tool("triage_accept", "Accept tickets from triage inbox — move them to a target status", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
ticket_ids: z.array(z.string()).describe("Array of ticket UUIDs to accept"),
|
|
6
|
+
target_status_id: z.string().describe("UUID of target status to move tickets to"),
|
|
7
|
+
assignee_id: z.string().optional().describe("UUID of assignee"),
|
|
8
|
+
}, async (params) => {
|
|
9
|
+
try {
|
|
10
|
+
const result = await api.post(`/api/projects/${params.project}/triage/accept`, {
|
|
11
|
+
ticketIds: params.ticket_ids,
|
|
12
|
+
targetStatusId: params.target_status_id,
|
|
13
|
+
assigneeId: params.assignee_id ?? null,
|
|
14
|
+
});
|
|
15
|
+
let text = `Accepted ${result.processed} ticket(s)`;
|
|
16
|
+
if (result.failed > 0)
|
|
17
|
+
text += `, ${result.failed} failed: ${result.errors.join("; ")}`;
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text }],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
25
|
+
isError: true,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=triage-accept.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerTriageList(server, api) {
|
|
3
|
+
server.tool("triage_list", "List tickets in triage inbox for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const tickets = await api.get(`/api/projects/${params.project}/triage`);
|
|
8
|
+
const text = tickets
|
|
9
|
+
.map((t) => `${t.displayNumber} [${t.priority}] ${t.title} (${t.scope || "-"})`)
|
|
10
|
+
.join("\n");
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text: text || "No tickets in triage." }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
18
|
+
isError: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=triage-list.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerTriageReject(server, api) {
|
|
3
|
+
server.tool("triage_reject", "Reject tickets from triage inbox — move them to cancelled", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
ticket_ids: z.array(z.string()).describe("Array of ticket UUIDs to reject"),
|
|
6
|
+
reason: z.string().optional().describe("Rejection reason (added as comment)"),
|
|
7
|
+
}, async (params) => {
|
|
8
|
+
try {
|
|
9
|
+
const result = await api.post(`/api/projects/${params.project}/triage/reject`, {
|
|
10
|
+
ticketIds: params.ticket_ids,
|
|
11
|
+
reason: params.reason ?? null,
|
|
12
|
+
});
|
|
13
|
+
let text = `Rejected ${result.processed} ticket(s)`;
|
|
14
|
+
if (result.failed > 0)
|
|
15
|
+
text += `, ${result.failed} failed: ${result.errors.join("; ")}`;
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text }],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
23
|
+
isError: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=triage-reject.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ApiClient } from "../api-client.js";
|
|
3
|
+
export declare function registerUpdateImplementationItem(server: McpServer, api: ApiClient): void;
|
|
4
|
+
//# sourceMappingURL=update-implementation-item.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerUpdateImplementationItem(server, api) {
|
|
3
|
+
server.tool("update_implementation_item", "Update an implementation item on a ticket", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
item_index: z.number().describe("0-based index in implementation table"),
|
|
6
|
+
status: z
|
|
7
|
+
.enum(["todo", "in-progress", "done", "skipped"])
|
|
8
|
+
.optional(),
|
|
9
|
+
note: z.string().optional(),
|
|
10
|
+
}, async (params) => {
|
|
11
|
+
try {
|
|
12
|
+
await api.patch(`/api/tickets/${params.number}/items/${params.item_index}`, {
|
|
13
|
+
status: params.status,
|
|
14
|
+
note: params.note,
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: `Item #${params.item_index} updated on ${params.number}`,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
return {
|
|
27
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
28
|
+
isError: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=update-implementation-item.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerUpdateTicket(server, api) {
|
|
3
|
+
server.tool("update_ticket", "Update ticket fields (status, title, content, priority, assignee, scope)", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
status: z.string().optional().describe("New status slug"),
|
|
6
|
+
title: z.string().optional(),
|
|
7
|
+
content: z.string().optional(),
|
|
8
|
+
priority: z.string().optional(),
|
|
9
|
+
assignee: z.string().optional().describe("Username or 'unassigned'"),
|
|
10
|
+
scope: z.string().optional(),
|
|
11
|
+
}, async (params) => {
|
|
12
|
+
try {
|
|
13
|
+
const { number, ...updates } = params;
|
|
14
|
+
const ticket = await api.put(`/api/tickets/${number}`, updates);
|
|
15
|
+
return {
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: "text",
|
|
19
|
+
text: `Updated ${ticket.displayNumber}: status=${ticket.status}`,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
27
|
+
isError: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=update-ticket.js.map
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** Sdílené typy pro MCP server */
|
|
2
|
+
export interface Ticket {
|
|
3
|
+
id: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
number: number;
|
|
6
|
+
displayNumber: string;
|
|
7
|
+
type: string;
|
|
8
|
+
title: string;
|
|
9
|
+
scope: string | null;
|
|
10
|
+
status: string;
|
|
11
|
+
priority: string;
|
|
12
|
+
estimate: string | null;
|
|
13
|
+
assigneeId: string | null;
|
|
14
|
+
assigneeName: string | null;
|
|
15
|
+
content: string | null;
|
|
16
|
+
affectedParts: string[];
|
|
17
|
+
implementationItems: ImplementationItem[];
|
|
18
|
+
comments: Comment[];
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ImplementationItem {
|
|
23
|
+
id: string;
|
|
24
|
+
area: string;
|
|
25
|
+
fileOrDetail: string;
|
|
26
|
+
status: string;
|
|
27
|
+
note: string | null;
|
|
28
|
+
sortOrder: number;
|
|
29
|
+
}
|
|
30
|
+
export interface Comment {
|
|
31
|
+
id: string;
|
|
32
|
+
text: string;
|
|
33
|
+
authorName: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
}
|
|
36
|
+
export interface Project {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
slug: string;
|
|
40
|
+
prefix: string;
|
|
41
|
+
description: string | null;
|
|
42
|
+
scopeTags: string[];
|
|
43
|
+
ticketTypes: string[];
|
|
44
|
+
createdAt: string;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
}
|
|
47
|
+
export interface TicketListItem {
|
|
48
|
+
displayNumber: string;
|
|
49
|
+
title: string;
|
|
50
|
+
scope: string | null;
|
|
51
|
+
status: string;
|
|
52
|
+
priority: string;
|
|
53
|
+
assigneeName: string | null;
|
|
54
|
+
}
|
|
55
|
+
export interface TriageResult {
|
|
56
|
+
processed: number;
|
|
57
|
+
failed: number;
|
|
58
|
+
errors: string[];
|
|
59
|
+
}
|
|
60
|
+
export interface Label {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
color: string;
|
|
64
|
+
sortOrder: number;
|
|
65
|
+
}
|
|
66
|
+
export interface Cycle {
|
|
67
|
+
id: string;
|
|
68
|
+
number: number;
|
|
69
|
+
name: string | null;
|
|
70
|
+
startDate: string;
|
|
71
|
+
endDate: string;
|
|
72
|
+
status: string;
|
|
73
|
+
totalTickets: number;
|
|
74
|
+
completedTickets: number;
|
|
75
|
+
createdAt: string;
|
|
76
|
+
}
|
|
77
|
+
export interface Epic {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
description: string | null;
|
|
81
|
+
color: string;
|
|
82
|
+
status: string;
|
|
83
|
+
targetDate: string | null;
|
|
84
|
+
totalTickets: number;
|
|
85
|
+
completedTickets: number;
|
|
86
|
+
createdAt: string;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
ADDED