@rui.branco/jira-mcp 1.7.6 → 1.7.7
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 +13 -0
- package/index.js +189 -99
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -225,6 +225,19 @@ For Server / Data Center deployments where Confluence lives on a different host,
|
|
|
225
225
|
|
|
226
226
|
**Why ADF for `confluence_get_page`?** The v1 `body.atlas_doc_format` expand is unreliable on modern Cloud pages — table cell background colors and some newer node types only survive the v2 `/api/v2/pages/<id>?body-format=atlas_doc_format` endpoint. `confluence_get_page` therefore does both requests in parallel and merges the v2 ADF body onto the v1 response, so callers get `body.view`, `body.storage` and `body.atlas_doc_format` in one shot.
|
|
227
227
|
|
|
228
|
+
### Confluence On-Demand Activation
|
|
229
|
+
|
|
230
|
+
By default, the 21 `confluence_*` tools are hidden from `tools/list` to reduce token footprint. A lightweight `confluence_enable` gateway tool is exposed instead. When a task needs Confluence, the client calls `confluence_enable` and the full tool set appears (the server sends `notifications/tools/list_changed`). Activation is per-process (not persisted to config) and does not bypass instance scopes.
|
|
231
|
+
|
|
232
|
+
To expose Confluence tools from boot (skip the activation step), set the `confluence` config key or the `JIRA_MCP_CONFLUENCE` environment variable:
|
|
233
|
+
|
|
234
|
+
| Method | Value |
|
|
235
|
+
|--------|-------|
|
|
236
|
+
| Config (`~/.config/jira-mcp/config.json`) | `"confluence": "always"` |
|
|
237
|
+
| Environment variable | `JIRA_MCP_CONFLUENCE=always` |
|
|
238
|
+
|
|
239
|
+
The default value is `"on-demand"`.
|
|
240
|
+
|
|
228
241
|
### Configuration
|
|
229
242
|
|
|
230
243
|
Config stored at `~/.config/jira-mcp/config.json`:
|
package/index.js
CHANGED
|
@@ -53,6 +53,15 @@ const jiraConfigPath = path.join(
|
|
|
53
53
|
);
|
|
54
54
|
const rawConfig = JSON.parse(fs.readFileSync(jiraConfigPath, "utf8"));
|
|
55
55
|
|
|
56
|
+
// Confluence tool visibility: 'on-demand' (default) hides the confluence_*
|
|
57
|
+
// tools until confluence_enable is called; 'always' exposes them from boot.
|
|
58
|
+
// Env JIRA_MCP_CONFLUENCE overrides the config key.
|
|
59
|
+
const confluenceMode = String(process.env.JIRA_MCP_CONFLUENCE || rawConfig.confluence || "on-demand").toLowerCase();
|
|
60
|
+
if (confluenceMode !== "always" && confluenceMode !== "on-demand") {
|
|
61
|
+
console.error(`jira-mcp: invalid confluence mode "${confluenceMode}", falling back to "on-demand"`);
|
|
62
|
+
}
|
|
63
|
+
let confluenceActive = confluenceMode === "always";
|
|
64
|
+
|
|
56
65
|
// Normalize config to multi-instance format
|
|
57
66
|
let instances;
|
|
58
67
|
if (rawConfig.instances) {
|
|
@@ -181,6 +190,8 @@ const TOOL_METADATA = {
|
|
|
181
190
|
jira_delete_ticket: { product: "jira", op: "destructive", category: "ticket" },
|
|
182
191
|
jira_remove_attachment: { product: "jira", op: "destructive", category: "attachment" },
|
|
183
192
|
jira_remove_instance: { product: "jira", op: "destructive", category: "config" },
|
|
193
|
+
// ---- Confluence activation ----
|
|
194
|
+
confluence_enable: { product: "confluence", op: "read" },
|
|
184
195
|
// ---- Confluence reads ----
|
|
185
196
|
confluence_get_spaces: { product: "confluence", op: "read" },
|
|
186
197
|
confluence_get_space: { product: "confluence", op: "read" },
|
|
@@ -758,7 +769,10 @@ function extractText(content, urls = []) {
|
|
|
758
769
|
} else if (node.type === "hardBreak") {
|
|
759
770
|
text += "\n";
|
|
760
771
|
} else if (node.type === "mention") {
|
|
761
|
-
text
|
|
772
|
+
// attrs.text already includes the leading "@" (e.g. "@Rui Branco").
|
|
773
|
+
// Don't prepend a second one.
|
|
774
|
+
const mentionText = node.attrs?.text || "@user";
|
|
775
|
+
text += mentionText.startsWith("@") ? mentionText : `@${mentionText}`;
|
|
762
776
|
} else if (node.type === "mediaGroup" || node.type === "mediaSingle") {
|
|
763
777
|
text += "[image attachment]\n";
|
|
764
778
|
} else if (
|
|
@@ -965,6 +979,54 @@ function autoLinkTextNodes(nodes, instance = defaultInstance) {
|
|
|
965
979
|
return result;
|
|
966
980
|
}
|
|
967
981
|
|
|
982
|
+
// Detect a markdown list item line. Returns {indent, ordered, text} or null.
|
|
983
|
+
// Bullets: -, *, + followed by a space. Ordered: "1." or "1)" followed by a space.
|
|
984
|
+
// The marker must be followed by whitespace so inline emphasis (*italic*) and
|
|
985
|
+
// horizontal rules (***) are NOT misread as list items.
|
|
986
|
+
function listItemMatch(line) {
|
|
987
|
+
const m = line.match(/^(\s*)([-*+]|\d+[.)])\s+(.*)$/);
|
|
988
|
+
if (!m) return null;
|
|
989
|
+
return { indent: m[1].length, ordered: /\d/.test(m[2]), text: m[3] };
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// Recursively parse a (possibly nested) markdown list starting at lines[startIdx].
|
|
993
|
+
// baseIndent is the indentation of items at this level; more-indented items are
|
|
994
|
+
// folded into the previous item as a nested list. Returns {node, nextIndex}.
|
|
995
|
+
async function parseListBlock(lines, startIdx, baseIndent, instance) {
|
|
996
|
+
const items = [];
|
|
997
|
+
let i = startIdx;
|
|
998
|
+
let ordered = null;
|
|
999
|
+
while (i < lines.length) {
|
|
1000
|
+
if (!lines[i].trim()) break; // blank line ends the list
|
|
1001
|
+
const m = listItemMatch(lines[i]);
|
|
1002
|
+
if (!m) break;
|
|
1003
|
+
if (m.indent < baseIndent) break; // dedent: belongs to a parent list
|
|
1004
|
+
if (m.indent > baseIndent) {
|
|
1005
|
+
// Deeper indent: nest under the previous item at this level.
|
|
1006
|
+
const sub = await parseListBlock(lines, i, m.indent, instance);
|
|
1007
|
+
if (items.length > 0) {
|
|
1008
|
+
items[items.length - 1].content.push(sub.node);
|
|
1009
|
+
} else {
|
|
1010
|
+
items.push({ type: "listItem", content: [sub.node] });
|
|
1011
|
+
}
|
|
1012
|
+
i = sub.nextIndex;
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
if (ordered === null) ordered = m.ordered; // list type set by first item
|
|
1016
|
+
else if (m.ordered !== ordered) break; // marker switched: caller starts a new list
|
|
1017
|
+
const inlineContent = await parseInlineFormatting(m.text, instance);
|
|
1018
|
+
items.push({
|
|
1019
|
+
type: "listItem",
|
|
1020
|
+
content: [{ type: "paragraph", content: inlineContent }],
|
|
1021
|
+
});
|
|
1022
|
+
i++;
|
|
1023
|
+
}
|
|
1024
|
+
return {
|
|
1025
|
+
node: { type: ordered ? "orderedList" : "bulletList", content: items },
|
|
1026
|
+
nextIndex: i,
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
|
|
968
1030
|
// Parse text with markdown formatting and @mentions, build ADF content
|
|
969
1031
|
async function buildCommentADF(text, instance = defaultInstance) {
|
|
970
1032
|
// Sanitize: replace em dashes and en dashes with hyphen
|
|
@@ -1077,35 +1139,17 @@ async function buildCommentADF(text, instance = defaultInstance) {
|
|
|
1077
1139
|
continue;
|
|
1078
1140
|
}
|
|
1079
1141
|
|
|
1080
|
-
// ---
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
}
|
|
1092
|
-
content.push({ type: "bulletList", content: listItems });
|
|
1093
|
-
continue;
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
// --- Ordered list (1. items) ---
|
|
1097
|
-
if (/^\d+\.\s/.test(trimmed)) {
|
|
1098
|
-
const listItems = [];
|
|
1099
|
-
while (i < lines.length && /^\d+\.\s/.test(lines[i].trim())) {
|
|
1100
|
-
const itemText = lines[i].trim().replace(/^\d+\.\s/, "");
|
|
1101
|
-
const inlineContent = await parseInlineFormatting(itemText, instance);
|
|
1102
|
-
listItems.push({
|
|
1103
|
-
type: "listItem",
|
|
1104
|
-
content: [{ type: "paragraph", content: inlineContent }],
|
|
1105
|
-
});
|
|
1106
|
-
i++;
|
|
1107
|
-
}
|
|
1108
|
-
content.push({ type: "orderedList", content: listItems });
|
|
1142
|
+
// --- Lists (bullet -,*,+ or ordered 1./1)) with nesting ---
|
|
1143
|
+
const listStart = listItemMatch(line);
|
|
1144
|
+
if (listStart) {
|
|
1145
|
+
const { node, nextIndex } = await parseListBlock(
|
|
1146
|
+
lines,
|
|
1147
|
+
i,
|
|
1148
|
+
listStart.indent,
|
|
1149
|
+
instance,
|
|
1150
|
+
);
|
|
1151
|
+
content.push(node);
|
|
1152
|
+
i = nextIndex;
|
|
1109
1153
|
continue;
|
|
1110
1154
|
}
|
|
1111
1155
|
|
|
@@ -1115,13 +1159,12 @@ async function buildCommentADF(text, instance = defaultInstance) {
|
|
|
1115
1159
|
i < lines.length &&
|
|
1116
1160
|
lines[i].trim() &&
|
|
1117
1161
|
!lines[i].trim().startsWith("```") &&
|
|
1118
|
-
|
|
1119
|
-
!lines[i].trim().startsWith("## ") &&
|
|
1120
|
-
!lines[i].trim().startsWith("### ") &&
|
|
1162
|
+
!/^#{1,6}\s/.test(lines[i].trim()) &&
|
|
1121
1163
|
!lines[i].trim().startsWith("> ") &&
|
|
1122
|
-
!lines[i]
|
|
1123
|
-
!/^\d+\.\s/.test(lines[i].trim()) &&
|
|
1164
|
+
!listItemMatch(lines[i]) &&
|
|
1124
1165
|
!/^-{3,}$/.test(lines[i].trim()) &&
|
|
1166
|
+
!/^\*{3,}$/.test(lines[i].trim()) &&
|
|
1167
|
+
!/^_{3,}$/.test(lines[i].trim()) &&
|
|
1125
1168
|
!(lines[i].trim().startsWith("|") && lines[i].trim().endsWith("|"))
|
|
1126
1169
|
) {
|
|
1127
1170
|
if (paragraphContent.length > 0) paragraphContent.push({ type: "hardBreak" });
|
|
@@ -1985,9 +2028,20 @@ async function getChangelogsBulk(jql, maxResults = 50, instance = defaultInstanc
|
|
|
1985
2028
|
|
|
1986
2029
|
// ============ MCP SERVER ============
|
|
1987
2030
|
|
|
2031
|
+
const SERVER_INSTRUCTIONS = `# jira-mcp usage rules
|
|
2032
|
+
|
|
2033
|
+
- \`instance\` (optional, on most tools): multi-instance setups only. Omit it — it auto-detects from the issue key prefix, else uses the default instance.
|
|
2034
|
+
- \`dryRun\` (optional, on mutating tools): if true, returns the HTTP request that would be sent (method, endpoint, body) without calling Atlassian. Multi-step tools only show the first write.
|
|
2035
|
+
${confluenceMode !== "always" ? "- Confluence tools are hidden until activated: call `confluence_enable` first when a task needs Confluence (pages, spaces, page comments, labels, attachments).\n" : ""}
|
|
2036
|
+
## Writing Jira comments (jira_add_comment / jira_reply_comment / jira_edit_comment)
|
|
2037
|
+
Write one short conversational paragraph: start with @DisplayName of who to notify (NOT [~accountId:...] syntax), say what changed, and end with the next step (e.g. 'Ready for verification.'). Keep it HIGH LEVEL for stakeholders/PO/QA — WHAT changed and the impact, not how it was built. Include technical detail (endpoints, payloads, API contracts) ONLY when the reader is a developer and it makes sense; otherwise leave out code, file paths, branch names, commit hashes, and framework-internal terms. NEVER use em dashes (—) or en dashes (–) — use commas, periods, or rewrite. Avoid bullet lists, headings, and bold unless the update genuinely needs them.
|
|
2038
|
+
|
|
2039
|
+
## Writing descriptions (jira_create_ticket / jira_update_ticket / jira_create_subtask)
|
|
2040
|
+
Structure with Markdown: a one/two-sentence overview, then ## / ### headings (Overview, Details, Acceptance Criteria), '-' bullet lists, numbered steps, tables for structured data, **bold** key terms, fenced \`\`\` blocks for code/payloads. Blank line between blocks. Concise and scannable. Never use em/en dashes.`;
|
|
2041
|
+
|
|
1988
2042
|
const server = new Server(
|
|
1989
2043
|
{ name: "jira-mcp", version: "1.0.0" },
|
|
1990
|
-
{ capabilities: { tools: {} } },
|
|
2044
|
+
{ capabilities: { tools: { listChanged: true } }, instructions: SERVER_INSTRUCTIONS },
|
|
1991
2045
|
);
|
|
1992
2046
|
|
|
1993
2047
|
// Inject `dryRun` into the schema of any mutating tool so MCP clients with
|
|
@@ -2006,13 +2060,16 @@ function _injectDryRunSchema(tool) {
|
|
|
2006
2060
|
...props,
|
|
2007
2061
|
dryRun: {
|
|
2008
2062
|
type: "boolean",
|
|
2009
|
-
description: "
|
|
2063
|
+
description: "Preview: return the would-be HTTP request without executing.",
|
|
2010
2064
|
},
|
|
2011
2065
|
},
|
|
2012
2066
|
},
|
|
2013
2067
|
};
|
|
2014
2068
|
}
|
|
2015
2069
|
|
|
2070
|
+
// Additive formatting guidance moved to SERVER_INSTRUCTIONS to reduce per-tool
|
|
2071
|
+
// token cost. Field descriptions retain their short base text only.
|
|
2072
|
+
|
|
2016
2073
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2017
2074
|
const rawTools = [
|
|
2018
2075
|
{
|
|
@@ -2024,7 +2081,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2024
2081
|
properties: {
|
|
2025
2082
|
instance: {
|
|
2026
2083
|
type: "string",
|
|
2027
|
-
description: "Instance name (
|
|
2084
|
+
description: "Instance name (optional).",
|
|
2028
2085
|
},
|
|
2029
2086
|
},
|
|
2030
2087
|
required: [],
|
|
@@ -2052,7 +2109,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2052
2109
|
},
|
|
2053
2110
|
instance: {
|
|
2054
2111
|
type: "string",
|
|
2055
|
-
description: "Instance name
|
|
2112
|
+
description: "Instance name (optional).",
|
|
2056
2113
|
},
|
|
2057
2114
|
},
|
|
2058
2115
|
required: ["issueKey"],
|
|
@@ -2078,7 +2135,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2078
2135
|
},
|
|
2079
2136
|
instance: {
|
|
2080
2137
|
type: "string",
|
|
2081
|
-
description: "Instance name (
|
|
2138
|
+
description: "Instance name (optional).",
|
|
2082
2139
|
},
|
|
2083
2140
|
},
|
|
2084
2141
|
required: ["jql"],
|
|
@@ -2087,7 +2144,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2087
2144
|
{
|
|
2088
2145
|
name: "jira_add_comment",
|
|
2089
2146
|
description:
|
|
2090
|
-
"Add a comment to a Jira ticket.
|
|
2147
|
+
"Add a comment to a Jira ticket. Follow the server instructions' comment style rules.",
|
|
2091
2148
|
inputSchema: {
|
|
2092
2149
|
type: "object",
|
|
2093
2150
|
properties: {
|
|
@@ -2095,10 +2152,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2095
2152
|
type: "string",
|
|
2096
2153
|
description: "The Jira issue key (e.g., MODS-123)",
|
|
2097
2154
|
},
|
|
2098
|
-
comment: {
|
|
2155
|
+
comment: {
|
|
2156
|
+
type: "string",
|
|
2157
|
+
description: "The comment text to add.",
|
|
2158
|
+
},
|
|
2099
2159
|
instance: {
|
|
2100
2160
|
type: "string",
|
|
2101
|
-
description: "Instance name
|
|
2161
|
+
description: "Instance name (optional).",
|
|
2102
2162
|
},
|
|
2103
2163
|
},
|
|
2104
2164
|
required: ["issueKey", "comment"],
|
|
@@ -2120,10 +2180,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2120
2180
|
description:
|
|
2121
2181
|
"The ID of the comment to reply to. Use jira_get_ticket to see comments and their IDs.",
|
|
2122
2182
|
},
|
|
2123
|
-
reply: {
|
|
2183
|
+
reply: {
|
|
2184
|
+
type: "string",
|
|
2185
|
+
description: "The reply text.",
|
|
2186
|
+
},
|
|
2124
2187
|
instance: {
|
|
2125
2188
|
type: "string",
|
|
2126
|
-
description: "Instance name
|
|
2189
|
+
description: "Instance name (optional).",
|
|
2127
2190
|
},
|
|
2128
2191
|
},
|
|
2129
2192
|
required: ["issueKey", "commentId", "reply"],
|
|
@@ -2132,7 +2195,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2132
2195
|
{
|
|
2133
2196
|
name: "jira_edit_comment",
|
|
2134
2197
|
description:
|
|
2135
|
-
"Edit an existing comment on a Jira ticket
|
|
2198
|
+
"Edit an existing comment on a Jira ticket (replaces the text). Follow the server instructions' comment style rules.",
|
|
2136
2199
|
inputSchema: {
|
|
2137
2200
|
type: "object",
|
|
2138
2201
|
properties: {
|
|
@@ -2145,10 +2208,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2145
2208
|
description:
|
|
2146
2209
|
"The ID of the comment to edit. Use jira_get_ticket to see comments and their IDs.",
|
|
2147
2210
|
},
|
|
2148
|
-
comment: {
|
|
2211
|
+
comment: {
|
|
2212
|
+
type: "string",
|
|
2213
|
+
description: "The new comment text.",
|
|
2214
|
+
},
|
|
2149
2215
|
instance: {
|
|
2150
2216
|
type: "string",
|
|
2151
|
-
description: "Instance name
|
|
2217
|
+
description: "Instance name (optional).",
|
|
2152
2218
|
},
|
|
2153
2219
|
},
|
|
2154
2220
|
required: ["issueKey", "commentId", "comment"],
|
|
@@ -2172,7 +2238,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2172
2238
|
},
|
|
2173
2239
|
instance: {
|
|
2174
2240
|
type: "string",
|
|
2175
|
-
description: "Instance name
|
|
2241
|
+
description: "Instance name (optional).",
|
|
2176
2242
|
},
|
|
2177
2243
|
},
|
|
2178
2244
|
required: ["issueKey", "commentId"],
|
|
@@ -2201,7 +2267,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2201
2267
|
},
|
|
2202
2268
|
instance: {
|
|
2203
2269
|
type: "string",
|
|
2204
|
-
description: "Instance name
|
|
2270
|
+
description: "Instance name (optional).",
|
|
2205
2271
|
},
|
|
2206
2272
|
},
|
|
2207
2273
|
required: ["issueKey"],
|
|
@@ -2262,7 +2328,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2262
2328
|
},
|
|
2263
2329
|
instance: {
|
|
2264
2330
|
type: "string",
|
|
2265
|
-
description: "Instance name
|
|
2331
|
+
description: "Instance name (optional).",
|
|
2266
2332
|
},
|
|
2267
2333
|
},
|
|
2268
2334
|
required: ["issueKey"],
|
|
@@ -2286,7 +2352,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2286
2352
|
},
|
|
2287
2353
|
instance: {
|
|
2288
2354
|
type: "string",
|
|
2289
|
-
description: "Instance name (
|
|
2355
|
+
description: "Instance name (optional).",
|
|
2290
2356
|
},
|
|
2291
2357
|
},
|
|
2292
2358
|
required: ["query"],
|
|
@@ -2316,7 +2382,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2316
2382
|
},
|
|
2317
2383
|
instance: {
|
|
2318
2384
|
type: "string",
|
|
2319
|
-
description: "Instance name (
|
|
2385
|
+
description: "Instance name (optional).",
|
|
2320
2386
|
},
|
|
2321
2387
|
},
|
|
2322
2388
|
required: [],
|
|
@@ -2408,7 +2474,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2408
2474
|
},
|
|
2409
2475
|
instance: {
|
|
2410
2476
|
type: "string",
|
|
2411
|
-
description: "Instance name
|
|
2477
|
+
description: "Instance name (optional).",
|
|
2412
2478
|
},
|
|
2413
2479
|
},
|
|
2414
2480
|
required: [],
|
|
@@ -2435,7 +2501,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2435
2501
|
},
|
|
2436
2502
|
description: {
|
|
2437
2503
|
type: "string",
|
|
2438
|
-
description:
|
|
2504
|
+
description:
|
|
2505
|
+
"The issue description text. Supports @mentions via @DisplayName.",
|
|
2439
2506
|
},
|
|
2440
2507
|
assignee: {
|
|
2441
2508
|
type: "string",
|
|
@@ -2478,7 +2545,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2478
2545
|
},
|
|
2479
2546
|
instance: {
|
|
2480
2547
|
type: "string",
|
|
2481
|
-
description: "Instance name
|
|
2548
|
+
description: "Instance name (optional).",
|
|
2482
2549
|
},
|
|
2483
2550
|
},
|
|
2484
2551
|
required: ["projectKey", "issueType", "summary"],
|
|
@@ -2501,7 +2568,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2501
2568
|
},
|
|
2502
2569
|
description: {
|
|
2503
2570
|
type: "string",
|
|
2504
|
-
description:
|
|
2571
|
+
description:
|
|
2572
|
+
"The subtask description text. Supports @mentions via @DisplayName.",
|
|
2505
2573
|
},
|
|
2506
2574
|
assignee: {
|
|
2507
2575
|
type: "string",
|
|
@@ -2522,7 +2590,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2522
2590
|
},
|
|
2523
2591
|
instance: {
|
|
2524
2592
|
type: "string",
|
|
2525
|
-
description: "Instance name
|
|
2593
|
+
description: "Instance name (optional).",
|
|
2526
2594
|
},
|
|
2527
2595
|
},
|
|
2528
2596
|
required: ["parentKey", "summary"],
|
|
@@ -2553,7 +2621,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2553
2621
|
},
|
|
2554
2622
|
instance: {
|
|
2555
2623
|
type: "string",
|
|
2556
|
-
description: "Instance name
|
|
2624
|
+
description: "Instance name (optional).",
|
|
2557
2625
|
},
|
|
2558
2626
|
},
|
|
2559
2627
|
required: ["inwardIssueKey", "outwardIssueKey", "linkType"],
|
|
@@ -2576,7 +2644,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2576
2644
|
},
|
|
2577
2645
|
instance: {
|
|
2578
2646
|
type: "string",
|
|
2579
|
-
description: "Instance name
|
|
2647
|
+
description: "Instance name (optional).",
|
|
2580
2648
|
},
|
|
2581
2649
|
},
|
|
2582
2650
|
required: ["issueKey"],
|
|
@@ -2607,7 +2675,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2607
2675
|
},
|
|
2608
2676
|
instance: {
|
|
2609
2677
|
type: "string",
|
|
2610
|
-
description: "Instance name
|
|
2678
|
+
description: "Instance name (optional).",
|
|
2611
2679
|
},
|
|
2612
2680
|
},
|
|
2613
2681
|
required: ["issueKey"],
|
|
@@ -2622,7 +2690,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2622
2690
|
properties: {
|
|
2623
2691
|
instance: {
|
|
2624
2692
|
type: "string",
|
|
2625
|
-
description: "Instance name (
|
|
2693
|
+
description: "Instance name (optional).",
|
|
2626
2694
|
},
|
|
2627
2695
|
},
|
|
2628
2696
|
required: [],
|
|
@@ -2641,7 +2709,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2641
2709
|
},
|
|
2642
2710
|
instance: {
|
|
2643
2711
|
type: "string",
|
|
2644
|
-
description: "Instance name
|
|
2712
|
+
description: "Instance name (optional).",
|
|
2645
2713
|
},
|
|
2646
2714
|
},
|
|
2647
2715
|
required: ["issueKey"],
|
|
@@ -2664,7 +2732,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2664
2732
|
},
|
|
2665
2733
|
instance: {
|
|
2666
2734
|
type: "string",
|
|
2667
|
-
description: "Instance name
|
|
2735
|
+
description: "Instance name (optional).",
|
|
2668
2736
|
},
|
|
2669
2737
|
},
|
|
2670
2738
|
required: ["issueKey", "linkedIssueKey"],
|
|
@@ -2691,7 +2759,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2691
2759
|
},
|
|
2692
2760
|
instance: {
|
|
2693
2761
|
type: "string",
|
|
2694
|
-
description: "Instance name
|
|
2762
|
+
description: "Instance name (optional).",
|
|
2695
2763
|
},
|
|
2696
2764
|
},
|
|
2697
2765
|
required: [],
|
|
@@ -2714,7 +2782,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2714
2782
|
},
|
|
2715
2783
|
instance: {
|
|
2716
2784
|
type: "string",
|
|
2717
|
-
description: "Instance name
|
|
2785
|
+
description: "Instance name (optional).",
|
|
2718
2786
|
},
|
|
2719
2787
|
},
|
|
2720
2788
|
required: ["issueKey", "accountId"],
|
|
@@ -2737,7 +2805,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2737
2805
|
},
|
|
2738
2806
|
instance: {
|
|
2739
2807
|
type: "string",
|
|
2740
|
-
description: "Instance name
|
|
2808
|
+
description: "Instance name (optional).",
|
|
2741
2809
|
},
|
|
2742
2810
|
},
|
|
2743
2811
|
required: ["issueKey", "accountId"],
|
|
@@ -2768,7 +2836,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2768
2836
|
},
|
|
2769
2837
|
instance: {
|
|
2770
2838
|
type: "string",
|
|
2771
|
-
description: "Instance name
|
|
2839
|
+
description: "Instance name (optional).",
|
|
2772
2840
|
},
|
|
2773
2841
|
},
|
|
2774
2842
|
required: ["issueKey", "timeSpent"],
|
|
@@ -2787,7 +2855,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2787
2855
|
},
|
|
2788
2856
|
instance: {
|
|
2789
2857
|
type: "string",
|
|
2790
|
-
description: "Instance name
|
|
2858
|
+
description: "Instance name (optional).",
|
|
2791
2859
|
},
|
|
2792
2860
|
},
|
|
2793
2861
|
required: ["issueKey"],
|
|
@@ -2818,7 +2886,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2818
2886
|
},
|
|
2819
2887
|
instance: {
|
|
2820
2888
|
type: "string",
|
|
2821
|
-
description: "Instance name
|
|
2889
|
+
description: "Instance name (optional).",
|
|
2822
2890
|
},
|
|
2823
2891
|
},
|
|
2824
2892
|
required: ["issueKey"],
|
|
@@ -2842,7 +2910,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2842
2910
|
},
|
|
2843
2911
|
instance: {
|
|
2844
2912
|
type: "string",
|
|
2845
|
-
description: "Instance name (
|
|
2913
|
+
description: "Instance name (optional).",
|
|
2846
2914
|
},
|
|
2847
2915
|
},
|
|
2848
2916
|
required: ["sprintId", "issueKeys"],
|
|
@@ -2865,7 +2933,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2865
2933
|
},
|
|
2866
2934
|
instance: {
|
|
2867
2935
|
type: "string",
|
|
2868
|
-
description: "Instance name (
|
|
2936
|
+
description: "Instance name (optional).",
|
|
2869
2937
|
},
|
|
2870
2938
|
},
|
|
2871
2939
|
required: ["boardId"],
|
|
@@ -2892,7 +2960,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2892
2960
|
},
|
|
2893
2961
|
instance: {
|
|
2894
2962
|
type: "string",
|
|
2895
|
-
description: "Instance name (
|
|
2963
|
+
description: "Instance name (optional).",
|
|
2896
2964
|
},
|
|
2897
2965
|
},
|
|
2898
2966
|
required: [],
|
|
@@ -2911,7 +2979,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2911
2979
|
},
|
|
2912
2980
|
instance: {
|
|
2913
2981
|
type: "string",
|
|
2914
|
-
description: "Instance name
|
|
2982
|
+
description: "Instance name (optional).",
|
|
2915
2983
|
},
|
|
2916
2984
|
},
|
|
2917
2985
|
required: ["projectKey"],
|
|
@@ -2926,7 +2994,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2926
2994
|
properties: {
|
|
2927
2995
|
instance: {
|
|
2928
2996
|
type: "string",
|
|
2929
|
-
description: "Instance name (
|
|
2997
|
+
description: "Instance name (optional).",
|
|
2930
2998
|
},
|
|
2931
2999
|
},
|
|
2932
3000
|
required: [],
|
|
@@ -2945,7 +3013,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2945
3013
|
},
|
|
2946
3014
|
instance: {
|
|
2947
3015
|
type: "string",
|
|
2948
|
-
description: "Instance name
|
|
3016
|
+
description: "Instance name (optional).",
|
|
2949
3017
|
},
|
|
2950
3018
|
},
|
|
2951
3019
|
required: ["projectKey"],
|
|
@@ -2964,7 +3032,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2964
3032
|
},
|
|
2965
3033
|
instance: {
|
|
2966
3034
|
type: "string",
|
|
2967
|
-
description: "Instance name
|
|
3035
|
+
description: "Instance name (optional).",
|
|
2968
3036
|
},
|
|
2969
3037
|
},
|
|
2970
3038
|
required: ["projectKey"],
|
|
@@ -2979,7 +3047,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2979
3047
|
properties: {
|
|
2980
3048
|
instance: {
|
|
2981
3049
|
type: "string",
|
|
2982
|
-
description: "Instance name
|
|
3050
|
+
description: "Instance name (optional).",
|
|
2983
3051
|
},
|
|
2984
3052
|
},
|
|
2985
3053
|
required: [],
|
|
@@ -2993,7 +3061,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2993
3061
|
type: "object",
|
|
2994
3062
|
properties: {
|
|
2995
3063
|
spaceKey: { type: "string", description: "Space key (e.g., 'ENG')." },
|
|
2996
|
-
instance: { type: "string", description: "Instance name
|
|
3064
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
2997
3065
|
},
|
|
2998
3066
|
required: ["spaceKey"],
|
|
2999
3067
|
},
|
|
@@ -3008,7 +3076,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3008
3076
|
spaceKey: { type: "string", description: "Unique space key (letters/numbers). Will be uppercased." },
|
|
3009
3077
|
name: { type: "string", description: "Human-readable space name." },
|
|
3010
3078
|
description: { type: "string", description: "Optional plain-text description." },
|
|
3011
|
-
instance: { type: "string", description: "Instance name
|
|
3079
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3012
3080
|
},
|
|
3013
3081
|
required: ["spaceKey", "name"],
|
|
3014
3082
|
},
|
|
@@ -3023,7 +3091,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3023
3091
|
spaceKey: { type: "string", description: "Space key to update." },
|
|
3024
3092
|
name: { type: "string", description: "New space name." },
|
|
3025
3093
|
description: { type: "string", description: "New plain-text description." },
|
|
3026
|
-
instance: { type: "string", description: "Instance name
|
|
3094
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3027
3095
|
},
|
|
3028
3096
|
required: ["spaceKey"],
|
|
3029
3097
|
},
|
|
@@ -3036,7 +3104,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3036
3104
|
type: "object",
|
|
3037
3105
|
properties: {
|
|
3038
3106
|
spaceKey: { type: "string", description: "Space key to delete." },
|
|
3039
|
-
instance: { type: "string", description: "Instance name
|
|
3107
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3040
3108
|
},
|
|
3041
3109
|
required: ["spaceKey"],
|
|
3042
3110
|
},
|
|
@@ -3052,7 +3120,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3052
3120
|
spaceKey: { type: "string", description: "Optional space key to scope the search." },
|
|
3053
3121
|
type: { type: "string", description: "Content type (default: page). e.g. page, blogpost, comment, attachment." },
|
|
3054
3122
|
limit: { type: "number", description: "Max results (default: 25)." },
|
|
3055
|
-
instance: { type: "string", description: "Instance name
|
|
3123
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3056
3124
|
},
|
|
3057
3125
|
required: ["query"],
|
|
3058
3126
|
},
|
|
@@ -3067,7 +3135,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3067
3135
|
spaceKey: { type: "string", description: "Optional space key to scope the query." },
|
|
3068
3136
|
sinceDays: { type: "number", description: "Days back from now (default: 30)." },
|
|
3069
3137
|
limit: { type: "number", description: "Max results (default: 25)." },
|
|
3070
|
-
instance: { type: "string", description: "Instance name
|
|
3138
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3071
3139
|
},
|
|
3072
3140
|
required: [],
|
|
3073
3141
|
},
|
|
@@ -3081,7 +3149,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3081
3149
|
properties: {
|
|
3082
3150
|
spaceKey: { type: "string", description: "Space key (required)." },
|
|
3083
3151
|
limit: { type: "number", description: "Max results (default: 50)." },
|
|
3084
|
-
instance: { type: "string", description: "Instance name
|
|
3152
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3085
3153
|
},
|
|
3086
3154
|
required: ["spaceKey"],
|
|
3087
3155
|
},
|
|
@@ -3095,7 +3163,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3095
3163
|
properties: {
|
|
3096
3164
|
pageId: { type: "string", description: "Parent page ID (required)." },
|
|
3097
3165
|
limit: { type: "number", description: "Max results (default: 50)." },
|
|
3098
|
-
instance: { type: "string", description: "Instance name
|
|
3166
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3099
3167
|
},
|
|
3100
3168
|
required: ["pageId"],
|
|
3101
3169
|
},
|
|
@@ -3109,7 +3177,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3109
3177
|
properties: {
|
|
3110
3178
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3111
3179
|
includeAdf: { type: "boolean", description: "Fetch ADF body via v2 API and merge (default: true)." },
|
|
3112
|
-
instance: { type: "string", description: "Instance name
|
|
3180
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3113
3181
|
},
|
|
3114
3182
|
required: ["pageId"],
|
|
3115
3183
|
},
|
|
@@ -3123,7 +3191,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3123
3191
|
properties: {
|
|
3124
3192
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3125
3193
|
limit: { type: "number", description: "Max results (default: 50)." },
|
|
3126
|
-
instance: { type: "string", description: "Instance name
|
|
3194
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3127
3195
|
},
|
|
3128
3196
|
required: ["pageId"],
|
|
3129
3197
|
},
|
|
@@ -3138,7 +3206,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3138
3206
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3139
3207
|
body: { type: "string", description: "Comment body (plain text by default, or storage XHTML if format=storage)." },
|
|
3140
3208
|
format: { type: "string", description: "'text' (default) or 'storage'." },
|
|
3141
|
-
instance: { type: "string", description: "Instance name
|
|
3209
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3142
3210
|
},
|
|
3143
3211
|
required: ["pageId", "body"],
|
|
3144
3212
|
},
|
|
@@ -3154,7 +3222,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3154
3222
|
title: { type: "string", description: "New page title (optional — retains current if omitted)." },
|
|
3155
3223
|
body: { type: "string", description: "New body as storage XHTML (optional — retains current if omitted)." },
|
|
3156
3224
|
version: { type: "number", description: "Explicit new version number. If omitted, current+1 is computed." },
|
|
3157
|
-
instance: { type: "string", description: "Instance name
|
|
3225
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3158
3226
|
},
|
|
3159
3227
|
required: ["pageId"],
|
|
3160
3228
|
},
|
|
@@ -3170,7 +3238,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3170
3238
|
title: { type: "string", description: "Page title (required)." },
|
|
3171
3239
|
body: { type: "string", description: "Storage-format XHTML body (required)." },
|
|
3172
3240
|
parentId: { type: "string", description: "Optional parent page ID to nest under." },
|
|
3173
|
-
instance: { type: "string", description: "Instance name
|
|
3241
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3174
3242
|
},
|
|
3175
3243
|
required: ["spaceKey", "title", "body"],
|
|
3176
3244
|
},
|
|
@@ -3182,7 +3250,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3182
3250
|
type: "object",
|
|
3183
3251
|
properties: {
|
|
3184
3252
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3185
|
-
instance: { type: "string", description: "Instance name
|
|
3253
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3186
3254
|
},
|
|
3187
3255
|
required: ["pageId"],
|
|
3188
3256
|
},
|
|
@@ -3194,7 +3262,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3194
3262
|
type: "object",
|
|
3195
3263
|
properties: {
|
|
3196
3264
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3197
|
-
instance: { type: "string", description: "Instance name
|
|
3265
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3198
3266
|
},
|
|
3199
3267
|
required: ["pageId"],
|
|
3200
3268
|
},
|
|
@@ -3207,7 +3275,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3207
3275
|
properties: {
|
|
3208
3276
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3209
3277
|
label: { type: "string", description: "Label name (required)." },
|
|
3210
|
-
instance: { type: "string", description: "Instance name
|
|
3278
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3211
3279
|
},
|
|
3212
3280
|
required: ["pageId", "label"],
|
|
3213
3281
|
},
|
|
@@ -3220,7 +3288,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3220
3288
|
properties: {
|
|
3221
3289
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3222
3290
|
label: { type: "string", description: "Label name (required)." },
|
|
3223
|
-
instance: { type: "string", description: "Instance name
|
|
3291
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3224
3292
|
},
|
|
3225
3293
|
required: ["pageId", "label"],
|
|
3226
3294
|
},
|
|
@@ -3233,7 +3301,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3233
3301
|
properties: {
|
|
3234
3302
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3235
3303
|
limit: { type: "number", description: "Max results (default: 50)." },
|
|
3236
|
-
instance: { type: "string", description: "Instance name
|
|
3304
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3237
3305
|
},
|
|
3238
3306
|
required: ["pageId"],
|
|
3239
3307
|
},
|
|
@@ -3250,7 +3318,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3250
3318
|
fileContent: { type: "string", description: "Base64-encoded file content (requires fileName)." },
|
|
3251
3319
|
fileName: { type: "string", description: "File name (required with fileContent; optional with filePath)." },
|
|
3252
3320
|
comment: { type: "string", description: "Optional attachment comment." },
|
|
3253
|
-
instance: { type: "string", description: "Instance name
|
|
3321
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3254
3322
|
},
|
|
3255
3323
|
required: ["pageId"],
|
|
3256
3324
|
},
|
|
@@ -3264,13 +3332,22 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3264
3332
|
properties: {
|
|
3265
3333
|
pageId: { type: "string", description: "Page ID (required)." },
|
|
3266
3334
|
filename: { type: "string", description: "Attachment filename (required)." },
|
|
3267
|
-
instance: { type: "string", description: "Instance name
|
|
3335
|
+
instance: { type: "string", description: "Instance name (optional)." },
|
|
3268
3336
|
},
|
|
3269
3337
|
required: ["pageId", "filename"],
|
|
3270
3338
|
},
|
|
3271
3339
|
},
|
|
3272
3340
|
];
|
|
3273
|
-
|
|
3341
|
+
let tools = rawTools;
|
|
3342
|
+
if (!confluenceActive) {
|
|
3343
|
+
tools = rawTools.filter(t => !t.name.startsWith("confluence_"));
|
|
3344
|
+
tools.push({
|
|
3345
|
+
name: "confluence_enable",
|
|
3346
|
+
description: "Activate the Confluence tool set (pages, spaces, page comments, labels, attachments, search). Call this first when a task needs Confluence; the confluence_* tools then become available. Activation only changes tool visibility for this server process; per-instance scopes still apply to every Confluence operation.",
|
|
3347
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
3348
|
+
});
|
|
3349
|
+
}
|
|
3350
|
+
return { tools: tools.map(_injectDryRunSchema) };
|
|
3274
3351
|
});
|
|
3275
3352
|
|
|
3276
3353
|
async function runWithPolicy(name, args, handler) {
|
|
@@ -3388,6 +3465,19 @@ async function runWithPolicy(name, args, handler) {
|
|
|
3388
3465
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
3389
3466
|
const { name, arguments: args } = request.params;
|
|
3390
3467
|
|
|
3468
|
+
if (name === "confluence_enable") {
|
|
3469
|
+
const wasActive = confluenceActive;
|
|
3470
|
+
confluenceActive = true;
|
|
3471
|
+
if (!wasActive) server.sendToolListChanged().catch((e) => console.error("jira-mcp: tools/list_changed notification failed:", e?.message || e));
|
|
3472
|
+
return { content: [{ type: "text", text: wasActive ? "Confluence tools were already active." : "Confluence tools activated — the confluence_* tools are now available." }] };
|
|
3473
|
+
}
|
|
3474
|
+
// A client with a cached tool list may call a confluence_* tool directly
|
|
3475
|
+
// while hidden — auto-activate instead of failing.
|
|
3476
|
+
if (!confluenceActive && TOOL_METADATA[name]?.product === "confluence" && name !== "confluence_enable") {
|
|
3477
|
+
confluenceActive = true;
|
|
3478
|
+
server.sendToolListChanged().catch((e) => console.error("jira-mcp: tools/list_changed notification failed:", e?.message || e));
|
|
3479
|
+
}
|
|
3480
|
+
|
|
3391
3481
|
return runWithPolicy(name, args, async () => {
|
|
3392
3482
|
if (name === "jira_get_myself") {
|
|
3393
3483
|
const inst = getInstanceByName(args.instance);
|
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.7",
|
|
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": {
|