@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,126 @@
1
+ import { DateTime } from "luxon";
2
+ /**
3
+ * Convert timestamp in milliseconds to ISO date string (YYYY-MM-DD)
4
+ */
5
+ export function timestampToIsoDate(timestamp) {
6
+ if (timestamp === undefined || timestamp === null) {
7
+ return undefined;
8
+ }
9
+ if (!Number.isFinite(timestamp)) {
10
+ return undefined;
11
+ }
12
+ return DateTime.fromMillis(timestamp).toFormat("yyyy-MM-dd");
13
+ }
14
+ /**
15
+ * Convert timestamp in milliseconds to ISO datetime string (YYYY-MM-DDTHH:mm:ss.sssZ)
16
+ */
17
+ export function timestampToIsoDateTime(timestamp) {
18
+ if (timestamp === undefined || timestamp === null) {
19
+ return undefined;
20
+ }
21
+ if (!Number.isFinite(timestamp)) {
22
+ return undefined;
23
+ }
24
+ return DateTime.fromMillis(timestamp).toISO() ?? undefined;
25
+ }
26
+ /**
27
+ * Map YoutrackIssue to MappedYoutrackIssue
28
+ */
29
+ export function mapIssue(issue) {
30
+ return {
31
+ ...issue,
32
+ };
33
+ }
34
+ /**
35
+ * Map YoutrackIssueDetails to MappedYoutrackIssueDetails
36
+ */
37
+ export function mapIssueDetails(issue) {
38
+ return {
39
+ ...issue,
40
+ created: timestampToIsoDateTime(issue.created),
41
+ updated: timestampToIsoDateTime(issue.updated),
42
+ resolved: timestampToIsoDateTime(issue.resolved),
43
+ };
44
+ }
45
+ /**
46
+ * Map YoutrackWorkItem to MappedYoutrackWorkItem
47
+ */
48
+ export function mapWorkItem(item) {
49
+ const mapped = {
50
+ ...item,
51
+ date: timestampToIsoDate(item.date) ?? "",
52
+ };
53
+ return mapped;
54
+ }
55
+ /**
56
+ * Map YoutrackIssueComment to MappedYoutrackIssueComment
57
+ */
58
+ export function mapComment(comment) {
59
+ const mapped = {
60
+ ...comment,
61
+ created: timestampToIsoDateTime(comment.created) ?? "",
62
+ updated: timestampToIsoDateTime(comment.updated),
63
+ };
64
+ return mapped;
65
+ }
66
+ /**
67
+ * Map array of issues
68
+ */
69
+ export function mapIssues(issues) {
70
+ return issues.map(mapIssue);
71
+ }
72
+ /**
73
+ * Map array of work items
74
+ */
75
+ export function mapWorkItems(items) {
76
+ return items.map(mapWorkItem);
77
+ }
78
+ /**
79
+ * Map array of comments
80
+ */
81
+ export function mapComments(comments) {
82
+ return comments.map(mapComment);
83
+ }
84
+ /**
85
+ * Format file size in bytes to human-readable format
86
+ */
87
+ export function formatFileSize(bytes) {
88
+ if (bytes === 0) {
89
+ return "0 Bytes";
90
+ }
91
+ const k = 1024;
92
+ const sizes = ["Bytes", "KB", "MB", "GB"];
93
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
94
+ return `${Math.round((bytes / Math.pow(k, i)) * 100) / 100} ${sizes[i]}`;
95
+ }
96
+ /**
97
+ * Map YoutrackAttachment to MappedYoutrackAttachment
98
+ */
99
+ export function mapAttachment(attachment) {
100
+ return {
101
+ id: attachment.id,
102
+ name: attachment.name,
103
+ author: attachment.author
104
+ ? {
105
+ id: attachment.author.id,
106
+ login: attachment.author.login,
107
+ name: attachment.author.name,
108
+ }
109
+ : undefined,
110
+ created: timestampToIsoDateTime(attachment.created) ?? "",
111
+ updated: timestampToIsoDateTime(attachment.updated),
112
+ size: attachment.size,
113
+ sizeFormatted: formatFileSize(attachment.size),
114
+ mimeType: attachment.mimeType,
115
+ extension: attachment.extension,
116
+ url: attachment.url,
117
+ thumbnailURL: attachment.thumbnailURL,
118
+ };
119
+ }
120
+ /**
121
+ * Map array of attachments
122
+ */
123
+ export function mapAttachments(attachments) {
124
+ return attachments.map(mapAttachment);
125
+ }
126
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1,4 @@
1
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare function toolSuccess<T>(payload: T): CallToolResult;
3
+ export declare function toolError(error: unknown): CallToolResult;
4
+ //# sourceMappingURL=tool-response.d.ts.map
@@ -0,0 +1,61 @@
1
+ import { ZodError } from "zod";
2
+ export function toolSuccess(payload) {
3
+ const structuredContent = {
4
+ success: true,
5
+ payload,
6
+ };
7
+ return {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: JSON.stringify(structuredContent, null, 2),
12
+ },
13
+ ],
14
+ structuredContent,
15
+ };
16
+ }
17
+ export function toolError(error) {
18
+ if (error instanceof ZodError) {
19
+ const structuredContent = {
20
+ success: false,
21
+ error: {
22
+ name: "ValidationError",
23
+ message: "Invalid input",
24
+ details: error.flatten(),
25
+ },
26
+ };
27
+ return {
28
+ content: [],
29
+ isError: true,
30
+ structuredContent,
31
+ };
32
+ }
33
+ if (error instanceof Error) {
34
+ const structuredContent = {
35
+ success: false,
36
+ error: {
37
+ name: error.name,
38
+ message: error.message,
39
+ },
40
+ };
41
+ return {
42
+ content: [],
43
+ isError: true,
44
+ structuredContent,
45
+ };
46
+ }
47
+ const structuredContent = {
48
+ success: false,
49
+ error: {
50
+ name: "UnknownError",
51
+ message: "An unknown error occurred",
52
+ details: error,
53
+ },
54
+ };
55
+ return {
56
+ content: [],
57
+ isError: true,
58
+ structuredContent,
59
+ };
60
+ }
61
+ //# sourceMappingURL=tool-response.js.map
@@ -0,0 +1,86 @@
1
+ import { type MappedYoutrackIssueComment, type MappedYoutrackWorkItem } from "./utils/mappers.js";
2
+ import type { ArticleCreateInput, ArticleListPayload, ArticlePayload, ArticleSearchInput, ArticleSearchPayload, ArticleUpdateInput, AttachmentDeleteInput, AttachmentDeletePayload, AttachmentDownloadPayload, AttachmentPayload, AttachmentsListPayload, AttachmentUploadInput, AttachmentUploadPayload, IssueCommentsPayload, IssueCommentCreateInput, IssueDetailsPayload, IssueLookupPayload, IssueSearchInput, IssueSearchPayload, IssuesCommentsPayload, IssuesDetailsPayload, IssuesLookupPayload, WorkItemBulkResultPayload, WorkItemDeletePayload, WorkItemInvalidDay, WorkItemReportPayload, WorkItemUsersReportPayload, YoutrackActivityItem, YoutrackConfig, YoutrackIssueAssignInput, YoutrackIssueCreateInput, YoutrackIssueUpdateInput, YoutrackProject, YoutrackProjectListPayload, YoutrackUser, YoutrackUserListPayload, YoutrackWorkItem, YoutrackWorkItemCreateInput, YoutrackWorkItemIdempotentCreateInput, YoutrackWorkItemPeriodCreateInput, YoutrackWorkItemReportOptions, YoutrackWorkItemUpdateInput } from "./types.js";
3
+ export declare class YoutrackClient {
4
+ private readonly config;
5
+ private readonly http;
6
+ private cachedCurrentUser?;
7
+ private readonly usersByLogin;
8
+ private readonly projectsByShortName;
9
+ constructor(config: YoutrackConfig);
10
+ getCurrentUser(): Promise<YoutrackUser>;
11
+ getUserByLogin(login: string): Promise<YoutrackUser | null>;
12
+ listUsers(): Promise<YoutrackUserListPayload>;
13
+ listProjects(): Promise<YoutrackProjectListPayload>;
14
+ getProjectByShortName(shortName: string): Promise<YoutrackProject | null>;
15
+ private getProjectById;
16
+ getIssue(issueId: string): Promise<IssueLookupPayload>;
17
+ getIssueDetails(issueId: string): Promise<IssueDetailsPayload>;
18
+ getIssueComments(issueId: string): Promise<IssueCommentsPayload>;
19
+ createIssueComment(input: IssueCommentCreateInput): Promise<{
20
+ comment: MappedYoutrackIssueComment;
21
+ }>;
22
+ getIssueActivities(issueId: string, { author, startDate, endDate }?: {
23
+ author?: string;
24
+ startDate?: number;
25
+ endDate?: number;
26
+ }): Promise<YoutrackActivityItem[]>;
27
+ createIssue(input: YoutrackIssueCreateInput): Promise<IssueLookupPayload>;
28
+ updateIssue(input: YoutrackIssueUpdateInput): Promise<IssueLookupPayload>;
29
+ assignIssue(input: YoutrackIssueAssignInput): Promise<IssueLookupPayload>;
30
+ getIssues(issueIds: string[]): Promise<IssuesLookupPayload>;
31
+ getIssuesDetails(issueIds: string[]): Promise<IssuesDetailsPayload>;
32
+ getMultipleIssuesComments(issueIds: string[]): Promise<IssuesCommentsPayload>;
33
+ searchIssuesByUserActivity(input: IssueSearchInput): Promise<IssueSearchPayload>;
34
+ private searchIssuesByUserActivitySimple;
35
+ private searchIssuesByUserActivityStrict;
36
+ listWorkItems({ author, startDate, endDate, issueId, top: limit, allUsers, }?: {
37
+ author?: string;
38
+ startDate?: string | number | Date;
39
+ endDate?: string | number | Date;
40
+ issueId?: string;
41
+ top?: number;
42
+ allUsers?: boolean;
43
+ }): Promise<YoutrackWorkItem[]>;
44
+ getWorkItemsForUsers(logins: string[], params?: {
45
+ startDate?: string | number | Date;
46
+ endDate?: string | number | Date;
47
+ issueId?: string;
48
+ }): Promise<YoutrackWorkItem[]>;
49
+ listAllUsersWorkItems(params?: {
50
+ startDate?: string | number | Date;
51
+ endDate?: string | number | Date;
52
+ issueId?: string;
53
+ }): Promise<YoutrackWorkItem[]>;
54
+ listRecentWorkItems(params?: {
55
+ users?: string[];
56
+ limit?: number;
57
+ }): Promise<YoutrackWorkItem[]>;
58
+ createWorkItem(input: YoutrackWorkItemCreateInput): Promise<YoutrackWorkItem>;
59
+ createWorkItemMapped(input: YoutrackWorkItemCreateInput): Promise<MappedYoutrackWorkItem>;
60
+ deleteWorkItem(issueId: string, workItemId: string): Promise<WorkItemDeletePayload>;
61
+ updateWorkItem(input: YoutrackWorkItemUpdateInput): Promise<YoutrackWorkItem>;
62
+ createWorkItemsForPeriod(input: YoutrackWorkItemPeriodCreateInput): Promise<WorkItemBulkResultPayload>;
63
+ createWorkItemIdempotent(input: YoutrackWorkItemIdempotentCreateInput): Promise<MappedYoutrackWorkItem | null>;
64
+ generateWorkItemReport(options?: YoutrackWorkItemReportOptions): Promise<WorkItemReportPayload>;
65
+ generateInvalidWorkItemReport(options?: YoutrackWorkItemReportOptions): Promise<WorkItemInvalidDay[]>;
66
+ generateUsersWorkItemReports(logins: string[], options?: YoutrackWorkItemReportOptions): Promise<WorkItemUsersReportPayload>;
67
+ getArticle(articleId: string): Promise<ArticlePayload>;
68
+ listArticles(args?: {
69
+ parentArticleId?: string;
70
+ projectId?: string;
71
+ }): Promise<ArticleListPayload>;
72
+ createArticle(input: ArticleCreateInput): Promise<ArticlePayload>;
73
+ updateArticle(input: ArticleUpdateInput): Promise<ArticlePayload>;
74
+ searchArticles(input: ArticleSearchInput): Promise<ArticleSearchPayload>;
75
+ listAttachments(issueId: string): Promise<AttachmentsListPayload>;
76
+ getAttachment(issueId: string, attachmentId: string): Promise<AttachmentPayload>;
77
+ getAttachmentDownloadInfo(issueId: string, attachmentId: string): Promise<AttachmentDownloadPayload>;
78
+ uploadAttachments(input: AttachmentUploadInput): Promise<AttachmentUploadPayload>;
79
+ deleteAttachment(input: AttachmentDeleteInput): Promise<AttachmentDeletePayload>;
80
+ private normalizeError;
81
+ private resolveAssignee;
82
+ private getIssueRaw;
83
+ private getWorkItemById;
84
+ private resolveReportBoundary;
85
+ }
86
+ //# sourceMappingURL=youtrack-client.d.ts.map