Skip to main content
Glama

jira_create_issue

Create new JIRA issues with project details, summaries, issue types, priorities, assignees, and custom fields to track tasks and bugs in development workflows.

Instructions

Creates a new JIRA issue with specified parameters

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectKeyYes
summaryYes
issueTypeYes
descriptionNo
priorityNo
assigneeNo
labelsNo
componentsNo
fixVersionsNo
parentIssueKeyNo
timeEstimateNo
environmentNo
storyPointsNo
customFieldsNo

Implementation Reference

  • The CreateIssueHandler class provides the MCP tool handler logic for 'jira_create_issue'. It validates input parameters using Zod, delegates business logic to CreateIssueUseCase, formats responses, and provides enhanced error messages.
    export class CreateIssueHandler extends BaseToolHandler< CreateIssueParams, string > { private readonly formatter: IssueCreationFormatter; /** * Create a new CreateIssueHandler with necessary dependencies * * @param createIssueUseCase - Use case for creating issues with validation * @param projectValidator - Validator for project-related validation * @param permissionChecker - Checker for permission-related validation */ constructor(private readonly createIssueUseCase: CreateIssueUseCase) { super("JIRA", "Create Issue"); this.formatter = new IssueCreationFormatter(); } /** * Execute the handler logic * Creates a new JIRA issue with comprehensive validation and formatting * Delegates business logic to the use case * * @param params - Parameters for issue creation */ protected async execute(params: CreateIssueParams): Promise<string> { try { // Step 1: Validate parameters const validatedParams = this.validateParameters(params); this.logger.info( `Creating JIRA issue in project: ${validatedParams.projectKey}`, ); // Step 2: Map parameters to use case request const useCaseRequest: CreateIssueUseCaseRequest = { projectKey: validatedParams.projectKey, summary: validatedParams.summary, issueType: validatedParams.issueType, description: validatedParams.description, customFields: validatedParams.customFields, }; // Step 3: Execute the use case this.logger.debug("Delegating to CreateIssueUseCase", { projectKey: validatedParams.projectKey, issueType: validatedParams.issueType, summary: validatedParams.summary, }); const createdIssue = await this.createIssueUseCase.execute(useCaseRequest); // Step 4: Format and return success response this.logger.info(`Successfully created issue: ${createdIssue.key}`); return this.formatter.format(createdIssue); } catch (error) { this.logger.error(`Failed to create JIRA issue: ${error}`); throw this.enhanceError(error, params.projectKey, params.issueType); } } /** * Validate parameters using Zod schema */ private validateParameters(params: CreateIssueParams): CreateIssueParams { const result = createIssueParamsSchema.safeParse(params); if (!result.success) { const errorMessage = `Invalid issue creation parameters: ${formatZodError( result.error, )}`; throw new IssueCreateParamsValidationError(errorMessage); } return result.data; } /** * Enhance error messages for better user guidance */ private enhanceError( error: unknown, projectKey?: string, issueType?: string, ): Error { if (error instanceof JiraNotFoundError) { return new Error( `❌ **Project Not Found**\n\nProject '${projectKey}' not found or you don't have permission to create issues.\n\n**Solutions:**\n- Verify the project key is correct\n- Check your JIRA permissions\n- Use \`jira_get_projects\` to see available projects\n\n**Example:** \`jira_create_issue projectKey=MYPROJ summary="Fix bug" issueType=Bug\``, ); } if (error instanceof JiraPermissionError) { return new Error( `❌ **Permission Denied**\n\nYou don't have permission to create issues in project '${projectKey}'.\n\n**Solutions:**\n- Check your JIRA permissions for this project\n- Contact your JIRA administrator\n- Verify you have CREATE_ISSUES permission\n\n**Required Permissions:** Create Issues`, ); } if (error instanceof IssueCreateParamsValidationError) { return new Error( `❌ **Validation Error**\n\n${error.message}\n\n**Solutions:**\n- Check the format of all parameters\n- Ensure required fields are provided\n- Verify field values match expected formats\n\n**Example:** \`jira_create_issue projectKey=PROJ summary="My issue" issueType=Task\``, ); } if (error instanceof JiraApiError) { return new Error( `❌ **JIRA API Error**\n\n${error.message}\n\n**Solutions:**\n- Check all required fields are provided\n- Verify field values match JIRA requirements\n- Ensure issue type '${issueType}' exists in project '${projectKey}'\n\n**Example:** \`jira_create_issue projectKey=PROJ summary="My issue" issueType=Task\``, ); } if (error instanceof Error) { return new Error( `❌ **Creation Failed**\n\n${error.message}\n\n**Solutions:**\n- Check your parameters are valid\n- Verify the project and issue type exist\n- Try with minimal required fields first\n\n**Example:** \`jira_create_issue projectKey=PROJ summary="Test issue" issueType=Task\``, ); } return new Error( "❌ **Unknown Error**\n\nAn unknown error occurred during issue creation.\n\nPlease check your parameters and try again.", ); } }
  • Zod schema defining the input parameters and validation rules for the jira_create_issue tool.
    export const createIssueParamsSchema = z.object({ // Required fields projectKey: z .string() .min(1, "Project key is required") .max(50, "Project key too long") .regex( /^[A-Z0-9_]+$/, "Project key must contain only uppercase letters, numbers, and underscores", ), summary: z .string() .min(1, "Summary is required") .max(255, "Summary must be 255 characters or less"), issueType: z .string() .min(1, "Issue type is required") .max(50, "Issue type name too long"), // Optional core fields description: z .string() .max(32767, "Description too long (max 32,767 characters)") .optional(), priority: z.enum(["Highest", "High", "Medium", "Low", "Lowest"]).optional(), assignee: z .string() .min(1, "Assignee cannot be empty") .max(255, "Assignee identifier too long") .optional(), // Array fields with limits labels: z .array(z.string().min(1).max(255)) .max(10, "Maximum 10 labels allowed") .optional(), components: z .array(z.string().min(1).max(255)) .max(5, "Maximum 5 components allowed") .optional(), fixVersions: z .array(z.string().min(1).max(255)) .max(3, "Maximum 3 fix versions allowed") .optional(), // Parent issue for subtasks parentIssueKey: issueKeySchema.optional(), // Time tracking timeEstimate: z .string() .regex( /^\d+[wdhm]$/, "Time estimate must be in format like '2w', '3d', '4h', '30m'", ) .optional(), // Environment field environment: z .string() .max(32767, "Environment description too long") .optional(), // Story points for agile storyPoints: z .number() .int() .min(0) .max(100, "Story points must be between 0 and 100") .optional(), // Custom fields (flexible object) customFields: z.record(z.string(), z.unknown()).optional(), });
  • Tool configuration registration for jira_create_issue, specifying name, description, input schema, and handler binding within the issue tools config factory.
    { name: "jira_create_issue", description: "Creates a new JIRA issue with specified parameters", params: createIssueParamsSchema.shape, handler: tools.jira_create_issue.handle.bind(tools.jira_create_issue), },
  • Factory function creating the jira_create_issue ToolHandler object by instantiating CreateIssueHandler and wrapping its handle method.
    jira_create_issue: { handle: async (args: unknown) => createIssueHandler.handle(args), },
  • CreateIssueUseCaseImpl provides the business logic helper for issue creation, including validations and repository interaction, used by the handler.
    export class CreateIssueUseCaseImpl implements CreateIssueUseCase { private readonly logger = logger; constructor( private readonly issueRepository: IssueRepository, private readonly projectValidator: ProjectValidator, private readonly permissionChecker: ProjectPermissionRepository, ) {} /** * Execute issue creation with comprehensive validation */ async execute(request: CreateIssueUseCaseRequest): Promise<Issue> { this.logger.debug("Starting issue creation process", { prefix: "JIRA:CreateIssueUseCase", projectKey: request.projectKey, summary: request.summary, }); // Step 1: Validate project exists await this.validateProject(request.projectKey); // Step 2: Check user permissions await this.validatePermissions(request.projectKey); // Step 3: Validate issue type if provided if (request.issueType) { await this.validateIssueType(request.projectKey, request.issueType); } // Step 4: Create the issue const issueData = this.buildCreateIssueRequest(request); const createdIssue = await this.issueRepository.createIssue(issueData); this.logger.debug("Issue creation completed successfully", { prefix: "JIRA:CreateIssueUseCase", issueKey: createdIssue.key, projectKey: request.projectKey, }); return createdIssue; } /** * Validate that the project exists and is accessible */ private async validateProject(projectKey: string): Promise<void> { this.logger.debug("Validating project existence", { prefix: "JIRA:CreateIssueUseCase", projectKey, }); try { await this.projectValidator.validateProject(projectKey); } catch (error) { this.logger.error("Project validation failed", { prefix: "JIRA:CreateIssueUseCase", projectKey, error, }); throw error; } } /** * Validate that the user has permission to create issues */ private async validatePermissions(projectKey: string): Promise<void> { this.logger.debug("Validating create issue permissions", { prefix: "JIRA:CreateIssueUseCase", projectKey, }); const hasPermission = await this.permissionChecker.hasCreateIssuePermission(projectKey); if (!hasPermission) { const error = new Error( `User does not have CREATE_ISSUES permission for project '${projectKey}'`, ); this.logger.error("Permission validation failed", { prefix: "JIRA:CreateIssueUseCase", projectKey, error: error.message, }); throw error; } } /** * Validate that the issue type exists in the project */ private async validateIssueType( projectKey: string, issueType: string, ): Promise<void> { this.logger.debug("Validating issue type", { prefix: "JIRA:CreateIssueUseCase", projectKey, issueType, }); try { await this.projectValidator.validateIssueType(projectKey, issueType); } catch (error) { this.logger.error("Issue type validation failed", { prefix: "JIRA:CreateIssueUseCase", projectKey, issueType, error, }); throw error; } } /** * Build the create issue request from the use case request */ private buildCreateIssueRequest( request: CreateIssueUseCaseRequest, ): CreateIssueRequest { const fields: CreateIssueRequest["fields"] = { project: { key: request.projectKey, }, summary: request.summary, issuetype: { name: request.issueType || "Task", }, }; // Convert description to ADF format if provided if (request.description) { const adfDescription = ensureADFFormat(request.description); if (adfDescription) { fields.description = adfDescription; } } // Add custom fields if provided if (request.customFields) { Object.assign(fields, request.customFields); } return { fields }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dsazz/mcp-jira'

If you have feedback or need assistance with the MCP directory API, please join our Discord server