mcp-jira-stdio 1.4.0 → 1.5.2
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/dist/index.js +365 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -439,7 +439,7 @@ var require_package2 = __commonJS({
|
|
|
439
439
|
"package.json"(exports, module) {
|
|
440
440
|
module.exports = {
|
|
441
441
|
name: "mcp-jira-stdio",
|
|
442
|
-
version: "1.
|
|
442
|
+
version: "1.5.2",
|
|
443
443
|
description: "Model Context Protocol (MCP) server for Jira API integration",
|
|
444
444
|
author: "graslt",
|
|
445
445
|
license: "MIT",
|
|
@@ -555,7 +555,9 @@ var TOOL_NAMES = {
|
|
|
555
555
|
UPDATE_ISSUE: "jira_update_issue",
|
|
556
556
|
ADD_COMMENT: "jira_add_comment",
|
|
557
557
|
GET_PROJECT_INFO: "jira_get_project_info",
|
|
558
|
-
CREATE_SUBTASK: "jira_create_subtask"
|
|
558
|
+
CREATE_SUBTASK: "jira_create_subtask",
|
|
559
|
+
GET_CREATE_META: "jira_get_create_meta",
|
|
560
|
+
GET_CUSTOM_FIELDS: "jira_get_custom_fields"
|
|
559
561
|
};
|
|
560
562
|
|
|
561
563
|
// src/utils/logger.ts
|
|
@@ -813,8 +815,16 @@ var CreateSubtaskInputSchema = z.object({
|
|
|
813
815
|
labels: z.array(z.string()).optional().describe("Subtask labels"),
|
|
814
816
|
components: z.array(z.string()).optional().describe("Component names")
|
|
815
817
|
});
|
|
818
|
+
var GetCreateMetaInputSchema = z.object({
|
|
819
|
+
projectKey: z.string().describe("Project key to get create metadata for").refine((v) => isValidProjectKey(v), "Invalid project key format"),
|
|
820
|
+
issueTypeName: z.string().optional().describe("Specific issue type name to get metadata for (optional)")
|
|
821
|
+
});
|
|
822
|
+
var GetCustomFieldsInputSchema = z.object({
|
|
823
|
+
projectKey: z.string().optional().describe("Project key to filter custom fields (optional)").refine((v) => v ? isValidProjectKey(v) : true, "Invalid project key format")
|
|
824
|
+
});
|
|
816
825
|
|
|
817
826
|
// src/utils/api-helpers.ts
|
|
827
|
+
var log2 = createLogger("api-helpers");
|
|
818
828
|
function ensureAdfDescription(desc) {
|
|
819
829
|
if (!desc) return desc;
|
|
820
830
|
if (typeof desc === "object") return desc;
|
|
@@ -929,20 +939,32 @@ function ensureAdfDescription(desc) {
|
|
|
929
939
|
return { type: "doc", version: 1, content };
|
|
930
940
|
}
|
|
931
941
|
async function getVisibleProjects(options = {}) {
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
942
|
+
const allProjects = [];
|
|
943
|
+
let startAt = 0;
|
|
944
|
+
let isLast = false;
|
|
945
|
+
while (!isLast) {
|
|
946
|
+
const params = {
|
|
947
|
+
startAt,
|
|
948
|
+
maxResults: 50
|
|
949
|
+
// Jira default, fetch 50 projects per page
|
|
950
|
+
};
|
|
951
|
+
if (options.expand) {
|
|
952
|
+
params.expand = options.expand.join(",");
|
|
953
|
+
}
|
|
954
|
+
if (options.recent) {
|
|
955
|
+
params.recent = options.recent;
|
|
956
|
+
}
|
|
957
|
+
const config = {
|
|
958
|
+
method: "GET",
|
|
959
|
+
url: "/project/search",
|
|
960
|
+
params
|
|
961
|
+
};
|
|
962
|
+
const response = await makeJiraRequest(config);
|
|
963
|
+
allProjects.push(...response.values);
|
|
964
|
+
isLast = response.isLast;
|
|
965
|
+
startAt += response.maxResults;
|
|
938
966
|
}
|
|
939
|
-
|
|
940
|
-
method: "GET",
|
|
941
|
-
url: "/project/search",
|
|
942
|
-
params
|
|
943
|
-
};
|
|
944
|
-
const response = await makeJiraRequest(config);
|
|
945
|
-
return response.values;
|
|
967
|
+
return allProjects;
|
|
946
968
|
}
|
|
947
969
|
async function getIssue(issueKey, options = {}) {
|
|
948
970
|
const params = {};
|
|
@@ -1125,7 +1147,10 @@ async function getStatuses(options = {}) {
|
|
|
1125
1147
|
return await makeJiraRequest(config);
|
|
1126
1148
|
}
|
|
1127
1149
|
async function addComment(issueKey, body, visibility) {
|
|
1128
|
-
const
|
|
1150
|
+
const adfBody = ensureAdfDescription(body);
|
|
1151
|
+
const data = {
|
|
1152
|
+
body: adfBody
|
|
1153
|
+
};
|
|
1129
1154
|
if (visibility) {
|
|
1130
1155
|
data.visibility = visibility;
|
|
1131
1156
|
}
|
|
@@ -1185,6 +1210,81 @@ async function createSubtask(parentIssueKey, subtaskData) {
|
|
|
1185
1210
|
const response = await makeJiraRequest(config);
|
|
1186
1211
|
return await getIssue(response.key);
|
|
1187
1212
|
}
|
|
1213
|
+
async function getCreateMeta(options = {}) {
|
|
1214
|
+
if (options.projectKeys && options.projectKeys.length === 1) {
|
|
1215
|
+
const projectKey = options.projectKeys[0];
|
|
1216
|
+
const allIssueTypes = await getIssueTypes(projectKey);
|
|
1217
|
+
let issueTypesToFetch = allIssueTypes;
|
|
1218
|
+
if (options.issueTypeNames && options.issueTypeNames.length > 0) {
|
|
1219
|
+
issueTypesToFetch = allIssueTypes.filter(
|
|
1220
|
+
(type) => options.issueTypeNames?.includes(type.name)
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
const issueTypesWithFields = [];
|
|
1224
|
+
for (const issueType of issueTypesToFetch) {
|
|
1225
|
+
try {
|
|
1226
|
+
const config2 = {
|
|
1227
|
+
method: "GET",
|
|
1228
|
+
url: `/issue/createmeta/${projectKey}/issuetypes/${issueType.id}`
|
|
1229
|
+
};
|
|
1230
|
+
const issueTypeMetadata = await makeJiraRequest(config2);
|
|
1231
|
+
const fieldsMap = {};
|
|
1232
|
+
if (issueTypeMetadata.values && Array.isArray(issueTypeMetadata.values)) {
|
|
1233
|
+
for (const field of issueTypeMetadata.values) {
|
|
1234
|
+
const fieldKey = field.key || field.fieldId || field.name;
|
|
1235
|
+
if (fieldKey) {
|
|
1236
|
+
fieldsMap[fieldKey] = field;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
issueTypesWithFields.push({
|
|
1241
|
+
id: issueType.id,
|
|
1242
|
+
name: issueType.name,
|
|
1243
|
+
description: issueType.description,
|
|
1244
|
+
iconUrl: issueType.iconUrl,
|
|
1245
|
+
subtask: issueType.subtask,
|
|
1246
|
+
fields: fieldsMap
|
|
1247
|
+
});
|
|
1248
|
+
} catch (error) {
|
|
1249
|
+
log2.error(`Failed to get metadata for issue type ${issueType.name}:`, error);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
const projectDetails = await getProjectDetails(projectKey);
|
|
1253
|
+
return {
|
|
1254
|
+
projects: [
|
|
1255
|
+
{
|
|
1256
|
+
id: projectDetails.id,
|
|
1257
|
+
key: projectDetails.key,
|
|
1258
|
+
name: projectDetails.name,
|
|
1259
|
+
issuetypes: issueTypesWithFields
|
|
1260
|
+
}
|
|
1261
|
+
]
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
const params = {};
|
|
1265
|
+
if (options.projectKeys && options.projectKeys.length > 0) {
|
|
1266
|
+
params.projectKeys = options.projectKeys.join(",");
|
|
1267
|
+
}
|
|
1268
|
+
if (options.issueTypeNames && options.issueTypeNames.length > 0) {
|
|
1269
|
+
params.issuetypeNames = options.issueTypeNames.join(",");
|
|
1270
|
+
}
|
|
1271
|
+
if (options.expand) {
|
|
1272
|
+
params.expand = options.expand;
|
|
1273
|
+
}
|
|
1274
|
+
const config = {
|
|
1275
|
+
method: "GET",
|
|
1276
|
+
url: "/issue/createmeta",
|
|
1277
|
+
params
|
|
1278
|
+
};
|
|
1279
|
+
return await makeJiraRequest(config);
|
|
1280
|
+
}
|
|
1281
|
+
async function getFields() {
|
|
1282
|
+
const config = {
|
|
1283
|
+
method: "GET",
|
|
1284
|
+
url: "/field"
|
|
1285
|
+
};
|
|
1286
|
+
return await makeJiraRequest(config);
|
|
1287
|
+
}
|
|
1188
1288
|
|
|
1189
1289
|
// src/utils/redaction.ts
|
|
1190
1290
|
function isRedactionEnabled() {
|
|
@@ -1307,9 +1407,12 @@ function formatSearchResultsResponse(result) {
|
|
|
1307
1407
|
};
|
|
1308
1408
|
}
|
|
1309
1409
|
const issuesList = result.issues.map((issue) => {
|
|
1310
|
-
const assignee = issue.fields
|
|
1311
|
-
|
|
1312
|
-
|
|
1410
|
+
const assignee = issue.fields?.assignee?.displayName || "Unassigned";
|
|
1411
|
+
const summary = issue.fields?.summary || "No summary";
|
|
1412
|
+
const status = issue.fields?.status?.name || "Unknown";
|
|
1413
|
+
const priority = issue.fields?.priority?.name || "None";
|
|
1414
|
+
return `\u2022 **${issue.key}** - ${summary}
|
|
1415
|
+
Status: ${status} | Assignee: ${assignee} | Priority: ${priority}`;
|
|
1313
1416
|
}).join("\n\n");
|
|
1314
1417
|
const rangeStart = result.startAt + 1;
|
|
1315
1418
|
const rangeEnd = Math.min(result.startAt + result.maxResults, result.total);
|
|
@@ -1339,23 +1442,34 @@ ${issuesList}${paginationInfo}`
|
|
|
1339
1442
|
}
|
|
1340
1443
|
function formatErrorResponse(error) {
|
|
1341
1444
|
let errorMessage = "An unexpected error occurred.";
|
|
1445
|
+
let hasCustomFieldError = false;
|
|
1342
1446
|
if (typeof error === "string") {
|
|
1343
1447
|
errorMessage = error;
|
|
1448
|
+
hasCustomFieldError = error.includes("customfield_");
|
|
1344
1449
|
} else if (error instanceof Error) {
|
|
1345
1450
|
errorMessage = error.message;
|
|
1451
|
+
hasCustomFieldError = error.message.includes("customfield_");
|
|
1346
1452
|
} else if (error?.response?.data) {
|
|
1347
1453
|
const jiraError = error.response.data;
|
|
1348
1454
|
if (jiraError.errorMessages && jiraError.errorMessages.length > 0) {
|
|
1349
1455
|
errorMessage = jiraError.errorMessages.join(", ");
|
|
1350
1456
|
} else if (jiraError.errors) {
|
|
1351
|
-
|
|
1457
|
+
const errors = Object.entries(jiraError.errors);
|
|
1458
|
+
errorMessage = errors.map(([field, message]) => `${field}: ${message}`).join(", ");
|
|
1459
|
+
hasCustomFieldError = errors.some(([field]) => field.startsWith("customfield_"));
|
|
1352
1460
|
}
|
|
1353
1461
|
}
|
|
1462
|
+
let hint = "";
|
|
1463
|
+
if (hasCustomFieldError) {
|
|
1464
|
+
hint = `
|
|
1465
|
+
|
|
1466
|
+
\u{1F4A1} **Hint:** This error involves custom fields. Use 'jira_get_create_meta' tool to discover required fields and their allowed values before creating an issue.`;
|
|
1467
|
+
}
|
|
1354
1468
|
return {
|
|
1355
1469
|
content: [
|
|
1356
1470
|
{
|
|
1357
1471
|
type: "text",
|
|
1358
|
-
text: `\u274C Error: ${errorMessage}`
|
|
1472
|
+
text: `\u274C Error: ${errorMessage}${hint}`
|
|
1359
1473
|
}
|
|
1360
1474
|
]
|
|
1361
1475
|
};
|
|
@@ -1522,9 +1636,99 @@ Last Updated: ${new Date(project.insight.lastIssueUpdateTime).toISOString()}` :
|
|
|
1522
1636
|
]
|
|
1523
1637
|
};
|
|
1524
1638
|
}
|
|
1639
|
+
function formatCreateMetaResponse(meta) {
|
|
1640
|
+
if (!meta.projects || meta.projects.length === 0) {
|
|
1641
|
+
return {
|
|
1642
|
+
content: [
|
|
1643
|
+
{
|
|
1644
|
+
type: "text",
|
|
1645
|
+
text: "No create metadata found for the specified project."
|
|
1646
|
+
}
|
|
1647
|
+
]
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
const project = meta.projects[0];
|
|
1651
|
+
if (!project) {
|
|
1652
|
+
return {
|
|
1653
|
+
content: [
|
|
1654
|
+
{
|
|
1655
|
+
type: "text",
|
|
1656
|
+
text: "No create metadata found for the specified project."
|
|
1657
|
+
}
|
|
1658
|
+
]
|
|
1659
|
+
};
|
|
1660
|
+
}
|
|
1661
|
+
const issueTypesList = project.issuetypes.map((issueType) => {
|
|
1662
|
+
const requiredFields = [];
|
|
1663
|
+
const optionalFields = [];
|
|
1664
|
+
Object.entries(issueType.fields).forEach(([fieldKey, field]) => {
|
|
1665
|
+
const allowedValuesText = field.allowedValues ? `
|
|
1666
|
+
Allowed values: ${field.allowedValues.map((v) => v.name || v.value || v.id).join(", ")}` : "";
|
|
1667
|
+
const defaultValueText = field.hasDefaultValue ? `
|
|
1668
|
+
Default: ${JSON.stringify(field.defaultValue)}` : "";
|
|
1669
|
+
const fieldInfo = ` \u2022 **${field.name}** (${fieldKey})
|
|
1670
|
+
Type: ${field.schema.type}${allowedValuesText}${defaultValueText}`;
|
|
1671
|
+
if (field.required) {
|
|
1672
|
+
requiredFields.push(fieldInfo);
|
|
1673
|
+
} else {
|
|
1674
|
+
optionalFields.push(fieldInfo);
|
|
1675
|
+
}
|
|
1676
|
+
});
|
|
1677
|
+
const requiredSection = requiredFields.length > 0 ? `**Required Fields:**
|
|
1678
|
+
${requiredFields.join("\n\n")}` : "No required fields";
|
|
1679
|
+
const optionalSection = optionalFields.length > 0 ? `
|
|
1680
|
+
|
|
1681
|
+
**Optional Fields:**
|
|
1682
|
+
${optionalFields.join("\n\n")}` : "";
|
|
1683
|
+
return `### ${issueType.name} (${issueType.subtask ? "Subtask" : "Issue"})
|
|
1684
|
+
${issueType.description}
|
|
1685
|
+
|
|
1686
|
+
${requiredSection}${optionalSection}`;
|
|
1687
|
+
}).join("\n\n---\n\n");
|
|
1688
|
+
return {
|
|
1689
|
+
content: [
|
|
1690
|
+
{
|
|
1691
|
+
type: "text",
|
|
1692
|
+
text: `**Create Metadata for Project: ${project.name} (${project.key})**
|
|
1693
|
+
|
|
1694
|
+
${issueTypesList}`
|
|
1695
|
+
}
|
|
1696
|
+
]
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
function formatCustomFieldsResponse(fields, projectKey) {
|
|
1700
|
+
const customFields = fields.filter((field) => field.custom);
|
|
1701
|
+
if (customFields.length === 0) {
|
|
1702
|
+
return {
|
|
1703
|
+
content: [
|
|
1704
|
+
{
|
|
1705
|
+
type: "text",
|
|
1706
|
+
text: projectKey ? `No custom fields found for project ${projectKey}.` : "No custom fields found."
|
|
1707
|
+
}
|
|
1708
|
+
]
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
const fieldsList = customFields.map((field) => {
|
|
1712
|
+
const schemaInfo = field.schema.custom ? `Custom Type: ${field.schema.custom}` : `Type: ${field.schema.type}`;
|
|
1713
|
+
return `\u2022 **${field.name}** (${field.key})
|
|
1714
|
+
${schemaInfo}
|
|
1715
|
+
ID: ${field.id}`;
|
|
1716
|
+
}).join("\n\n");
|
|
1717
|
+
const header = projectKey ? `Found ${customFields.length} custom field(s) for project ${projectKey}:` : `Found ${customFields.length} custom field(s):`;
|
|
1718
|
+
return {
|
|
1719
|
+
content: [
|
|
1720
|
+
{
|
|
1721
|
+
type: "text",
|
|
1722
|
+
text: `${header}
|
|
1723
|
+
|
|
1724
|
+
${fieldsList}`
|
|
1725
|
+
}
|
|
1726
|
+
]
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1525
1729
|
|
|
1526
1730
|
// src/utils/error-handler.ts
|
|
1527
|
-
var
|
|
1731
|
+
var log3 = createLogger("error-handler");
|
|
1528
1732
|
var JiraApiError = class extends Error {
|
|
1529
1733
|
constructor(message, statusCode, jiraErrors, originalError) {
|
|
1530
1734
|
super(message);
|
|
@@ -1535,7 +1739,7 @@ var JiraApiError = class extends Error {
|
|
|
1535
1739
|
}
|
|
1536
1740
|
};
|
|
1537
1741
|
function handleError(error) {
|
|
1538
|
-
|
|
1742
|
+
log3.error("Tool error:", error);
|
|
1539
1743
|
if (typeof error === "string") {
|
|
1540
1744
|
return formatErrorResponse(error);
|
|
1541
1745
|
}
|
|
@@ -1572,7 +1776,7 @@ function handleError(error) {
|
|
|
1572
1776
|
}
|
|
1573
1777
|
|
|
1574
1778
|
// src/tools/get-visible-projects.ts
|
|
1575
|
-
var
|
|
1779
|
+
var log4 = createLogger("tool:get-visible-projects");
|
|
1576
1780
|
var getVisibleProjectsTool = {
|
|
1577
1781
|
name: TOOL_NAMES.GET_VISIBLE_PROJECTS,
|
|
1578
1782
|
description: "Retrieves all projects accessible to the authenticated user. Returns project keys, names, descriptions, and basic metadata.",
|
|
@@ -1598,21 +1802,21 @@ var getVisibleProjectsTool = {
|
|
|
1598
1802
|
async function handleGetVisibleProjects(input) {
|
|
1599
1803
|
try {
|
|
1600
1804
|
const validated = validateInput(GetVisibleProjectsInputSchema, input);
|
|
1601
|
-
|
|
1805
|
+
log4.info("Getting visible projects...");
|
|
1602
1806
|
const getParams = {};
|
|
1603
1807
|
if (validated.expand !== void 0) getParams.expand = validated.expand;
|
|
1604
1808
|
if (validated.recent !== void 0) getParams.recent = validated.recent;
|
|
1605
1809
|
const projects = await getVisibleProjects(getParams);
|
|
1606
|
-
|
|
1810
|
+
log4.info(`Found ${projects.length} project(s)`);
|
|
1607
1811
|
return formatProjectsResponse(projects);
|
|
1608
1812
|
} catch (error) {
|
|
1609
|
-
|
|
1813
|
+
log4.error("Error in handleGetVisibleProjects:", error);
|
|
1610
1814
|
return handleError(error);
|
|
1611
1815
|
}
|
|
1612
1816
|
}
|
|
1613
1817
|
|
|
1614
1818
|
// src/tools/get-issue.ts
|
|
1615
|
-
var
|
|
1819
|
+
var log5 = createLogger("tool:get-issue");
|
|
1616
1820
|
var getIssueTool = {
|
|
1617
1821
|
name: TOOL_NAMES.GET_ISSUE,
|
|
1618
1822
|
description: 'Retrieve details for a specific Jira issue by key or URL. Use this when the user mentions an issue like "PAYWALL-943" or pastes a Jira link (e.g., https://your.atlassian.net/browse/PAYWALL-943). Returns status, assignee, priority, project, type, labels, components, timestamps, and description.',
|
|
@@ -1643,21 +1847,21 @@ async function handleGetIssue(input) {
|
|
|
1643
1847
|
const validated = validateInput(GetIssueInputSchema, input);
|
|
1644
1848
|
const trimmedInput = (validated.issueKey || "").trim();
|
|
1645
1849
|
const key = extractIssueKey(trimmedInput) || trimmedInput;
|
|
1646
|
-
|
|
1850
|
+
log5.info(`Getting issue ${key}...`);
|
|
1647
1851
|
const getParams = {};
|
|
1648
1852
|
if (validated.expand !== void 0) getParams.expand = validated.expand;
|
|
1649
1853
|
if (validated.fields !== void 0) getParams.fields = validated.fields;
|
|
1650
1854
|
const issue = await getIssue(key, getParams);
|
|
1651
|
-
|
|
1855
|
+
log5.info(`Retrieved issue ${issue.key}`);
|
|
1652
1856
|
return formatIssueResponse(issue);
|
|
1653
1857
|
} catch (error) {
|
|
1654
|
-
|
|
1858
|
+
log5.error("Error in handleGetIssue:", error);
|
|
1655
1859
|
return handleError(error);
|
|
1656
1860
|
}
|
|
1657
1861
|
}
|
|
1658
1862
|
|
|
1659
1863
|
// src/tools/search-issues.ts
|
|
1660
|
-
var
|
|
1864
|
+
var log6 = createLogger("tool:search-issues");
|
|
1661
1865
|
var searchIssuesTool = {
|
|
1662
1866
|
name: TOOL_NAMES.SEARCH_ISSUES,
|
|
1663
1867
|
description: 'Search for Jira issues using JQL. Supports complex queries with pagination and field selection. Examples: "project = PROJECT AND status = Open", "assignee = currentUser()". For pagination, use nextPageToken from previous response.',
|
|
@@ -1697,7 +1901,7 @@ var searchIssuesTool = {
|
|
|
1697
1901
|
async function handleSearchIssues(input) {
|
|
1698
1902
|
try {
|
|
1699
1903
|
const validated = validateInput(SearchIssuesInputSchema, input);
|
|
1700
|
-
|
|
1904
|
+
log6.info(`Searching issues with JQL: "${validated.jql}"...`);
|
|
1701
1905
|
const searchParams = {
|
|
1702
1906
|
jql: validated.jql
|
|
1703
1907
|
};
|
|
@@ -1706,16 +1910,16 @@ async function handleSearchIssues(input) {
|
|
|
1706
1910
|
if (validated.fields !== void 0) searchParams.fields = validated.fields;
|
|
1707
1911
|
if (validated.expand !== void 0) searchParams.expand = validated.expand;
|
|
1708
1912
|
const result = await searchIssues(searchParams);
|
|
1709
|
-
|
|
1913
|
+
log6.info(`Found ${result.total} issue(s), showing ${result.issues.length}`);
|
|
1710
1914
|
return formatSearchResultsResponse(result);
|
|
1711
1915
|
} catch (error) {
|
|
1712
|
-
|
|
1916
|
+
log6.error("Error in handleSearchIssues:", error);
|
|
1713
1917
|
return handleError(error);
|
|
1714
1918
|
}
|
|
1715
1919
|
}
|
|
1716
1920
|
|
|
1717
1921
|
// src/tools/get-my-issues.ts
|
|
1718
|
-
var
|
|
1922
|
+
var log7 = createLogger("tool:get-my-issues");
|
|
1719
1923
|
var getMyIssuesTool = {
|
|
1720
1924
|
name: TOOL_NAMES.GET_MY_ISSUES,
|
|
1721
1925
|
description: "Retrieves issues assigned to current user, sorted by most recently updated first. Supports pagination and field selection. For pagination, use nextPageToken from previous response.",
|
|
@@ -1751,23 +1955,23 @@ var getMyIssuesTool = {
|
|
|
1751
1955
|
async function handleGetMyIssues(input) {
|
|
1752
1956
|
try {
|
|
1753
1957
|
const validated = validateInput(GetMyIssuesInputSchema, input);
|
|
1754
|
-
|
|
1958
|
+
log7.info("Getting issues assigned to current user...");
|
|
1755
1959
|
const getParams = {};
|
|
1756
1960
|
if (validated.nextPageToken !== void 0) getParams.nextPageToken = validated.nextPageToken;
|
|
1757
1961
|
if (validated.maxResults !== void 0) getParams.maxResults = validated.maxResults;
|
|
1758
1962
|
if (validated.fields !== void 0) getParams.fields = validated.fields;
|
|
1759
1963
|
if (validated.expand !== void 0) getParams.expand = validated.expand;
|
|
1760
1964
|
const result = await getMyIssues(getParams);
|
|
1761
|
-
|
|
1965
|
+
log7.info(`Found ${result.total} issue(s) assigned to you, showing ${result.issues.length}`);
|
|
1762
1966
|
return formatSearchResultsResponse(result);
|
|
1763
1967
|
} catch (error) {
|
|
1764
|
-
|
|
1968
|
+
log7.error("Error in handleGetMyIssues:", error);
|
|
1765
1969
|
return handleError(error);
|
|
1766
1970
|
}
|
|
1767
1971
|
}
|
|
1768
1972
|
|
|
1769
1973
|
// src/tools/get-issue-types.ts
|
|
1770
|
-
var
|
|
1974
|
+
var log8 = createLogger("tool:get-issue-types");
|
|
1771
1975
|
var getIssueTypesTool = {
|
|
1772
1976
|
name: TOOL_NAMES.GET_ISSUE_TYPES,
|
|
1773
1977
|
description: "Retrieves available issue types. Can get global issue types or project-specific issue types including regular issues and subtasks (Bug, Story, Task, Epic, etc.).",
|
|
@@ -1786,21 +1990,21 @@ async function handleGetIssueTypes(input) {
|
|
|
1786
1990
|
try {
|
|
1787
1991
|
const validated = validateInput(GetIssueTypesInputSchema, input);
|
|
1788
1992
|
if (validated.projectKey) {
|
|
1789
|
-
|
|
1993
|
+
log8.info(`Getting issue types for project ${validated.projectKey}...`);
|
|
1790
1994
|
} else {
|
|
1791
|
-
|
|
1995
|
+
log8.info("Getting global issue types...");
|
|
1792
1996
|
}
|
|
1793
1997
|
const issueTypes = await getIssueTypes(validated.projectKey);
|
|
1794
|
-
|
|
1998
|
+
log8.info(`Found ${issueTypes.length} issue type(s)`);
|
|
1795
1999
|
return formatIssueTypesResponse(issueTypes);
|
|
1796
2000
|
} catch (error) {
|
|
1797
|
-
|
|
2001
|
+
log8.error("Error in handleGetIssueTypes:", error);
|
|
1798
2002
|
return handleError(error);
|
|
1799
2003
|
}
|
|
1800
2004
|
}
|
|
1801
2005
|
|
|
1802
2006
|
// src/tools/get-users.ts
|
|
1803
|
-
var
|
|
2007
|
+
var log9 = createLogger("tool:get-users");
|
|
1804
2008
|
var getUsersTool = {
|
|
1805
2009
|
name: TOOL_NAMES.GET_USERS,
|
|
1806
2010
|
description: "Search for users by name, email, username, or account ID. Returns display name, email, account status, and account type. Supports pagination.",
|
|
@@ -1840,13 +2044,13 @@ async function handleGetUsers(input) {
|
|
|
1840
2044
|
try {
|
|
1841
2045
|
const validated = validateInput(GetUsersInputSchema, input);
|
|
1842
2046
|
if (validated.query) {
|
|
1843
|
-
|
|
2047
|
+
log9.info(`Searching users with query: "${validated.query}"...`);
|
|
1844
2048
|
} else if (validated.username) {
|
|
1845
|
-
|
|
2049
|
+
log9.info(`Searching for username: "${validated.username}"...`);
|
|
1846
2050
|
} else if (validated.accountId) {
|
|
1847
|
-
|
|
2051
|
+
log9.info(`Searching for account ID: "${validated.accountId}"...`);
|
|
1848
2052
|
} else {
|
|
1849
|
-
|
|
2053
|
+
log9.info("Getting all users...");
|
|
1850
2054
|
}
|
|
1851
2055
|
const getParams = {};
|
|
1852
2056
|
if (validated.query !== void 0) getParams.query = validated.query;
|
|
@@ -1855,16 +2059,16 @@ async function handleGetUsers(input) {
|
|
|
1855
2059
|
if (validated.startAt !== void 0) getParams.startAt = validated.startAt;
|
|
1856
2060
|
if (validated.maxResults !== void 0) getParams.maxResults = validated.maxResults;
|
|
1857
2061
|
const users = await getUsers(getParams);
|
|
1858
|
-
|
|
2062
|
+
log9.info(`Found ${users.length} user(s)`);
|
|
1859
2063
|
return formatUsersResponse(users);
|
|
1860
2064
|
} catch (error) {
|
|
1861
|
-
|
|
2065
|
+
log9.error("Error in handleGetUsers:", error);
|
|
1862
2066
|
return handleError(error);
|
|
1863
2067
|
}
|
|
1864
2068
|
}
|
|
1865
2069
|
|
|
1866
2070
|
// src/tools/get-priorities.ts
|
|
1867
|
-
var
|
|
2071
|
+
var log10 = createLogger("tool:get-priorities");
|
|
1868
2072
|
var getPrioritiesTool = {
|
|
1869
2073
|
name: TOOL_NAMES.GET_PRIORITIES,
|
|
1870
2074
|
description: "Retrieves available priorities (e.g., Highest, High, Medium, Low, Lowest). Returns IDs, names, and descriptions.",
|
|
@@ -1877,18 +2081,18 @@ var getPrioritiesTool = {
|
|
|
1877
2081
|
async function handleGetPriorities(input) {
|
|
1878
2082
|
try {
|
|
1879
2083
|
validateInput(GetPrioritiesInputSchema, input);
|
|
1880
|
-
|
|
2084
|
+
log10.info("Getting all priority levels...");
|
|
1881
2085
|
const priorities = await getPriorities();
|
|
1882
|
-
|
|
2086
|
+
log10.info(`Found ${priorities.length} priority level(s)`);
|
|
1883
2087
|
return formatPrioritiesResponse(priorities);
|
|
1884
2088
|
} catch (error) {
|
|
1885
|
-
|
|
2089
|
+
log10.error("Error in handleGetPriorities:", error);
|
|
1886
2090
|
return handleError(error);
|
|
1887
2091
|
}
|
|
1888
2092
|
}
|
|
1889
2093
|
|
|
1890
2094
|
// src/tools/get-statuses.ts
|
|
1891
|
-
var
|
|
2095
|
+
var log11 = createLogger("tool:get-statuses");
|
|
1892
2096
|
var getStatusesTool = {
|
|
1893
2097
|
name: TOOL_NAMES.GET_STATUSES,
|
|
1894
2098
|
description: "Retrieves available statuses (global or project-specific, e.g., To Do, In Progress, Done). Returns status categories and workflow information.",
|
|
@@ -1911,28 +2115,28 @@ async function handleGetStatuses(input) {
|
|
|
1911
2115
|
try {
|
|
1912
2116
|
const validated = validateInput(GetStatusesInputSchema, input);
|
|
1913
2117
|
if (validated.projectKey && validated.issueTypeId) {
|
|
1914
|
-
|
|
2118
|
+
log11.info(
|
|
1915
2119
|
`Getting statuses for project ${validated.projectKey} and issue type ${validated.issueTypeId}...`
|
|
1916
2120
|
);
|
|
1917
2121
|
} else if (validated.projectKey) {
|
|
1918
|
-
|
|
2122
|
+
log11.info(`Getting statuses for project ${validated.projectKey}...`);
|
|
1919
2123
|
} else {
|
|
1920
|
-
|
|
2124
|
+
log11.info("Getting global statuses...");
|
|
1921
2125
|
}
|
|
1922
2126
|
const getParams = {};
|
|
1923
2127
|
if (validated.projectKey !== void 0) getParams.projectKey = validated.projectKey;
|
|
1924
2128
|
if (validated.issueTypeId !== void 0) getParams.issueTypeId = validated.issueTypeId;
|
|
1925
2129
|
const statuses = await getStatuses(getParams);
|
|
1926
|
-
|
|
2130
|
+
log11.info(`Found ${statuses.length} status(es)`);
|
|
1927
2131
|
return formatStatusesResponse(statuses);
|
|
1928
2132
|
} catch (error) {
|
|
1929
|
-
|
|
2133
|
+
log11.error("Error in handleGetStatuses:", error);
|
|
1930
2134
|
return handleError(error);
|
|
1931
2135
|
}
|
|
1932
2136
|
}
|
|
1933
2137
|
|
|
1934
2138
|
// src/tools/create-issue.ts
|
|
1935
|
-
var
|
|
2139
|
+
var log12 = createLogger("tool:create-issue");
|
|
1936
2140
|
var createIssueTool = {
|
|
1937
2141
|
name: TOOL_NAMES.CREATE_ISSUE,
|
|
1938
2142
|
description: 'Creates a new Jira issue in the specified project. Supports setting issue type, priority, assignee, labels, components, and custom fields. Description accepts plain text and is auto-formatted to ADF: lines ending with ":" become headings, numbered lines create ordered lists, and URLs are linkified. For required custom fields, supply them via customFields (e.g., { "customfield_12345": { id: "..." } }). Returns the created issue with all details.',
|
|
@@ -1993,7 +2197,7 @@ var createIssueTool = {
|
|
|
1993
2197
|
async function handleCreateIssue(input) {
|
|
1994
2198
|
try {
|
|
1995
2199
|
const validated = validateInput(CreateIssueInputSchema, input);
|
|
1996
|
-
|
|
2200
|
+
log12.info(`Creating issue in project ${validated.projectKey}...`);
|
|
1997
2201
|
const createParams = {
|
|
1998
2202
|
projectKey: validated.projectKey,
|
|
1999
2203
|
summary: validated.summary,
|
|
@@ -2013,20 +2217,20 @@ async function handleCreateIssue(input) {
|
|
|
2013
2217
|
}
|
|
2014
2218
|
if (validated.returnIssue === false) {
|
|
2015
2219
|
const key = typeof issueOrKey === "string" ? issueOrKey : issueOrKey.key;
|
|
2016
|
-
|
|
2220
|
+
log12.info(`Created issue ${key}`);
|
|
2017
2221
|
return formatSuccessResponse(`Issue created: ${key}`);
|
|
2018
2222
|
}
|
|
2019
2223
|
const issue = issueOrKey;
|
|
2020
|
-
|
|
2224
|
+
log12.info(`Created issue ${issue.key}`);
|
|
2021
2225
|
return formatIssueResponse(issue);
|
|
2022
2226
|
} catch (error) {
|
|
2023
|
-
|
|
2227
|
+
log12.error("Error in handleCreateIssue:", error);
|
|
2024
2228
|
return handleError(error);
|
|
2025
2229
|
}
|
|
2026
2230
|
}
|
|
2027
2231
|
|
|
2028
2232
|
// src/tools/update-issue.ts
|
|
2029
|
-
var
|
|
2233
|
+
var log13 = createLogger("tool:update-issue");
|
|
2030
2234
|
var updateIssueTool = {
|
|
2031
2235
|
name: TOOL_NAMES.UPDATE_ISSUE,
|
|
2032
2236
|
description: 'Updates an existing Jira issue by its key. Supports updating summary, description, priority, assignee, labels, and components. Description accepts plain text and is auto-formatted to ADF: headings (lines ending with ":"), numbered/bullet lists, and links. Only specified fields will be updated.',
|
|
@@ -2075,7 +2279,7 @@ var updateIssueTool = {
|
|
|
2075
2279
|
async function handleUpdateIssue(input) {
|
|
2076
2280
|
try {
|
|
2077
2281
|
const validated = validateInput(UpdateIssueInputSchema, input);
|
|
2078
|
-
|
|
2282
|
+
log13.info(`Updating issue ${validated.issueKey}...`);
|
|
2079
2283
|
const updateParams = {};
|
|
2080
2284
|
if (validated.summary !== void 0) updateParams.summary = validated.summary;
|
|
2081
2285
|
if (validated.description !== void 0) updateParams.description = validated.description;
|
|
@@ -2085,20 +2289,20 @@ async function handleUpdateIssue(input) {
|
|
|
2085
2289
|
if (validated.components !== void 0) updateParams.components = validated.components;
|
|
2086
2290
|
await updateIssue(validated.issueKey, updateParams);
|
|
2087
2291
|
if (validated.returnIssue === false) {
|
|
2088
|
-
|
|
2292
|
+
log13.info(`Updated issue ${validated.issueKey}`);
|
|
2089
2293
|
return formatSuccessResponse(`Issue ${validated.issueKey} updated successfully`);
|
|
2090
2294
|
}
|
|
2091
2295
|
const updatedIssue = await getIssue(validated.issueKey);
|
|
2092
|
-
|
|
2296
|
+
log13.info(`Updated issue ${updatedIssue.key}`);
|
|
2093
2297
|
return formatIssueResponse(updatedIssue);
|
|
2094
2298
|
} catch (error) {
|
|
2095
|
-
|
|
2299
|
+
log13.error("Error in handleUpdateIssue:", error);
|
|
2096
2300
|
return handleError(error);
|
|
2097
2301
|
}
|
|
2098
2302
|
}
|
|
2099
2303
|
|
|
2100
2304
|
// src/tools/add-comment.ts
|
|
2101
|
-
var
|
|
2305
|
+
var log14 = createLogger("tool:add-comment");
|
|
2102
2306
|
var addCommentTool = {
|
|
2103
2307
|
name: TOOL_NAMES.ADD_COMMENT,
|
|
2104
2308
|
description: "Adds a comment to an issue. Supports visibility restrictions for groups or roles. Returns the created comment with author details and timestamp.",
|
|
@@ -2137,18 +2341,18 @@ var addCommentTool = {
|
|
|
2137
2341
|
async function handleAddComment(input) {
|
|
2138
2342
|
try {
|
|
2139
2343
|
const validated = validateInput(AddCommentInputSchema, input);
|
|
2140
|
-
|
|
2344
|
+
log14.info(`Adding comment to issue ${validated.issueKey}...`);
|
|
2141
2345
|
const comment = await addComment(validated.issueKey, validated.body, validated.visibility);
|
|
2142
|
-
|
|
2346
|
+
log14.info(`Added comment to ${validated.issueKey}`);
|
|
2143
2347
|
return formatCommentResponse(comment);
|
|
2144
2348
|
} catch (error) {
|
|
2145
|
-
|
|
2349
|
+
log14.error("Error in handleAddComment:", error);
|
|
2146
2350
|
return handleError(error);
|
|
2147
2351
|
}
|
|
2148
2352
|
}
|
|
2149
2353
|
|
|
2150
2354
|
// src/tools/get-project-info.ts
|
|
2151
|
-
var
|
|
2355
|
+
var log15 = createLogger("tool:get-project-info");
|
|
2152
2356
|
var getProjectInfoTool = {
|
|
2153
2357
|
name: TOOL_NAMES.GET_PROJECT_INFO,
|
|
2154
2358
|
description: "Retrieves detailed information about a project (components, versions, issue types, roles, insights). More comprehensive than the basic project list.",
|
|
@@ -2172,18 +2376,18 @@ var getProjectInfoTool = {
|
|
|
2172
2376
|
async function handleGetProjectInfo(input) {
|
|
2173
2377
|
try {
|
|
2174
2378
|
const validated = validateInput(GetProjectInfoInputSchema, input);
|
|
2175
|
-
|
|
2379
|
+
log15.info(`Getting detailed project information for ${validated.projectKey}...`);
|
|
2176
2380
|
const project = await getProjectDetails(validated.projectKey, validated.expand);
|
|
2177
|
-
|
|
2381
|
+
log15.info(`Retrieved project details for ${project.key}`);
|
|
2178
2382
|
return formatProjectDetailsResponse(project);
|
|
2179
2383
|
} catch (error) {
|
|
2180
|
-
|
|
2384
|
+
log15.error("Error in handleGetProjectInfo:", error);
|
|
2181
2385
|
return handleError(error);
|
|
2182
2386
|
}
|
|
2183
2387
|
}
|
|
2184
2388
|
|
|
2185
2389
|
// src/tools/create-subtask.ts
|
|
2186
|
-
var
|
|
2390
|
+
var log16 = createLogger("tool:create-subtask");
|
|
2187
2391
|
var createSubtaskTool = {
|
|
2188
2392
|
name: TOOL_NAMES.CREATE_SUBTASK,
|
|
2189
2393
|
description: "Creates a subtask under an existing parent issue. Automatically determines the correct project and subtask issue type. Supports setting priority, assignee, labels, and components.",
|
|
@@ -2230,7 +2434,7 @@ var createSubtaskTool = {
|
|
|
2230
2434
|
async function handleCreateSubtask(input) {
|
|
2231
2435
|
try {
|
|
2232
2436
|
const validated = validateInput(CreateSubtaskInputSchema, input);
|
|
2233
|
-
|
|
2437
|
+
log16.info(`Creating subtask under parent issue ${validated.parentIssueKey}...`);
|
|
2234
2438
|
const subtaskParams = {
|
|
2235
2439
|
summary: validated.summary
|
|
2236
2440
|
};
|
|
@@ -2240,10 +2444,80 @@ async function handleCreateSubtask(input) {
|
|
|
2240
2444
|
if (validated.labels !== void 0) subtaskParams.labels = validated.labels;
|
|
2241
2445
|
if (validated.components !== void 0) subtaskParams.components = validated.components;
|
|
2242
2446
|
const subtask = await createSubtask(validated.parentIssueKey, subtaskParams);
|
|
2243
|
-
|
|
2447
|
+
log16.info(`Created subtask ${subtask.key}`);
|
|
2244
2448
|
return formatIssueResponse(subtask);
|
|
2245
2449
|
} catch (error) {
|
|
2246
|
-
|
|
2450
|
+
log16.error("Error in handleCreateSubtask:", error);
|
|
2451
|
+
return handleError(error);
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
// src/tools/get-create-meta.ts
|
|
2456
|
+
var log17 = createLogger("tool:get-create-meta");
|
|
2457
|
+
var getCreateMetaTool = {
|
|
2458
|
+
name: TOOL_NAMES.GET_CREATE_META,
|
|
2459
|
+
description: "Retrieves create metadata for a project, showing all available fields (including custom fields) for creating issues. Shows required vs optional fields, field types, and allowed values. Use this before creating issues to discover what fields are needed.",
|
|
2460
|
+
inputSchema: {
|
|
2461
|
+
type: "object",
|
|
2462
|
+
properties: {
|
|
2463
|
+
projectKey: {
|
|
2464
|
+
type: "string",
|
|
2465
|
+
description: "Project key to get create metadata for (e.g., PROJECT)"
|
|
2466
|
+
},
|
|
2467
|
+
issueTypeName: {
|
|
2468
|
+
type: "string",
|
|
2469
|
+
description: "Specific issue type name to get metadata for (optional)"
|
|
2470
|
+
}
|
|
2471
|
+
},
|
|
2472
|
+
required: ["projectKey"]
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
async function handleGetCreateMeta(input) {
|
|
2476
|
+
try {
|
|
2477
|
+
const validated = validateInput(GetCreateMetaInputSchema, input);
|
|
2478
|
+
log17.info(`Getting create metadata for project ${validated.projectKey}...`);
|
|
2479
|
+
const options = {
|
|
2480
|
+
projectKeys: [validated.projectKey],
|
|
2481
|
+
expand: "projects.issuetypes.fields"
|
|
2482
|
+
};
|
|
2483
|
+
if (validated.issueTypeName) {
|
|
2484
|
+
options.issueTypeNames = [validated.issueTypeName];
|
|
2485
|
+
}
|
|
2486
|
+
const meta = await getCreateMeta(options);
|
|
2487
|
+
log17.info(`Retrieved create metadata for ${validated.projectKey}`);
|
|
2488
|
+
return formatCreateMetaResponse(meta);
|
|
2489
|
+
} catch (error) {
|
|
2490
|
+
log17.error("Error in handleGetCreateMeta:", error);
|
|
2491
|
+
return handleError(error);
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
// src/tools/get-custom-fields.ts
|
|
2496
|
+
var log18 = createLogger("tool:get-custom-fields");
|
|
2497
|
+
var getCustomFieldsTool = {
|
|
2498
|
+
name: TOOL_NAMES.GET_CUSTOM_FIELDS,
|
|
2499
|
+
description: "Retrieves all custom fields available in Jira. Shows custom field names, IDs (e.g., customfield_10071), and types. Useful for discovering what custom fields exist and their identifiers.",
|
|
2500
|
+
inputSchema: {
|
|
2501
|
+
type: "object",
|
|
2502
|
+
properties: {
|
|
2503
|
+
projectKey: {
|
|
2504
|
+
type: "string",
|
|
2505
|
+
description: "Project key to filter custom fields (optional)"
|
|
2506
|
+
}
|
|
2507
|
+
},
|
|
2508
|
+
required: []
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2511
|
+
async function handleGetCustomFields(input) {
|
|
2512
|
+
try {
|
|
2513
|
+
const validated = validateInput(GetCustomFieldsInputSchema, input);
|
|
2514
|
+
const projectMsg = validated.projectKey ? ` for project ${validated.projectKey}` : "";
|
|
2515
|
+
log18.info(`Getting custom fields${projectMsg}...`);
|
|
2516
|
+
const fields = await getFields();
|
|
2517
|
+
log18.info(`Retrieved ${fields.filter((f) => f.custom).length} custom fields`);
|
|
2518
|
+
return formatCustomFieldsResponse(fields, validated.projectKey);
|
|
2519
|
+
} catch (error) {
|
|
2520
|
+
log18.error("Error in handleGetCustomFields:", error);
|
|
2247
2521
|
return handleError(error);
|
|
2248
2522
|
}
|
|
2249
2523
|
}
|
|
@@ -2256,7 +2530,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
2256
2530
|
} catch {
|
|
2257
2531
|
}
|
|
2258
2532
|
}
|
|
2259
|
-
var
|
|
2533
|
+
var log19 = createLogger("server");
|
|
2260
2534
|
var toolHandlers = /* @__PURE__ */ new Map([
|
|
2261
2535
|
[TOOL_NAMES.GET_VISIBLE_PROJECTS, handleGetVisibleProjects],
|
|
2262
2536
|
[TOOL_NAMES.GET_ISSUE, handleGetIssue],
|
|
@@ -2270,7 +2544,9 @@ var toolHandlers = /* @__PURE__ */ new Map([
|
|
|
2270
2544
|
[TOOL_NAMES.UPDATE_ISSUE, handleUpdateIssue],
|
|
2271
2545
|
[TOOL_NAMES.ADD_COMMENT, handleAddComment],
|
|
2272
2546
|
[TOOL_NAMES.GET_PROJECT_INFO, handleGetProjectInfo],
|
|
2273
|
-
[TOOL_NAMES.CREATE_SUBTASK, handleCreateSubtask]
|
|
2547
|
+
[TOOL_NAMES.CREATE_SUBTASK, handleCreateSubtask],
|
|
2548
|
+
[TOOL_NAMES.GET_CREATE_META, handleGetCreateMeta],
|
|
2549
|
+
[TOOL_NAMES.GET_CUSTOM_FIELDS, handleGetCustomFields]
|
|
2274
2550
|
]);
|
|
2275
2551
|
var allTools = [
|
|
2276
2552
|
getVisibleProjectsTool,
|
|
@@ -2285,7 +2561,9 @@ var allTools = [
|
|
|
2285
2561
|
updateIssueTool,
|
|
2286
2562
|
addCommentTool,
|
|
2287
2563
|
getProjectInfoTool,
|
|
2288
|
-
createSubtaskTool
|
|
2564
|
+
createSubtaskTool,
|
|
2565
|
+
getCreateMetaTool,
|
|
2566
|
+
getCustomFieldsTool
|
|
2289
2567
|
];
|
|
2290
2568
|
async function main() {
|
|
2291
2569
|
const isDryRun = (process.env.DRY_RUN || "").toLowerCase() === "1" || (process.env.DRY_RUN || "").toLowerCase() === "true";
|
|
@@ -2356,7 +2634,7 @@ async function main() {
|
|
|
2356
2634
|
console.error("\u{1F680} Jira MCP server running on stdio");
|
|
2357
2635
|
}
|
|
2358
2636
|
main().catch((error) => {
|
|
2359
|
-
|
|
2637
|
+
log19.error("Fatal error:", error);
|
|
2360
2638
|
process.exit(1);
|
|
2361
2639
|
});
|
|
2362
2640
|
//# sourceMappingURL=index.js.map
|