Skip to main content
Glama

create_jira_issues

Bulk create Jira issues using field dictionaries for multiple entries. Specify issue types like 'Bug', 'Task', or 'Story' as per your Jira instance, and optionally reload created issues.

Instructions

Bulk create new Jira issues. IMPORTANT: For 'issue_type', use the exact case-sensitive types in your Jira instance (common: 'Bug', 'Task', 'Story', 'Epic')

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
field_listYesA list of field dictionaries, each representing an issue to create
prefetchNoWhether to reload created issues (default: true)

Implementation Reference

  • Main handler: validates and transforms input field_list to v3 API format, handles description ADF conversion, issue type normalization, calls bulk_create_issues on v3 client, processes issues and errors in response.
    async def create_jira_issues( self, field_list: List[Dict[str, Any]], prefetch: bool = True ) -> List[Dict[str, Any]]: """Bulk create new Jira issues using v3 REST API. Parameters: field_list (List[Dict[str, Any]]): a list of dicts each containing field names and the values to use. Each dict is an individual issue to create. prefetch (bool): True reloads the created issue Resource so all of its data is present in the value returned (Default: True) Returns: List[Dict[str, Any]]: List of created issues with their details Issue Types: Common issue types include: 'Bug', 'Task', 'Story', 'Epic', 'New Feature', 'Improvement' Note: Available issue types vary by Jira instance and project Example: # Create multiple issues in bulk await create_jira_issues([ { 'project': 'PROJ', 'summary': 'Implement user authentication', 'description': 'Add login and registration functionality', 'issue_type': 'Story' # Note: case-sensitive, match to your Jira instance types }, { 'project': 'PROJ', 'summary': 'Fix navigation bar display on mobile', 'description': 'Navigation bar is not displaying correctly on mobile devices', 'issue_type': 'Bug', 'priority': {'name': 'High'}, 'labels': ['mobile', 'ui'] } ]) """ logger.info("Starting create_jira_issues...") try: # Process each field dict to ensure proper formatting for v3 API processed_field_list = [] for fields in field_list: # Create a properly formatted issue dictionary issue_dict = {} # Process required fields first to ensure they exist # Project field - required if "project" not in fields: raise ValueError("Each issue must have a 'project' field") project_value = fields["project"] if isinstance(project_value, str): issue_dict["project"] = {"key": project_value} else: issue_dict["project"] = project_value # Summary field - required if "summary" not in fields: raise ValueError("Each issue must have a 'summary' field") issue_dict["summary"] = fields["summary"] # Description field - convert to ADF format for v3 API if it's a simple string if "description" in fields: description = fields["description"] if isinstance(description, str): # Convert simple string to Atlassian Document Format issue_dict["description"] = { "type": "doc", "version": 1, "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": description } ] } ] } else: # Assume it's already in ADF format issue_dict["description"] = description # Issue type field - required, handle both 'issuetype' and 'issue_type' issue_type = None if "issuetype" in fields: issue_type = fields["issuetype"] elif "issue_type" in fields: issue_type = fields["issue_type"] else: raise ValueError( "Each issue must have an 'issuetype' or 'issue_type' field" ) # Check for common issue type variants and fix case-sensitivity issues logger.debug( f"Processing bulk issue_type: '{issue_type}' (type: {type(issue_type)})" ) common_types = [ "bug", "task", "story", "epic", "improvement", "newfeature", "new feature", ] if isinstance(issue_type, str): issue_type_lower = issue_type.lower() if issue_type_lower in common_types: # Convert first letter to uppercase for standard Jira types issue_type_proper = issue_type_lower.capitalize() if ( issue_type_lower == "new feature" or issue_type_lower == "newfeature" ): issue_type_proper = "New Feature" logger.debug( f"Converting issue type from '{issue_type}' to '{issue_type_proper}'" ) issue_dict["issuetype"] = {"name": issue_type_proper} else: # Use the type as provided - some Jira instances have custom types issue_dict["issuetype"] = {"name": issue_type} else: issue_dict["issuetype"] = issue_type # Process other fields for key, value in fields.items(): if key in [ "project", "summary", "description", "issuetype", "issue_type", ]: # Skip fields we've already processed continue # Handle special fields that require specific formats if key == "assignees" or key == "assignee": # Convert string to array for assignees or proper format for assignee if isinstance(value, str): if key == "assignees": issue_dict[key] = [value] if value else [] else: # assignee issue_dict[key] = {"name": value} if value else None elif isinstance(value, list) and key == "assignee" and value: # If assignee is a list but should be a dict with name issue_dict[key] = {"name": value[0]} else: issue_dict[key] = value elif key == "labels": # Convert string to array for labels if isinstance(value, str): issue_dict[key] = [value] if value else [] else: issue_dict[key] = value elif key == "milestone": # Convert string to number for milestone if isinstance(value, str) and value.isdigit(): issue_dict[key] = int(value) else: issue_dict[key] = value else: issue_dict[key] = value # Add to the field list in v3 API format processed_field_list.append({"fields": issue_dict}) logger.debug(f"Processed field list: {json.dumps(processed_field_list, indent=2)}") # Use v3 API client v3_client = self._get_v3_api_client() # Call the bulk create API response_data = await v3_client.bulk_create_issues(processed_field_list) # Process the results to maintain compatibility with existing interface processed_results = [] # Handle successful issues if "issues" in response_data: for issue in response_data["issues"]: processed_results.append({ "key": issue.get("key"), "id": issue.get("id"), "self": issue.get("self"), "success": True, }) # Handle errors if "errors" in response_data: for error in response_data["errors"]: processed_results.append({ "error": error, "success": False, }) logger.info(f"Successfully processed {len(processed_results)} issue creations") return processed_results except Exception as e: error_msg = f"Failed to create issues in bulk: {type(e).__name__}: {str(e)}" logger.error(error_msg, exc_info=True) print(error_msg) raise ValueError(error_msg)
  • Tool registration in list_tools(): defines name 'create_jira_issues', description, and inputSchema for field_list array.
    name=JiraTools.CREATE_ISSUES.value, description="Bulk create new Jira issues. IMPORTANT: For 'issue_type', use the exact case-sensitive types in your Jira instance (common: 'Bug', 'Task', 'Story', 'Epic')", inputSchema={ "type": "object", "properties": { "field_list": { "type": "array", "description": "A list of field dictionaries, each representing an issue to create", "items": { "type": "object", "description": "Field dictionary for a single issue", }, }, "prefetch": { "type": "boolean", "description": "Whether to reload created issues (default: true)", }, }, "required": ["field_list"], }, ),
  • Tool dispatch in call_tool(): extracts arguments, calls jira_server.create_jira_issues(field_list, prefetch).
    case JiraTools.CREATE_ISSUES.value: logger.info("Calling async tool create_jira_issues...") field_list = arguments.get("field_list") if not field_list: raise ValueError("Missing required argument: field_list") prefetch = arguments.get("prefetch", True) result = await jira_server.create_jira_issues(field_list, prefetch) logger.info("Async tool create_jira_issues completed.")
  • Low-level helper: makes HTTP POST to /rest/api/3/issue/bulk with issueUpdates payload, handles response with issues and errors.
    async def bulk_create_issues( self, issue_updates: list ) -> Dict[str, Any]: """ Bulk create issues using the v3 REST API. Creates up to 50 issues and, where the option to create subtasks is enabled in Jira, subtasks. Transitions may be applied, to move the issues or subtasks to a workflow step other than the default start step, and issue properties set. Args: issue_updates: List of issue creation specifications. Each item should contain 'fields' dict with issue fields, and optionally 'update' dict for additional operations during creation. Returns: Dict containing: - issues: List of successfully created issues with their details - errors: List of errors for failed issue creations Raises: ValueError: If required parameters are missing or bulk creation fails """ if not issue_updates: raise ValueError("issue_updates list cannot be empty") if len(issue_updates) > 50: raise ValueError("Cannot create more than 50 issues in a single bulk operation") # Build the request payload for v3 API payload = {"issueUpdates": issue_updates} endpoint = "/issue/bulk" logger.debug(f"Bulk creating issues with v3 API endpoint: {endpoint}") logger.debug(f"Payload: {json.dumps(payload, indent=2)}") response_data = await self._make_v3_api_request("POST", endpoint, data=payload) logger.debug(f"Bulk create response: {json.dumps(response_data, indent=2)}") return response_data
  • Helper: lazily initializes the JiraV3APIClient used for all v3 API calls including bulk_create_issues.
    def _get_v3_api_client(self) -> JiraV3APIClient: """Get or create a v3 API client instance""" if not self._v3_api_client: self._v3_api_client = JiraV3APIClient( server_url=self.server_url, username=self.username, password=self.password, token=self.token, ) return self._v3_api_client

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

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