@rokealvo/jira-mcp 1.2.1 → 1.2.3

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/build/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { Server as f } from "@modelcontextprotocol/sdk/server/index.js";
3
- import { StdioServerTransport as h } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import { ListPromptsRequestSchema as g, GetPromptRequestSchema as I, McpError as c, ErrorCode as p, ListToolsRequestSchema as w, CallToolRequestSchema as _ } from "@modelcontextprotocol/sdk/types.js";
2
+ import { Server as h } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport as f } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { ListPromptsRequestSchema as g, GetPromptRequestSchema as I, McpError as c, ErrorCode as u, ListToolsRequestSchema as w, CallToolRequestSchema as _ } from "@modelcontextprotocol/sdk/types.js";
5
5
  class y {
6
6
  baseUrl;
7
7
  headers;
@@ -154,7 +154,8 @@ class y {
154
154
  ...e,
155
155
  headers: this.headers
156
156
  });
157
- return s.ok || await this.handleFetchError(s, t), s.json();
157
+ if (s.ok || await this.handleFetchError(s, t), !(s.status === 204 || s.headers.get("content-length") === "0"))
158
+ return s.json();
158
159
  }
159
160
  async searchIssues(t) {
160
161
  const e = new URLSearchParams({
@@ -205,12 +206,12 @@ class y {
205
206
  `/rest/api/3/issue/${a.key}/comment`
206
207
  ), n = this.cleanIssue(a), o = r.comments.map(
207
208
  (d) => this.cleanComment(d)
208
- ), u = o.flatMap(
209
+ ), p = o.flatMap(
209
210
  (d) => d.mentions
210
211
  );
211
212
  return n.relatedIssues = [
212
213
  ...n.relatedIssues,
213
- ...u
214
+ ...p
214
215
  ], n.comments = o, n;
215
216
  })
216
217
  );
