Skip to main content
Glama

jira_create_issue

Create new Jira issues with detailed specifications including project, issue type, priority, assignee, and custom fields. Automatically formats plain text descriptions to structured ADF format with headings and lists.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
assigneeNoAssignee account ID (optional)
componentsNoComponent names (optional)
customFieldsNoAdditional Jira fields, e.g. { "customfield_10071": value }. Use this to set required custom fields.
descriptionNoDetailed issue description (optional). Accepts plain text (auto-formatted to ADF) or an ADF document.
issueTypeYesIssue type name (e.g., Bug, Story, Task, Epic)
labelsNoIssue labels (optional)
priorityNoIssue priority name (e.g., High, Medium, Low) - optional
projectKeyYesProject key where the issue will be created
returnIssueNoIf false, returns only the issue key without fetching full details
summaryYesIssue summary/title

Implementation Reference

  • Main MCP tool handler function that validates input using Zod schema, prepares parameters, calls the low-level createIssue API helper, handles optional full issue fetch, logs activity, and formats success/error responses.
    export async function handleCreateIssue(input: unknown): Promise<McpToolResponse> { try { const validated = validateInput(CreateIssueInputSchema, input); log.info(`Creating issue in project ${validated.projectKey}...`); const createParams: any = { projectKey: validated.projectKey, summary: validated.summary, issueType: validated.issueType, }; if (validated.description !== undefined) createParams.description = validated.description; if (validated.priority !== undefined) createParams.priority = validated.priority; if (validated.assignee !== undefined) createParams.assignee = validated.assignee; if (validated.labels !== undefined) createParams.labels = validated.labels; if (validated.components !== undefined) createParams.components = validated.components; if (validated.customFields !== undefined) createParams.customFields = validated.customFields; if (validated.format !== undefined) createParams.format = validated.format; let issueOrKey; if (validated.returnIssue === false) { issueOrKey = await createIssue(createParams, { returnIssue: false }); } else { // Default behavior: request full issue; keep API surface compatible with tests issueOrKey = await createIssue(createParams); } if (validated.returnIssue === false) { const key = typeof issueOrKey === 'string' ? issueOrKey : (issueOrKey as any).key; log.info(`Created issue ${key}`); return formatSuccessResponse(`Issue created: ${key}`); } const issue = issueOrKey as any; log.info(`Created issue ${issue.key}`); return formatIssueResponse(issue); } catch (error) { log.error('Error in handleCreateIssue:', error); return handleError(error); } }
  • MCP Tool object definition including name 'jira_create_issue', detailed description, and JSON Schema for input validation (used when listing tools).
    export const createIssueTool: Tool = { name: TOOL_NAMES.CREATE_ISSUE, description: 'Creates a new Jira issue in the specified project. Supports setting issue type, priority, assignee, labels, components, and custom fields. Description format is controlled by the "format" parameter (default: markdown). For required custom fields, supply them via customFields (e.g., { "customfield_12345": { id: "..." } }). Returns the created issue with all details.', inputSchema: { type: 'object', properties: { projectKey: { type: 'string', description: 'Project key where the issue will be created', }, summary: { type: 'string', description: 'Issue summary/title', minLength: 1, }, description: { anyOf: [{ type: 'string' }, { type: 'object' }], description: 'Detailed issue description (optional). Format depends on the "format" parameter.', }, issueType: { type: 'string', description: 'Issue type name (e.g., Bug, Story, Task, Epic)', }, priority: { type: 'string', description: 'Issue priority name (e.g., High, Medium, Low) - optional', }, assignee: { type: 'string', description: 'Assignee account ID (optional)', }, labels: { type: 'array', items: { type: 'string' }, description: 'Issue labels (optional)', default: [], }, components: { type: 'array', items: { type: 'string' }, description: 'Component names (optional)', default: [], }, customFields: { type: 'object', additionalProperties: true, description: 'Additional Jira fields, e.g. { "customfield_10071": value }. Use this to set required custom fields.', }, returnIssue: { type: 'boolean', description: 'If false, returns only the issue key without fetching full details', default: true, }, format: { type: 'string', enum: ['markdown', 'adf', 'plain'], description: 'Description format: "markdown" (converts Markdown to ADF, default), "adf" (use as-is ADF object), "plain" (converts plain text to ADF with basic formatting)', default: 'markdown', }, }, required: ['projectKey', 'summary', 'issueType'], }, };
  • src/index.ts:32-49 (registration)
    Registration of all tool handler functions in a Map keyed by tool name, including 'jira_create_issue' -> handleCreateIssue. Used in CallToolRequestHandler for execution dispatch.
    const toolHandlers = new Map<string, (input: unknown) => Promise<any>>([ [TOOL_NAMES.GET_VISIBLE_PROJECTS, tools.handleGetVisibleProjects], [TOOL_NAMES.GET_ISSUE, tools.handleGetIssue], [TOOL_NAMES.SEARCH_ISSUES, tools.handleSearchIssues], [TOOL_NAMES.GET_MY_ISSUES, tools.handleGetMyIssues], [TOOL_NAMES.GET_ISSUE_TYPES, tools.handleGetIssueTypes], [TOOL_NAMES.GET_USERS, tools.handleGetUsers], [TOOL_NAMES.GET_PRIORITIES, tools.handleGetPriorities], [TOOL_NAMES.GET_STATUSES, tools.handleGetStatuses], [TOOL_NAMES.CREATE_ISSUE, tools.handleCreateIssue], [TOOL_NAMES.UPDATE_ISSUE, tools.handleUpdateIssue], [TOOL_NAMES.ADD_COMMENT, tools.handleAddComment], [TOOL_NAMES.GET_PROJECT_INFO, tools.handleGetProjectInfo], [TOOL_NAMES.CREATE_SUBTASK, tools.handleCreateSubtask], [TOOL_NAMES.GET_CREATE_META, tools.handleGetCreateMeta], [TOOL_NAMES.GET_CUSTOM_FIELDS, tools.handleGetCustomFields], [TOOL_NAMES.CREATE_ISSUE_LINK, tools.handleCreateIssueLink], ]);
  • src/index.ts:52-69 (registration)
    Array of all Tool objects (with schemas) returned by ListToolsRequestHandler, including createIssueTool for 'jira_create_issue'.
    const allTools = [ tools.getVisibleProjectsTool, tools.getIssueTool, tools.searchIssuesTool, tools.getMyIssuesTool, tools.getIssueTypesTool, tools.getUsersTool, tools.getPrioritiesTool, tools.getStatusesTool, tools.createIssueTool, tools.updateIssueTool, tools.addCommentTool, tools.getProjectInfoTool, tools.createSubtaskTool, tools.getCreateMetaTool, tools.getCustomFieldsTool, tools.createIssueLinkTool, ];
  • Core API helper that constructs the Jira POST /rest/api/3/issue payload (including ADF description conversion), sends the request via makeJiraRequest, optionally fetches the full created issue with getIssue, and returns issue key or full details.
    export async function createIssue( issueData: { projectKey: string; summary: string; description?: string; issueType: string; priority?: string; assignee?: string; labels?: string[]; components?: string[]; customFields?: Record<string, any>; format?: 'markdown' | 'adf' | 'plain'; }, options: { returnIssue?: boolean } = { returnIssue: true } ): Promise<JiraIssue | string> { const fields: Record<string, any> = { project: { key: issueData.projectKey }, summary: issueData.summary, issuetype: { name: issueData.issueType }, }; if (issueData.description !== undefined) { fields.description = ensureAdfDescription( issueData.description, issueData.format || 'markdown' ); } if (issueData.priority) { fields.priority = { name: issueData.priority }; } if (issueData.assignee) { fields.assignee = { accountId: issueData.assignee }; } if (issueData.labels && issueData.labels.length > 0) { fields.labels = issueData.labels; } if (issueData.components && issueData.components.length > 0) { fields.components = issueData.components.map((name) => ({ name })); } // Merge any custom fields provided by the caller if (issueData.customFields && typeof issueData.customFields === 'object') { for (const [key, value] of Object.entries(issueData.customFields)) { // Do not overwrite standard fields if accidentally duplicated if (!(key in fields)) { fields[key] = value; } } } const config: AxiosRequestConfig = { method: 'POST', url: '/issue', data: { fields }, }; const response = await makeJiraRequest<{ key: string; id: string; self: string }>(config); if (options.returnIssue === false) { return response.key; } // Return the created issue return await getIssue(response.key); }

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/freema/mcp-jira-stdio'

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