Skip to main content
Glama
raalarcon9705

raalarcon-jira-mcp-server

create_issue

Create a new Jira issue or subtask in a project, specifying type, summary, and optional details. Returns the issue key, ID, and URL.

Instructions

Create a new Jira issue (Bug, Story, Task, Epic, etc.) or subtask. Returns the created issue key, ID, and URL. Use get_issue_types to find valid issueType values for the project. To create a subtask, specify the parent issue key.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectKeyYesProject key (e.g., "PROJ") where the issue will be created. Use get_projects to find available keys.
summaryYesIssue title/summary (max 255 characters). This is the main identifier shown in issue lists.
descriptionNoDetailed issue description. Supports plain text, Markdown, or Atlassian Document Format (ADF) for rich formatting. Markdown will be automatically converted to ADF. For mentions, use format: @[accountId:displayName] (get accountId from get_users tool).
issueTypeYesIssue type name (e.g., "Bug", "Story", "Task", "Epic"). Use get_issue_types to find valid values.
priorityNoPriority level: "Highest", "High", "Medium", "Low", "Lowest". Defaults to project default if not specified.
assigneeNoAccount ID of the user to assign the issue to. Use get_users to find account IDs.
parentNoIssue key of the parent issue (e.g., "PROJ-123"). Required to create a subtask.
labelsNoArray of label names for categorization and filtering (e.g., ["bug", "urgent", "frontend"]).
componentsNoArray of component names that this issue affects (e.g., ["API", "Database", "UI"]).
fixVersionsNoArray of version names where this issue will be fixed (e.g., ["v1.2", "v2.0"]).
customFieldsNoCustom field values as key-value pairs. Field keys are project-specific.

