@k-system/tickr-mcp 0.1.5 → 0.3.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/formatters.js +1 -0
- package/dist/index.js +103 -1
- package/dist/tools/add-project-member.d.ts +4 -0
- package/dist/tools/add-project-member.js +32 -0
- package/dist/tools/apply-preset.d.ts +4 -0
- package/dist/tools/apply-preset.js +26 -0
- package/dist/tools/complete-dev-task.js +3 -1
- package/dist/tools/create-cycle.d.ts +4 -0
- package/dist/tools/create-cycle.js +32 -0
- package/dist/tools/create-epic.d.ts +4 -0
- package/dist/tools/create-epic.js +36 -0
- package/dist/tools/create-implementation-item.d.ts +4 -0
- package/dist/tools/create-implementation-item.js +32 -0
- package/dist/tools/create-label.d.ts +4 -0
- package/dist/tools/create-label.js +30 -0
- package/dist/tools/create-project.d.ts +4 -0
- package/dist/tools/create-project.js +33 -0
- package/dist/tools/create-status.d.ts +4 -0
- package/dist/tools/create-status.js +42 -0
- package/dist/tools/create-ticket.js +2 -0
- package/dist/tools/delete-attachment.d.ts +4 -0
- package/dist/tools/delete-attachment.js +26 -0
- package/dist/tools/delete-comment.d.ts +4 -0
- package/dist/tools/delete-comment.js +22 -0
- package/dist/tools/delete-cycle.d.ts +4 -0
- package/dist/tools/delete-cycle.js +26 -0
- package/dist/tools/delete-epic.d.ts +4 -0
- package/dist/tools/delete-epic.js +26 -0
- package/dist/tools/delete-implementation-item.d.ts +4 -0
- package/dist/tools/delete-implementation-item.js +26 -0
- package/dist/tools/delete-label.d.ts +4 -0
- package/dist/tools/delete-label.js +26 -0
- package/dist/tools/delete-status.d.ts +4 -0
- package/dist/tools/delete-status.js +26 -0
- package/dist/tools/delete-ticket.d.ts +4 -0
- package/dist/tools/delete-ticket.js +25 -0
- package/dist/tools/fail-dev-task.d.ts +4 -0
- package/dist/tools/fail-dev-task.js +29 -0
- package/dist/tools/get-board.d.ts +4 -0
- package/dist/tools/get-board.js +37 -0
- package/dist/tools/get-my-tasks.d.ts +4 -0
- package/dist/tools/get-my-tasks.js +20 -0
- package/dist/tools/get-next-statuses.d.ts +4 -0
- package/dist/tools/get-next-statuses.js +30 -0
- package/dist/tools/get-project.d.ts +4 -0
- package/dist/tools/get-project.js +20 -0
- package/dist/tools/list-attachments.d.ts +4 -0
- package/dist/tools/list-attachments.js +37 -0
- package/dist/tools/list-comments.d.ts +4 -0
- package/dist/tools/list-comments.js +31 -0
- package/dist/tools/list-dev-assignments.d.ts +4 -0
- package/dist/tools/list-dev-assignments.js +27 -0
- package/dist/tools/list-project-members.d.ts +4 -0
- package/dist/tools/list-project-members.js +29 -0
- package/dist/tools/list-projects.d.ts +4 -0
- package/dist/tools/list-projects.js +22 -0
- package/dist/tools/list-relations.d.ts +4 -0
- package/dist/tools/list-relations.js +30 -0
- package/dist/tools/list-statuses.d.ts +4 -0
- package/dist/tools/list-statuses.js +25 -0
- package/dist/tools/list-transitions.d.ts +4 -0
- package/dist/tools/list-transitions.js +25 -0
- package/dist/tools/list-workflow-presets.d.ts +4 -0
- package/dist/tools/list-workflow-presets.js +22 -0
- package/dist/tools/remove-project-member.d.ts +4 -0
- package/dist/tools/remove-project-member.js +26 -0
- package/dist/tools/update-comment.d.ts +4 -0
- package/dist/tools/update-comment.js +24 -0
- package/dist/tools/update-cycle.d.ts +4 -0
- package/dist/tools/update-cycle.js +39 -0
- package/dist/tools/update-epic.d.ts +4 -0
- package/dist/tools/update-epic.js +42 -0
- package/dist/tools/update-implementation-item.js +1 -1
- package/dist/tools/update-label.d.ts +4 -0
- package/dist/tools/update-label.js +33 -0
- package/dist/tools/update-project-member-role.d.ts +4 -0
- package/dist/tools/update-project-member-role.js +29 -0
- package/dist/tools/update-status.d.ts +4 -0
- package/dist/tools/update-status.js +39 -0
- package/dist/tools/update-ticket.js +12 -4
- package/dist/tools/update-transitions.d.ts +4 -0
- package/dist/tools/update-transitions.js +37 -0
- package/package.json +2 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerDeleteLabel(server, api) {
|
|
3
|
+
server.tool("delete_label", "Delete a label from a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
label_id: z.string().describe("UUID of the label to delete"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
await api.delete(`/api/projects/${params.project}/labels/${params.label_id}`);
|
|
9
|
+
return {
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: "text",
|
|
13
|
+
text: `Label ${params.label_id} deleted from project ${params.project}`,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
21
|
+
isError: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=delete-label.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerDeleteStatus(server, api) {
|
|
3
|
+
server.tool("delete_status", "Delete a workflow status from a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
status_id: z.string().describe("Status ID to delete"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
await api.delete(`/api/projects/${params.project}/statuses/${params.status_id}`);
|
|
9
|
+
return {
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: "text",
|
|
13
|
+
text: `Status ${params.status_id} deleted from project ${params.project}`,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
21
|
+
isError: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=delete-status.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerDeleteTicket(server, api) {
|
|
3
|
+
server.tool("delete_ticket", "Delete a ticket by display number", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
await api.delete(`/api/tickets/${params.number}`);
|
|
8
|
+
return {
|
|
9
|
+
content: [
|
|
10
|
+
{
|
|
11
|
+
type: "text",
|
|
12
|
+
text: `Ticket ${params.number} deleted`,
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
20
|
+
isError: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=delete-ticket.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerFailDevTask(server, api) {
|
|
3
|
+
server.tool("fail_dev_task", "Mark a dev agent task as failed with a reason", {
|
|
4
|
+
assignment_id: z.string().describe("UUID of the dev agent assignment"),
|
|
5
|
+
reason: z.string().describe("Reason why the task failed"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
const reason = params.reason.replace(/\\n/g, "\n");
|
|
9
|
+
await api.post(`/api/dev-queue/fail/${params.assignment_id}`, {
|
|
10
|
+
reason,
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: "text",
|
|
16
|
+
text: `Task ${params.assignment_id} marked as failed.`,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
24
|
+
isError: true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=fail-dev-task.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetBoard(server, api) {
|
|
3
|
+
server.tool("get_board", "Get kanban board view for a project (tickets grouped by status columns)", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const columns = await api.get(`/api/projects/${params.project}/board`);
|
|
8
|
+
const lines = [];
|
|
9
|
+
for (const col of columns) {
|
|
10
|
+
const emoji = col.statusEmoji ? `${col.statusEmoji} ` : "";
|
|
11
|
+
lines.push(`## ${emoji}${col.status} (${col.tickets.length})`);
|
|
12
|
+
lines.push("");
|
|
13
|
+
if (col.tickets.length === 0) {
|
|
14
|
+
lines.push("_No tickets_");
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
lines.push("| Ticket | Title | Priority | Assignee | Scope |");
|
|
18
|
+
lines.push("|--------|-------|----------|----------|-------|");
|
|
19
|
+
for (const t of col.tickets) {
|
|
20
|
+
lines.push(`| ${t.displayNumber} | ${t.title} | ${t.priority} | ${t.assigneeName || "-"} | ${t.scope || "-"} |`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
lines.push("");
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: lines.join("\n") || "Board is empty." }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=get-board.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function registerGetMyTasks(server, api) {
|
|
2
|
+
server.tool("get_my_tasks", "Get tickets assigned to the current user across all projects", {}, async () => {
|
|
3
|
+
try {
|
|
4
|
+
const tickets = await api.get("/api/my-tasks");
|
|
5
|
+
const text = tickets
|
|
6
|
+
.map((t) => `${t.displayNumber} [${t.status}] ${t.title} (${t.priority}, ${t.scope || "-"})`)
|
|
7
|
+
.join("\n");
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: "text", text: text || "No tasks assigned to you." }],
|
|
10
|
+
};
|
|
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-my-tasks.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetNextStatuses(server, api) {
|
|
3
|
+
server.tool("get_next_statuses", "Get available next statuses for a ticket (based on current status and user role)", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' or 'TKR-BUG-0042'"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const statuses = await api.get(`/api/tickets/${params.number}/next-statuses`);
|
|
8
|
+
if (statuses.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: `No available transitions for ${params.number}` }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const lines = [
|
|
14
|
+
"| # | Status | Emoji | Color | Category |",
|
|
15
|
+
"|---|--------|-------|-------|----------|",
|
|
16
|
+
...statuses.map((s, i) => `| ${i + 1} | ${s.name} | ${s.emoji || "-"} | ${s.color} | ${s.category} |`),
|
|
17
|
+
];
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
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=get-next-statuses.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatProjectMarkdown } from "../formatters.js";
|
|
3
|
+
export function registerGetProject(server, api) {
|
|
4
|
+
server.tool("get_project", "Get project detail by slug", {
|
|
5
|
+
slug: z.string().describe("Project slug, e.g. 'tickr'"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
const project = await api.get(`/api/projects/${params.slug}`);
|
|
9
|
+
const md = formatProjectMarkdown(project);
|
|
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-project.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListAttachments(server, api) {
|
|
3
|
+
server.tool("list_attachments", "List attachments on a ticket", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const attachments = await api.get(`/api/tickets/${params.number}/attachments`);
|
|
8
|
+
if (attachments.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: "No attachments on this ticket." }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const lines = [
|
|
14
|
+
"| # | File | Type | Size | Uploaded By | Date |",
|
|
15
|
+
"|---|------|------|------|-------------|------|",
|
|
16
|
+
...attachments.map((a, i) => `| ${i + 1} | ${a.fileName} | ${a.contentType} | ${formatSize(a.size)} | ${a.createdByName || "-"} | ${a.createdAt} |`),
|
|
17
|
+
];
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
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
|
+
function formatSize(bytes) {
|
|
31
|
+
if (bytes < 1024)
|
|
32
|
+
return `${bytes} B`;
|
|
33
|
+
if (bytes < 1024 * 1024)
|
|
34
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
35
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=list-attachments.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListComments(server, api) {
|
|
3
|
+
server.tool("list_comments", "List comments on a ticket", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' (legacy) or 'TKR-BUG-0042' (typed)"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const comments = await api.get(`/api/tickets/${params.number}/comments`);
|
|
8
|
+
if (comments.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: "No comments on this ticket." }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const lines = [];
|
|
14
|
+
for (const c of comments) {
|
|
15
|
+
lines.push(`**${c.authorName}** (${c.createdAt}):`);
|
|
16
|
+
lines.push(c.text);
|
|
17
|
+
lines.push("");
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
26
|
+
isError: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=list-comments.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 registerListDevAssignments(server: McpServer, api: ApiClient): void;
|
|
4
|
+
//# sourceMappingURL=list-dev-assignments.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function registerListDevAssignments(server, api) {
|
|
2
|
+
server.tool("list_dev_assignments", "List all dev queue assignments (pending, in-progress, completed, failed)", {}, async () => {
|
|
3
|
+
try {
|
|
4
|
+
const assignments = await api.get("/api/dev-queue/assignments");
|
|
5
|
+
if (assignments.length === 0) {
|
|
6
|
+
return {
|
|
7
|
+
content: [{ type: "text", text: "No dev assignments found." }],
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const lines = [
|
|
11
|
+
"| # | Ticket | Title | Status | Agent | Assigned | Completed |",
|
|
12
|
+
"|---|--------|-------|--------|-------|----------|-----------|",
|
|
13
|
+
...assignments.map((a, i) => `| ${i + 1} | ${a.ticketDisplayNumber} | ${a.ticketTitle} | ${a.status} | ${a.agentName || "-"} | ${a.assignedAt} | ${a.completedAt || "-"} |`),
|
|
14
|
+
];
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
return {
|
|
21
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
22
|
+
isError: true,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=list-dev-assignments.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 registerListProjectMembers(server: McpServer, api: ApiClient): void;
|
|
4
|
+
//# sourceMappingURL=list-project-members.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListProjectMembers(server, api) {
|
|
3
|
+
server.tool("list_project_members", "List members of a project with their roles", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const members = await api.get(`/api/projects/${params.project}/members`);
|
|
8
|
+
if (!members || members.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: "No members found." }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const header = "| User | Email | Role | Added |";
|
|
14
|
+
const separator = "|------|-------|------|-------|";
|
|
15
|
+
const rows = members.map((m) => `| ${m.userName} | ${m.email} | ${m.role} | ${m.addedAt?.substring(0, 10) ?? "—"} |`);
|
|
16
|
+
const text = [header, separator, ...rows].join("\n");
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
24
|
+
isError: true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=list-project-members.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function registerListProjects(server, api) {
|
|
2
|
+
server.tool("list_projects", "List all projects accessible to the current user", {}, async () => {
|
|
3
|
+
try {
|
|
4
|
+
const projects = await api.get("/api/projects");
|
|
5
|
+
const lines = [
|
|
6
|
+
"| Name | Slug | Prefix | Scope Tags | Ticket Types |",
|
|
7
|
+
"|------|------|--------|------------|--------------|",
|
|
8
|
+
...projects.map((p) => `| ${p.name} | ${p.slug} | ${p.prefix} | ${p.scopeTags?.join(", ") || "-"} | ${p.ticketTypes?.join(", ") || "-"} |`),
|
|
9
|
+
];
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: lines.join("\n") || "No projects found." }],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
17
|
+
isError: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=list-projects.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListRelations(server, api) {
|
|
3
|
+
server.tool("list_relations", "List all relations for a ticket", {
|
|
4
|
+
number: z.string().describe("Ticket display number, e.g. 'TKR-42' or 'TKR-BUG-0042'"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const relations = await api.get(`/api/tickets/${params.number}/relations`);
|
|
8
|
+
if (relations.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: `No relations for ${params.number}` }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const lines = [
|
|
14
|
+
"| # | Direction | Type | Ticket | Title | Status |",
|
|
15
|
+
"|---|-----------|------|--------|-------|--------|",
|
|
16
|
+
...relations.map((r, i) => `| ${i + 1} | ${r.direction} | ${r.type} | ${r.displayNumber} | ${r.title} | ${r.status} |`),
|
|
17
|
+
];
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
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=list-relations.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListStatuses(server, api) {
|
|
3
|
+
server.tool("list_statuses", "List workflow statuses for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const statuses = await api.get(`/api/projects/${params.project}/statuses`);
|
|
8
|
+
const lines = [
|
|
9
|
+
"| # | Name | Slug | Emoji | Color | Category | Default | Terminal |",
|
|
10
|
+
"|---|------|------|-------|-------|----------|---------|----------|",
|
|
11
|
+
...statuses.map((s, i) => `| ${i + 1} | ${s.name} | ${s.slug} | ${s.emoji || "-"} | ${s.color} | ${s.category} | ${s.isDefault ? "Yes" : "No"} | ${s.isTerminal ? "Yes" : "No"} |`),
|
|
12
|
+
];
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: lines.join("\n") || "No statuses found." }],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
20
|
+
isError: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=list-statuses.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListTransitions(server, api) {
|
|
3
|
+
server.tool("list_transitions", "List workflow transitions for a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
}, async (params) => {
|
|
6
|
+
try {
|
|
7
|
+
const transitions = await api.get(`/api/projects/${params.project}/transitions`);
|
|
8
|
+
const lines = [
|
|
9
|
+
"| # | From | To | Allowed Roles |",
|
|
10
|
+
"|---|------|----|---------------|",
|
|
11
|
+
...transitions.map((t, i) => `| ${i + 1} | ${t.fromStatusName} | ${t.toStatusName} | ${t.allowedRoles?.join(", ") || "-"} |`),
|
|
12
|
+
];
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: lines.join("\n") || "No transitions found." }],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
20
|
+
isError: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=list-transitions.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 registerListWorkflowPresets(server: McpServer, api: ApiClient): void;
|
|
4
|
+
//# sourceMappingURL=list-workflow-presets.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function registerListWorkflowPresets(server, api) {
|
|
2
|
+
server.tool("list_workflow_presets", "List all available workflow presets", {}, async () => {
|
|
3
|
+
try {
|
|
4
|
+
const presets = await api.get("/api/workflow-presets");
|
|
5
|
+
const lines = [
|
|
6
|
+
"| # | Name | Description | Statuses | Transitions |",
|
|
7
|
+
"|---|------|-------------|----------|-------------|",
|
|
8
|
+
...presets.map((p, i) => `| ${i + 1} | ${p.name} | ${p.description || "-"} | ${p.statusCount} | ${p.transitionCount} |`),
|
|
9
|
+
];
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: lines.join("\n") || "No presets found." }],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
17
|
+
isError: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=list-workflow-presets.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 registerRemoveProjectMember(server: McpServer, api: ApiClient): void;
|
|
4
|
+
//# sourceMappingURL=remove-project-member.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerRemoveProjectMember(server, api) {
|
|
3
|
+
server.tool("remove_project_member", "Remove a member from a project", {
|
|
4
|
+
project: z.string().describe("Project slug"),
|
|
5
|
+
user_id: z.string().describe("UUID of the user to remove"),
|
|
6
|
+
}, async (params) => {
|
|
7
|
+
try {
|
|
8
|
+
await api.delete(`/api/projects/${params.project}/members/${params.user_id}`);
|
|
9
|
+
return {
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: "text",
|
|
13
|
+
text: `Member ${params.user_id} removed from project "${params.project}"`,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
21
|
+
isError: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=remove-project-member.js.map
|