@aashari/mcp-server-atlassian-jira
Version:
Node.js/TypeScript MCP server for Atlassian Jira. Equips AI systems (LLMs) with tools to list/get projects, search/get issues (using JQL/ID), and view dev info (commits, PRs). Connects AI capabilities directly into Jira project management and issue tracki
158 lines (157 loc) • 6.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const logger_util_js_1 = require("../utils/logger.util.js");
const transport_util_js_1 = require("../utils/transport.util.js");
const error_util_js_1 = require("../utils/error.util.js");
// Create a contextualized logger for this file
const serviceLogger = logger_util_js_1.Logger.forContext('services/vendor.atlassian.issues.service.ts');
// Log service initialization
serviceLogger.debug('Jira issues service initialized');
/**
* Base API path for Jira REST API v3
* @see https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/
* @constant {string}
*/
const API_PATH = '/rest/api/3';
/**
* @namespace VendorAtlassianIssuesService
* @description Service for interacting with Jira Issues API.
* Provides methods for searching issues and retrieving issue details.
* All methods require valid Atlassian credentials configured in the environment.
*/
/**
* Search Jira issues with JQL and optional filtering and pagination
*
* Retrieves a list of issues from Jira based on JQL query with support for various filters
* and pagination options. Issues can be filtered by fields, properties, etc.
*
* @async
* @memberof VendorAtlassianIssuesService
* @param {SearchIssuesParams} [params={}] - Optional parameters for customizing the request
* @param {string} [params.jql] - JQL query string to filter issues
* @param {number} [params.startAt] - Pagination start index
* @param {number} [params.maxResults] - Maximum number of results to return
* @param {string[]} [params.fields] - Fields to include in the response
* @param {string[]} [params.expand] - Fields to expand in the response
* @param {boolean} [params.validateQuery] - Whether to validate the JQL query
* @param {string[]} [params.properties] - Properties to include in the response
* @param {boolean} [params.fieldsByKeys] - Whether to return fields by keys
* @param {string} [params.nextPageToken] - Token for retrieving the next page of results
* @param {boolean} [params.reconcileIssues] - Whether to reconcile issues
* @returns {Promise<IssuesResponse>} Promise containing the issues response with results and pagination info
* @throws {Error} If Atlassian credentials are missing or API request fails
* @example
* // Search for issues in a specific project
* const response = await search({
* jql: 'project = HSP',
* maxResults: 10
* });
*/
async function search(params = {}) {
const methodLogger = logger_util_js_1.Logger.forContext('services/vendor.atlassian.issues.service.ts', 'search');
methodLogger.debug('Searching Jira issues with params:', params);
const credentials = (0, transport_util_js_1.getAtlassianCredentials)();
if (!credentials) {
throw (0, error_util_js_1.createAuthMissingError)('Search issues');
}
// Build query parameters
const queryParams = new URLSearchParams();
// JQL query
if (params.jql) {
queryParams.set('jql', params.jql);
}
// Pagination
if (params.startAt !== undefined) {
queryParams.set('startAt', params.startAt.toString());
}
if (params.maxResults !== undefined) {
queryParams.set('maxResults', params.maxResults.toString());
}
// Fields and expansion
if (params.fields?.length) {
queryParams.set('fields', params.fields.join(','));
}
if (params.expand?.length) {
queryParams.set('expand', params.expand.join(','));
}
// Additional options
if (params.validateQuery !== undefined) {
queryParams.set('validateQuery', params.validateQuery.toString());
}
if (params.properties?.length) {
queryParams.set('properties', params.properties.join(','));
}
if (params.fieldsByKeys !== undefined) {
queryParams.set('fieldsByKeys', params.fieldsByKeys.toString());
}
if (params.nextPageToken) {
queryParams.set('nextPageToken', params.nextPageToken);
}
if (params.reconcileIssues !== undefined) {
queryParams.set('reconcileIssues', params.reconcileIssues.toString());
}
const queryString = queryParams.toString()
? `?${queryParams.toString()}`
: '';
const path = `${API_PATH}/search${queryString}`;
methodLogger.debug(`Calling Jira API: ${path}`);
return (0, transport_util_js_1.fetchAtlassian)(credentials, path);
}
/**
* Get detailed information about a specific Jira issue
*
* Retrieves comprehensive details about a single issue, including fields,
* comments, attachments, and other metadata.
*
* @async
* @memberof VendorAtlassianIssuesService
* @param {string} idOrKey - The ID or key of the issue to retrieve
* @param {GetIssueByIdParams} [params={}] - Optional parameters for customizing the response
* @param {string[]} [params.fields] - Fields to include in the response
* @param {string[]} [params.expand] - Fields to expand in the response
* @param {string[]} [params.properties] - Properties to include in the response
* @param {boolean} [params.fieldsByKeys] - Whether to return fields by keys
* @param {boolean} [params.updateHistory] - Whether to update the issue view history
* @returns {Promise<Issue>} Promise containing the detailed issue information
* @throws {Error} If Atlassian credentials are missing or API request fails
* @example
* // Get issue details with specific fields
* const issue = await get('HSP-123', {
* fields: ['summary', 'description', 'status'],
* updateHistory: true
* });
*/
async function get(idOrKey, params = {}) {
const methodLogger = logger_util_js_1.Logger.forContext('services/vendor.atlassian.issues.service.ts', 'get');
methodLogger.debug(`Getting Jira issue ${idOrKey}`);
const credentials = (0, transport_util_js_1.getAtlassianCredentials)();
if (!credentials) {
throw (0, error_util_js_1.createAuthMissingError)(`Get issue ${idOrKey}`);
}
// Build query parameters
const queryParams = new URLSearchParams();
// Fields and expansion
if (params.fields?.length) {
queryParams.set('fields', params.fields.join(','));
}
if (params.expand?.length) {
queryParams.set('expand', params.expand.join(','));
}
// Additional options
if (params.properties?.length) {
queryParams.set('properties', params.properties.join(','));
}
if (params.fieldsByKeys !== undefined) {
queryParams.set('fieldsByKeys', params.fieldsByKeys.toString());
}
if (params.updateHistory !== undefined) {
queryParams.set('updateHistory', params.updateHistory.toString());
}
const queryString = queryParams.toString()
? `?${queryParams.toString()}`
: '';
const path = `${API_PATH}/issue/${encodeURIComponent(idOrKey)}${queryString}`;
methodLogger.debug(`Calling Jira API: ${path}`);
return (0, transport_util_js_1.fetchAtlassian)(credentials, path);
}
exports.default = { search, get };