feat(jira): new Atlassian Jira integration
Jira Cloud and On-Prem/Data Center (27 commands): JQL ingestion with an OCSF mapper and JQL query, full issue lifecycle (create/get/edit/delete, transitions, assign), comments, remote web links and issue links, attachments (upload/download/delete), field and user lookups, and agile boards/sprints/epics. Basic (email + API token) or Personal Access Token authentication; API v3 + ADF bodies on Cloud, v2 on On-Prem. Stdlib-only, no extra Python dependencies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
id: jira
|
||||
name: Jira
|
||||
version: 1.0.0
|
||||
description: "Atlassian Jira (REST API, Cloud and On-Prem/Data Center) — issue lifecycle (create/read/edit/delete, transitions, assign), comments, web + issue links, attachments (upload/download/delete), field and user lookups, agile boards/sprints/epics, plus issue ingestion (get_incidents) with an OCSF mapper. Basic (email + API token) or Personal Access Token authentication. Stdlib-only, no extra Python dependencies."
|
||||
changelog: "1.0.0 — Initial release: JQL ingestion + query, full issue CRUD and transitions, comments, links, attachments, fields/users, and agile board/sprint/epic listing. Cloud (API v3, ADF bodies) and On-Prem (API v2) supported."
|
||||
category: ticketing
|
||||
|
||||
# Per-instance configuration. For Jira Cloud set cloud_id (found at
|
||||
# admin.atlassian.com/s/<cloud_id>/users) and keep the default server_url; for
|
||||
# On-Prem/Data Center leave cloud_id empty and set server_url to your Jira URL.
|
||||
# Authentication: Basic (username = account email + api_key = API token) OR a
|
||||
# Personal Access Token (pat). Provide only one method.
|
||||
config_schema:
|
||||
properties:
|
||||
server_url:
|
||||
type: string
|
||||
description: "Base URL. Jira Cloud: https://api.atlassian.com/ex/jira (default). On-Prem: your Jira server URL."
|
||||
default: https://api.atlassian.com/ex/jira
|
||||
cloud_id:
|
||||
type: string
|
||||
description: "Jira Cloud ID (leave empty for On-Prem/Data Center)"
|
||||
username:
|
||||
type: string
|
||||
description: "Account email (Basic auth)"
|
||||
api_key:
|
||||
type: string
|
||||
description: "API token (Basic auth)"
|
||||
x-soar-sensitive: true
|
||||
pat:
|
||||
type: string
|
||||
description: "Personal Access Token (use instead of username/api_key)"
|
||||
x-soar-sensitive: true
|
||||
required:
|
||||
- server_url
|
||||
|
||||
commands:
|
||||
# ── Ingestion / search ────────────────────────────────────────────────────
|
||||
- id: get_incidents
|
||||
name: jira-get-incidents
|
||||
description: "Fetch Jira issues matching a JQL query for ingestion. Returns {result:[...flattened issues...]}; use result as the alert rule results path."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
query: { type: string, description: "JQL query (e.g. status != Done). Do not add an ORDER BY — the fetch adds one." }
|
||||
after: { type: string, description: "Lower bound on created time, ISO8601 or epoch (incremental fetch watermark, applied as created >= ...)" }
|
||||
max: { type: number, description: "Maximum issues to fetch (default 50)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
ingest:
|
||||
results_path: result
|
||||
dedup_key: id
|
||||
incremental_field: after
|
||||
- id: query_issues
|
||||
name: jira-query-issues
|
||||
description: "Run a JQL query and return flattened issues."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
query: { type: string, description: "JQL query string" }
|
||||
max_results: { type: number, description: "Maximum issues (default 50)" }
|
||||
next_page_token: { type: string, description: "Token for the next page (Jira Cloud only)" }
|
||||
start_at: { type: number, description: "Index of the first issue (On-Prem; Cloud uses next_page_token)" }
|
||||
required: [query]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_issue
|
||||
name: jira-get-issue
|
||||
description: "Retrieve a single issue by ID or key (flattened)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key, e.g. PROJ-123 (issue_id or issue_key required)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Issue lifecycle ───────────────────────────────────────────────────────
|
||||
- id: create_issue
|
||||
name: jira-create-issue
|
||||
description: "Create a new issue. Provide project_key (or project_name), issue_type_name (or issue_type_id) and a summary."
|
||||
inputs_schema:
|
||||
properties:
|
||||
project_key: { type: string, description: "Project key (project_key or project_name required)" }
|
||||
project_name: { type: string, description: "Project name (resolved to a key; project_key or project_name required)" }
|
||||
issue_type_name: { type: string, description: "Issue type name, e.g. Task, Bug (issue_type_name or issue_type_id required)" }
|
||||
issue_type_id: { type: string, description: "Issue type ID (issue_type_name or issue_type_id required)" }
|
||||
summary: { type: string, description: "Issue summary (required)" }
|
||||
description: { type: string, description: "Issue description" }
|
||||
priority: { type: string, description: "Priority name, e.g. High, Medium" }
|
||||
labels: { type: string, description: "Comma-separated labels" }
|
||||
components: { type: string, description: "Comma-separated component names (must already exist)" }
|
||||
assignee_id: { type: string, description: "Assignee account ID (Cloud)" }
|
||||
assignee: { type: string, description: "Assignee username (On-Prem)" }
|
||||
due_date: { type: string, description: "Due date (yyyy-mm-dd)" }
|
||||
fields_json: { type: string, description: "Raw fields JSON merged into the request (advanced; wins on key conflicts)" }
|
||||
required: [summary]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: edit_issue
|
||||
name: jira-edit-issue
|
||||
description: "Edit an issue's fields, and/or move it with status/transition (see jira-list-transitions)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
summary: { type: string, description: "New summary" }
|
||||
description: { type: string, description: "New description" }
|
||||
priority: { type: string, description: "Priority name" }
|
||||
labels: { type: string, description: "Comma-separated labels (replaces existing)" }
|
||||
components: { type: string, description: "Comma-separated component names (replaces existing)" }
|
||||
assignee_id: { type: string, description: "Assignee account ID (Cloud)" }
|
||||
assignee: { type: string, description: "Assignee username (On-Prem)" }
|
||||
due_date: { type: string, description: "Due date (yyyy-mm-dd)" }
|
||||
status: { type: string, description: "Target status name — transitions the issue (mutually exclusive with transition)" }
|
||||
transition: { type: string, description: "Transition name to apply (mutually exclusive with status)" }
|
||||
fields_json: { type: string, description: "Raw fields JSON merged into the request (advanced)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: delete_issue
|
||||
name: jira-delete-issue
|
||||
description: "Delete an issue (its sub-tasks are deleted too)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: assign_issue
|
||||
name: jira-assign-issue
|
||||
description: "Assign an issue to a user (assignee_id for Cloud, assignee for On-Prem)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
assignee_id: { type: string, description: "Assignee account ID (Cloud)" }
|
||||
assignee: { type: string, description: "Assignee username (On-Prem)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: list_transitions
|
||||
name: jira-list-transitions
|
||||
description: "List the transitions available for an issue in its current status."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Comments ──────────────────────────────────────────────────────────────
|
||||
- id: add_comment
|
||||
name: jira-add-comment
|
||||
description: "Add a comment to an issue."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
comment: { type: string, description: "Comment body" }
|
||||
visibility: { type: string, description: "Restrict visibility to a role, e.g. Administrators" }
|
||||
required: [comment]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_comments
|
||||
name: jira-get-comments
|
||||
description: "Return the comments of an issue."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
limit: { type: number, description: "Maximum comments (default 50)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: edit_comment
|
||||
name: jira-edit-comment
|
||||
description: "Edit an existing comment on an issue."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
comment_id: { type: string, description: "Comment ID" }
|
||||
comment: { type: string, description: "New comment body" }
|
||||
visibility: { type: string, description: "Restrict visibility to a role" }
|
||||
required: [comment_id, comment]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: delete_comment
|
||||
name: jira-delete-comment
|
||||
description: "Delete a comment from an issue."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
comment_id: { type: string, description: "Comment ID" }
|
||||
required: [comment_id]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Links ─────────────────────────────────────────────────────────────────
|
||||
- id: add_link
|
||||
name: jira-add-link
|
||||
description: "Add a remote web link (URL) to an issue."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
url: { type: string, description: "URL to link" }
|
||||
title: { type: string, description: "Link title" }
|
||||
summary: { type: string, description: "Link summary" }
|
||||
relationship: { type: string, description: "Relationship to the issue, e.g. causes" }
|
||||
required: [url, title]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: link_issues
|
||||
name: jira-link-issues
|
||||
description: "Create a link between two issues (see jira-get-link-types for link_type names)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
inward_issue: { type: string, description: "Inward issue key or ID" }
|
||||
outward_issue: { type: string, description: "Outward issue key or ID" }
|
||||
link_type: { type: string, description: "Link type name, e.g. Blocks, Duplicate" }
|
||||
comment: { type: string, description: "Optional comment to add to the inward issue" }
|
||||
required: [inward_issue, outward_issue, link_type]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_link_types
|
||||
name: jira-get-link-types
|
||||
description: "List all issue link types."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Attachments ───────────────────────────────────────────────────────────
|
||||
- id: upload_file
|
||||
name: jira-upload-file
|
||||
description: "Attach a file to an issue (content provided as base64)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
issue_id: { type: string, description: "Issue ID (issue_id or issue_key required)" }
|
||||
issue_key: { type: string, description: "Issue key (issue_id or issue_key required)" }
|
||||
file_name: { type: string, description: "Attachment file name" }
|
||||
content_base64: { type: string, description: "File content, base64-encoded" }
|
||||
required: [file_name, content_base64]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_attachment
|
||||
name: jira-get-attachment
|
||||
description: "Download an attachment's content by attachment ID (returned as base64)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
attachment_id: { type: string, description: "Attachment ID (from jira-get-issue)" }
|
||||
required: [attachment_id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: delete_attachment
|
||||
name: jira-delete-attachment
|
||||
description: "Delete an attachment by attachment ID."
|
||||
inputs_schema:
|
||||
properties:
|
||||
attachment_id: { type: string, description: "Attachment ID" }
|
||||
required: [attachment_id]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Fields / users ────────────────────────────────────────────────────────
|
||||
- id: list_fields
|
||||
name: jira-list-fields
|
||||
description: "List the system and custom issue fields."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
limit: { type: number, description: "Maximum fields (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_id_by_attribute
|
||||
name: jira-get-id-by-attribute
|
||||
description: "Resolve a user's account ID (Cloud) or username (On-Prem) from a display name or email."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
attribute: { type: string, description: "Display name or email address to search for" }
|
||||
max_results: { type: number, description: "Maximum candidates to consider (default 50)" }
|
||||
required: [attribute]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: get_user_info
|
||||
name: jira-get-user-info
|
||||
description: "Get a user's details (account_id for Cloud; key or username for On-Prem). With no identifier, returns the caller."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
account_id: { type: string, description: "Account ID (Cloud)" }
|
||||
key: { type: string, description: "User key (On-Prem)" }
|
||||
username: { type: string, description: "Username (On-Prem)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Agile: boards / sprints / epics ───────────────────────────────────────
|
||||
- id: board_list
|
||||
name: jira-board-list
|
||||
description: "List agile boards (optionally filter by name, project or type)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
board_id: { type: string, description: "Return only this board" }
|
||||
board_name: { type: string, description: "Filter by board name" }
|
||||
project_key_id: { type: string, description: "Filter by project key or ID" }
|
||||
type: { type: string, description: "Board type: scrum, kanban or simple" }
|
||||
limit: { type: number, description: "Maximum boards (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: board_issue_list
|
||||
name: jira-board-issue-list
|
||||
description: "List the issues of a board (flattened)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
board_id: { type: string, description: "Board ID" }
|
||||
jql_query: { type: string, description: "JQL to filter the issues" }
|
||||
limit: { type: number, description: "Maximum issues (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: [board_id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: board_sprint_list
|
||||
name: jira-board-sprint-list
|
||||
description: "List the sprints of a board."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
board_id: { type: string, description: "Board ID" }
|
||||
limit: { type: number, description: "Maximum sprints (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: [board_id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: sprint_issue_list
|
||||
name: jira-sprint-issue-list
|
||||
description: "List the issues of a sprint (flattened)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
sprint_id: { type: string, description: "Sprint ID" }
|
||||
jql_query: { type: string, description: "JQL to filter the issues" }
|
||||
limit: { type: number, description: "Maximum issues (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: [sprint_id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: epic_issue_list
|
||||
name: jira-epic-issue-list
|
||||
description: "List the issues that belong to an epic (flattened)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
epic_id: { type: string, description: "Epic ID (epic_id or epic_key required)" }
|
||||
epic_key: { type: string, description: "Epic key (epic_id or epic_key required)" }
|
||||
jql_query: { type: string, description: "JQL to filter the issues" }
|
||||
limit: { type: number, description: "Maximum issues (default 50)" }
|
||||
offset: { type: number, description: "Starting index (default 0)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
- id: test_connection
|
||||
name: jira-test-connection
|
||||
description: "Verify connectivity and credentials by reading the current user (used by the Test button)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
ingestion:
|
||||
command: get_incidents
|
||||
mapper: get_incidents
|
||||
default_incident_type: "Jira Issue"
|
||||
Reference in New Issue
Block a user