@rui.branco/jira-mcp 1.6.10 → 1.6.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +33 -27
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1527,7 +1527,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1527
1527
  {
1528
1528
  name: "jira_add_instance",
1529
1529
  description:
1530
- "Add or update a Jira instance configuration. Saves to config and makes it available immediately without restart. Use this to connect to a new Jira instance during a session.",
1530
+ "Add or update a Jira instance configuration. Saves to config and makes it available immediately without restart. To add a new instance, provide name + email + token + baseUrl. To update an existing instance (e.g. change projects or set as default), just provide name and the fields to change.",
1531
1531
  inputSchema: {
1532
1532
  type: "object",
1533
1533
  properties: {
@@ -1537,27 +1537,27 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1537
1537
  },
1538
1538
  email: {
1539
1539
  type: "string",
1540
- description: "Jira account email",
1540
+ description: "Jira account email (required for new instances)",
1541
1541
  },
1542
1542
  token: {
1543
1543
  type: "string",
1544
- description: "Jira API token (from https://id.atlassian.com/manage-profile/security/api-tokens)",
1544
+ description: "Jira API token (required for new instances)",
1545
1545
  },
1546
1546
  baseUrl: {
1547
1547
  type: "string",
1548
- description: "Jira base URL (e.g., https://company.atlassian.net)",
1548
+ description: "Jira base URL (required for new instances, e.g., https://company.atlassian.net)",
1549
1549
  },
1550
1550
  projects: {
1551
1551
  type: "array",
1552
1552
  items: { type: "string" },
1553
- description: "Project key prefixes to auto-route to this instance (e.g., ['PROJ', 'ENG'])",
1553
+ description: "Project key prefixes to auto-route to this instance (e.g., ['PROJ', 'ENG']). Replaces existing projects.",
1554
1554
  },
1555
1555
  setDefault: {
1556
1556
  type: "boolean",
1557
1557
  description: "Set this instance as the default (default: false)",
1558
1558
  },
1559
1559
  },
1560
- required: ["name", "email", "token", "baseUrl"],
1560
+ required: ["name"],
1561
1561
  },
1562
1562
  },
1563
1563
  {
@@ -1635,6 +1635,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1635
1635
  ],
1636
1636
  };
1637
1637
  } else if (name === "jira_get_ticket") {
1638
+ if (!args.issueKey) {
1639
+ return { content: [{ type: "text", text: "Error: Missing required parameter 'issueKey'. You passed 'ticketId' which is not a valid parameter. Use 'issueKey' instead (e.g. issueKey: \"MODS-12115\")." }] };
1640
+ }
1638
1641
  const downloadImages = args.downloadImages !== false;
1639
1642
  const fetchFigma = args.fetchFigma !== false;
1640
1643
  const inst = args.instance ? getInstanceByName(args.instance) : null;
@@ -2035,31 +2038,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2035
2038
  }
2036
2039
  } else if (name === "jira_add_instance") {
2037
2040
  const instName = args.name.trim();
2038
- const projects = (args.projects || []).map((p) => p.toUpperCase());
2039
- const authStr = Buffer.from(`${args.email}:${args.token}`).toString("base64");
2040
- const newInstance = {
2041
- name: instName,
2042
- email: args.email,
2043
- token: args.token,
2044
- baseUrl: args.baseUrl.replace(/\/$/, ""),
2045
- projects,
2046
- auth: authStr,
2047
- };
2041
+ const existingIdx = instances.findIndex((i) => i.name === instName);
2042
+ const isUpdate = existingIdx >= 0;
2043
+
2044
+ // For new instances, email/token/baseUrl are required
2045
+ if (!isUpdate && (!args.email || !args.token || !args.baseUrl)) {
2046
+ return {
2047
+ content: [{ type: "text", text: "New instance requires email, token, and baseUrl." }],
2048
+ isError: true,
2049
+ };
2050
+ }
2051
+
2052
+ // Merge with existing or create new
2053
+ const existing = isUpdate ? instances[existingIdx] : {};
2054
+ const email = args.email || existing.email;
2055
+ const token = args.token || existing.token;
2056
+ const baseUrl = args.baseUrl ? args.baseUrl.replace(/\/$/, "") : existing.baseUrl;
2057
+ const projects = args.projects ? args.projects.map((p) => p.toUpperCase()) : (existing.projects || []);
2058
+ const authStr = Buffer.from(`${email}:${token}`).toString("base64");
2059
+
2060
+ const newInstance = { name: instName, email, token, baseUrl, projects, auth: authStr };
2048
2061
 
2049
2062
  // Update in-memory instances
2050
- const existingIdx = instances.findIndex((i) => i.name === instName);
2051
- if (existingIdx >= 0) {
2063
+ if (isUpdate) {
2052
2064
  instances[existingIdx] = newInstance;
2053
2065
  } else {
2054
2066
  instances.push(newInstance);
2055
2067
  }
2056
2068
 
2057
- // Update default if requested or if it's the first instance
2058
- if (args.setDefault || instances.length === 1) {
2059
- // Can't reassign const, but defaultInstance is used via getInstanceByName/getInstanceForKey
2060
- // which search the instances array, so this is handled by rawConfig.defaultInstance below
2061
- }
2062
-
2063
2069
  // Persist to config file
2064
2070
  const savedConfig = loadConfigFile();
2065
2071
  if (!savedConfig.instances) {
@@ -2082,7 +2088,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2082
2088
  }
2083
2089
 
2084
2090
  // Save without the computed auth field
2085
- const toSave = { name: instName, email: args.email, token: args.token, baseUrl: newInstance.baseUrl, projects };
2091
+ const toSave = { name: instName, email, token, baseUrl, projects };
2086
2092
  const savedIdx = savedConfig.instances.findIndex((i) => i.name === instName);
2087
2093
  if (savedIdx >= 0) {
2088
2094
  savedConfig.instances[savedIdx] = toSave;
@@ -2094,8 +2100,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2094
2100
  }
2095
2101
  fs.writeFileSync(jiraConfigPath, JSON.stringify(savedConfig, null, 2));
2096
2102
 
2097
- const action = existingIdx >= 0 ? "Updated" : "Added";
2098
- let text = `${action} instance "${instName}" (${newInstance.baseUrl}).`;
2103
+ const action = isUpdate ? "Updated" : "Added";
2104
+ let text = `${action} instance "${instName}" (${baseUrl}).`;
2099
2105
  if (projects.length > 0) text += ` Projects: ${projects.join(", ")}.`;
2100
2106
  if (args.setDefault) text += " Set as default.";
2101
2107
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rui.branco/jira-mcp",
3
- "version": "1.6.10",
3
+ "version": "1.6.12",
4
4
  "description": "Jira MCP server for Claude Code - fetch tickets, search with JQL, update tickets, manage comments, change status, and get Figma designs",
5
5
  "main": "index.js",
6
6
  "bin": {