Implementation Reference

  • The 'create_issue' tool is registered as part of the issue tools array in createIssueTools(). Its name is 'create_issue' with a description and inputSchema defining the required/optional parameters (projectKey, summary, issueType required; description, priority, assignee, parent, labels, components, fixVersions, customFields optional).
      },
      {
        name: 'get_issue',
        description: 'Retrieve detailed information about a specific Jira issue including status, assignee, description, comments, and workflow data. Use this to get current state before making updates.',
        inputSchema: {
          type: 'object',
          properties: {
            issueKey: {
              type: 'string',
              description: 'Issue key (e.g., "PROJ-123") or numeric issue ID. This is the unique identifier for the issue.',
            },
            expand: {
              type: 'string',
              description: 'Comma-separated list of additional data: renderedFields,names,schema,transitions,operations,editmeta,changelog',
            },
            fields: {
              type: 'array',
              items: { type: 'string' },
              description: 'Specific fields to return (e.g., ["summary", "status", "assignee"]). If not specified, returns all fields.',
            },
          },
          required: ['issueKey'],
        },
      },
      {
        name: 'update_issue',
        description: 'Update fields of an existing Jira issue or convert to subtask. Only provided fields will be updated. Use get_issue first to see current values. Returns success confirmation.',
        inputSchema: {
          type: 'object',
          properties: {
            issueKey: {
              type: 'string',
              description: 'Issue key (e.g., "PROJ-123") to update. This is the unique identifier for the issue.',
            },
            summary: {
              type: 'string',
              description: 'New issue title/summary (max 255 characters). Replaces the existing summary.',
            },
            description: {
              type: 'string',
              description: 'New issue description. Replaces the existing description. Supports plain text, Markdown, or ADF. Markdown will be automatically converted to ADF. For mentions, use format: @[accountId:displayName] (get accountId from get_users tool).',
            },
            priority: {
              type: 'string',
              description: 'New priority: "Highest", "High", "Medium", "Low", "Lowest". Replaces current priority.',
            },
            assignee: {
              type: 'string',
              description: 'Account ID of new assignee. Use get_users to find account IDs. Set to null to unassign.',
            },
            parent: {
              type: 'string',
              description: 'Issue key of the parent issue (e.g., "PROJ-123"). Use to convert issue to subtask or change parent.',
            },
            labels: {
              type: 'array',
              items: { type: 'string' },
              description: 'Complete array of labels (replaces all existing labels). Use empty array to remove all labels.',
            },
            components: {
              type: 'array',
              items: { type: 'string' },
              description: 'Complete array of components (replaces all existing components). Use empty array to remove all components.',
            },
            fixVersions: {
              type: 'array',
              items: { type: 'string' },
              description: 'Complete array of fix versions (replaces all existing versions). Use empty array to remove all versions.',
            },
            customFields: {
              type: 'object',
              description: 'Custom field values as key-value pairs. Only specified fields will be updated.',
            },
          },
          required: ['issueKey'],
        },
      },
      {
        name: 'delete_issue',
        description: 'Permanently delete a Jira issue. This action cannot be undone. Use with caution. Returns success confirmation.',
        inputSchema: {
          type: 'object',
          properties: {
            issueKey: {
              type: 'string',
              description: 'Issue key (e.g., "PROJ-123") to delete. This is the unique identifier for the issue.',
            },
            deleteSubtasks: {
              type: 'boolean',
              description: 'Whether to also delete all subtasks of this issue. Defaults to false (subtasks will remain).',
              default: false,
            },
          },
          required: ['issueKey'],
        },
      },
    ];
  • The handler for 'create_issue' in handleIssueTool(). Validates args using createIssueSchema, calls jiraClient.createIssue(validatedArgs), and returns a success message with the created issue key.
    case 'create_issue': {
      const validatedArgs = await createIssueSchema.validate(args);
      const issue = await jiraClient.createIssue(validatedArgs);
    
      return {
        content: [
          {
            type: 'text',
            text: `Issue ${issue.key} created successfully`,
          },
        ],
      };
    }
  • The yup validation schema for 'create_issue'. Defines validation rules: projectKey (string, required), summary (string, required, max 255), description (mixed, optional, transforms markdown to ADF), issueType (string, required), priority (string, optional), assignee (string, optional), parent (string, optional), labels (string[], optional), components (string[], optional), fixVersions (string[], optional), customFields (object, optional).
    export const createIssueSchema = yup.object({
      projectKey: yup.string().required('Project key is required'),
      summary: yup.string().required('Summary is required').max(255, 'Summary too long'),
      description: yup.mixed()
        .optional()
        .transform(function (value) {
          // If it's a string and looks like markdown, convert to ADF
          if (typeof value === 'string' && isMarkdown(value)) {
            return markdownToADF(value);
          }
          return value;
        }),
      issueType: yup.string().required('Issue type is required'),
      priority: yup.string().optional(),
      assignee: yup.string().optional(),
      parent: yup.string().optional(),
      labels: yup.array().of(yup.string()).optional(),
      components: yup.array().of(yup.string()).optional(),
      fixVersions: yup.array().of(yup.string()).optional(),
      customFields: yup.object().optional(),
    });
  • The JiraClient.createIssue() method that executes the actual Jira API call. Builds issueData with fields from input, conditionally adds optional fields (description, priority, assignee, parent, labels, components, fixVersions, customFields), then calls this.jira.issues.createIssue(issueData).
    async createIssue(input: CreateIssueInput) {
      try {
        const issueData: CreateIssue = {
          fields: {
            project: { key: input.projectKey },
            summary: input.summary,
            issuetype: { name: input.issueType },
          },
        };
    
        if (input.description) {
          issueData.fields.description = input.description as Document;
        }
    
        if (input.priority) {
          issueData.fields.priority = { name: input.priority };
        }
    
        if (input.assignee) {
          issueData.fields.assignee = { accountId: input.assignee };
        }
    
        if (input.parent) {
          issueData.fields.parent = { key: input.parent };
        }
    
        if (input.labels && input.labels.length > 0) {
          issueData.fields.labels = input.labels.filter(label => label !== undefined) as string[];
        }
    
        if (input.components && input.components.length > 0) {
          issueData.fields.components = input.components.map(name => ({ name }));
        }
    
        if (input.fixVersions && input.fixVersions.length > 0) {
          issueData.fields.fixVersions = input.fixVersions.map(name => ({ name }));
        }
    
        if (input.customFields) {
          Object.assign(issueData.fields, input.customFields);
        }
    
        const response = await this.jira.issues.createIssue(issueData);
        return response;
      } catch (error) {
        throw new Error(`Failed to create issue: ${error instanceof Error ? error.message : 'Unknown error'}`);
      }
    }
  • src/index.ts:72-77 (registration)
    In the main server's CallToolRequestSchema handler, the 'create_issue' name (via name.startsWith('create_issue')) is routed to handleIssueTool().
      name.startsWith('create_issue') ||
      name.startsWith('get_issue') ||
      name.startsWith('update_issue') ||
      name.startsWith('delete_issue')
    ) {
      return await handleIssueTool(name, args || {}, this.jiraClient);
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses return values (issue key, ID, URL) and subtask creation behavior. Lacks discussion of idempotency, permissions, or side effects, but given no annotations, the description provides reasonable transparency for a creation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each adding distinct value: purpose, return, validation hint, and subtask guidance. No redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 11 parameters with nested objects and no output schema, the description covers the essential behavior, return, and special cases (subtasks). It compensates for missing output schema by stating what is returned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the description adds significant value beyond the schema by cross-referencing companion tools (get_issue_types, get_projects, get_users) and explaining Markdown/ADF conversion and mention format. This greatly aids correct parameter usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates a new Jira issue, listing specific types (Bug, Story, Task, Epic, subtask). It distinguishes from sibling tools like update_issue or delete_issue by focusing on creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear guidance on when to use: to create issues and subtasks. Suggests using get_issue_types and get_projects for valid values, but does not explicitly state when not to use or mention alternatives beyond the context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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

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