mcp-jira-stdio 1.6.1 → 1.7.1
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/README.md +12 -0
- package/dist/index.js +139 -15
- package/dist/index.js.map +1 -1
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -338,6 +338,18 @@ jira_get_visible_projects({
|
|
|
338
338
|
- Look for errors in Claude Desktop logs
|
|
339
339
|
- Use `task inspector` to debug
|
|
340
340
|
|
|
341
|
+
**Timeout when running multiple instances with npx**
|
|
342
|
+
|
|
343
|
+
If you're running multiple Claude Code sessions simultaneously and experience timeouts, this is caused by `npx` cache/registry locking — not the MCP server itself. Each instance tries to verify the package, causing conflicts. To fix this, install the package globally instead:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
npm install -g mcp-jira-stdio
|
|
347
|
+
claude mcp add jira mcp-jira-stdio \
|
|
348
|
+
--env JIRA_BASE_URL=... \
|
|
349
|
+
--env JIRA_EMAIL=... \
|
|
350
|
+
--env JIRA_API_TOKEN=...
|
|
351
|
+
```
|
|
352
|
+
|
|
341
353
|
### Debug Commands
|
|
342
354
|
|
|
343
355
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
40
40
|
|
|
41
41
|
// node_modules/dotenv/package.json
|
|
42
42
|
var require_package = __commonJS({
|
|
43
|
-
"node_modules/dotenv/package.json"(exports, module) {
|
|
43
|
+
"node_modules/dotenv/package.json"(exports$1, module) {
|
|
44
44
|
module.exports = {
|
|
45
45
|
name: "dotenv",
|
|
46
46
|
version: "17.2.3",
|
|
@@ -108,7 +108,7 @@ var require_package = __commonJS({
|
|
|
108
108
|
|
|
109
109
|
// node_modules/dotenv/lib/main.js
|
|
110
110
|
var require_main = __commonJS({
|
|
111
|
-
"node_modules/dotenv/lib/main.js"(exports, module) {
|
|
111
|
+
"node_modules/dotenv/lib/main.js"(exports$1, module) {
|
|
112
112
|
var fs = __require("fs");
|
|
113
113
|
var path = __require("path");
|
|
114
114
|
var os = __require("os");
|
|
@@ -437,10 +437,10 @@ var require_main = __commonJS({
|
|
|
437
437
|
|
|
438
438
|
// package.json
|
|
439
439
|
var require_package2 = __commonJS({
|
|
440
|
-
"package.json"(exports, module) {
|
|
440
|
+
"package.json"(exports$1, module) {
|
|
441
441
|
module.exports = {
|
|
442
442
|
name: "mcp-jira-stdio",
|
|
443
|
-
version: "1.
|
|
443
|
+
version: "1.7.1",
|
|
444
444
|
description: "Model Context Protocol (MCP) server for Jira API integration",
|
|
445
445
|
author: "graslt",
|
|
446
446
|
license: "MIT",
|
|
@@ -486,29 +486,29 @@ var require_package2 = __commonJS({
|
|
|
486
486
|
"ai"
|
|
487
487
|
],
|
|
488
488
|
engines: {
|
|
489
|
-
node: ">=
|
|
489
|
+
node: ">=20.0.0"
|
|
490
490
|
},
|
|
491
491
|
dependencies: {
|
|
492
492
|
"@modelcontextprotocol/sdk": "^1.17.1",
|
|
493
493
|
axios: "^1.7.0",
|
|
494
|
-
"md-to-adf": "^0.
|
|
494
|
+
"md-to-adf": "^0.5.0",
|
|
495
495
|
zod: "^3.22.4"
|
|
496
496
|
},
|
|
497
497
|
devDependencies: {
|
|
498
498
|
"@types/node": "^22.5.0",
|
|
499
499
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
500
500
|
"@typescript-eslint/parser": "^8.0.0",
|
|
501
|
-
"@vitest/coverage-v8": "^
|
|
502
|
-
"@vitest/ui": "^
|
|
501
|
+
"@vitest/coverage-v8": "^4.0.10",
|
|
502
|
+
"@vitest/ui": "^4.0.10",
|
|
503
503
|
dotenv: "^17.2.1",
|
|
504
504
|
eslint: "^9.9.0",
|
|
505
505
|
"eslint-config-prettier": "^9.1.0",
|
|
506
506
|
"eslint-plugin-prettier": "^5.2.0",
|
|
507
507
|
prettier: "^3.5.0",
|
|
508
|
-
tsup: "^8.
|
|
508
|
+
tsup: "^8.5.1",
|
|
509
509
|
tsx: "^4.16.0",
|
|
510
510
|
typescript: "^5.5.0",
|
|
511
|
-
vitest: "^
|
|
511
|
+
vitest: "^4.0.10"
|
|
512
512
|
},
|
|
513
513
|
files: [
|
|
514
514
|
"dist",
|
|
@@ -526,6 +526,10 @@ var require_package2 = __commonJS({
|
|
|
526
526
|
homepage: "https://github.com/freema/mcp-jira-stdio#readme",
|
|
527
527
|
publishConfig: {
|
|
528
528
|
access: "public"
|
|
529
|
+
},
|
|
530
|
+
overrides: {
|
|
531
|
+
glob: ">=11.0.4",
|
|
532
|
+
marked: ">=4.0.10"
|
|
529
533
|
}
|
|
530
534
|
};
|
|
531
535
|
}
|
|
@@ -560,7 +564,8 @@ var TOOL_NAMES = {
|
|
|
560
564
|
CREATE_SUBTASK: "jira_create_subtask",
|
|
561
565
|
GET_CREATE_META: "jira_get_create_meta",
|
|
562
566
|
GET_CUSTOM_FIELDS: "jira_get_custom_fields",
|
|
563
|
-
CREATE_ISSUE_LINK: "jira_create_issue_link"
|
|
567
|
+
CREATE_ISSUE_LINK: "jira_create_issue_link",
|
|
568
|
+
GET_COMMENTS: "jira_get_comments"
|
|
564
569
|
};
|
|
565
570
|
|
|
566
571
|
// src/utils/logger.ts
|
|
@@ -844,6 +849,12 @@ var CreateIssueLinkInputSchema = z.object({
|
|
|
844
849
|
'Link type: "blocks", "is blocked by", "relates", "duplicates", "clones", or custom link type name'
|
|
845
850
|
)
|
|
846
851
|
});
|
|
852
|
+
var GetCommentsInputSchema = z.object({
|
|
853
|
+
issueKey: z.string().describe("Issue key to get comments for (e.g., PROJECT-123)").refine((v) => isValidIssueKey(v), "Invalid issue key format"),
|
|
854
|
+
maxResults: z.number().min(1).max(100).optional().describe("Maximum number of comments to return (default: 50)"),
|
|
855
|
+
orderBy: z.enum(["created", "-created", "+created"]).optional().describe('Sort order for comments: "created" (oldest first), "-created" (newest first)'),
|
|
856
|
+
startAt: z.number().min(0).optional().describe("Index of first comment to return (for pagination)")
|
|
857
|
+
});
|
|
847
858
|
function ensureAdfDescription(desc, format = "markdown") {
|
|
848
859
|
if (!desc) return desc;
|
|
849
860
|
if (typeof desc === "object") return desc;
|
|
@@ -1194,6 +1205,24 @@ async function addComment(issueKey, body, visibility, format) {
|
|
|
1194
1205
|
};
|
|
1195
1206
|
return await makeJiraRequest(config);
|
|
1196
1207
|
}
|
|
1208
|
+
async function getComments(issueKey, options = {}) {
|
|
1209
|
+
const params = {};
|
|
1210
|
+
if (options.maxResults !== void 0) {
|
|
1211
|
+
params.maxResults = options.maxResults;
|
|
1212
|
+
}
|
|
1213
|
+
if (options.orderBy !== void 0) {
|
|
1214
|
+
params.orderBy = options.orderBy;
|
|
1215
|
+
}
|
|
1216
|
+
if (options.startAt !== void 0) {
|
|
1217
|
+
params.startAt = options.startAt;
|
|
1218
|
+
}
|
|
1219
|
+
const config = {
|
|
1220
|
+
method: "GET",
|
|
1221
|
+
url: `/issue/${issueKey}/comment`,
|
|
1222
|
+
params
|
|
1223
|
+
};
|
|
1224
|
+
return await makeJiraRequest(config);
|
|
1225
|
+
}
|
|
1197
1226
|
async function getProjectDetails(projectKey, expand) {
|
|
1198
1227
|
const params = {};
|
|
1199
1228
|
if (expand) {
|
|
@@ -1627,6 +1656,44 @@ ${comment.body}`
|
|
|
1627
1656
|
]
|
|
1628
1657
|
};
|
|
1629
1658
|
}
|
|
1659
|
+
function formatCommentsResponse(response, issueKey) {
|
|
1660
|
+
if (!response.comments || response.comments.length === 0) {
|
|
1661
|
+
return {
|
|
1662
|
+
content: [
|
|
1663
|
+
{
|
|
1664
|
+
type: "text",
|
|
1665
|
+
text: `No comments found for issue ${issueKey}.`
|
|
1666
|
+
}
|
|
1667
|
+
]
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
const commentsList = response.comments.map((comment) => {
|
|
1671
|
+
const bodyText = typeof comment.body === "string" ? comment.body : adfToPlainText(comment.body);
|
|
1672
|
+
const visibilityText = comment.visibility ? ` [${comment.visibility.type}: ${comment.visibility.value}]` : "";
|
|
1673
|
+
const authorName = comment.author?.displayName || "Unknown";
|
|
1674
|
+
const createdDate = comment.created ? new Date(comment.created).toISOString() : "N/A";
|
|
1675
|
+
const updatedDate = comment.updated ? new Date(comment.updated).toISOString() : "N/A";
|
|
1676
|
+
const wasEdited = comment.created !== comment.updated;
|
|
1677
|
+
return `**${authorName}** - ${createdDate}${wasEdited ? ` (edited: ${updatedDate})` : ""}${visibilityText}
|
|
1678
|
+
${bodyText}`;
|
|
1679
|
+
}).join("\n\n---\n\n");
|
|
1680
|
+
const total = response.total;
|
|
1681
|
+
const showingStart = response.startAt + 1;
|
|
1682
|
+
const showingEnd = Math.min(response.startAt + response.comments.length, total);
|
|
1683
|
+
const paginationInfo = total > response.comments.length ? `
|
|
1684
|
+
|
|
1685
|
+
*Showing ${showingStart}-${showingEnd} of ${total} comments*` : "";
|
|
1686
|
+
return {
|
|
1687
|
+
content: [
|
|
1688
|
+
{
|
|
1689
|
+
type: "text",
|
|
1690
|
+
text: `**Comments for ${issueKey}** (${response.comments.length} comment${response.comments.length !== 1 ? "s" : ""}):
|
|
1691
|
+
|
|
1692
|
+
${commentsList}${paginationInfo}`
|
|
1693
|
+
}
|
|
1694
|
+
]
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1630
1697
|
function formatProjectDetailsResponse(project) {
|
|
1631
1698
|
const leadText = project.lead ? `${project.lead.displayName} (${project.lead.accountId})` : "No lead assigned";
|
|
1632
1699
|
const componentsText = project.components.length > 0 ? project.components.map((c) => c.name).join(", ") : "None";
|
|
@@ -2618,6 +2685,61 @@ async function handleCreateIssueLink(input) {
|
|
|
2618
2685
|
}
|
|
2619
2686
|
}
|
|
2620
2687
|
|
|
2688
|
+
// src/tools/get-comments.ts
|
|
2689
|
+
var log19 = createLogger("tool:get-comments");
|
|
2690
|
+
var getCommentsTool = {
|
|
2691
|
+
name: TOOL_NAMES.GET_COMMENTS,
|
|
2692
|
+
description: "Retrieves all comments for a Jira issue. Returns comment author, content, timestamps, and visibility settings. Supports pagination for issues with many comments.",
|
|
2693
|
+
inputSchema: {
|
|
2694
|
+
type: "object",
|
|
2695
|
+
properties: {
|
|
2696
|
+
issueKey: {
|
|
2697
|
+
type: "string",
|
|
2698
|
+
description: "Issue key to get comments for (e.g., PROJECT-123)"
|
|
2699
|
+
},
|
|
2700
|
+
maxResults: {
|
|
2701
|
+
type: "number",
|
|
2702
|
+
description: "Maximum number of comments to return (default: 50, max: 100)",
|
|
2703
|
+
minimum: 1,
|
|
2704
|
+
maximum: 100
|
|
2705
|
+
},
|
|
2706
|
+
orderBy: {
|
|
2707
|
+
type: "string",
|
|
2708
|
+
enum: ["created", "-created", "+created"],
|
|
2709
|
+
description: 'Sort order for comments: "created" or "+created" (oldest first), "-created" (newest first)'
|
|
2710
|
+
},
|
|
2711
|
+
startAt: {
|
|
2712
|
+
type: "number",
|
|
2713
|
+
description: "Index of first comment to return (for pagination, default: 0)",
|
|
2714
|
+
minimum: 0
|
|
2715
|
+
}
|
|
2716
|
+
},
|
|
2717
|
+
required: ["issueKey"]
|
|
2718
|
+
}
|
|
2719
|
+
};
|
|
2720
|
+
async function handleGetComments(input) {
|
|
2721
|
+
try {
|
|
2722
|
+
const validated = validateInput(GetCommentsInputSchema, input);
|
|
2723
|
+
log19.info(`Getting comments for issue ${validated.issueKey}...`);
|
|
2724
|
+
const options = {};
|
|
2725
|
+
if (validated.maxResults !== void 0) {
|
|
2726
|
+
options.maxResults = validated.maxResults;
|
|
2727
|
+
}
|
|
2728
|
+
if (validated.orderBy !== void 0) {
|
|
2729
|
+
options.orderBy = validated.orderBy;
|
|
2730
|
+
}
|
|
2731
|
+
if (validated.startAt !== void 0) {
|
|
2732
|
+
options.startAt = validated.startAt;
|
|
2733
|
+
}
|
|
2734
|
+
const comments = await getComments(validated.issueKey, options);
|
|
2735
|
+
log19.info(`Retrieved ${comments.comments.length} comment(s) for ${validated.issueKey}`);
|
|
2736
|
+
return formatCommentsResponse(comments, validated.issueKey);
|
|
2737
|
+
} catch (error) {
|
|
2738
|
+
log19.error("Error in handleGetComments:", error);
|
|
2739
|
+
return handleError(error);
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2621
2743
|
// src/index.ts
|
|
2622
2744
|
if (process.env.NODE_ENV !== "production") {
|
|
2623
2745
|
try {
|
|
@@ -2626,7 +2748,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
2626
2748
|
} catch {
|
|
2627
2749
|
}
|
|
2628
2750
|
}
|
|
2629
|
-
var
|
|
2751
|
+
var log20 = createLogger("server");
|
|
2630
2752
|
var toolHandlers = /* @__PURE__ */ new Map([
|
|
2631
2753
|
[TOOL_NAMES.GET_VISIBLE_PROJECTS, handleGetVisibleProjects],
|
|
2632
2754
|
[TOOL_NAMES.GET_ISSUE, handleGetIssue],
|
|
@@ -2643,7 +2765,8 @@ var toolHandlers = /* @__PURE__ */ new Map([
|
|
|
2643
2765
|
[TOOL_NAMES.CREATE_SUBTASK, handleCreateSubtask],
|
|
2644
2766
|
[TOOL_NAMES.GET_CREATE_META, handleGetCreateMeta],
|
|
2645
2767
|
[TOOL_NAMES.GET_CUSTOM_FIELDS, handleGetCustomFields],
|
|
2646
|
-
[TOOL_NAMES.CREATE_ISSUE_LINK, handleCreateIssueLink]
|
|
2768
|
+
[TOOL_NAMES.CREATE_ISSUE_LINK, handleCreateIssueLink],
|
|
2769
|
+
[TOOL_NAMES.GET_COMMENTS, handleGetComments]
|
|
2647
2770
|
]);
|
|
2648
2771
|
var allTools = [
|
|
2649
2772
|
getVisibleProjectsTool,
|
|
@@ -2661,7 +2784,8 @@ var allTools = [
|
|
|
2661
2784
|
createSubtaskTool,
|
|
2662
2785
|
getCreateMetaTool,
|
|
2663
2786
|
getCustomFieldsTool,
|
|
2664
|
-
createIssueLinkTool
|
|
2787
|
+
createIssueLinkTool,
|
|
2788
|
+
getCommentsTool
|
|
2665
2789
|
];
|
|
2666
2790
|
async function main() {
|
|
2667
2791
|
const isDryRun = (process.env.DRY_RUN || "").toLowerCase() === "1" || (process.env.DRY_RUN || "").toLowerCase() === "true";
|
|
@@ -2732,7 +2856,7 @@ async function main() {
|
|
|
2732
2856
|
console.error("\u{1F680} Jira MCP server running on stdio");
|
|
2733
2857
|
}
|
|
2734
2858
|
main().catch((error) => {
|
|
2735
|
-
|
|
2859
|
+
log20.error("Fatal error:", error);
|
|
2736
2860
|
process.exit(1);
|
|
2737
2861
|
});
|
|
2738
2862
|
//# sourceMappingURL=index.js.map
|