issue-scribe-mcp 1.2.0 → 1.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.
@@ -0,0 +1,204 @@
1
+ import { z } from "zod";
2
+ import { getOctokit } from "../lib/octokit.js";
3
+ import { collectPaginated, PaginationSchema, resolvePagination } from "../lib/pagination.js";
4
+ import { executeTool } from "../lib/response.js";
5
+ import { assertConfirmation } from "../lib/safety.js";
6
+ const CreateLabelSchema = z.object({
7
+ owner: z.string(),
8
+ repo: z.string(),
9
+ name: z.string(),
10
+ color: z.string(),
11
+ description: z.string().optional(),
12
+ });
13
+ const UpdateLabelSchema = z.object({
14
+ owner: z.string(),
15
+ repo: z.string(),
16
+ name: z.string(),
17
+ new_name: z.string().optional(),
18
+ color: z.string().optional(),
19
+ description: z.string().optional(),
20
+ });
21
+ const DeleteLabelSchema = z.object({
22
+ owner: z.string(),
23
+ repo: z.string(),
24
+ name: z.string(),
25
+ dry_run: z.boolean().optional(),
26
+ confirm_token: z.string().optional(),
27
+ });
28
+ const ListLabelsSchema = z.object({
29
+ owner: z.string(),
30
+ repo: z.string(),
31
+ }).merge(PaginationSchema);
32
+ export const labelTools = [
33
+ {
34
+ definition: {
35
+ name: "github_create_label",
36
+ description: "Create a new repository label",
37
+ inputSchema: {
38
+ type: "object",
39
+ properties: {
40
+ owner: { type: "string", description: "Repository owner" },
41
+ repo: { type: "string", description: "Repository name" },
42
+ name: { type: "string", description: "Label name" },
43
+ color: { type: "string", description: "Hex color without #" },
44
+ description: { type: "string", description: "Label description (optional)" },
45
+ },
46
+ required: ["owner", "repo", "name", "color"],
47
+ },
48
+ },
49
+ handler: async (rawArgs) => executeTool(rawArgs, CreateLabelSchema, "Failed to create label", async (args) => {
50
+ const label = await getOctokit().rest.issues.createLabel({
51
+ owner: args.owner,
52
+ repo: args.repo,
53
+ name: args.name,
54
+ color: args.color,
55
+ description: args.description,
56
+ });
57
+ return {
58
+ success: true,
59
+ label: {
60
+ name: label.data.name,
61
+ color: label.data.color,
62
+ description: label.data.description,
63
+ url: label.data.url,
64
+ },
65
+ message: `Label \"${args.name}\" created successfully`,
66
+ };
67
+ }),
68
+ },
69
+ {
70
+ definition: {
71
+ name: "github_update_label",
72
+ description: "Update an existing repository label",
73
+ inputSchema: {
74
+ type: "object",
75
+ properties: {
76
+ owner: { type: "string", description: "Repository owner" },
77
+ repo: { type: "string", description: "Repository name" },
78
+ name: { type: "string", description: "Current label name" },
79
+ new_name: { type: "string", description: "New name (optional)" },
80
+ color: { type: "string", description: "New hex color without # (optional)" },
81
+ description: { type: "string", description: "New description (optional)" },
82
+ },
83
+ required: ["owner", "repo", "name"],
84
+ },
85
+ },
86
+ handler: async (rawArgs) => executeTool(rawArgs, UpdateLabelSchema, "Failed to update label", async (args) => {
87
+ const label = await getOctokit().rest.issues.updateLabel({
88
+ owner: args.owner,
89
+ repo: args.repo,
90
+ name: args.name,
91
+ new_name: args.new_name,
92
+ color: args.color,
93
+ description: args.description,
94
+ });
95
+ return {
96
+ success: true,
97
+ label: {
98
+ name: label.data.name,
99
+ color: label.data.color,
100
+ description: label.data.description,
101
+ url: label.data.url,
102
+ },
103
+ message: `Label \"${args.name}\" updated successfully`,
104
+ };
105
+ }),
106
+ },
107
+ {
108
+ definition: {
109
+ name: "github_delete_label",
110
+ description: "Delete a repository label with dry-run and confirmation safeguards",
111
+ inputSchema: {
112
+ type: "object",
113
+ properties: {
114
+ owner: { type: "string", description: "Repository owner" },
115
+ repo: { type: "string", description: "Repository name" },
116
+ name: { type: "string", description: "Label name to delete" },
117
+ dry_run: { type: "boolean", description: "Preview deletion without executing (optional, default: false)" },
118
+ confirm_token: { type: "string", description: "Must be \"CONFIRM\" to execute delete when dry_run=false" },
119
+ },
120
+ required: ["owner", "repo", "name"],
121
+ },
122
+ },
123
+ handler: async (rawArgs) => executeTool(rawArgs, DeleteLabelSchema, "Failed to delete label", async (args) => {
124
+ const label = await getOctokit().rest.issues.getLabel({
125
+ owner: args.owner,
126
+ repo: args.repo,
127
+ name: args.name,
128
+ });
129
+ if (args.dry_run ?? false) {
130
+ return {
131
+ success: true,
132
+ dry_run: true,
133
+ action: "delete_label",
134
+ target: {
135
+ name: label.data.name,
136
+ color: label.data.color,
137
+ description: label.data.description,
138
+ },
139
+ message: "Dry run only. No deletion executed.",
140
+ };
141
+ }
142
+ assertConfirmation(args.confirm_token, "Label deletion");
143
+ await getOctokit().rest.issues.deleteLabel({
144
+ owner: args.owner,
145
+ repo: args.repo,
146
+ name: args.name,
147
+ });
148
+ return {
149
+ success: true,
150
+ dry_run: false,
151
+ message: `Label \"${args.name}\" deleted successfully from ${args.owner}/${args.repo}`,
152
+ };
153
+ }),
154
+ },
155
+ {
156
+ definition: {
157
+ name: "github_list_labels",
158
+ description: "List repository labels with pagination",
159
+ inputSchema: {
160
+ type: "object",
161
+ properties: {
162
+ owner: { type: "string", description: "Repository owner" },
163
+ repo: { type: "string", description: "Repository name" },
164
+ page: { type: "number", description: "Page number (optional, default: 1)" },
165
+ per_page: { type: "number", description: "Results per page, max 100 (optional, default: 30)" },
166
+ fetch_all: { type: "boolean", description: "Fetch all pages (optional, default: false)" },
167
+ },
168
+ required: ["owner", "repo"],
169
+ },
170
+ },
171
+ handler: async (rawArgs) => executeTool(rawArgs, ListLabelsSchema, "Failed to list labels", async (args) => {
172
+ const pagination = resolvePagination(args, {
173
+ page: 1,
174
+ perPage: 30,
175
+ fetchAll: false,
176
+ });
177
+ const labels = await collectPaginated(pagination, async (page, perPage) => {
178
+ const response = await getOctokit().rest.issues.listLabelsForRepo({
179
+ owner: args.owner,
180
+ repo: args.repo,
181
+ page,
182
+ per_page: perPage,
183
+ });
184
+ return response.data;
185
+ });
186
+ return {
187
+ success: true,
188
+ count: labels.items.length,
189
+ labels: labels.items.map((label) => ({
190
+ name: label.name,
191
+ color: label.color,
192
+ description: label.description,
193
+ url: label.url,
194
+ })),
195
+ pagination: {
196
+ page: labels.page,
197
+ per_page: labels.per_page,
198
+ fetch_all: labels.fetch_all,
199
+ pages_fetched: labels.pages_fetched,
200
+ },
201
+ };
202
+ }),
203
+ },
204
+ ];