@rui.branco/jira-mcp 1.7.9 → 1.7.10
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/index.js +53 -8
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -474,9 +474,12 @@ async function fetchJira(endpoint, options = {}, instance = defaultInstance) {
|
|
|
474
474
|
});
|
|
475
475
|
if (!response.ok) {
|
|
476
476
|
const errorBody = await response.text().catch(() => "");
|
|
477
|
-
|
|
477
|
+
const error = new Error(
|
|
478
478
|
`Jira API error: ${response.status} ${response.statusText}${errorBody ? ` - ${errorBody}` : ""}`,
|
|
479
479
|
);
|
|
480
|
+
error.status = response.status;
|
|
481
|
+
error.body = errorBody;
|
|
482
|
+
throw error;
|
|
480
483
|
}
|
|
481
484
|
const text = await response.text();
|
|
482
485
|
return text ? JSON.parse(text) : {};
|
|
@@ -2351,7 +2354,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2351
2354
|
{
|
|
2352
2355
|
name: "jira_search_users",
|
|
2353
2356
|
description:
|
|
2354
|
-
"Search for Jira users by name or email. Returns account IDs and display names. Use this to find users for mentions or assignments. When multiple Jira instances are configured, use the 'instance' parameter to specify which one.",
|
|
2357
|
+
"Search for Jira users by name or email. Returns account IDs and display names. Use this to find users for mentions or assignments. For assignment-oriented searches, provide issueKey or projectKey to find users assignable to that issue or project when global user browsing is unavailable. When multiple Jira instances are configured, use the 'instance' parameter to specify which one.",
|
|
2355
2358
|
inputSchema: {
|
|
2356
2359
|
type: "object",
|
|
2357
2360
|
properties: {
|
|
@@ -2364,6 +2367,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2364
2367
|
type: "number",
|
|
2365
2368
|
description: "Max results (default 5)",
|
|
2366
2369
|
},
|
|
2370
|
+
issueKey: {
|
|
2371
|
+
type: "string",
|
|
2372
|
+
description:
|
|
2373
|
+
"Optional issue key for assignment-oriented searches (e.g., 'MODS-123'). If global user search is empty or user browsing is forbidden, search users assignable to this issue. The instance is auto-detected from the issue key when omitted.",
|
|
2374
|
+
},
|
|
2375
|
+
projectKey: {
|
|
2376
|
+
type: "string",
|
|
2377
|
+
description:
|
|
2378
|
+
"Optional project key for assignment-oriented searches (e.g., 'MODS'). If global user search is empty or user browsing is forbidden, search users assignable to this project. Used when issueKey is not provided.",
|
|
2379
|
+
},
|
|
2367
2380
|
instance: {
|
|
2368
2381
|
type: "string",
|
|
2369
2382
|
description: "Instance name (optional).",
|
|
@@ -3505,13 +3518,45 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3505
3518
|
],
|
|
3506
3519
|
};
|
|
3507
3520
|
} else if (name === "jira_search_users") {
|
|
3508
|
-
const inst =
|
|
3521
|
+
const inst = resolveInstanceForTool(name, args);
|
|
3509
3522
|
const maxResults = args.maxResults || 5;
|
|
3510
|
-
const
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3523
|
+
const hasAssignmentContext = Boolean(args.issueKey || args.projectKey);
|
|
3524
|
+
let users;
|
|
3525
|
+
let useAssignableFallback = false;
|
|
3526
|
+
|
|
3527
|
+
try {
|
|
3528
|
+
users = await fetchJira(
|
|
3529
|
+
`/user/search?query=${encodeURIComponent(args.query)}&maxResults=${maxResults}`,
|
|
3530
|
+
{},
|
|
3531
|
+
inst,
|
|
3532
|
+
);
|
|
3533
|
+
} catch (error) {
|
|
3534
|
+
const errorDetail = String(error.body || error.message || "").toLowerCase();
|
|
3535
|
+
if (
|
|
3536
|
+
hasAssignmentContext &&
|
|
3537
|
+
error.status === 403 &&
|
|
3538
|
+
/(browse users|user browsing|users and groups)/.test(errorDetail)
|
|
3539
|
+
) {
|
|
3540
|
+
useAssignableFallback = true;
|
|
3541
|
+
} else {
|
|
3542
|
+
throw error;
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
if (
|
|
3547
|
+
useAssignableFallback ||
|
|
3548
|
+
(hasAssignmentContext && (!users || users.length === 0))
|
|
3549
|
+
) {
|
|
3550
|
+
const scope = args.issueKey
|
|
3551
|
+
? `issueKey=${encodeURIComponent(args.issueKey)}`
|
|
3552
|
+
: `project=${encodeURIComponent(args.projectKey)}`;
|
|
3553
|
+
users = await fetchJira(
|
|
3554
|
+
`/user/assignable/search?${scope}&query=${encodeURIComponent(args.query)}&maxResults=${maxResults}`,
|
|
3555
|
+
{},
|
|
3556
|
+
inst,
|
|
3557
|
+
);
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3515
3560
|
if (!users || users.length === 0) {
|
|
3516
3561
|
return {
|
|
3517
3562
|
content: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rui.branco/jira-mcp",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.10",
|
|
4
4
|
"description": "Jira & Confluence MCP server for any MCP-compatible AI client (Claude Code, Codex, Antigravity, Cursor, etc.) - fetch tickets, search with JQL, update tickets, manage comments, change status, get Figma designs. Optional per-tool scopes, dry-run, audit log, and rate limiting.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|