@vitalyostanin/youtrack-mcp 0.2.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.
Files changed (39) hide show
  1. package/README-ru.md +283 -0
  2. package/README.md +290 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.js +13 -0
  5. package/dist/src/config.d.ts +10 -0
  6. package/dist/src/config.js +68 -0
  7. package/dist/src/server.d.ts +8 -0
  8. package/dist/src/server.js +48 -0
  9. package/dist/src/tools/article-search-tools.d.ts +4 -0
  10. package/dist/src/tools/article-search-tools.js +31 -0
  11. package/dist/src/tools/article-tools.d.ts +4 -0
  12. package/dist/src/tools/article-tools.js +98 -0
  13. package/dist/src/tools/attachment-tools.d.ts +4 -0
  14. package/dist/src/tools/attachment-tools.js +100 -0
  15. package/dist/src/tools/issue-search-tools.d.ts +4 -0
  16. package/dist/src/tools/issue-search-tools.js +56 -0
  17. package/dist/src/tools/issue-tools.d.ts +4 -0
  18. package/dist/src/tools/issue-tools.js +190 -0
  19. package/dist/src/tools/project-tools.d.ts +4 -0
  20. package/dist/src/tools/project-tools.js +35 -0
  21. package/dist/src/tools/service-info.d.ts +4 -0
  22. package/dist/src/tools/service-info.js +61 -0
  23. package/dist/src/tools/user-tools.d.ts +4 -0
  24. package/dist/src/tools/user-tools.js +46 -0
  25. package/dist/src/tools/workitem-report-tools.d.ts +4 -0
  26. package/dist/src/tools/workitem-report-tools.js +62 -0
  27. package/dist/src/tools/workitem-tools.d.ts +4 -0
  28. package/dist/src/tools/workitem-tools.js +247 -0
  29. package/dist/src/types.d.ts +433 -0
  30. package/dist/src/types.js +2 -0
  31. package/dist/src/utils/date.d.ts +34 -0
  32. package/dist/src/utils/date.js +147 -0
  33. package/dist/src/utils/mappers.d.ts +76 -0
  34. package/dist/src/utils/mappers.js +126 -0
  35. package/dist/src/utils/tool-response.d.ts +4 -0
  36. package/dist/src/utils/tool-response.js +61 -0
  37. package/dist/src/youtrack-client.d.ts +86 -0
  38. package/dist/src/youtrack-client.js +1220 -0
  39. package/package.json +65 -0
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { toolError, toolSuccess } from "../utils/tool-response.js";
3
+ const projectLookupArgs = {
4
+ shortName: z.string().min(1).describe("Project short name"),
5
+ };
6
+ const projectLookupSchema = z.object(projectLookupArgs);
7
+ export function registerProjectTools(server, client) {
8
+ server.tool("projects_list", "List all YouTrack projects. Note: Returns predefined fields only - id, shortName, name.", {}, async () => {
9
+ try {
10
+ const projects = await client.listProjects();
11
+ const response = toolSuccess(projects);
12
+ return response;
13
+ }
14
+ catch (error) {
15
+ const errorResponse = toolError(error);
16
+ return errorResponse;
17
+ }
18
+ });
19
+ server.tool("project_get", "Get YouTrack project by short name. Note: Returns predefined fields only - id, shortName, name.", projectLookupArgs, async (rawInput) => {
20
+ try {
21
+ const payload = projectLookupSchema.parse(rawInput);
22
+ const project = await client.getProjectByShortName(payload.shortName);
23
+ if (!project) {
24
+ throw new Error(`Project with short name '${payload.shortName}' not found`);
25
+ }
26
+ const response = toolSuccess({ project });
27
+ return response;
28
+ }
29
+ catch (error) {
30
+ const errorResponse = toolError(error);
31
+ return errorResponse;
32
+ }
33
+ });
34
+ }
35
+ //# sourceMappingURL=project-tools.js.map
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { YoutrackClient } from "../youtrack-client.js";
3
+ export declare function registerServiceInfoTool(server: McpServer, client: YoutrackClient): void;
4
+ //# sourceMappingURL=service-info.d.ts.map
@@ -0,0 +1,61 @@
1
+ import { ZodError } from "zod";
2
+ import { loadConfig, enrichConfigWithRedaction } from "../config.js";
3
+ export function registerServiceInfoTool(server, client) {
4
+ server.tool("service_info", "Get YouTrack integration status and environment configuration", async () => {
5
+ try {
6
+ const config = loadConfig();
7
+ const currentUser = await client.getCurrentUser();
8
+ const payload = {
9
+ service: {
10
+ name: "youtrack-mcp",
11
+ version: "0.1.0",
12
+ },
13
+ configuration: enrichConfigWithRedaction(config),
14
+ };
15
+ const result = {
16
+ content: [],
17
+ structuredContent: {
18
+ ...payload,
19
+ currentUser,
20
+ },
21
+ };
22
+ return result;
23
+ }
24
+ catch (error) {
25
+ if (error instanceof ZodError) {
26
+ const result = {
27
+ content: [],
28
+ isError: true,
29
+ structuredContent: {
30
+ name: "ValidationError",
31
+ message: "Invalid configuration",
32
+ details: error.flatten(),
33
+ },
34
+ };
35
+ return result;
36
+ }
37
+ if (error instanceof Error) {
38
+ const result = {
39
+ content: [],
40
+ isError: true,
41
+ structuredContent: {
42
+ name: error.name,
43
+ message: error.message,
44
+ },
45
+ };
46
+ return result;
47
+ }
48
+ const result = {
49
+ content: [],
50
+ isError: true,
51
+ structuredContent: {
52
+ name: "UnknownError",
53
+ message: "An unknown error occurred",
54
+ details: error,
55
+ },
56
+ };
57
+ return result;
58
+ }
59
+ });
60
+ }
61
+ //# sourceMappingURL=service-info.js.map
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { YoutrackClient } from "../youtrack-client.js";
3
+ export declare function registerUserTools(server: McpServer, client: YoutrackClient): void;
4
+ //# sourceMappingURL=user-tools.d.ts.map
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ import { toolError, toolSuccess } from "../utils/tool-response.js";
3
+ const userLookupArgs = {
4
+ login: z.string().min(1).describe("User login"),
5
+ };
6
+ const userLookupSchema = z.object(userLookupArgs);
7
+ export function registerUserTools(server, client) {
8
+ server.tool("users_list", "List all YouTrack users. Note: Returns predefined fields only - id, login, name, fullName, email.", {}, async () => {
9
+ try {
10
+ const users = await client.listUsers();
11
+ const response = toolSuccess(users);
12
+ return response;
13
+ }
14
+ catch (error) {
15
+ const errorResponse = toolError(error);
16
+ return errorResponse;
17
+ }
18
+ });
19
+ server.tool("user_get", "Get YouTrack user by login. Note: Returns predefined fields only - id, login, name, fullName, email.", userLookupArgs, async (rawInput) => {
20
+ try {
21
+ const payload = userLookupSchema.parse(rawInput);
22
+ const user = await client.getUserByLogin(payload.login);
23
+ if (!user) {
24
+ throw new Error(`User with login '${payload.login}' not found`);
25
+ }
26
+ const response = toolSuccess({ user });
27
+ return response;
28
+ }
29
+ catch (error) {
30
+ const errorResponse = toolError(error);
31
+ return errorResponse;
32
+ }
33
+ });
34
+ server.tool("user_current", "Get current authenticated user. Note: Returns predefined fields only - id, login, name, fullName, email.", {}, async () => {
35
+ try {
36
+ const user = await client.getCurrentUser();
37
+ const response = toolSuccess({ user });
38
+ return response;
39
+ }
40
+ catch (error) {
41
+ const errorResponse = toolError(error);
42
+ return errorResponse;
43
+ }
44
+ });
45
+ }
46
+ //# sourceMappingURL=user-tools.js.map
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { YoutrackClient } from "../youtrack-client.js";
3
+ export declare function registerWorkitemReportTools(server: McpServer, client: YoutrackClient): void;
4
+ //# sourceMappingURL=workitem-report-tools.d.ts.map
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+ import { toolError, toolSuccess } from "../utils/tool-response.js";
3
+ const sharedDate = z.union([z.string().regex(/\d{4}-\d{2}-\d{2}/), z.number(), z.date()]);
4
+ const reportBaseArgs = {
5
+ author: z.string().optional().describe("Work item author login"),
6
+ issueId: z.string().optional().describe("Issue code"),
7
+ startDate: sharedDate.optional().describe("Period start date"),
8
+ endDate: sharedDate.optional().describe("Period end date"),
9
+ expectedDailyMinutes: z.number().int().positive().optional().describe("Daily expected minutes"),
10
+ excludeWeekends: z.boolean().optional().describe("Exclude weekends"),
11
+ excludeHolidays: z.boolean().optional().describe("Exclude holidays"),
12
+ holidays: z.array(sharedDate).optional().describe("List of holiday dates"),
13
+ preHolidays: z.array(sharedDate).optional().describe("List of pre-holiday dates"),
14
+ allUsers: z.boolean().optional().describe("Include work items for all users"),
15
+ };
16
+ const reportArgsSchema = z.object(reportBaseArgs);
17
+ const reportUsersArgsSchema = z.object({
18
+ users: z.array(z.string().min(1)).min(1).describe("User logins"),
19
+ ...reportBaseArgs,
20
+ });
21
+ export function registerWorkitemReportTools(server, client) {
22
+ server.tool("workitems_report_summary", "Summary report for work items in period. Note: Work items in report include predefined fields only - id, date, duration (minutes, presentation), text, description, issue (id, idReadable), author (id, login, name, email).", reportBaseArgs, async (rawInput) => {
23
+ try {
24
+ const payload = reportArgsSchema.parse(rawInput);
25
+ const report = await client.generateWorkItemReport(payload);
26
+ const response = toolSuccess({ report });
27
+ return response;
28
+ }
29
+ catch (error) {
30
+ const errorResponse = toolError(error);
31
+ return errorResponse;
32
+ }
33
+ });
34
+ server.tool("workitems_report_invalid", "List of days with deviation from expected. Note: Work items in report include predefined fields only - id, date, duration (minutes, presentation), text, description, issue (id, idReadable), author (id, login, name, email).", reportBaseArgs, async (rawInput) => {
35
+ try {
36
+ const payload = reportArgsSchema.parse(rawInput);
37
+ const invalidDays = await client.generateInvalidWorkItemReport(payload);
38
+ const response = toolSuccess({ invalidDays });
39
+ return response;
40
+ }
41
+ catch (error) {
42
+ const errorResponse = toolError(error);
43
+ return errorResponse;
44
+ }
45
+ });
46
+ server.tool("workitems_report_users", "Work items report for list of users. Note: Work items in report include predefined fields only - id, date, duration (minutes, presentation), text, description, issue (id, idReadable), author (id, login, name, email).", {
47
+ users: z.array(z.string().min(1)).min(1).describe("User logins"),
48
+ ...reportBaseArgs,
49
+ }, async (rawInput) => {
50
+ try {
51
+ const payload = reportUsersArgsSchema.parse(rawInput);
52
+ const report = await client.generateUsersWorkItemReports(payload.users, payload);
53
+ const response = toolSuccess(report);
54
+ return response;
55
+ }
56
+ catch (error) {
57
+ const errorResponse = toolError(error);
58
+ return errorResponse;
59
+ }
60
+ });
61
+ }
62
+ //# sourceMappingURL=workitem-report-tools.js.map
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { YoutrackClient } from "../youtrack-client.js";
3
+ export declare function registerWorkitemTools(server: McpServer, client: YoutrackClient): void;
4
+ //# sourceMappingURL=workitem-tools.d.ts.map
@@ -0,0 +1,247 @@
1
+ import { z } from "zod";
2
+ import { mapWorkItem, mapWorkItems } from "../utils/mappers.js";
3
+ import { toolError, toolSuccess } from "../utils/tool-response.js";
4
+ const isoDate = z
5
+ .string()
6
+ .regex(/\d{4}-\d{2}-\d{2}/)
7
+ .describe("Date in YYYY-MM-DD format");
8
+ const dateInput = z.union([isoDate, z.number(), z.date()]);
9
+ const baseFilterArgs = {
10
+ issueId: z.string().optional().describe("Issue code (e.g., PROJ-123)"),
11
+ author: z.string().optional().describe("Work item author login"),
12
+ startDate: dateInput.optional().describe("Period start date"),
13
+ endDate: dateInput.optional().describe("Period end date"),
14
+ allUsers: z.boolean().optional().describe("Get work items for all users"),
15
+ };
16
+ const workItemsListSchema = z.object(baseFilterArgs);
17
+ const workItemsForUsersArgs = {
18
+ ...baseFilterArgs,
19
+ users: z.array(z.string().min(1)).min(1).describe("User logins"),
20
+ };
21
+ const workItemsUsersSchema = z.object(workItemsForUsersArgs);
22
+ const workItemCreateArgs = {
23
+ issueId: z.string().min(1).describe("Issue ID"),
24
+ date: dateInput.describe("Date"),
25
+ minutes: z.number().int().positive().describe("Minutes"),
26
+ summary: z.string().optional().describe("Brief text"),
27
+ description: z.string().optional().describe("Description"),
28
+ usesMarkdown: z.boolean().optional().describe("Use Markdown formatting"),
29
+ };
30
+ const workItemCreateSchema = z.object(workItemCreateArgs);
31
+ const workItemIdempotentArgs = {
32
+ issueId: z.string().min(1).describe("Issue ID"),
33
+ date: dateInput.describe("Date"),
34
+ minutes: z.number().int().positive().describe("Minutes"),
35
+ description: z.string().min(1).describe("Text to search for existing work item"),
36
+ usesMarkdown: z.boolean().optional().describe("Use Markdown formatting"),
37
+ };
38
+ const workItemIdempotentSchema = z.object(workItemIdempotentArgs);
39
+ const workItemUpdateArgs = {
40
+ issueId: z.string().min(1).describe("Issue ID"),
41
+ workItemId: z.string().min(1).describe("Work item ID"),
42
+ date: dateInput.optional().describe("New date"),
43
+ minutes: z.number().int().positive().optional().describe("New minutes"),
44
+ summary: z.string().optional().describe("New text"),
45
+ description: z.string().optional().describe("New description"),
46
+ usesMarkdown: z.boolean().optional().describe("Use Markdown formatting"),
47
+ };
48
+ const workItemUpdateSchema = z.object(workItemUpdateArgs);
49
+ const workItemDeleteArgs = {
50
+ issueId: z.string().min(1).describe("Issue ID"),
51
+ workItemId: z.string().min(1).describe("Work item ID"),
52
+ };
53
+ const workItemDeleteSchema = z.object(workItemDeleteArgs);
54
+ const workItemsPeriodArgs = {
55
+ issueId: z.string().min(1).describe("Issue ID"),
56
+ startDate: dateInput.describe("Period start date"),
57
+ endDate: dateInput.describe("Period end date"),
58
+ minutes: z.number().int().positive().describe("Minutes per day"),
59
+ summary: z.string().optional().describe("Brief text"),
60
+ description: z.string().optional().describe("Description"),
61
+ usesMarkdown: z.boolean().optional().describe("Use Markdown formatting"),
62
+ excludeWeekends: z.boolean().optional().describe("Exclude weekends"),
63
+ excludeHolidays: z.boolean().optional().describe("Exclude holidays"),
64
+ holidays: z.array(dateInput).optional().describe("Holidays"),
65
+ preHolidays: z.array(dateInput).optional().describe("Pre-holiday days"),
66
+ };
67
+ const workItemsPeriodSchema = z.object(workItemsPeriodArgs);
68
+ const workItemsReportArgs = {
69
+ author: z.string().optional().describe("Author login"),
70
+ issueId: z.string().optional().describe("Issue code"),
71
+ startDate: dateInput.optional().describe("Period start date"),
72
+ endDate: dateInput.optional().describe("Period end date"),
73
+ expectedDailyMinutes: z.number().int().positive().optional().describe("Expected minutes"),
74
+ excludeWeekends: z.boolean().optional().describe("Exclude weekends"),
75
+ excludeHolidays: z.boolean().optional().describe("Exclude holidays"),
76
+ holidays: z.array(dateInput).optional().describe("Holidays"),
77
+ preHolidays: z.array(dateInput).optional().describe("Pre-holiday days"),
78
+ allUsers: z.boolean().optional().describe("Get report for all users"),
79
+ };
80
+ const workItemsReportSchema = z.object(workItemsReportArgs);
81
+ const workItemsRecentArgs = {
82
+ users: z.array(z.string().min(1)).optional().describe("User logins (defaults to current user)"),
83
+ limit: z.number().int().positive().max(200).optional().describe("Maximum number of items (default 50)"),
84
+ };
85
+ const workItemsRecentSchema = z.object(workItemsRecentArgs);
86
+ export function registerWorkitemTools(server, client) {
87
+ server.tool("workitems_list", "Get list of work items. Note: Returns predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", baseFilterArgs, async (rawInput) => {
88
+ try {
89
+ const payload = workItemsListSchema.parse(rawInput);
90
+ const items = await client.listWorkItems(payload);
91
+ const response = toolSuccess({ items: mapWorkItems(items) });
92
+ return response;
93
+ }
94
+ catch (error) {
95
+ const errorResponse = toolError(error);
96
+ return errorResponse;
97
+ }
98
+ });
99
+ server.tool("workitems_all_users", "Get work items for all users. Note: Returns predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", baseFilterArgs, async (rawInput) => {
100
+ try {
101
+ const payload = workItemsListSchema.parse(rawInput);
102
+ const items = await client.listAllUsersWorkItems(payload);
103
+ const response = toolSuccess({ items: mapWorkItems(items) });
104
+ return response;
105
+ }
106
+ catch (error) {
107
+ const errorResponse = toolError(error);
108
+ return errorResponse;
109
+ }
110
+ });
111
+ server.tool("workitems_for_users", "Get work items for selected users. Note: Returns predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemsForUsersArgs, async (rawInput) => {
112
+ try {
113
+ const payload = workItemsUsersSchema.parse(rawInput);
114
+ const items = await client.getWorkItemsForUsers(payload.users, payload);
115
+ const response = toolSuccess({ items: mapWorkItems(items), users: payload.users });
116
+ return response;
117
+ }
118
+ catch (error) {
119
+ const errorResponse = toolError(error);
120
+ return errorResponse;
121
+ }
122
+ });
123
+ server.tool("workitem_create", "Create work item record. Note: Response includes predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemCreateArgs, async (rawInput) => {
124
+ try {
125
+ const payload = workItemCreateSchema.parse(rawInput);
126
+ const item = await client.createWorkItemMapped({
127
+ issueId: payload.issueId,
128
+ date: payload.date,
129
+ minutes: payload.minutes,
130
+ summary: payload.summary,
131
+ description: payload.description,
132
+ usesMarkdown: payload.usesMarkdown,
133
+ });
134
+ const response = toolSuccess({ item });
135
+ return response;
136
+ }
137
+ catch (error) {
138
+ const errorResponse = toolError(error);
139
+ return errorResponse;
140
+ }
141
+ });
142
+ server.tool("workitem_create_idempotent", "Create work item record if similar one does not exist. Note: Response includes predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemIdempotentArgs, async (rawInput) => {
143
+ try {
144
+ const payload = workItemIdempotentSchema.parse(rawInput);
145
+ const item = await client.createWorkItemIdempotent({
146
+ issueId: payload.issueId,
147
+ date: payload.date,
148
+ minutes: payload.minutes,
149
+ description: payload.description,
150
+ usesMarkdown: payload.usesMarkdown,
151
+ });
152
+ const response = toolSuccess({ created: item !== null, item });
153
+ return response;
154
+ }
155
+ catch (error) {
156
+ const errorResponse = toolError(error);
157
+ return errorResponse;
158
+ }
159
+ });
160
+ server.tool("workitem_update", "Update work item record. Note: Response includes predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemUpdateArgs, async (rawInput) => {
161
+ try {
162
+ const payload = workItemUpdateSchema.parse(rawInput);
163
+ if (payload.date === undefined &&
164
+ payload.minutes === undefined &&
165
+ payload.summary === undefined &&
166
+ payload.description === undefined) {
167
+ throw new Error("At least one field must be provided for update");
168
+ }
169
+ const item = await client.updateWorkItem({
170
+ issueId: payload.issueId,
171
+ workItemId: payload.workItemId,
172
+ date: payload.date,
173
+ minutes: payload.minutes,
174
+ summary: payload.summary,
175
+ description: payload.description,
176
+ usesMarkdown: payload.usesMarkdown,
177
+ });
178
+ const response = toolSuccess({ item: mapWorkItem(item) });
179
+ return response;
180
+ }
181
+ catch (error) {
182
+ const errorResponse = toolError(error);
183
+ return errorResponse;
184
+ }
185
+ });
186
+ server.tool("workitem_delete", "Delete work item record", workItemDeleteArgs, async (rawInput) => {
187
+ try {
188
+ const payload = workItemDeleteSchema.parse(rawInput);
189
+ const result = await client.deleteWorkItem(payload.issueId, payload.workItemId);
190
+ const response = toolSuccess(result);
191
+ return response;
192
+ }
193
+ catch (error) {
194
+ const errorResponse = toolError(error);
195
+ return errorResponse;
196
+ }
197
+ });
198
+ server.tool("workitems_create_period", "Create work items for period. Note: Created work items include predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemsPeriodArgs, async (rawInput) => {
199
+ try {
200
+ const payload = workItemsPeriodSchema.parse(rawInput);
201
+ const result = await client.createWorkItemsForPeriod({
202
+ issueId: payload.issueId,
203
+ startDate: payload.startDate,
204
+ endDate: payload.endDate,
205
+ minutes: payload.minutes,
206
+ summary: payload.summary,
207
+ description: payload.description,
208
+ usesMarkdown: payload.usesMarkdown,
209
+ excludeWeekends: payload.excludeWeekends,
210
+ excludeHolidays: payload.excludeHolidays,
211
+ holidays: payload.holidays,
212
+ preHolidays: payload.preHolidays,
213
+ });
214
+ const response = toolSuccess(result);
215
+ return response;
216
+ }
217
+ catch (error) {
218
+ const errorResponse = toolError(error);
219
+ return errorResponse;
220
+ }
221
+ });
222
+ server.tool("workitems_report", "Generate work items report", workItemsReportArgs, async (rawInput) => {
223
+ try {
224
+ const payload = workItemsReportSchema.parse(rawInput);
225
+ const report = await client.generateWorkItemReport(payload);
226
+ const response = toolSuccess(report);
227
+ return response;
228
+ }
229
+ catch (error) {
230
+ const errorResponse = toolError(error);
231
+ return errorResponse;
232
+ }
233
+ });
234
+ server.tool("workitems_recent", "Get recent work items sorted by update time descending. Note: Returns predefined fields only - id, date, duration (minutes, presentation), text, textPreview, usesMarkdown, description, issue (id, idReadable), author (id, login, name, email).", workItemsRecentArgs, async (rawInput) => {
235
+ try {
236
+ const payload = workItemsRecentSchema.parse(rawInput);
237
+ const items = await client.listRecentWorkItems(payload);
238
+ const response = toolSuccess({ items: mapWorkItems(items), count: items.length });
239
+ return response;
240
+ }
241
+ catch (error) {
242
+ const errorResponse = toolError(error);
243
+ return errorResponse;
244
+ }
245
+ });
246
+ }
247
+ //# sourceMappingURL=workitem-tools.js.map