@@ -288,10 +289,10 @@ class y {
288
289
  issueTypes: await Promise.all(
289
290
  a.map(async (n) => {
290
291
  try {
291
- let u = (await this.fetchJson(
292
+ let p = (await this.fetchJson(
292
293
  `/rest/api/3/issue/createmeta/${t}/issuetypes/${n.id}`
293
294
  )).fields || [];
294
- return s && (u = u.map((d) => ({
295
+ return s && (p = p.map((d) => ({
295
296
  fieldId: d.fieldId,
296
297
  name: d.name,
297
298
  required: d.required,
@@ -303,7 +304,7 @@ class y {
303
304
  name: n.name,
304
305
  description: n.description,
305
306
  subtask: n.subtask,
306
- fields: u
307
+ fields: p
307
308
  };
308
309
  } catch (o) {
309
310
  return {
@@ -499,10 +500,10 @@ class b extends y {
499
500
  issueTypes: await Promise.all(
500
501
  a.map(async (n) => {
501
502
  try {
502
- let u = (await this.fetchJson(
503
+ let p = (await this.fetchJson(
503
504
  `/rest/api/3/issue/createmeta/${t}/issuetypes/${n.id}`
504
505
  )).values || [];
505
- return s && (u = u.map((d) => ({
506
+ return s && (p = p.map((d) => ({
506
507
  fieldId: d.fieldId,
507
508
  name: d.name,
508
509
  required: d.required,
@@ -514,7 +515,7 @@ class b extends y {
514
515
  name: n.name,
515
516
  description: n.description,
516
517
  subtask: n.subtask,
517
- fields: u
518
+ fields: p
518
519
  };
519
520
  } catch (o) {
520
521
  return {
@@ -863,7 +864,7 @@ class S {
863
864
  server;
864
865
  jiraApi;
865
866
  constructor() {
866
- this.server = new f(
867
+ this.server = new h(
867
868
  {
868
869
  name: "jira-mcp",
869
870
  version: "0.3.0"
@@ -900,7 +901,7 @@ class S {
900
901
  })), this.server.setRequestHandler(I, async (t) => {
901
902
  const { name: e } = t.params, s = m[e];
902
903
  if (!s)
903
- throw new c(p.InvalidParams, `Unknown prompt: ${e}`);
904
+ throw new c(u.InvalidParams, `Unknown prompt: ${e}`);
904
905
  return {
905
906
  messages: [
906
907
  {
@@ -1021,7 +1022,19 @@ See prompt "update_issue_workflow" for guidelines.`,
1021
1022
  },
1022
1023
  {
1023
1024
  name: "get_transitions",
1024
- description: "Get available status transitions for a JIRA issue",
1025
+ description: `Get available status transitions for a JIRA issue.
1026
+
1027
+ ⚠️ IMPORTANT: You MUST call this tool BEFORE attempting any transition!
1028
+ - Only transitions returned by this tool are valid
1029
+ - Transition availability depends on workflow rules (e.g., user can only have one task "В работе")
1030
+ - If desired transition is not in the list, inform the user — do NOT guess or invent transition names/IDs
1031
+ - Returns array with: id (use this for transition_issue), name, to.name (target status)
1032
+
1033
+ ⚠️ STATUS MISMATCH RULE: When user requests a specific status (e.g., "в работу", "на ревью"):
1034
+ 1. Compare available transitions with the requested status
1035
+ 2. If exact match NOT found — ALWAYS ASK the user which status to use
1036
+ 3. Present the list of available transitions to choose from
1037
+ 4. NEVER silently choose a "similar" status on your own`,
1025
1038
  inputSchema: {
1026
1039
  type: "object",
1027
1040
  properties: {
@@ -1038,6 +1051,20 @@ See prompt "update_issue_workflow" for guidelines.`,
1038
1051
  name: "transition_issue",
1039
1052
  description: `Change the status of a JIRA issue by performing a transition.
1040
1053
 
1054
+ ⚠️ CRITICAL: ALWAYS call get_transitions FIRST to get valid transition IDs!
1055
+ - NEVER guess or invent transition IDs — use ONLY IDs from get_transitions response
1056
+ - If the desired transition is not available, tell the user and explain possible reasons:
1057
+ - Workflow rules may restrict transitions (e.g., only one task "В работе" per user)
1058
+ - Current status may not allow direct transition to target status
1059
+ - User permissions may limit available transitions
1060
+
1061
+ ⚠️ STATUS MISMATCH RULE:
1062
+ - If user requested a specific status that is NOT in available transitions:
1063
+ - STOP and ASK user which available status to use
1064
+ - List all available transitions with their target statuses
1065
+ - Explain why requested status may be unavailable
1066
+ - NEVER silently substitute a different status — this confuses users!
1067
+
1041
1068
  ⚠️ CANCELLATION RULE: When transitioning to "Отмена" (Cancel), you MUST first:
1042
1069
  1. Ask user for cancellation reason
1043
1070
  2. Add comment with the reason using add_comment
@@ -1230,7 +1257,7 @@ Remember to add a comment with cancellation reason first.`,
1230
1257
  case "search_issues": {
1231
1258
  if (!e.searchString || typeof e.searchString != "string")
1232
1259
  throw new c(
1233
- p.InvalidParams,
1260
+ u.InvalidParams,
1234
1261
  "Search string is required"
1235
1262
  );
1236
1263
  const s = await this.jiraApi.searchIssues(e.searchString);
@@ -1243,7 +1270,7 @@ Remember to add a comment with cancellation reason first.`,
1243
1270
  case "get_epic_children": {
1244
1271
  if (!e.epicKey || typeof e.epicKey != "string")
1245
1272
  throw new c(
1246
- p.InvalidParams,
1273
+ u.InvalidParams,
1247
1274
  "Epic key is required"
1248
1275
  );
1249
1276
  const s = await this.jiraApi.getEpicChildren(e.epicKey);
@@ -1256,7 +1283,7 @@ Remember to add a comment with cancellation reason first.`,
1256
1283
  case "get_issue": {
1257
1284
  if (!e.issueId || typeof e.issueId != "string")
1258
1285
  throw new c(
1259
- p.InvalidParams,
1286
+ u.InvalidParams,
1260
1287
  "Issue ID is required"
1261
1288
  );
1262
1289
  const s = await this.jiraApi.getIssueWithComments(
@@ -1271,7 +1298,7 @@ Remember to add a comment with cancellation reason first.`,
1271
1298
  case "create_issue": {
1272
1299
  if (!e.projectKey || typeof e.projectKey != "string" || !e.issueType || typeof e.issueType != "string" || !e.summary || typeof e.summary != "string")
1273
1300
  throw new c(
1274
- p.InvalidParams,
1301
+ u.InvalidParams,
1275
1302
  "projectKey, issueType, and summary are required"
1276
1303
  );
1277
1304
  const s = await this.jiraApi.createIssue(
@@ -1290,7 +1317,7 @@ Remember to add a comment with cancellation reason first.`,
1290
1317
  case "update_issue": {
1291
1318
  if (!e.issueKey || typeof e.issueKey != "string" || !e.fields || typeof e.fields != "object")
1292
1319
  throw new c(
1293
- p.InvalidParams,
1320
+ u.InvalidParams,
1294
1321
  "issueKey and fields object are required"
1295
1322
  );
1296
1323
  return await this.jiraApi.updateIssue(e.issueKey, e.fields), {
@@ -1309,7 +1336,7 @@ Remember to add a comment with cancellation reason first.`,
1309
1336
  case "get_transitions": {
1310
1337
  if (!e.issueKey || typeof e.issueKey != "string")
1311
1338
  throw new c(
1312
- p.InvalidParams,
1339
+ u.InvalidParams,
1313
1340
  "Issue key is required"
1314
1341
  );
1315
1342
  const s = await this.jiraApi.getTransitions(e.issueKey);
@@ -1322,7 +1349,7 @@ Remember to add a comment with cancellation reason first.`,
1322
1349
  case "transition_issue": {
1323
1350
  if (!e.issueKey || typeof e.issueKey != "string" || !e.transitionId || typeof e.transitionId != "string")
1324
1351
  throw new c(
1325
- p.InvalidParams,
1352
+ u.InvalidParams,
1326
1353
  "issueKey and transitionId are required"
1327
1354
  );
1328
1355
  return await this.jiraApi.transitionIssue(
@@ -1347,7 +1374,7 @@ Remember to add a comment with cancellation reason first.`,
1347
1374
  case "add_attachment": {
1348
1375
  if (!e.issueKey || typeof e.issueKey != "string" || !e.fileContent || typeof e.fileContent != "string" || !e.filename || typeof e.filename != "string")
1349
1376
  throw new c(
1350
- p.InvalidParams,
1377
+ u.InvalidParams,
1351
1378
  "issueKey, fileContent, and filename are required"
1352
1379
  );
1353
1380
  const s = Buffer.from(e.fileContent, "base64"), i = await this.jiraApi.addAttachment(
@@ -1375,7 +1402,7 @@ Remember to add a comment with cancellation reason first.`,
1375
1402
  case "add_comment": {
1376
1403
  if (!e.issueIdOrKey || typeof e.issueIdOrKey != "string" || !e.body || typeof e.body != "string")
1377
1404
  throw new c(
1378
- p.InvalidParams,
1405
+ u.InvalidParams,
1379
1406
  "issueIdOrKey and body are required"
1380
1407
  );
1381
1408
  const s = await this.jiraApi.addCommentToIssue(
@@ -1391,7 +1418,7 @@ Remember to add a comment with cancellation reason first.`,
1391
1418
  case "get_create_meta": {
1392
1419
  if (!e.projectKey || typeof e.projectKey != "string")
1393
1420
  throw new c(
1394
- p.InvalidParams,
1421
+ u.InvalidParams,
1395
1422
  "projectKey is required"
1396
1423
  );
1397
1424
  const s = await this.jiraApi.getCreateMeta(
@@ -1408,7 +1435,7 @@ Remember to add a comment with cancellation reason first.`,
1408
1435
  case "get_field_options": {
1409
1436
  if (!e.projectKey || typeof e.projectKey != "string" || !e.issueTypeId || typeof e.issueTypeId != "string" || !e.fieldId || typeof e.fieldId != "string")
1410
1437
  throw new c(
1411
- p.InvalidParams,
1438
+ u.InvalidParams,
1412
1439
  "projectKey, issueTypeId, and fieldId are required"
1413
1440
  );
1414
1441
  const s = await this.jiraApi.getFieldOptions(
@@ -1441,7 +1468,7 @@ Remember to add a comment with cancellation reason first.`,
1441
1468
  case "get_users": {
1442
1469
  if (!e.query || typeof e.query != "string")
1443
1470
  throw new c(
1444
- p.InvalidParams,
1471
+ u.InvalidParams,
1445
1472
  "query is required"
1446
1473
  );
1447
1474
  const s = await this.jiraApi.getUsers(
@@ -1457,7 +1484,7 @@ Remember to add a comment with cancellation reason first.`,
1457
1484
  case "delete_issue": {
1458
1485
  if (!e.issueKey || typeof e.issueKey != "string")
1459
1486
  throw new c(
1460
- p.InvalidParams,
1487
+ u.InvalidParams,
1461
1488
  "issueKey is required"
1462
1489
  );
1463
1490
  return await this.jiraApi.deleteIssue(e.issueKey), {
@@ -1476,7 +1503,7 @@ Remember to add a comment with cancellation reason first.`,
1476
1503
  case "get_attachment": {
1477
1504
  if (!e.attachmentId || typeof e.attachmentId != "string")
1478
1505
  throw new c(
1479
- p.InvalidParams,
1506
+ u.InvalidParams,
1480
1507
  "attachmentId is required"
1481
1508
  );
1482
1509
  const s = await this.jiraApi.getAttachment(e.attachmentId);
@@ -1503,25 +1530,25 @@ Remember to add a comment with cancellation reason first.`,
1503
1530
  }
1504
1531
  default:
1505
1532
  throw new c(
1506
- p.MethodNotFound,
1533
+ u.MethodNotFound,
1507
1534
  `Unknown tool: ${t.params.name}`
1508
1535
  );
1509
1536
  }
1510
1537
  } catch (e) {
1511
1538
  throw e instanceof c ? e : new c(
1512
- p.InternalError,
1539
+ u.InternalError,
1513
1540
  e instanceof Error ? e.message : "Unknown error occurred"
1514
1541
  );
1515
1542
  }
1516
1543
  });
1517
1544
  }
1518
1545
  async run() {
1519
- const t = new h();
1546
+ const t = new f();
1520
1547
  await this.server.connect(t);
1521
1548
  }
1522
1549
  }
1523
- const J = process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("jira-mcp");
1524
- J && new S().run().catch(() => {
1550
+ const T = process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("jira-mcp");
1551
+ T && new S().run().catch(() => {
1525
1552
  });
1526
1553
  export {
1527
1554
  S as JiraServer
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/services/jira-api.ts","../src/services/jira-server-api.ts","../src/index.ts"],"sourcesContent":["import {\n AddCommentResponse,\n AdfDoc,\n CleanAttachment,\n CleanComment,\n CleanJiraIssue,\n JiraCommentResponse,\n SearchIssuesResponse,\n} from \"../types/jira.js\";\n\nexport class JiraApiService {\n protected baseUrl: string;\n protected headers: Headers;\n\n constructor(baseUrl: string, email: string, apiToken: string, authType: 'basic' | 'bearer' = 'basic') {\n this.baseUrl = baseUrl;\n \n let authHeader: string;\n if (authType === 'bearer') {\n // For Jira Data Center Personal Access Tokens (PATs)\n authHeader = `Bearer ${apiToken}`;\n } else {\n // For Basic authentication with username/password or API token\n const auth = Buffer.from(`${email}:${apiToken}`).toString(\"base64\");\n authHeader = `Basic ${auth}`;\n }\n \n this.headers = new Headers({\n Authorization: authHeader,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n });\n }\n\n protected async handleFetchError(\n response: Response,\n url?: string\n ): Promise<never> {\n if (!response.ok) {\n let message = response.statusText;\n let errorData: any = {};\n try {\n errorData = await response.json();\n\n // Try different error formats that Jira uses\n if (\n Array.isArray(errorData.errorMessages) &&\n errorData.errorMessages.length > 0\n ) {\n // Format: { errorMessages: [\"msg1\", \"msg2\"] }\n message = errorData.errorMessages.join(\"; \");\n } else if (errorData.message) {\n // Format: { message: \"error message\" }\n message = errorData.message;\n } else if (errorData.errorMessage) {\n // Format: { errorMessage: \"error message\" }\n message = errorData.errorMessage;\n } else if (errorData.errors && typeof errorData.errors === \"object\") {\n // Format: { errors: { fieldName: \"error for field\", anotherField: \"another error\" } }\n const errorMessages = Object.entries(errorData.errors)\n .map(([field, msg]) => `${field}: ${msg}`)\n .join(\"; \");\n if (errorMessages) {\n message = errorMessages;\n }\n }\n\n // If we still only have statusText but have error data, stringify it\n if (message === response.statusText && Object.keys(errorData).length > 0) {\n message = JSON.stringify(errorData);\n }\n } catch (e) {\n // Could not parse as JSON, try to get text\n try {\n const text = await response.text();\n if (text) {\n message = text.substring(0, 500); // Limit length\n }\n } catch {\n // Ignore\n }\n }\n\n throw new Error(\n `JIRA API Error: ${message} (Status: ${response.status})`\n );\n }\n\n throw new Error(\"Unknown error occurred during fetch operation.\");\n }\n\n /**\n * Extracts issue mentions from Atlassian document content\n * Looks for nodes that were auto-converted to issue links\n */\n protected extractIssueMentions(\n content: any[],\n source: \"description\" | \"comment\",\n commentId?: string\n ): CleanJiraIssue[\"relatedIssues\"] {\n const mentions: NonNullable<CleanJiraIssue[\"relatedIssues\"]> = [];\n\n const processNode = (node: any) => {\n if (node.type === \"inlineCard\" && node.attrs?.url) {\n const match = node.attrs.url.match(/\\/browse\\/([A-Z]+-\\d+)/);\n if (match) {\n mentions.push({\n key: match[1],\n type: \"mention\",\n source,\n commentId,\n });\n }\n }\n\n if (node.type === \"text\" && node.text) {\n const matches = node.text.match(/[A-Z]+-\\d+/g) || [];\n matches.forEach((key: string) => {\n mentions.push({\n key,\n type: \"mention\",\n source,\n commentId,\n });\n });\n }\n\n if (node.content) {\n node.content.forEach(processNode);\n }\n };\n\n content.forEach(processNode);\n return [...new Map(mentions.map((m) => [m.key, m])).values()];\n }\n\n protected cleanComment(comment: {\n id: string;\n body?: {\n content?: any[];\n };\n author?: {\n displayName?: string;\n };\n created: string;\n updated: string;\n }): CleanComment {\n const body = comment.body?.content\n ? this.extractTextContent(comment.body.content)\n : \"\";\n const mentions = comment.body?.content\n ? this.extractIssueMentions(comment.body.content, \"comment\", comment.id)\n : [];\n\n return {\n id: comment.id,\n body,\n author: comment.author?.displayName,\n created: comment.created,\n updated: comment.updated,\n mentions: mentions,\n };\n }\n\n protected cleanAttachment(attachment: any): CleanAttachment {\n return {\n id: attachment.id,\n filename: attachment.filename,\n mimeType: attachment.mimeType,\n size: attachment.size,\n created: attachment.created,\n author: attachment.author?.displayName,\n content: attachment.content,\n thumbnail: attachment.thumbnail,\n };\n }\n\n /**\n * Recursively extracts text content from Atlassian Document Format nodes\n */\n protected extractTextContent(content: any[]): string {\n if (!Array.isArray(content)) return \"\";\n\n return content\n .map((node) => {\n if (node.type === \"text\") {\n return node.text || \"\";\n }\n if (node.content) {\n return this.extractTextContent(node.content);\n }\n return \"\";\n })\n .join(\"\");\n }\n\n protected cleanIssue(issue: any): CleanJiraIssue {\n let description = \"\";\n if (issue.fields?.description) {\n if (typeof issue.fields.description === \"string\") {\n // Jira Server: plain text\n description = issue.fields.description;\n } else if (issue.fields.description.content) {\n // Jira Cloud: ADF format\n description = this.extractTextContent(issue.fields.description.content);\n }\n }\n\n const cleanedIssue: CleanJiraIssue = {\n id: issue.id,\n key: issue.key,\n summary: issue.fields?.summary,\n status: issue.fields?.status?.name,\n created: issue.fields?.created,\n updated: issue.fields?.updated,\n description,\n relatedIssues: [],\n };\n\n if (issue.fields?.description?.content) {\n const mentions = this.extractIssueMentions(\n issue.fields.description.content,\n \"description\"\n );\n if (mentions.length > 0) {\n cleanedIssue.relatedIssues = mentions;\n }\n }\n\n if (issue.fields?.issuelinks?.length > 0) {\n const links = issue.fields.issuelinks.map((link: any) => {\n const linkedIssue = link.inwardIssue || link.outwardIssue;\n const relationship = link.type.inward || link.type.outward;\n return {\n key: linkedIssue.key,\n summary: linkedIssue.fields?.summary,\n type: \"link\" as const,\n relationship,\n source: \"description\" as const,\n };\n });\n\n cleanedIssue.relatedIssues = [\n ...(cleanedIssue.relatedIssues || []),\n ...links,\n ];\n }\n\n if (issue.fields?.parent) {\n cleanedIssue.parent = {\n id: issue.fields.parent.id,\n key: issue.fields.parent.key,\n summary: issue.fields.parent.fields?.summary,\n };\n }\n\n if (issue.fields?.customfield_10014) {\n cleanedIssue.epicLink = {\n id: issue.fields.customfield_10014,\n key: issue.fields.customfield_10014,\n summary: undefined,\n };\n }\n\n if (issue.fields?.subtasks?.length > 0) {\n cleanedIssue.children = issue.fields.subtasks.map((subtask: any) => ({\n id: subtask.id,\n key: subtask.key,\n summary: subtask.fields?.summary,\n }));\n }\n\n if (issue.fields?.attachment?.length > 0) {\n cleanedIssue.attachments = issue.fields.attachment.map((a: any) =>\n this.cleanAttachment(a)\n );\n }\n\n return cleanedIssue;\n }\n\n protected async fetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const response = await fetch(this.baseUrl + url, {\n ...init,\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response, url);\n }\n\n return response.json();\n }\n\n async searchIssues(searchString: string): Promise<SearchIssuesResponse> {\n const params = new URLSearchParams({\n jql: searchString,\n maxResults: \"50\",\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n const data = await this.fetchJson<any>(`/rest/api/3/search?${params}`);\n\n return {\n total: data.total,\n issues: data.issues.map((issue: any) => this.cleanIssue(issue)),\n };\n }\n\n async getEpicChildren(epicKey: string): Promise<CleanJiraIssue[]> {\n const params = new URLSearchParams({\n jql: `\"Epic Link\" = ${epicKey}`,\n maxResults: \"100\",\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n const data = await this.fetchJson<any>(`/rest/api/3/search?${params}`);\n\n const issuesWithComments = await Promise.all(\n data.issues.map(async (issue: any) => {\n const commentsData = await this.fetchJson<any>(\n `/rest/api/3/issue/${issue.key}/comment`\n );\n const cleanedIssue = this.cleanIssue(issue);\n const comments = commentsData.comments.map((comment: any) =>\n this.cleanComment(comment)\n );\n\n const commentMentions = comments.flatMap(\n (comment: CleanComment) => comment.mentions\n );\n cleanedIssue.relatedIssues = [\n ...cleanedIssue.relatedIssues,\n ...commentMentions,\n ];\n\n cleanedIssue.comments = comments;\n return cleanedIssue;\n })\n );\n\n return issuesWithComments;\n }\n\n async getIssueWithComments(issueId: string): Promise<CleanJiraIssue> {\n const params = new URLSearchParams({\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n \"attachment\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n let issueData, commentsData;\n try {\n [issueData, commentsData] = await Promise.all([\n this.fetchJson<any>(`/rest/api/3/issue/${issueId}?${params}`),\n this.fetchJson<any>(`/rest/api/3/issue/${issueId}/comment`),\n ]);\n } catch (error: any) {\n if (error instanceof Error && error.message.includes(\"(Status: 404)\")) {\n throw new Error(`Issue not found: ${issueId}`);\n }\n\n throw error;\n }\n\n const issue = this.cleanIssue(issueData);\n const comments = commentsData.comments.map((comment: any) =>\n this.cleanComment(comment)\n );\n\n const commentMentions = comments.flatMap(\n (comment: CleanComment) => comment.mentions\n );\n issue.relatedIssues = [...issue.relatedIssues, ...commentMentions];\n\n issue.comments = comments;\n\n if (issue.epicLink) {\n try {\n const epicData = await this.fetchJson<any>(\n `/rest/api/3/issue/${issue.epicLink.key}?fields=summary`\n );\n issue.epicLink.summary = epicData.fields?.summary;\n } catch (error) {\n console.error(\"Failed to fetch epic details:\", error);\n }\n }\n\n return issue;\n }\n\n async createIssue(\n projectKey: string,\n issueType: string,\n summary: string,\n description?: string,\n fields?: Record<string, any>\n ): Promise<{ id: string; key: string }> {\n const payload = {\n fields: {\n project: {\n key: projectKey,\n },\n summary,\n issuetype: {\n name: issueType,\n },\n ...(description && { description }),\n ...fields,\n },\n };\n\n return this.fetchJson<{ id: string; key: string }>(\"/rest/api/3/issue\", {\n method: \"POST\",\n body: JSON.stringify(payload),\n });\n }\n\n async getCreateMeta(\n projectKey: string,\n issueTypeName?: string,\n compact?: boolean\n ): Promise<any> {\n // Get available issue types for the project\n const issueTypesData = await this.fetchJson<{ issueTypes: Array<{ id: string; name: string; description?: string; subtask: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes`\n );\n\n let issueTypes = issueTypesData.issueTypes || [];\n\n // Filter by issue type name if provided\n if (issueTypeName) {\n issueTypes = issueTypes.filter(\n (it) => it.name.toLowerCase() === issueTypeName.toLowerCase()\n );\n }\n\n // Get fields for each issue type\n const result = {\n projectKey,\n issueTypes: await Promise.all(\n issueTypes.map(async (issueType) => {\n try {\n const fieldsData = await this.fetchJson<{ fields: Array<{ fieldId: string; name: string; required: boolean; schema?: any; allowedValues?: any[]; hasDefaultValue?: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueType.id}`\n );\n\n let fields = fieldsData.fields || [];\n\n // In compact mode, replace allowedValues with count\n if (compact) {\n fields = fields.map((f) => ({\n fieldId: f.fieldId,\n name: f.name,\n required: f.required,\n schema: f.schema,\n hasDefaultValue: f.hasDefaultValue,\n allowedValuesCount: f.allowedValues?.length ?? 0,\n }));\n }\n\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields,\n };\n } catch (error) {\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields: [],\n error: error instanceof Error ? error.message : \"Failed to fetch fields\",\n };\n }\n })\n ),\n };\n\n return result;\n }\n\n async getFieldOptions(\n projectKey: string,\n issueTypeId: string,\n fieldId: string\n ): Promise<any[]> {\n const fieldsData = await this.fetchJson<{ fields: Array<{ fieldId: string; allowedValues?: any[] }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueTypeId}`\n );\n\n const field = (fieldsData.fields || []).find((f) => f.fieldId === fieldId);\n return field?.allowedValues ?? [];\n }\n\n async updateIssue(\n issueKey: string,\n fields: Record<string, any>\n ): Promise<void> {\n await this.fetchJson(`/rest/api/3/issue/${issueKey}`, {\n method: \"PUT\",\n body: JSON.stringify({ fields }),\n });\n }\n\n async getTransitions(\n issueKey: string\n ): Promise<Array<{ id: string; name: string; to: { name: string } }>> {\n const data = await this.fetchJson<any>(\n `/rest/api/3/issue/${issueKey}/transitions`\n );\n return data.transitions;\n }\n\n async transitionIssue(\n issueKey: string,\n transitionId: string,\n comment?: string\n ): Promise<void> {\n const payload: any = {\n transition: { id: transitionId },\n };\n\n if (comment) {\n payload.update = {\n comment: [\n {\n add: {\n body: {\n type: \"doc\",\n version: 1,\n content: [\n {\n type: \"paragraph\",\n content: [\n {\n type: \"text\",\n text: comment,\n },\n ],\n },\n ],\n },\n },\n },\n ],\n };\n }\n\n await this.fetchJson(`/rest/api/3/issue/${issueKey}/transitions`, {\n method: \"POST\",\n body: JSON.stringify(payload),\n });\n }\n\n async addAttachment(\n issueKey: string,\n file: Buffer,\n filename: string\n ): Promise<{ id: string; filename: string }> {\n const formData = new FormData();\n formData.append(\"file\", new Blob([new Uint8Array(file)]), filename);\n\n const headers = new Headers(this.headers);\n headers.delete(\"Content-Type\");\n headers.set(\"X-Atlassian-Token\", \"no-check\");\n\n const response = await fetch(\n `${this.baseUrl}/rest/api/3/issue/${issueKey}/attachments`,\n {\n method: \"POST\",\n headers,\n body: formData,\n }\n );\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n\n const data = await response.json();\n\n const attachment = data[0];\n return {\n id: attachment.id,\n filename: attachment.filename,\n };\n }\n\n /**\n * Converts plain text to a basic Atlassian Document Format (ADF) structure.\n */\n private createAdfFromBody(text: string): AdfDoc {\n return {\n version: 1,\n type: \"doc\",\n content: [\n {\n type: \"paragraph\",\n content: [\n {\n type: \"text\",\n text: text,\n },\n ],\n },\n ],\n };\n }\n\n /**\n * Adds a comment to a JIRA issue.\n */\n async addCommentToIssue(\n issueIdOrKey: string,\n body: string\n ): Promise<AddCommentResponse> {\n const adfBody = this.createAdfFromBody(body);\n\n const payload = {\n body: adfBody,\n };\n\n const response = await this.fetchJson<JiraCommentResponse>(\n `/rest/api/3/issue/${issueIdOrKey}/comment`,\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n }\n );\n\n return {\n id: response.id,\n author: response.author.displayName,\n created: response.created,\n updated: response.updated,\n body: this.extractTextContent(response.body.content),\n };\n }\n\n async getServerInfo(): Promise<{\n version: string;\n versionNumbers: number[];\n deploymentType: string;\n buildNumber: number;\n serverTitle: string;\n }> {\n return this.fetchJson(`/rest/api/3/serverInfo`);\n }\n\n async getProjects(): Promise<Array<{\n id: string;\n key: string;\n name: string;\n projectTypeKey: string;\n lead?: { displayName: string; accountId?: string };\n }>> {\n const data = await this.fetchJson<any[]>(`/rest/api/3/project`);\n return data.map((project) => ({\n id: project.id,\n key: project.key,\n name: project.name,\n projectTypeKey: project.projectTypeKey,\n lead: project.lead ? {\n displayName: project.lead.displayName,\n accountId: project.lead.accountId,\n } : undefined,\n }));\n }\n\n async getUsers(query: string, maxResults: number = 50): Promise<Array<{\n accountId: string;\n displayName: string;\n emailAddress?: string;\n active: boolean;\n }>> {\n const params = new URLSearchParams({\n query,\n maxResults: maxResults.toString(),\n });\n const data = await this.fetchJson<any[]>(`/rest/api/3/user/search?${params}`);\n return data.map((user) => ({\n accountId: user.accountId,\n displayName: user.displayName,\n emailAddress: user.emailAddress,\n active: user.active,\n }));\n }\n\n async deleteIssue(issueKey: string): Promise<void> {\n const response = await fetch(`${this.baseUrl}/rest/api/3/issue/${issueKey}`, {\n method: \"DELETE\",\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n }\n\n async getAttachment(attachmentId: string): Promise<{\n content: string; // base64 encoded\n filename: string;\n mimeType: string;\n }> {\n // First, get attachment metadata to get the content URL\n const metadata = await this.fetchJson<{\n id: string;\n filename: string;\n mimeType: string;\n content: string;\n }>(`/rest/api/3/attachment/${attachmentId}`);\n\n // Fetch the actual content from the content URL\n const response = await fetch(metadata.content, {\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const base64 = Buffer.from(arrayBuffer).toString(\"base64\");\n\n return {\n content: base64,\n filename: metadata.filename,\n mimeType: metadata.mimeType,\n };\n }\n}\n","// JiraServerApiService: Jira Server (Data Center) implementation\n// This class should override methods as needed for Jira Server differences\nimport { JiraApiService } from \"./jira-api.js\";\nimport type { CleanComment, CleanJiraIssue } from \"../types/jira.js\";\n\nexport class JiraServerApiService extends JiraApiService {\n constructor(baseUrl: string, email: string, apiToken: string, authType: 'basic' | 'bearer' = 'basic') {\n // For Jira Server/Data Center:\n // - Basic Auth: username/password or API token (traditional method)\n // - Bearer Auth: Personal Access Tokens (PATs) available in Data Center 8.14.0+\n super(baseUrl, email, apiToken, authType);\n }\n\n // Example: Override fetchJson to use /rest/api/2/ instead of /rest/api/3/\n protected overrideApiPath(path: string): string {\n // Replace /rest/api/3/ with /rest/api/2/ for Jira Server\n return path.replace(\"/rest/api/3/\", \"/rest/api/2/\");\n }\n\n // Override fetchJson to use the correct API path\n protected async fetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const serverUrl = this.overrideApiPath(url);\n return super.fetchJson<T>(serverUrl, init);\n }\n\n // Override getCreateMeta to use API v2 endpoints for Jira Server 9.0+\n async getCreateMeta(\n projectKey: string,\n issueTypeName?: string,\n compact?: boolean\n ): Promise<any> {\n // For Jira Server 9.0+, use the new paginated endpoints (same structure as Cloud but API v2)\n const issueTypesData = await this.fetchJson<{ values: Array<{ id: string; name: string; description?: string; subtask: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes`\n );\n\n let issueTypes = issueTypesData.values || [];\n\n // Filter by issue type name if provided\n if (issueTypeName) {\n issueTypes = issueTypes.filter(\n (it) => it.name.toLowerCase() === issueTypeName.toLowerCase()\n );\n }\n\n // Get fields for each issue type\n const result = {\n projectKey,\n issueTypes: await Promise.all(\n issueTypes.map(async (issueType) => {\n try {\n const fieldsData = await this.fetchJson<{ values: Array<{ fieldId: string; name: string; required: boolean; schema?: any; allowedValues?: any[]; hasDefaultValue?: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueType.id}`\n );\n\n let fields = fieldsData.values || [];\n\n // In compact mode, replace allowedValues with count\n if (compact) {\n fields = fields.map((f) => ({\n fieldId: f.fieldId,\n name: f.name,\n required: f.required,\n schema: f.schema,\n hasDefaultValue: f.hasDefaultValue,\n allowedValuesCount: f.allowedValues?.length ?? 0,\n }));\n }\n\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields,\n };\n } catch (error) {\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields: [],\n error: error instanceof Error ? error.message : \"Failed to fetch fields\",\n };\n }\n })\n ),\n };\n\n return result;\n }\n\n // Override getFieldOptions for Jira Server (uses 'values' instead of 'fields')\n async getFieldOptions(\n projectKey: string,\n issueTypeId: string,\n fieldId: string\n ): Promise<any[]> {\n const fieldsData = await this.fetchJson<{ values: Array<{ fieldId: string; allowedValues?: any[] }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueTypeId}`\n );\n\n const field = (fieldsData.values || []).find((f) => f.fieldId === fieldId);\n return field?.allowedValues ?? [];\n }\n\n // Override getUsers for Jira Server (uses 'username' parameter instead of 'query')\n async getUsers(query: string, maxResults: number = 50): Promise<Array<{\n accountId: string;\n displayName: string;\n emailAddress?: string;\n active: boolean;\n }>> {\n const params = new URLSearchParams({\n username: query,\n maxResults: maxResults.toString(),\n });\n const data = await this.fetchJson<any[]>(`/rest/api/3/user/search?${params}`);\n return data.map((user) => ({\n // Jira Server uses 'name' or 'key' instead of 'accountId'\n accountId: user.key || user.name,\n displayName: user.displayName,\n emailAddress: user.emailAddress,\n active: user.active,\n }));\n }\n\n // Override addCommentToIssue for Jira Server (uses plain text instead of ADF)\n async addCommentToIssue(\n issueIdOrKey: string,\n body: string\n ): Promise<{\n id: string;\n author: string;\n created: string;\n updated: string;\n body: string;\n }> {\n // Jira Server API v2 expects plain text body, not ADF\n const payload = {\n body: body,\n };\n\n const response = await this.fetchJson<{\n id: string;\n author: { displayName: string };\n created: string;\n updated: string;\n body: string;\n }>(\n `/rest/api/3/issue/${issueIdOrKey}/comment`,\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n }\n );\n\n return {\n id: response.id,\n author: response.author.displayName,\n created: response.created,\n updated: response.updated,\n body: response.body,\n };\n }\n\n // Override deleteIssue for Jira Server (uses API v2)\n async deleteIssue(issueKey: string): Promise<void> {\n const response = await fetch(`${this.baseUrl}/rest/api/2/issue/${issueKey}`, {\n method: \"DELETE\",\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n }\n\n // Override cleanComment for Jira Server (body is plain text, not ADF)\n protected cleanComment(comment: {\n id: string;\n body?: string | { content?: any[] };\n author?: {\n displayName?: string;\n };\n created: string;\n updated: string;\n }): CleanComment {\n // Debug: log raw comment to understand API response format\n console.error(\"[DEBUG cleanComment] Raw comment:\", JSON.stringify(comment, null, 2));\n\n // Jira Server API v2 returns body as plain text string\n // Jira Cloud API v3 returns body as ADF object with content array\n let body: string;\n let mentions: CleanJiraIssue[\"relatedIssues\"] = [];\n\n if (typeof comment.body === \"string\") {\n // Jira Server: body is plain text\n body = comment.body;\n // Extract issue mentions from plain text (e.g., PROJECT-123)\n mentions = this.extractIssueMentionsFromText(body, \"comment\", comment.id);\n } else if (comment.body?.content) {\n // Jira Cloud: body is ADF object\n body = this.extractTextContent(comment.body.content);\n mentions = this.extractIssueMentions(comment.body.content, \"comment\", comment.id);\n } else {\n body = \"\";\n }\n\n return {\n id: comment.id,\n body,\n author: comment.author?.displayName,\n created: comment.created,\n updated: comment.updated,\n mentions,\n };\n }\n\n // Extract issue mentions from plain text (for Jira Server)\n protected extractIssueMentionsFromText(\n text: string,\n source: \"description\" | \"comment\",\n commentId?: string\n ): CleanJiraIssue[\"relatedIssues\"] {\n if (!text) return [];\n\n const matches = text.match(/[A-Z]+-\\d+/g) || [];\n const uniqueKeys = [...new Set(matches)];\n\n return uniqueKeys.map((key) => ({\n key,\n type: \"mention\" as const,\n source,\n commentId,\n }));\n }\n}\n","#!/usr/bin/env node\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ErrorCode,\n ListToolsRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { JiraApiService } from \"./services/jira-api.js\";\nimport { JiraServerApiService } from \"./services/jira-server-api.js\";\n\nfunction getEnvConfig() {\n const JIRA_API_TOKEN = process.env.JIRA_API_TOKEN ?? \"\";\n const JIRA_BASE_URL = process.env.JIRA_BASE_URL ?? \"\";\n const JIRA_USER_EMAIL = process.env.JIRA_USER_EMAIL ?? \"\";\n const JIRA_TYPE = (process.env.JIRA_TYPE === \"server\" ? \"server\" : \"cloud\") as\n | \"cloud\"\n | \"server\";\n const JIRA_AUTH_TYPE = (process.env.JIRA_AUTH_TYPE === \"bearer\" ? \"bearer\" : \"basic\") as\n | \"basic\"\n | \"bearer\";\n\n if (!JIRA_API_TOKEN || !JIRA_BASE_URL || !JIRA_USER_EMAIL) {\n throw new Error(\n \"JIRA_API_TOKEN, JIRA_USER_EMAIL and JIRA_BASE_URL environment variables are required\",\n );\n }\n\n return { JIRA_API_TOKEN, JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_TYPE, JIRA_AUTH_TYPE };\n}\n\n// ============================================================================\n// PROMPTS - Инструкции и регламенты для агентов\n// ============================================================================\n\nconst JIRA_PROMPTS: Record<string, { description: string; content: string }> = {\n jira_guidelines: {\n description: \"Общие правила и регламенты работы с Jira в компании\",\n content: `# Регламент работы с Jira\n\n## Общие принципы\n- Все изменения статусов должны отражать реальное состояние работы\n- Комментарии пишутся на русском языке\n- При любых изменениях, затрагивающих других участников, оставляй комментарий\n\n## Статусы и переходы\n\n### Workflow задачи:\n1. **Бэклог** — задача запланирована, но работа не начата\n2. **Очередь** — задача в очереди на выполнение\n3. **В работе** — код в процессе написания\n4. **Ревью** — код готов к проверке, создан PR/MR\n5. **Local test** — задача на локальном тестировании\n6. **Dev** — код в ветке dev\n7. **Stage (не проверено)** — код в ветке stage, тестирование не проведено\n8. **Релиз-кандидат** — проверено на stage, готово к релизу\n9. **Тест на проде** — код на проде, ожидает проверки\n10. **Готово на проде** — задача завершена и проверена\n\n### Особые статусы:\n- **Заблокирована** — работа приостановлена (указать причину в комментарии)\n- **Отложено** — задача отложена на неопределённый срок\n- **Отмена** — задача отменена (ОБЯЗАТЕЛЬНО с комментарием о причине!)\n\n## Создание задач\n- Summary должен быть кратким и информативным (не более 100 символов)\n- Description должен содержать достаточно информации для понимания задачи\n- Обязательно указывай компонент (component) для правильной маршрутизации\n- Для багов: шаги воспроизведения, ожидаемый и фактический результат\n\n## Отмена задач\n- ЗАПРЕЩЕНО отменять задачу без указания причины в комментарии\n- Причина должна быть информативной: \"дубликат IM3-1234\", \"неактуально после релиза X\", и т.д.\n\n## Удаление задач\n- Удаление задач запрещено политикой безопасности\n- Вместо удаления используй статус \"Отмена\" с комментарием\n\n## Комментарии\n- Используй комментарии для важной информации, которая должна остаться в истории\n- При блокировке — указывай причину и ссылку на блокирующую задачу\n- При передаче задачи — описывай текущее состояние и что осталось сделать`,\n },\n\n create_issue_workflow: {\n description: \"Пошаговый процесс создания задачи в Jira\",\n content: `# Создание задачи в Jira\n\n## Перед созданием ОБЯЗАТЕЛЬНО уточни у пользователя:\n\n### Основная информация:\n1. **Проект** — в каком проекте создать (IM3, SD, FT, ETPP и т.д.)\n2. **Тип задачи** — Баг, Story, Task, Sub-task\n3. **Краткое описание** (summary) — что нужно сделать, до 100 символов\n4. **Подробное описание** (description) — детали задачи\n\n### Для багов дополнительно запроси:\n- Шаги воспроизведения (пронумерованный список)\n- Ожидаемый результат\n- Фактический результат\n- Окружение (браузер, ОС, URL) — если релевантно\n- Скриншоты или логи — если есть\n\n### Для Story/Task уточни:\n- Критерии приёмки (acceptance criteria)\n- Связанные задачи (если есть)\n\n## Порядок действий:\n\n1. **Получи схему полей:**\n \\`\\`\\`\n get_create_meta(projectKey, issueTypeName, compact=true)\n \\`\\`\\`\n\n2. **Для обязательных полей с вариантами получи опции:**\n \\`\\`\\`\n get_field_options(projectKey, issueTypeId, fieldId)\n \\`\\`\\`\n\n3. **Покажи пользователю** итоговые данные перед созданием\n\n4. **Создай задачу:**\n \\`\\`\\`\n create_issue(projectKey, issueType, summary, description, fields)\n \\`\\`\\`\n\n5. **Верни пользователю** ключ и ссылку на созданную задачу\n\n## Пример описания бага:\n\n\\`\\`\\`\nШаги воспроизведения:\n1. Открыть страницу /checkout\n2. Добавить товар в корзину\n3. Нажать \"Оформить заказ\"\n\nОжидаемый результат:\nОткрывается форма оформления заказа\n\nФактический результат:\nСтраница показывает ошибку 500\n\nОкружение:\n- URL: https://example.com/checkout\n- Браузер: Chrome 120\n- ОС: Windows 11\n\\`\\`\\``,\n },\n\n cancel_issue_workflow: {\n description: \"Процесс отмены задачи (требует указания причины)\",\n content: `# Отмена задачи в Jira\n\n## ⚠️ ВАЖНО: Задачу НЕЛЬЗЯ отменять без причины!\n\n## Порядок действий:\n\n### 1. Спроси причину отмены\nПрежде чем отменять задачу, ОБЯЗАТЕЛЬНО спроси у пользователя:\n- \"Почему задача отменяется?\"\n- \"Укажите причину отмены для комментария\"\n\n### 2. Примеры корректных причин:\n- \"Дубликат задачи IM3-1234\"\n- \"Неактуально после релиза версии 2.5\"\n- \"Функционал реализован в рамках IM3-5678\"\n- \"Отменено по решению Product Owner (имя)\"\n- \"Требования изменились, создана новая задача IM3-9999\"\n\n### 3. Добавь комментарий с причиной:\n\\`\\`\\`\nadd_comment(issueKey, \"Причина отмены: <причина от пользователя>\")\n\\`\\`\\`\n\n### 4. Получи ID перехода \"Отмена\":\n\\`\\`\\`\nget_transitions(issueKey)\n// Найди переход с name=\"Отмена\"\n\\`\\`\\`\n\n### 5. Выполни переход:\n\\`\\`\\`\ntransition_issue(issueKey, transitionId)\n\\`\\`\\`\n\n## Запрещено:\n- ❌ Отменять задачу без комментария с причиной\n- ❌ Использовать причины типа \"не нужно\", \"отмена\" без пояснения\n\n## Если пользователь не хочет указывать причину:\nОбъясни, что это требование регламента компании, и причина важна для:\n- Истории проекта\n- Понимания, почему задача не была выполнена\n- Аудита и отчётности`,\n },\n\n transition_issue_workflow: {\n description: \"Правила смены статусов задач\",\n content: `# Смена статуса задачи в Jira\n\n## Общие правила:\n- Статус должен отражать реальное состояние работы\n- Не пропускай промежуточные статусы без веской причины\n- При переходе в финальные статусы убедись, что работа действительно завершена\n\n## Особые случаи:\n\n### Переход в \"Отмена\":\n⚠️ ОБЯЗАТЕЛЬНО сначала добавь комментарий с причиной отмены!\nСм. prompt \"cancel_issue_workflow\" для подробностей.\n\n### Переход в \"Заблокирована\":\n- Укажи в комментарии причину блокировки\n- Добавь ссылку на блокирующую задачу (если есть)\n- Пример: \"Заблокировано: ждём завершения IM3-1234 (интеграция с API)\"\n\n### Переход в \"Ревью\":\n- Должен существовать Pull Request / Merge Request\n- Желательно добавить ссылку на PR в комментарий\n\n### Переход в \"Dev\" / \"Stage\":\n- Код должен быть смержен в соответствующую ветку\n- Задача задеплоена на окружение\n\n### Переход в \"Тест на проде\":\n- Код задеплоен на production\n- Задача готова к финальной проверке\n\n### Переход в \"Готово на проде\":\n- Задача проверена на production\n- Все acceptance criteria выполнены\n- Нет открытых sub-tasks\n\n## Получение доступных переходов:\n\\`\\`\\`\nget_transitions(issueKey)\n// Вернёт список доступных переходов с их ID\n\\`\\`\\`\n\n## Выполнение перехода:\n\\`\\`\\`\ntransition_issue(issueKey, transitionId, comment?)\n// comment — опциональный комментарий к переходу\n\\`\\`\\``,\n },\n\n update_issue_workflow: {\n description: \"Правила обновления задач\",\n content: `# Обновление задачи в Jira\n\n## Что можно обновлять:\n- summary — краткое описание\n- description — подробное описание\n- assignee — исполнитель\n- priority — приоритет\n- labels — метки\n- components — компоненты\n- customfield_* — кастомные поля\n\n## Правила:\n\n### При изменении исполнителя (assignee):\n- Если задача в работе — согласуй с текущим исполнителем\n- Добавь комментарий о причине переназначения\n\n### При изменении приоритета:\n- Повышение приоритета — укажи причину в комментарии\n- Понижение приоритета — согласуй с автором задачи\n\n### При изменении описания:\n- Не удаляй важную информацию\n- Если меняешь суть задачи — лучше создай новую\n\n## Пример обновления:\n\\`\\`\\`\nupdate_issue(issueKey, {\n summary: \"Новый заголовок\",\n priority: { name: \"High\" },\n assignee: { name: \"username\" }\n})\n\\`\\`\\`\n\n## Для поиска пользователей:\n\\`\\`\\`\nget_users(query) // поиск по имени или email\n\\`\\`\\``,\n },\n};\n\nexport class JiraServer {\n public server: Server;\n private jiraApi: JiraApiService;\n\n constructor() {\n this.server = new Server(\n {\n name: \"jira-mcp\",\n version: \"0.3.0\",\n },\n {\n capabilities: {\n tools: {},\n prompts: {},\n },\n },\n );\n\n const { JIRA_API_TOKEN, JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_TYPE, JIRA_AUTH_TYPE } = getEnvConfig();\n\n if (JIRA_TYPE === \"server\") {\n this.jiraApi = new JiraServerApiService(\n JIRA_BASE_URL,\n JIRA_USER_EMAIL,\n JIRA_API_TOKEN,\n JIRA_AUTH_TYPE,\n );\n } else {\n this.jiraApi = new JiraApiService(\n JIRA_BASE_URL,\n JIRA_USER_EMAIL,\n JIRA_API_TOKEN,\n JIRA_AUTH_TYPE,\n );\n }\n\n this.setupToolHandlers();\n\n this.server.onerror = (error) => {};\n process.on(\"SIGINT\", async () => {\n await this.server.close();\n process.exit(0);\n });\n }\n\n private setupToolHandlers() {\n // ========================================================================\n // PROMPTS HANDLERS\n // ========================================================================\n\n this.server.setRequestHandler(ListPromptsRequestSchema, async () => ({\n prompts: Object.entries(JIRA_PROMPTS).map(([name, { description }]) => ({\n name,\n description,\n })),\n }));\n\n this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const { name } = request.params;\n const prompt = JIRA_PROMPTS[name];\n\n if (!prompt) {\n throw new McpError(ErrorCode.InvalidParams, `Unknown prompt: ${name}`);\n }\n\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: prompt.content,\n },\n },\n ],\n };\n });\n\n // ========================================================================\n // TOOLS HANDLERS\n // ========================================================================\n\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: \"search_issues\",\n description: \"Search JIRA issues using JQL\",\n inputSchema: {\n type: \"object\",\n properties: {\n searchString: {\n type: \"string\",\n description: \"JQL search string\",\n },\n },\n required: [\"searchString\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_epic_children\",\n description:\n \"Get all child issues in an epic including their comments\",\n inputSchema: {\n type: \"object\",\n properties: {\n epicKey: {\n type: \"string\",\n description: \"The key of the epic issue\",\n },\n },\n required: [\"epicKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_issue\",\n description:\n \"Get detailed information about a specific JIRA issue including comments\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueId: {\n type: \"string\",\n description: \"The ID or key of the JIRA issue\",\n },\n },\n required: [\"issueId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"create_issue\",\n description: `Create a new JIRA issue.\n\n📋 BEFORE CREATING: Ask user for project, issue type, summary, and description.\nFor bugs: also ask for reproduction steps, expected/actual results.\nUse get_create_meta first to check required fields.\nSee prompt \"create_issue_workflow\" for detailed guidelines.`,\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key where the issue will be created\",\n },\n issueType: {\n type: \"string\",\n description:\n 'The type of issue to create (e.g., \"Bug\", \"Story\", \"Task\")',\n },\n summary: {\n type: \"string\",\n description: \"The issue summary/title\",\n },\n description: {\n type: \"string\",\n description: \"The issue description\",\n },\n fields: {\n type: \"object\",\n description: \"Additional fields to set on the issue\",\n additionalProperties: true,\n },\n },\n required: [\"projectKey\", \"issueType\", \"summary\"],\n additionalProperties: false,\n },\n },\n {\n name: \"update_issue\",\n description: `Update an existing JIRA issue.\n\n📝 When changing assignee or priority, consider adding a comment explaining why.\nSee prompt \"update_issue_workflow\" for guidelines.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to update\",\n },\n fields: {\n type: \"object\",\n description: \"Fields to update on the issue\",\n additionalProperties: true,\n },\n },\n required: [\"issueKey\", \"fields\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_transitions\",\n description: \"Get available status transitions for a JIRA issue\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to get transitions for\",\n },\n },\n required: [\"issueKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"transition_issue\",\n description: `Change the status of a JIRA issue by performing a transition.\n\n⚠️ CANCELLATION RULE: When transitioning to \"Отмена\" (Cancel), you MUST first:\n1. Ask user for cancellation reason\n2. Add comment with the reason using add_comment\n3. Only then perform the transition\nSee prompt \"cancel_issue_workflow\" for details.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to transition\",\n },\n transitionId: {\n type: \"string\",\n description: \"The ID of the transition to perform\",\n },\n comment: {\n type: \"string\",\n description: \"Optional comment to add with the transition\",\n },\n },\n required: [\"issueKey\", \"transitionId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"add_attachment\",\n description: \"Add a file attachment to a JIRA issue\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to add attachment to\",\n },\n fileContent: {\n type: \"string\",\n description: \"Base64 encoded content of the file\",\n },\n filename: {\n type: \"string\",\n description: \"Name of the file to be attached\",\n },\n },\n required: [\"issueKey\", \"fileContent\", \"filename\"],\n additionalProperties: false,\n },\n },\n {\n name: \"add_comment\",\n description: \"Add a comment to a JIRA issue\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueIdOrKey: {\n type: \"string\",\n description: \"The ID or key of the issue to add the comment to\",\n },\n body: {\n type: \"string\",\n description: \"The content of the comment (plain text)\",\n },\n },\n required: [\"issueIdOrKey\", \"body\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_create_meta\",\n description: \"Get metadata for creating issues in a project, including available issue types and required fields. Use compact=true to get a smaller response with field counts instead of full allowedValues arrays.\",\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key to get creation metadata for\",\n },\n issueTypeName: {\n type: \"string\",\n description: \"Optional: filter to a specific issue type name\",\n },\n compact: {\n type: \"boolean\",\n description: \"If true, returns allowedValuesCount instead of full allowedValues arrays (reduces response size significantly)\",\n },\n },\n required: [\"projectKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_field_options\",\n description: \"Get allowed values for a specific field when creating issues. Use this after get_create_meta with compact=true to fetch options for fields that have allowedValuesCount > 0.\",\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key\",\n },\n issueTypeId: {\n type: \"string\",\n description: \"The issue type ID (from get_create_meta response)\",\n },\n fieldId: {\n type: \"string\",\n description: \"The field ID to get allowed values for (e.g., 'components', 'customfield_12405')\",\n },\n },\n required: [\"projectKey\", \"issueTypeId\", \"fieldId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_server_info\",\n description: \"Get JIRA server information including version and deployment type\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: \"get_projects\",\n description: \"Get all JIRA projects accessible to the current user\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: \"get_users\",\n description: \"Search for JIRA users by name or email. Useful for finding assignees.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Search query (name or email)\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 50)\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n },\n {\n name: \"delete_issue\",\n description: `Delete a JIRA issue permanently.\n\n⚠️ NOTE: Most users don't have delete permissions.\nIf deletion fails, use transition to \"Отмена\" (Cancel) status instead.\nRemember to add a comment with cancellation reason first.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to delete (e.g., IM3-1234)\",\n },\n },\n required: [\"issueKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_attachment\",\n description: \"Download a JIRA attachment by ID. Returns base64 encoded content. Use get_issue first to see available attachments with their IDs.\",\n inputSchema: {\n type: \"object\",\n properties: {\n attachmentId: {\n type: \"string\",\n description: \"The ID of the attachment to download\",\n },\n },\n required: [\"attachmentId\"],\n additionalProperties: false,\n },\n },\n ],\n }));\n\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n try {\n const args = request.params.arguments as Record<string, any>;\n\n switch (request.params.name) {\n case \"search_issues\": {\n if (!args.searchString || typeof args.searchString !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Search string is required\",\n );\n }\n const response = await this.jiraApi.searchIssues(args.searchString);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_epic_children\": {\n if (!args.epicKey || typeof args.epicKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Epic key is required\",\n );\n }\n const response = await this.jiraApi.getEpicChildren(args.epicKey);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_issue\": {\n if (!args.issueId || typeof args.issueId !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Issue ID is required\",\n );\n }\n const response = await this.jiraApi.getIssueWithComments(\n args.issueId,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"create_issue\": {\n // Basic validation\n if (\n !args.projectKey ||\n typeof args.projectKey !== \"string\" ||\n !args.issueType ||\n typeof args.issueType !== \"string\" ||\n !args.summary ||\n typeof args.summary !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey, issueType, and summary are required\",\n );\n }\n const response = await this.jiraApi.createIssue(\n args.projectKey,\n args.issueType,\n args.summary,\n args.description as string | undefined,\n args.fields as Record<string, any> | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"update_issue\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.fields ||\n typeof args.fields !== \"object\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey and fields object are required\",\n );\n }\n await this.jiraApi.updateIssue(args.issueKey, args.fields);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { message: `Issue ${args.issueKey} updated successfully` },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"get_transitions\": {\n if (!args.issueKey || typeof args.issueKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Issue key is required\",\n );\n }\n const response = await this.jiraApi.getTransitions(args.issueKey);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"transition_issue\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.transitionId ||\n typeof args.transitionId !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey and transitionId are required\",\n );\n }\n await this.jiraApi.transitionIssue(\n args.issueKey,\n args.transitionId,\n args.comment as string | undefined,\n );\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: `Issue ${args.issueKey} transitioned successfully${args.comment ? \" with comment\" : \"\"}`,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"add_attachment\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.fileContent ||\n typeof args.fileContent !== \"string\" ||\n !args.filename ||\n typeof args.filename !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey, fileContent, and filename are required\",\n );\n }\n const fileBuffer = Buffer.from(args.fileContent, \"base64\");\n const result = await this.jiraApi.addAttachment(\n args.issueKey,\n fileBuffer,\n args.filename,\n );\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: `File ${args.filename} attached successfully to issue ${args.issueKey}`,\n attachmentId: result.id,\n filename: result.filename,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"add_comment\": {\n if (\n !args.issueIdOrKey ||\n typeof args.issueIdOrKey !== \"string\" ||\n !args.body ||\n typeof args.body !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueIdOrKey and body are required\",\n );\n }\n const response = await this.jiraApi.addCommentToIssue(\n args.issueIdOrKey,\n args.body,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_create_meta\": {\n if (!args.projectKey || typeof args.projectKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey is required\",\n );\n }\n const meta = await this.jiraApi.getCreateMeta(\n args.projectKey,\n args.issueTypeName as string | undefined,\n args.compact as boolean | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(meta, null, 2) },\n ],\n };\n }\n case \"get_field_options\": {\n if (\n !args.projectKey ||\n typeof args.projectKey !== \"string\" ||\n !args.issueTypeId ||\n typeof args.issueTypeId !== \"string\" ||\n !args.fieldId ||\n typeof args.fieldId !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey, issueTypeId, and fieldId are required\",\n );\n }\n const options = await this.jiraApi.getFieldOptions(\n args.projectKey,\n args.issueTypeId,\n args.fieldId,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(options, null, 2) },\n ],\n };\n }\n case \"get_server_info\": {\n const serverInfo = await this.jiraApi.getServerInfo();\n return {\n content: [\n { type: \"text\", text: JSON.stringify(serverInfo, null, 2) },\n ],\n };\n }\n case \"get_projects\": {\n const projects = await this.jiraApi.getProjects();\n return {\n content: [\n { type: \"text\", text: JSON.stringify(projects, null, 2) },\n ],\n };\n }\n case \"get_users\": {\n if (!args.query || typeof args.query !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"query is required\",\n );\n }\n const users = await this.jiraApi.getUsers(\n args.query,\n args.maxResults as number | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(users, null, 2) },\n ],\n };\n }\n case \"delete_issue\": {\n if (!args.issueKey || typeof args.issueKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey is required\",\n );\n }\n await this.jiraApi.deleteIssue(args.issueKey);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { message: `Issue ${args.issueKey} deleted successfully` },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"get_attachment\": {\n if (!args.attachmentId || typeof args.attachmentId !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"attachmentId is required\",\n );\n }\n const attachment = await this.jiraApi.getAttachment(args.attachmentId);\n\n // Check if it's an image type that Claude can view\n const isImage = attachment.mimeType.startsWith(\"image/\");\n\n if (isImage) {\n return {\n content: [\n {\n type: \"text\",\n text: `Attachment: ${attachment.filename} (${attachment.mimeType})`,\n },\n {\n type: \"image\",\n data: attachment.content,\n mimeType: attachment.mimeType,\n } as any,\n ],\n };\n }\n\n // For non-image files, return base64 as text\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(attachment, null, 2),\n },\n ],\n };\n }\n default:\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n } catch (error) {\n // Keep generic error handling\n if (error instanceof McpError) {\n throw error;\n }\n throw new McpError(\n ErrorCode.InternalError,\n error instanceof Error ? error.message : \"Unknown error occurred\",\n );\n }\n });\n }\n\n async run() {\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n // JIRA MCP server running on stdio\n }\n}\n\n// Only run stdio transport when this file is the main entry point\n// When run via npx, argv[1] is the bin name (jira-mcp), not index.js\nconst isMainModule =\n process.argv[1]?.endsWith(\"index.js\") ||\n process.argv[1]?.endsWith(\"index.ts\") ||\n process.argv[1]?.endsWith(\"jira-mcp\");\nif (isMainModule) {\n const server = new JiraServer();\n server.run().catch(() => {});\n}\n"],"names":["JiraApiService","baseUrl","email","apiToken","authType","authHeader","response","url","message","errorData","errorMessages","field","msg","text","content","source","commentId","mentions","processNode","node","match","key","m","comment","body","attachment","issue","description","cleanedIssue","links","link","linkedIssue","relationship","subtask","a","init","searchString","params","data","epicKey","commentsData","comments","commentMentions","issueId","issueData","error","epicData","projectKey","issueType","summary","fields","payload","issueTypeName","compact","issueTypes","it","f","issueTypeId","fieldId","issueKey","transitionId","file","filename","formData","headers","issueIdOrKey","project","query","maxResults","user","attachmentId","metadata","arrayBuffer","JiraServerApiService","path","serverUrl","matches","getEnvConfig","JIRA_API_TOKEN","JIRA_BASE_URL","JIRA_USER_EMAIL","JIRA_TYPE","JIRA_AUTH_TYPE","JIRA_PROMPTS","JiraServer","Server","ListPromptsRequestSchema","name","GetPromptRequestSchema","request","prompt","McpError","ErrorCode","ListToolsRequestSchema","CallToolRequestSchema","args","fileBuffer","result","meta","options","serverInfo","projects","users","transport","StdioServerTransport","isMainModule"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/services/jira-api.ts","../src/services/jira-server-api.ts","../src/index.ts"],"sourcesContent":["import {\n AddCommentResponse,\n AdfDoc,\n CleanAttachment,\n CleanComment,\n CleanJiraIssue,\n JiraCommentResponse,\n SearchIssuesResponse,\n} from \"../types/jira.js\";\n\nexport class JiraApiService {\n protected baseUrl: string;\n protected headers: Headers;\n\n constructor(baseUrl: string, email: string, apiToken: string, authType: 'basic' | 'bearer' = 'basic') {\n this.baseUrl = baseUrl;\n \n let authHeader: string;\n if (authType === 'bearer') {\n // For Jira Data Center Personal Access Tokens (PATs)\n authHeader = `Bearer ${apiToken}`;\n } else {\n // For Basic authentication with username/password or API token\n const auth = Buffer.from(`${email}:${apiToken}`).toString(\"base64\");\n authHeader = `Basic ${auth}`;\n }\n \n this.headers = new Headers({\n Authorization: authHeader,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n });\n }\n\n protected async handleFetchError(\n response: Response,\n url?: string\n ): Promise<never> {\n if (!response.ok) {\n let message = response.statusText;\n let errorData: any = {};\n try {\n errorData = await response.json();\n\n // Try different error formats that Jira uses\n if (\n Array.isArray(errorData.errorMessages) &&\n errorData.errorMessages.length > 0\n ) {\n // Format: { errorMessages: [\"msg1\", \"msg2\"] }\n message = errorData.errorMessages.join(\"; \");\n } else if (errorData.message) {\n // Format: { message: \"error message\" }\n message = errorData.message;\n } else if (errorData.errorMessage) {\n // Format: { errorMessage: \"error message\" }\n message = errorData.errorMessage;\n } else if (errorData.errors && typeof errorData.errors === \"object\") {\n // Format: { errors: { fieldName: \"error for field\", anotherField: \"another error\" } }\n const errorMessages = Object.entries(errorData.errors)\n .map(([field, msg]) => `${field}: ${msg}`)\n .join(\"; \");\n if (errorMessages) {\n message = errorMessages;\n }\n }\n\n // If we still only have statusText but have error data, stringify it\n if (message === response.statusText && Object.keys(errorData).length > 0) {\n message = JSON.stringify(errorData);\n }\n } catch (e) {\n // Could not parse as JSON, try to get text\n try {\n const text = await response.text();\n if (text) {\n message = text.substring(0, 500); // Limit length\n }\n } catch {\n // Ignore\n }\n }\n\n throw new Error(\n `JIRA API Error: ${message} (Status: ${response.status})`\n );\n }\n\n throw new Error(\"Unknown error occurred during fetch operation.\");\n }\n\n /**\n * Extracts issue mentions from Atlassian document content\n * Looks for nodes that were auto-converted to issue links\n */\n protected extractIssueMentions(\n content: any[],\n source: \"description\" | \"comment\",\n commentId?: string\n ): CleanJiraIssue[\"relatedIssues\"] {\n const mentions: NonNullable<CleanJiraIssue[\"relatedIssues\"]> = [];\n\n const processNode = (node: any) => {\n if (node.type === \"inlineCard\" && node.attrs?.url) {\n const match = node.attrs.url.match(/\\/browse\\/([A-Z]+-\\d+)/);\n if (match) {\n mentions.push({\n key: match[1],\n type: \"mention\",\n source,\n commentId,\n });\n }\n }\n\n if (node.type === \"text\" && node.text) {\n const matches = node.text.match(/[A-Z]+-\\d+/g) || [];\n matches.forEach((key: string) => {\n mentions.push({\n key,\n type: \"mention\",\n source,\n commentId,\n });\n });\n }\n\n if (node.content) {\n node.content.forEach(processNode);\n }\n };\n\n content.forEach(processNode);\n return [...new Map(mentions.map((m) => [m.key, m])).values()];\n }\n\n protected cleanComment(comment: {\n id: string;\n body?: {\n content?: any[];\n };\n author?: {\n displayName?: string;\n };\n created: string;\n updated: string;\n }): CleanComment {\n const body = comment.body?.content\n ? this.extractTextContent(comment.body.content)\n : \"\";\n const mentions = comment.body?.content\n ? this.extractIssueMentions(comment.body.content, \"comment\", comment.id)\n : [];\n\n return {\n id: comment.id,\n body,\n author: comment.author?.displayName,\n created: comment.created,\n updated: comment.updated,\n mentions: mentions,\n };\n }\n\n protected cleanAttachment(attachment: any): CleanAttachment {\n return {\n id: attachment.id,\n filename: attachment.filename,\n mimeType: attachment.mimeType,\n size: attachment.size,\n created: attachment.created,\n author: attachment.author?.displayName,\n content: attachment.content,\n thumbnail: attachment.thumbnail,\n };\n }\n\n /**\n * Recursively extracts text content from Atlassian Document Format nodes\n */\n protected extractTextContent(content: any[]): string {\n if (!Array.isArray(content)) return \"\";\n\n return content\n .map((node) => {\n if (node.type === \"text\") {\n return node.text || \"\";\n }\n if (node.content) {\n return this.extractTextContent(node.content);\n }\n return \"\";\n })\n .join(\"\");\n }\n\n protected cleanIssue(issue: any): CleanJiraIssue {\n let description = \"\";\n if (issue.fields?.description) {\n if (typeof issue.fields.description === \"string\") {\n // Jira Server: plain text\n description = issue.fields.description;\n } else if (issue.fields.description.content) {\n // Jira Cloud: ADF format\n description = this.extractTextContent(issue.fields.description.content);\n }\n }\n\n const cleanedIssue: CleanJiraIssue = {\n id: issue.id,\n key: issue.key,\n summary: issue.fields?.summary,\n status: issue.fields?.status?.name,\n created: issue.fields?.created,\n updated: issue.fields?.updated,\n description,\n relatedIssues: [],\n };\n\n if (issue.fields?.description?.content) {\n const mentions = this.extractIssueMentions(\n issue.fields.description.content,\n \"description\"\n );\n if (mentions.length > 0) {\n cleanedIssue.relatedIssues = mentions;\n }\n }\n\n if (issue.fields?.issuelinks?.length > 0) {\n const links = issue.fields.issuelinks.map((link: any) => {\n const linkedIssue = link.inwardIssue || link.outwardIssue;\n const relationship = link.type.inward || link.type.outward;\n return {\n key: linkedIssue.key,\n summary: linkedIssue.fields?.summary,\n type: \"link\" as const,\n relationship,\n source: \"description\" as const,\n };\n });\n\n cleanedIssue.relatedIssues = [\n ...(cleanedIssue.relatedIssues || []),\n ...links,\n ];\n }\n\n if (issue.fields?.parent) {\n cleanedIssue.parent = {\n id: issue.fields.parent.id,\n key: issue.fields.parent.key,\n summary: issue.fields.parent.fields?.summary,\n };\n }\n\n if (issue.fields?.customfield_10014) {\n cleanedIssue.epicLink = {\n id: issue.fields.customfield_10014,\n key: issue.fields.customfield_10014,\n summary: undefined,\n };\n }\n\n if (issue.fields?.subtasks?.length > 0) {\n cleanedIssue.children = issue.fields.subtasks.map((subtask: any) => ({\n id: subtask.id,\n key: subtask.key,\n summary: subtask.fields?.summary,\n }));\n }\n\n if (issue.fields?.attachment?.length > 0) {\n cleanedIssue.attachments = issue.fields.attachment.map((a: any) =>\n this.cleanAttachment(a)\n );\n }\n\n return cleanedIssue;\n }\n\n protected async fetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const response = await fetch(this.baseUrl + url, {\n ...init,\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response, url);\n }\n\n // Handle 204 No Content - return undefined for void operations (transitions, updates)\n if (response.status === 204 || response.headers.get('content-length') === '0') {\n return undefined as T;\n }\n\n return response.json();\n }\n\n async searchIssues(searchString: string): Promise<SearchIssuesResponse> {\n const params = new URLSearchParams({\n jql: searchString,\n maxResults: \"50\",\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n const data = await this.fetchJson<any>(`/rest/api/3/search?${params}`);\n\n return {\n total: data.total,\n issues: data.issues.map((issue: any) => this.cleanIssue(issue)),\n };\n }\n\n async getEpicChildren(epicKey: string): Promise<CleanJiraIssue[]> {\n const params = new URLSearchParams({\n jql: `\"Epic Link\" = ${epicKey}`,\n maxResults: \"100\",\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n const data = await this.fetchJson<any>(`/rest/api/3/search?${params}`);\n\n const issuesWithComments = await Promise.all(\n data.issues.map(async (issue: any) => {\n const commentsData = await this.fetchJson<any>(\n `/rest/api/3/issue/${issue.key}/comment`\n );\n const cleanedIssue = this.cleanIssue(issue);\n const comments = commentsData.comments.map((comment: any) =>\n this.cleanComment(comment)\n );\n\n const commentMentions = comments.flatMap(\n (comment: CleanComment) => comment.mentions\n );\n cleanedIssue.relatedIssues = [\n ...cleanedIssue.relatedIssues,\n ...commentMentions,\n ];\n\n cleanedIssue.comments = comments;\n return cleanedIssue;\n })\n );\n\n return issuesWithComments;\n }\n\n async getIssueWithComments(issueId: string): Promise<CleanJiraIssue> {\n const params = new URLSearchParams({\n fields: [\n \"id\",\n \"key\",\n \"summary\",\n \"description\",\n \"status\",\n \"created\",\n \"updated\",\n \"parent\",\n \"subtasks\",\n \"customfield_10014\",\n \"issuelinks\",\n \"attachment\",\n ].join(\",\"),\n expand: \"names,renderedFields\",\n });\n\n let issueData, commentsData;\n try {\n [issueData, commentsData] = await Promise.all([\n this.fetchJson<any>(`/rest/api/3/issue/${issueId}?${params}`),\n this.fetchJson<any>(`/rest/api/3/issue/${issueId}/comment`),\n ]);\n } catch (error: any) {\n if (error instanceof Error && error.message.includes(\"(Status: 404)\")) {\n throw new Error(`Issue not found: ${issueId}`);\n }\n\n throw error;\n }\n\n const issue = this.cleanIssue(issueData);\n const comments = commentsData.comments.map((comment: any) =>\n this.cleanComment(comment)\n );\n\n const commentMentions = comments.flatMap(\n (comment: CleanComment) => comment.mentions\n );\n issue.relatedIssues = [...issue.relatedIssues, ...commentMentions];\n\n issue.comments = comments;\n\n if (issue.epicLink) {\n try {\n const epicData = await this.fetchJson<any>(\n `/rest/api/3/issue/${issue.epicLink.key}?fields=summary`\n );\n issue.epicLink.summary = epicData.fields?.summary;\n } catch (error) {\n console.error(\"Failed to fetch epic details:\", error);\n }\n }\n\n return issue;\n }\n\n async createIssue(\n projectKey: string,\n issueType: string,\n summary: string,\n description?: string,\n fields?: Record<string, any>\n ): Promise<{ id: string; key: string }> {\n const payload = {\n fields: {\n project: {\n key: projectKey,\n },\n summary,\n issuetype: {\n name: issueType,\n },\n ...(description && { description }),\n ...fields,\n },\n };\n\n return this.fetchJson<{ id: string; key: string }>(\"/rest/api/3/issue\", {\n method: \"POST\",\n body: JSON.stringify(payload),\n });\n }\n\n async getCreateMeta(\n projectKey: string,\n issueTypeName?: string,\n compact?: boolean\n ): Promise<any> {\n // Get available issue types for the project\n const issueTypesData = await this.fetchJson<{ issueTypes: Array<{ id: string; name: string; description?: string; subtask: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes`\n );\n\n let issueTypes = issueTypesData.issueTypes || [];\n\n // Filter by issue type name if provided\n if (issueTypeName) {\n issueTypes = issueTypes.filter(\n (it) => it.name.toLowerCase() === issueTypeName.toLowerCase()\n );\n }\n\n // Get fields for each issue type\n const result = {\n projectKey,\n issueTypes: await Promise.all(\n issueTypes.map(async (issueType) => {\n try {\n const fieldsData = await this.fetchJson<{ fields: Array<{ fieldId: string; name: string; required: boolean; schema?: any; allowedValues?: any[]; hasDefaultValue?: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueType.id}`\n );\n\n let fields = fieldsData.fields || [];\n\n // In compact mode, replace allowedValues with count\n if (compact) {\n fields = fields.map((f) => ({\n fieldId: f.fieldId,\n name: f.name,\n required: f.required,\n schema: f.schema,\n hasDefaultValue: f.hasDefaultValue,\n allowedValuesCount: f.allowedValues?.length ?? 0,\n }));\n }\n\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields,\n };\n } catch (error) {\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields: [],\n error: error instanceof Error ? error.message : \"Failed to fetch fields\",\n };\n }\n })\n ),\n };\n\n return result;\n }\n\n async getFieldOptions(\n projectKey: string,\n issueTypeId: string,\n fieldId: string\n ): Promise<any[]> {\n const fieldsData = await this.fetchJson<{ fields: Array<{ fieldId: string; allowedValues?: any[] }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueTypeId}`\n );\n\n const field = (fieldsData.fields || []).find((f) => f.fieldId === fieldId);\n return field?.allowedValues ?? [];\n }\n\n async updateIssue(\n issueKey: string,\n fields: Record<string, any>\n ): Promise<void> {\n await this.fetchJson(`/rest/api/3/issue/${issueKey}`, {\n method: \"PUT\",\n body: JSON.stringify({ fields }),\n });\n }\n\n async getTransitions(\n issueKey: string\n ): Promise<Array<{ id: string; name: string; to: { name: string } }>> {\n const data = await this.fetchJson<any>(\n `/rest/api/3/issue/${issueKey}/transitions`\n );\n return data.transitions;\n }\n\n async transitionIssue(\n issueKey: string,\n transitionId: string,\n comment?: string\n ): Promise<void> {\n const payload: any = {\n transition: { id: transitionId },\n };\n\n if (comment) {\n payload.update = {\n comment: [\n {\n add: {\n body: {\n type: \"doc\",\n version: 1,\n content: [\n {\n type: \"paragraph\",\n content: [\n {\n type: \"text\",\n text: comment,\n },\n ],\n },\n ],\n },\n },\n },\n ],\n };\n }\n\n await this.fetchJson(`/rest/api/3/issue/${issueKey}/transitions`, {\n method: \"POST\",\n body: JSON.stringify(payload),\n });\n }\n\n async addAttachment(\n issueKey: string,\n file: Buffer,\n filename: string\n ): Promise<{ id: string; filename: string }> {\n const formData = new FormData();\n formData.append(\"file\", new Blob([new Uint8Array(file)]), filename);\n\n const headers = new Headers(this.headers);\n headers.delete(\"Content-Type\");\n headers.set(\"X-Atlassian-Token\", \"no-check\");\n\n const response = await fetch(\n `${this.baseUrl}/rest/api/3/issue/${issueKey}/attachments`,\n {\n method: \"POST\",\n headers,\n body: formData,\n }\n );\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n\n const data = await response.json();\n\n const attachment = data[0];\n return {\n id: attachment.id,\n filename: attachment.filename,\n };\n }\n\n /**\n * Converts plain text to a basic Atlassian Document Format (ADF) structure.\n */\n private createAdfFromBody(text: string): AdfDoc {\n return {\n version: 1,\n type: \"doc\",\n content: [\n {\n type: \"paragraph\",\n content: [\n {\n type: \"text\",\n text: text,\n },\n ],\n },\n ],\n };\n }\n\n /**\n * Adds a comment to a JIRA issue.\n */\n async addCommentToIssue(\n issueIdOrKey: string,\n body: string\n ): Promise<AddCommentResponse> {\n const adfBody = this.createAdfFromBody(body);\n\n const payload = {\n body: adfBody,\n };\n\n const response = await this.fetchJson<JiraCommentResponse>(\n `/rest/api/3/issue/${issueIdOrKey}/comment`,\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n }\n );\n\n return {\n id: response.id,\n author: response.author.displayName,\n created: response.created,\n updated: response.updated,\n body: this.extractTextContent(response.body.content),\n };\n }\n\n async getServerInfo(): Promise<{\n version: string;\n versionNumbers: number[];\n deploymentType: string;\n buildNumber: number;\n serverTitle: string;\n }> {\n return this.fetchJson(`/rest/api/3/serverInfo`);\n }\n\n async getProjects(): Promise<Array<{\n id: string;\n key: string;\n name: string;\n projectTypeKey: string;\n lead?: { displayName: string; accountId?: string };\n }>> {\n const data = await this.fetchJson<any[]>(`/rest/api/3/project`);\n return data.map((project) => ({\n id: project.id,\n key: project.key,\n name: project.name,\n projectTypeKey: project.projectTypeKey,\n lead: project.lead ? {\n displayName: project.lead.displayName,\n accountId: project.lead.accountId,\n } : undefined,\n }));\n }\n\n async getUsers(query: string, maxResults: number = 50): Promise<Array<{\n accountId: string;\n displayName: string;\n emailAddress?: string;\n active: boolean;\n }>> {\n const params = new URLSearchParams({\n query,\n maxResults: maxResults.toString(),\n });\n const data = await this.fetchJson<any[]>(`/rest/api/3/user/search?${params}`);\n return data.map((user) => ({\n accountId: user.accountId,\n displayName: user.displayName,\n emailAddress: user.emailAddress,\n active: user.active,\n }));\n }\n\n async deleteIssue(issueKey: string): Promise<void> {\n const response = await fetch(`${this.baseUrl}/rest/api/3/issue/${issueKey}`, {\n method: \"DELETE\",\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n }\n\n async getAttachment(attachmentId: string): Promise<{\n content: string; // base64 encoded\n filename: string;\n mimeType: string;\n }> {\n // First, get attachment metadata to get the content URL\n const metadata = await this.fetchJson<{\n id: string;\n filename: string;\n mimeType: string;\n content: string;\n }>(`/rest/api/3/attachment/${attachmentId}`);\n\n // Fetch the actual content from the content URL\n const response = await fetch(metadata.content, {\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const base64 = Buffer.from(arrayBuffer).toString(\"base64\");\n\n return {\n content: base64,\n filename: metadata.filename,\n mimeType: metadata.mimeType,\n };\n }\n}\n","// JiraServerApiService: Jira Server (Data Center) implementation\n// This class should override methods as needed for Jira Server differences\nimport { JiraApiService } from \"./jira-api.js\";\nimport type { CleanComment, CleanJiraIssue } from \"../types/jira.js\";\n\nexport class JiraServerApiService extends JiraApiService {\n constructor(baseUrl: string, email: string, apiToken: string, authType: 'basic' | 'bearer' = 'basic') {\n // For Jira Server/Data Center:\n // - Basic Auth: username/password or API token (traditional method)\n // - Bearer Auth: Personal Access Tokens (PATs) available in Data Center 8.14.0+\n super(baseUrl, email, apiToken, authType);\n }\n\n // Example: Override fetchJson to use /rest/api/2/ instead of /rest/api/3/\n protected overrideApiPath(path: string): string {\n // Replace /rest/api/3/ with /rest/api/2/ for Jira Server\n return path.replace(\"/rest/api/3/\", \"/rest/api/2/\");\n }\n\n // Override fetchJson to use the correct API path\n protected async fetchJson<T>(url: string, init?: RequestInit): Promise<T> {\n const serverUrl = this.overrideApiPath(url);\n return super.fetchJson<T>(serverUrl, init);\n }\n\n // Override getCreateMeta to use API v2 endpoints for Jira Server 9.0+\n async getCreateMeta(\n projectKey: string,\n issueTypeName?: string,\n compact?: boolean\n ): Promise<any> {\n // For Jira Server 9.0+, use the new paginated endpoints (same structure as Cloud but API v2)\n const issueTypesData = await this.fetchJson<{ values: Array<{ id: string; name: string; description?: string; subtask: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes`\n );\n\n let issueTypes = issueTypesData.values || [];\n\n // Filter by issue type name if provided\n if (issueTypeName) {\n issueTypes = issueTypes.filter(\n (it) => it.name.toLowerCase() === issueTypeName.toLowerCase()\n );\n }\n\n // Get fields for each issue type\n const result = {\n projectKey,\n issueTypes: await Promise.all(\n issueTypes.map(async (issueType) => {\n try {\n const fieldsData = await this.fetchJson<{ values: Array<{ fieldId: string; name: string; required: boolean; schema?: any; allowedValues?: any[]; hasDefaultValue?: boolean }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueType.id}`\n );\n\n let fields = fieldsData.values || [];\n\n // In compact mode, replace allowedValues with count\n if (compact) {\n fields = fields.map((f) => ({\n fieldId: f.fieldId,\n name: f.name,\n required: f.required,\n schema: f.schema,\n hasDefaultValue: f.hasDefaultValue,\n allowedValuesCount: f.allowedValues?.length ?? 0,\n }));\n }\n\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields,\n };\n } catch (error) {\n return {\n id: issueType.id,\n name: issueType.name,\n description: issueType.description,\n subtask: issueType.subtask,\n fields: [],\n error: error instanceof Error ? error.message : \"Failed to fetch fields\",\n };\n }\n })\n ),\n };\n\n return result;\n }\n\n // Override getFieldOptions for Jira Server (uses 'values' instead of 'fields')\n async getFieldOptions(\n projectKey: string,\n issueTypeId: string,\n fieldId: string\n ): Promise<any[]> {\n const fieldsData = await this.fetchJson<{ values: Array<{ fieldId: string; allowedValues?: any[] }> }>(\n `/rest/api/3/issue/createmeta/${projectKey}/issuetypes/${issueTypeId}`\n );\n\n const field = (fieldsData.values || []).find((f) => f.fieldId === fieldId);\n return field?.allowedValues ?? [];\n }\n\n // Override getUsers for Jira Server (uses 'username' parameter instead of 'query')\n async getUsers(query: string, maxResults: number = 50): Promise<Array<{\n accountId: string;\n displayName: string;\n emailAddress?: string;\n active: boolean;\n }>> {\n const params = new URLSearchParams({\n username: query,\n maxResults: maxResults.toString(),\n });\n const data = await this.fetchJson<any[]>(`/rest/api/3/user/search?${params}`);\n return data.map((user) => ({\n // Jira Server uses 'name' or 'key' instead of 'accountId'\n accountId: user.key || user.name,\n displayName: user.displayName,\n emailAddress: user.emailAddress,\n active: user.active,\n }));\n }\n\n // Override addCommentToIssue for Jira Server (uses plain text instead of ADF)\n async addCommentToIssue(\n issueIdOrKey: string,\n body: string\n ): Promise<{\n id: string;\n author: string;\n created: string;\n updated: string;\n body: string;\n }> {\n // Jira Server API v2 expects plain text body, not ADF\n const payload = {\n body: body,\n };\n\n const response = await this.fetchJson<{\n id: string;\n author: { displayName: string };\n created: string;\n updated: string;\n body: string;\n }>(\n `/rest/api/3/issue/${issueIdOrKey}/comment`,\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n }\n );\n\n return {\n id: response.id,\n author: response.author.displayName,\n created: response.created,\n updated: response.updated,\n body: response.body,\n };\n }\n\n // Override deleteIssue for Jira Server (uses API v2)\n async deleteIssue(issueKey: string): Promise<void> {\n const response = await fetch(`${this.baseUrl}/rest/api/2/issue/${issueKey}`, {\n method: \"DELETE\",\n headers: this.headers,\n });\n\n if (!response.ok) {\n await this.handleFetchError(response);\n }\n }\n\n // Override cleanComment for Jira Server (body is plain text, not ADF)\n protected cleanComment(comment: {\n id: string;\n body?: string | { content?: any[] };\n author?: {\n displayName?: string;\n };\n created: string;\n updated: string;\n }): CleanComment {\n // Debug: log raw comment to understand API response format\n console.error(\"[DEBUG cleanComment] Raw comment:\", JSON.stringify(comment, null, 2));\n\n // Jira Server API v2 returns body as plain text string\n // Jira Cloud API v3 returns body as ADF object with content array\n let body: string;\n let mentions: CleanJiraIssue[\"relatedIssues\"] = [];\n\n if (typeof comment.body === \"string\") {\n // Jira Server: body is plain text\n body = comment.body;\n // Extract issue mentions from plain text (e.g., PROJECT-123)\n mentions = this.extractIssueMentionsFromText(body, \"comment\", comment.id);\n } else if (comment.body?.content) {\n // Jira Cloud: body is ADF object\n body = this.extractTextContent(comment.body.content);\n mentions = this.extractIssueMentions(comment.body.content, \"comment\", comment.id);\n } else {\n body = \"\";\n }\n\n return {\n id: comment.id,\n body,\n author: comment.author?.displayName,\n created: comment.created,\n updated: comment.updated,\n mentions,\n };\n }\n\n // Extract issue mentions from plain text (for Jira Server)\n protected extractIssueMentionsFromText(\n text: string,\n source: \"description\" | \"comment\",\n commentId?: string\n ): CleanJiraIssue[\"relatedIssues\"] {\n if (!text) return [];\n\n const matches = text.match(/[A-Z]+-\\d+/g) || [];\n const uniqueKeys = [...new Set(matches)];\n\n return uniqueKeys.map((key) => ({\n key,\n type: \"mention\" as const,\n source,\n commentId,\n }));\n }\n}\n","#!/usr/bin/env node\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ErrorCode,\n ListToolsRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { JiraApiService } from \"./services/jira-api.js\";\nimport { JiraServerApiService } from \"./services/jira-server-api.js\";\n\nfunction getEnvConfig() {\n const JIRA_API_TOKEN = process.env.JIRA_API_TOKEN ?? \"\";\n const JIRA_BASE_URL = process.env.JIRA_BASE_URL ?? \"\";\n const JIRA_USER_EMAIL = process.env.JIRA_USER_EMAIL ?? \"\";\n const JIRA_TYPE = (process.env.JIRA_TYPE === \"server\" ? \"server\" : \"cloud\") as\n | \"cloud\"\n | \"server\";\n const JIRA_AUTH_TYPE = (process.env.JIRA_AUTH_TYPE === \"bearer\" ? \"bearer\" : \"basic\") as\n | \"basic\"\n | \"bearer\";\n\n if (!JIRA_API_TOKEN || !JIRA_BASE_URL || !JIRA_USER_EMAIL) {\n throw new Error(\n \"JIRA_API_TOKEN, JIRA_USER_EMAIL and JIRA_BASE_URL environment variables are required\",\n );\n }\n\n return { JIRA_API_TOKEN, JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_TYPE, JIRA_AUTH_TYPE };\n}\n\n// ============================================================================\n// PROMPTS - Инструкции и регламенты для агентов\n// ============================================================================\n\nconst JIRA_PROMPTS: Record<string, { description: string; content: string }> = {\n jira_guidelines: {\n description: \"Общие правила и регламенты работы с Jira в компании\",\n content: `# Регламент работы с Jira\n\n## Общие принципы\n- Все изменения статусов должны отражать реальное состояние работы\n- Комментарии пишутся на русском языке\n- При любых изменениях, затрагивающих других участников, оставляй комментарий\n\n## Статусы и переходы\n\n### Workflow задачи:\n1. **Бэклог** — задача запланирована, но работа не начата\n2. **Очередь** — задача в очереди на выполнение\n3. **В работе** — код в процессе написания\n4. **Ревью** — код готов к проверке, создан PR/MR\n5. **Local test** — задача на локальном тестировании\n6. **Dev** — код в ветке dev\n7. **Stage (не проверено)** — код в ветке stage, тестирование не проведено\n8. **Релиз-кандидат** — проверено на stage, готово к релизу\n9. **Тест на проде** — код на проде, ожидает проверки\n10. **Готово на проде** — задача завершена и проверена\n\n### Особые статусы:\n- **Заблокирована** — работа приостановлена (указать причину в комментарии)\n- **Отложено** — задача отложена на неопределённый срок\n- **Отмена** — задача отменена (ОБЯЗАТЕЛЬНО с комментарием о причине!)\n\n## Создание задач\n- Summary должен быть кратким и информативным (не более 100 символов)\n- Description должен содержать достаточно информации для понимания задачи\n- Обязательно указывай компонент (component) для правильной маршрутизации\n- Для багов: шаги воспроизведения, ожидаемый и фактический результат\n\n## Отмена задач\n- ЗАПРЕЩЕНО отменять задачу без указания причины в комментарии\n- Причина должна быть информативной: \"дубликат IM3-1234\", \"неактуально после релиза X\", и т.д.\n\n## Удаление задач\n- Удаление задач запрещено политикой безопасности\n- Вместо удаления используй статус \"Отмена\" с комментарием\n\n## Комментарии\n- Используй комментарии для важной информации, которая должна остаться в истории\n- При блокировке — указывай причину и ссылку на блокирующую задачу\n- При передаче задачи — описывай текущее состояние и что осталось сделать`,\n },\n\n create_issue_workflow: {\n description: \"Пошаговый процесс создания задачи в Jira\",\n content: `# Создание задачи в Jira\n\n## Перед созданием ОБЯЗАТЕЛЬНО уточни у пользователя:\n\n### Основная информация:\n1. **Проект** — в каком проекте создать (IM3, SD, FT, ETPP и т.д.)\n2. **Тип задачи** — Баг, Story, Task, Sub-task\n3. **Краткое описание** (summary) — что нужно сделать, до 100 символов\n4. **Подробное описание** (description) — детали задачи\n\n### Для багов дополнительно запроси:\n- Шаги воспроизведения (пронумерованный список)\n- Ожидаемый результат\n- Фактический результат\n- Окружение (браузер, ОС, URL) — если релевантно\n- Скриншоты или логи — если есть\n\n### Для Story/Task уточни:\n- Критерии приёмки (acceptance criteria)\n- Связанные задачи (если есть)\n\n## Порядок действий:\n\n1. **Получи схему полей:**\n \\`\\`\\`\n get_create_meta(projectKey, issueTypeName, compact=true)\n \\`\\`\\`\n\n2. **Для обязательных полей с вариантами получи опции:**\n \\`\\`\\`\n get_field_options(projectKey, issueTypeId, fieldId)\n \\`\\`\\`\n\n3. **Покажи пользователю** итоговые данные перед созданием\n\n4. **Создай задачу:**\n \\`\\`\\`\n create_issue(projectKey, issueType, summary, description, fields)\n \\`\\`\\`\n\n5. **Верни пользователю** ключ и ссылку на созданную задачу\n\n## Пример описания бага:\n\n\\`\\`\\`\nШаги воспроизведения:\n1. Открыть страницу /checkout\n2. Добавить товар в корзину\n3. Нажать \"Оформить заказ\"\n\nОжидаемый результат:\nОткрывается форма оформления заказа\n\nФактический результат:\nСтраница показывает ошибку 500\n\nОкружение:\n- URL: https://example.com/checkout\n- Браузер: Chrome 120\n- ОС: Windows 11\n\\`\\`\\``,\n },\n\n cancel_issue_workflow: {\n description: \"Процесс отмены задачи (требует указания причины)\",\n content: `# Отмена задачи в Jira\n\n## ⚠️ ВАЖНО: Задачу НЕЛЬЗЯ отменять без причины!\n\n## Порядок действий:\n\n### 1. Спроси причину отмены\nПрежде чем отменять задачу, ОБЯЗАТЕЛЬНО спроси у пользователя:\n- \"Почему задача отменяется?\"\n- \"Укажите причину отмены для комментария\"\n\n### 2. Примеры корректных причин:\n- \"Дубликат задачи IM3-1234\"\n- \"Неактуально после релиза версии 2.5\"\n- \"Функционал реализован в рамках IM3-5678\"\n- \"Отменено по решению Product Owner (имя)\"\n- \"Требования изменились, создана новая задача IM3-9999\"\n\n### 3. Добавь комментарий с причиной:\n\\`\\`\\`\nadd_comment(issueKey, \"Причина отмены: <причина от пользователя>\")\n\\`\\`\\`\n\n### 4. Получи ID перехода \"Отмена\":\n\\`\\`\\`\nget_transitions(issueKey)\n// Найди переход с name=\"Отмена\"\n\\`\\`\\`\n\n### 5. Выполни переход:\n\\`\\`\\`\ntransition_issue(issueKey, transitionId)\n\\`\\`\\`\n\n## Запрещено:\n- ❌ Отменять задачу без комментария с причиной\n- ❌ Использовать причины типа \"не нужно\", \"отмена\" без пояснения\n\n## Если пользователь не хочет указывать причину:\nОбъясни, что это требование регламента компании, и причина важна для:\n- Истории проекта\n- Понимания, почему задача не была выполнена\n- Аудита и отчётности`,\n },\n\n transition_issue_workflow: {\n description: \"Правила смены статусов задач\",\n content: `# Смена статуса задачи в Jira\n\n## Общие правила:\n- Статус должен отражать реальное состояние работы\n- Не пропускай промежуточные статусы без веской причины\n- При переходе в финальные статусы убедись, что работа действительно завершена\n\n## Особые случаи:\n\n### Переход в \"Отмена\":\n⚠️ ОБЯЗАТЕЛЬНО сначала добавь комментарий с причиной отмены!\nСм. prompt \"cancel_issue_workflow\" для подробностей.\n\n### Переход в \"Заблокирована\":\n- Укажи в комментарии причину блокировки\n- Добавь ссылку на блокирующую задачу (если есть)\n- Пример: \"Заблокировано: ждём завершения IM3-1234 (интеграция с API)\"\n\n### Переход в \"Ревью\":\n- Должен существовать Pull Request / Merge Request\n- Желательно добавить ссылку на PR в комментарий\n\n### Переход в \"Dev\" / \"Stage\":\n- Код должен быть смержен в соответствующую ветку\n- Задача задеплоена на окружение\n\n### Переход в \"Тест на проде\":\n- Код задеплоен на production\n- Задача готова к финальной проверке\n\n### Переход в \"Готово на проде\":\n- Задача проверена на production\n- Все acceptance criteria выполнены\n- Нет открытых sub-tasks\n\n## Получение доступных переходов:\n\\`\\`\\`\nget_transitions(issueKey)\n// Вернёт список доступных переходов с их ID\n\\`\\`\\`\n\n## Выполнение перехода:\n\\`\\`\\`\ntransition_issue(issueKey, transitionId, comment?)\n// comment — опциональный комментарий к переходу\n\\`\\`\\``,\n },\n\n update_issue_workflow: {\n description: \"Правила обновления задач\",\n content: `# Обновление задачи в Jira\n\n## Что можно обновлять:\n- summary — краткое описание\n- description — подробное описание\n- assignee — исполнитель\n- priority — приоритет\n- labels — метки\n- components — компоненты\n- customfield_* — кастомные поля\n\n## Правила:\n\n### При изменении исполнителя (assignee):\n- Если задача в работе — согласуй с текущим исполнителем\n- Добавь комментарий о причине переназначения\n\n### При изменении приоритета:\n- Повышение приоритета — укажи причину в комментарии\n- Понижение приоритета — согласуй с автором задачи\n\n### При изменении описания:\n- Не удаляй важную информацию\n- Если меняешь суть задачи — лучше создай новую\n\n## Пример обновления:\n\\`\\`\\`\nupdate_issue(issueKey, {\n summary: \"Новый заголовок\",\n priority: { name: \"High\" },\n assignee: { name: \"username\" }\n})\n\\`\\`\\`\n\n## Для поиска пользователей:\n\\`\\`\\`\nget_users(query) // поиск по имени или email\n\\`\\`\\``,\n },\n};\n\nexport class JiraServer {\n public server: Server;\n private jiraApi: JiraApiService;\n\n constructor() {\n this.server = new Server(\n {\n name: \"jira-mcp\",\n version: \"0.3.0\",\n },\n {\n capabilities: {\n tools: {},\n prompts: {},\n },\n },\n );\n\n const { JIRA_API_TOKEN, JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_TYPE, JIRA_AUTH_TYPE } = getEnvConfig();\n\n if (JIRA_TYPE === \"server\") {\n this.jiraApi = new JiraServerApiService(\n JIRA_BASE_URL,\n JIRA_USER_EMAIL,\n JIRA_API_TOKEN,\n JIRA_AUTH_TYPE,\n );\n } else {\n this.jiraApi = new JiraApiService(\n JIRA_BASE_URL,\n JIRA_USER_EMAIL,\n JIRA_API_TOKEN,\n JIRA_AUTH_TYPE,\n );\n }\n\n this.setupToolHandlers();\n\n this.server.onerror = (error) => {};\n process.on(\"SIGINT\", async () => {\n await this.server.close();\n process.exit(0);\n });\n }\n\n private setupToolHandlers() {\n // ========================================================================\n // PROMPTS HANDLERS\n // ========================================================================\n\n this.server.setRequestHandler(ListPromptsRequestSchema, async () => ({\n prompts: Object.entries(JIRA_PROMPTS).map(([name, { description }]) => ({\n name,\n description,\n })),\n }));\n\n this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const { name } = request.params;\n const prompt = JIRA_PROMPTS[name];\n\n if (!prompt) {\n throw new McpError(ErrorCode.InvalidParams, `Unknown prompt: ${name}`);\n }\n\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: prompt.content,\n },\n },\n ],\n };\n });\n\n // ========================================================================\n // TOOLS HANDLERS\n // ========================================================================\n\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: \"search_issues\",\n description: \"Search JIRA issues using JQL\",\n inputSchema: {\n type: \"object\",\n properties: {\n searchString: {\n type: \"string\",\n description: \"JQL search string\",\n },\n },\n required: [\"searchString\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_epic_children\",\n description:\n \"Get all child issues in an epic including their comments\",\n inputSchema: {\n type: \"object\",\n properties: {\n epicKey: {\n type: \"string\",\n description: \"The key of the epic issue\",\n },\n },\n required: [\"epicKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_issue\",\n description:\n \"Get detailed information about a specific JIRA issue including comments\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueId: {\n type: \"string\",\n description: \"The ID or key of the JIRA issue\",\n },\n },\n required: [\"issueId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"create_issue\",\n description: `Create a new JIRA issue.\n\n📋 BEFORE CREATING: Ask user for project, issue type, summary, and description.\nFor bugs: also ask for reproduction steps, expected/actual results.\nUse get_create_meta first to check required fields.\nSee prompt \"create_issue_workflow\" for detailed guidelines.`,\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key where the issue will be created\",\n },\n issueType: {\n type: \"string\",\n description:\n 'The type of issue to create (e.g., \"Bug\", \"Story\", \"Task\")',\n },\n summary: {\n type: \"string\",\n description: \"The issue summary/title\",\n },\n description: {\n type: \"string\",\n description: \"The issue description\",\n },\n fields: {\n type: \"object\",\n description: \"Additional fields to set on the issue\",\n additionalProperties: true,\n },\n },\n required: [\"projectKey\", \"issueType\", \"summary\"],\n additionalProperties: false,\n },\n },\n {\n name: \"update_issue\",\n description: `Update an existing JIRA issue.\n\n📝 When changing assignee or priority, consider adding a comment explaining why.\nSee prompt \"update_issue_workflow\" for guidelines.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to update\",\n },\n fields: {\n type: \"object\",\n description: \"Fields to update on the issue\",\n additionalProperties: true,\n },\n },\n required: [\"issueKey\", \"fields\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_transitions\",\n description: `Get available status transitions for a JIRA issue.\n\n⚠️ IMPORTANT: You MUST call this tool BEFORE attempting any transition!\n- Only transitions returned by this tool are valid\n- Transition availability depends on workflow rules (e.g., user can only have one task \"В работе\")\n- If desired transition is not in the list, inform the user — do NOT guess or invent transition names/IDs\n- Returns array with: id (use this for transition_issue), name, to.name (target status)\n\n⚠️ STATUS MISMATCH RULE: When user requests a specific status (e.g., \"в работу\", \"на ревью\"):\n1. Compare available transitions with the requested status\n2. If exact match NOT found — ALWAYS ASK the user which status to use\n3. Present the list of available transitions to choose from\n4. NEVER silently choose a \"similar\" status on your own`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to get transitions for\",\n },\n },\n required: [\"issueKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"transition_issue\",\n description: `Change the status of a JIRA issue by performing a transition.\n\n⚠️ CRITICAL: ALWAYS call get_transitions FIRST to get valid transition IDs!\n- NEVER guess or invent transition IDs — use ONLY IDs from get_transitions response\n- If the desired transition is not available, tell the user and explain possible reasons:\n - Workflow rules may restrict transitions (e.g., only one task \"В работе\" per user)\n - Current status may not allow direct transition to target status\n - User permissions may limit available transitions\n\n⚠️ STATUS MISMATCH RULE:\n- If user requested a specific status that is NOT in available transitions:\n - STOP and ASK user which available status to use\n - List all available transitions with their target statuses\n - Explain why requested status may be unavailable\n- NEVER silently substitute a different status — this confuses users!\n\n⚠️ CANCELLATION RULE: When transitioning to \"Отмена\" (Cancel), you MUST first:\n1. Ask user for cancellation reason\n2. Add comment with the reason using add_comment\n3. Only then perform the transition\nSee prompt \"cancel_issue_workflow\" for details.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to transition\",\n },\n transitionId: {\n type: \"string\",\n description: \"The ID of the transition to perform\",\n },\n comment: {\n type: \"string\",\n description: \"Optional comment to add with the transition\",\n },\n },\n required: [\"issueKey\", \"transitionId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"add_attachment\",\n description: \"Add a file attachment to a JIRA issue\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to add attachment to\",\n },\n fileContent: {\n type: \"string\",\n description: \"Base64 encoded content of the file\",\n },\n filename: {\n type: \"string\",\n description: \"Name of the file to be attached\",\n },\n },\n required: [\"issueKey\", \"fileContent\", \"filename\"],\n additionalProperties: false,\n },\n },\n {\n name: \"add_comment\",\n description: \"Add a comment to a JIRA issue\",\n inputSchema: {\n type: \"object\",\n properties: {\n issueIdOrKey: {\n type: \"string\",\n description: \"The ID or key of the issue to add the comment to\",\n },\n body: {\n type: \"string\",\n description: \"The content of the comment (plain text)\",\n },\n },\n required: [\"issueIdOrKey\", \"body\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_create_meta\",\n description: \"Get metadata for creating issues in a project, including available issue types and required fields. Use compact=true to get a smaller response with field counts instead of full allowedValues arrays.\",\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key to get creation metadata for\",\n },\n issueTypeName: {\n type: \"string\",\n description: \"Optional: filter to a specific issue type name\",\n },\n compact: {\n type: \"boolean\",\n description: \"If true, returns allowedValuesCount instead of full allowedValues arrays (reduces response size significantly)\",\n },\n },\n required: [\"projectKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_field_options\",\n description: \"Get allowed values for a specific field when creating issues. Use this after get_create_meta with compact=true to fetch options for fields that have allowedValuesCount > 0.\",\n inputSchema: {\n type: \"object\",\n properties: {\n projectKey: {\n type: \"string\",\n description: \"The project key\",\n },\n issueTypeId: {\n type: \"string\",\n description: \"The issue type ID (from get_create_meta response)\",\n },\n fieldId: {\n type: \"string\",\n description: \"The field ID to get allowed values for (e.g., 'components', 'customfield_12405')\",\n },\n },\n required: [\"projectKey\", \"issueTypeId\", \"fieldId\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_server_info\",\n description: \"Get JIRA server information including version and deployment type\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: \"get_projects\",\n description: \"Get all JIRA projects accessible to the current user\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: \"get_users\",\n description: \"Search for JIRA users by name or email. Useful for finding assignees.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Search query (name or email)\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 50)\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n },\n {\n name: \"delete_issue\",\n description: `Delete a JIRA issue permanently.\n\n⚠️ NOTE: Most users don't have delete permissions.\nIf deletion fails, use transition to \"Отмена\" (Cancel) status instead.\nRemember to add a comment with cancellation reason first.`,\n inputSchema: {\n type: \"object\",\n properties: {\n issueKey: {\n type: \"string\",\n description: \"The key of the issue to delete (e.g., IM3-1234)\",\n },\n },\n required: [\"issueKey\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_attachment\",\n description: \"Download a JIRA attachment by ID. Returns base64 encoded content. Use get_issue first to see available attachments with their IDs.\",\n inputSchema: {\n type: \"object\",\n properties: {\n attachmentId: {\n type: \"string\",\n description: \"The ID of the attachment to download\",\n },\n },\n required: [\"attachmentId\"],\n additionalProperties: false,\n },\n },\n ],\n }));\n\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n try {\n const args = request.params.arguments as Record<string, any>;\n\n switch (request.params.name) {\n case \"search_issues\": {\n if (!args.searchString || typeof args.searchString !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Search string is required\",\n );\n }\n const response = await this.jiraApi.searchIssues(args.searchString);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_epic_children\": {\n if (!args.epicKey || typeof args.epicKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Epic key is required\",\n );\n }\n const response = await this.jiraApi.getEpicChildren(args.epicKey);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_issue\": {\n if (!args.issueId || typeof args.issueId !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Issue ID is required\",\n );\n }\n const response = await this.jiraApi.getIssueWithComments(\n args.issueId,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"create_issue\": {\n // Basic validation\n if (\n !args.projectKey ||\n typeof args.projectKey !== \"string\" ||\n !args.issueType ||\n typeof args.issueType !== \"string\" ||\n !args.summary ||\n typeof args.summary !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey, issueType, and summary are required\",\n );\n }\n const response = await this.jiraApi.createIssue(\n args.projectKey,\n args.issueType,\n args.summary,\n args.description as string | undefined,\n args.fields as Record<string, any> | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"update_issue\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.fields ||\n typeof args.fields !== \"object\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey and fields object are required\",\n );\n }\n await this.jiraApi.updateIssue(args.issueKey, args.fields);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { message: `Issue ${args.issueKey} updated successfully` },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"get_transitions\": {\n if (!args.issueKey || typeof args.issueKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"Issue key is required\",\n );\n }\n const response = await this.jiraApi.getTransitions(args.issueKey);\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"transition_issue\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.transitionId ||\n typeof args.transitionId !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey and transitionId are required\",\n );\n }\n await this.jiraApi.transitionIssue(\n args.issueKey,\n args.transitionId,\n args.comment as string | undefined,\n );\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: `Issue ${args.issueKey} transitioned successfully${args.comment ? \" with comment\" : \"\"}`,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"add_attachment\": {\n if (\n !args.issueKey ||\n typeof args.issueKey !== \"string\" ||\n !args.fileContent ||\n typeof args.fileContent !== \"string\" ||\n !args.filename ||\n typeof args.filename !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey, fileContent, and filename are required\",\n );\n }\n const fileBuffer = Buffer.from(args.fileContent, \"base64\");\n const result = await this.jiraApi.addAttachment(\n args.issueKey,\n fileBuffer,\n args.filename,\n );\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n message: `File ${args.filename} attached successfully to issue ${args.issueKey}`,\n attachmentId: result.id,\n filename: result.filename,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"add_comment\": {\n if (\n !args.issueIdOrKey ||\n typeof args.issueIdOrKey !== \"string\" ||\n !args.body ||\n typeof args.body !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueIdOrKey and body are required\",\n );\n }\n const response = await this.jiraApi.addCommentToIssue(\n args.issueIdOrKey,\n args.body,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(response, null, 2) },\n ],\n };\n }\n case \"get_create_meta\": {\n if (!args.projectKey || typeof args.projectKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey is required\",\n );\n }\n const meta = await this.jiraApi.getCreateMeta(\n args.projectKey,\n args.issueTypeName as string | undefined,\n args.compact as boolean | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(meta, null, 2) },\n ],\n };\n }\n case \"get_field_options\": {\n if (\n !args.projectKey ||\n typeof args.projectKey !== \"string\" ||\n !args.issueTypeId ||\n typeof args.issueTypeId !== \"string\" ||\n !args.fieldId ||\n typeof args.fieldId !== \"string\"\n ) {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"projectKey, issueTypeId, and fieldId are required\",\n );\n }\n const options = await this.jiraApi.getFieldOptions(\n args.projectKey,\n args.issueTypeId,\n args.fieldId,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(options, null, 2) },\n ],\n };\n }\n case \"get_server_info\": {\n const serverInfo = await this.jiraApi.getServerInfo();\n return {\n content: [\n { type: \"text\", text: JSON.stringify(serverInfo, null, 2) },\n ],\n };\n }\n case \"get_projects\": {\n const projects = await this.jiraApi.getProjects();\n return {\n content: [\n { type: \"text\", text: JSON.stringify(projects, null, 2) },\n ],\n };\n }\n case \"get_users\": {\n if (!args.query || typeof args.query !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"query is required\",\n );\n }\n const users = await this.jiraApi.getUsers(\n args.query,\n args.maxResults as number | undefined,\n );\n return {\n content: [\n { type: \"text\", text: JSON.stringify(users, null, 2) },\n ],\n };\n }\n case \"delete_issue\": {\n if (!args.issueKey || typeof args.issueKey !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"issueKey is required\",\n );\n }\n await this.jiraApi.deleteIssue(args.issueKey);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { message: `Issue ${args.issueKey} deleted successfully` },\n null,\n 2,\n ),\n },\n ],\n };\n }\n case \"get_attachment\": {\n if (!args.attachmentId || typeof args.attachmentId !== \"string\") {\n throw new McpError(\n ErrorCode.InvalidParams,\n \"attachmentId is required\",\n );\n }\n const attachment = await this.jiraApi.getAttachment(args.attachmentId);\n\n // Check if it's an image type that Claude can view\n const isImage = attachment.mimeType.startsWith(\"image/\");\n\n if (isImage) {\n return {\n content: [\n {\n type: \"text\",\n text: `Attachment: ${attachment.filename} (${attachment.mimeType})`,\n },\n {\n type: \"image\",\n data: attachment.content,\n mimeType: attachment.mimeType,\n } as any,\n ],\n };\n }\n\n // For non-image files, return base64 as text\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(attachment, null, 2),\n },\n ],\n };\n }\n default:\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n } catch (error) {\n // Keep generic error handling\n if (error instanceof McpError) {\n throw error;\n }\n throw new McpError(\n ErrorCode.InternalError,\n error instanceof Error ? error.message : \"Unknown error occurred\",\n );\n }\n });\n }\n\n async run() {\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n // JIRA MCP server running on stdio\n }\n}\n\n// Only run stdio transport when this file is the main entry point\n// When run via npx, argv[1] is the bin name (jira-mcp), not index.js\nconst isMainModule =\n process.argv[1]?.endsWith(\"index.js\") ||\n process.argv[1]?.endsWith(\"index.ts\") ||\n process.argv[1]?.endsWith(\"jira-mcp\");\nif (isMainModule) {\n const server = new JiraServer();\n server.run().catch(() => {});\n}\n"],"names":["JiraApiService","baseUrl","email","apiToken","authType","authHeader","response","url","message","errorData","errorMessages","field","msg","text","content","source","commentId","mentions","processNode","node","match","key","m","comment","body","attachment","issue","description","cleanedIssue","links","link","linkedIssue","relationship","subtask","a","init","searchString","params","data","epicKey","commentsData","comments","commentMentions","issueId","issueData","error","epicData","projectKey","issueType","summary","fields","payload","issueTypeName","compact","issueTypes","it","f","issueTypeId","fieldId","issueKey","transitionId","file","filename","formData","headers","issueIdOrKey","project","query","maxResults","user","attachmentId","metadata","arrayBuffer","JiraServerApiService","path","serverUrl","matches","getEnvConfig","JIRA_API_TOKEN","JIRA_BASE_URL","JIRA_USER_EMAIL","JIRA_TYPE","JIRA_AUTH_TYPE","JIRA_PROMPTS","JiraServer","Server","ListPromptsRequestSchema","name","GetPromptRequestSchema","request","prompt","McpError","ErrorCode","ListToolsRequestSchema","CallToolRequestSchema","args","fileBuffer","result","meta","options","serverInfo","projects","users","transport","StdioServerTransport","isMainModule"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokealvo/jira-mcp",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "JIRA MCP Server",
5
5
  "type": "module",
6
6
  "bin": {