Create, read, update, and delete Jira issues. Use when managing Stories, Tasks, Bugs, or Epics - includes field updates and metadata.
86
Quality
82%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Optimize this skill with Tessl
npx tessl skill review --optimize ./data/skills-md/01000001-01001110/agent-jira-skills/jira-issues/SKILL.mdCreate, read, update, and delete issues in Jira Cloud. Manage issue fields, transitions, and metadata.
interface JiraIssue {
id: string;
key: string;
self: string;
fields: {
summary: string;
description?: {
type: 'doc';
version: 1;
content: Array<{
type: string;
content?: Array<{
type: string;
text: string;
}>;
}>;
};
status: { name: string; id: string };
assignee?: { accountId: string; displayName: string };
reporter?: { accountId: string; displayName: string };
priority?: { name: string; id: string };
issuetype: { name: string; id: string };
project: { key: string; id: string };
created: string;
updated: string;
labels?: string[];
components?: Array<{ id: string; name: string }>;
};
}
interface CreateIssueInput {
projectKey: string;
summary: string;
issueType: 'Story' | 'Task' | 'Bug' | 'Epic' | string;
description?: string;
assigneeAccountId?: string;
labels?: string[];
priority?: string;
}async function createIssue(
client: JiraClient,
input: CreateIssueInput
): Promise<{ id: string; key: string; self: string }> {
const body: any = {
fields: {
project: { key: input.projectKey },
summary: input.summary,
issuetype: { name: input.issueType },
},
};
// Add description in Atlassian Document Format (ADF)
if (input.description) {
body.fields.description = {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: input.description,
},
],
},
],
};
}
if (input.assigneeAccountId) {
body.fields.assignee = { id: input.assigneeAccountId };
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
return client.request<{ id: string; key: string; self: string }>('/issue', {
method: 'POST',
body: JSON.stringify(body),
});
}async function getIssue(
client: JiraClient,
issueKeyOrId: string,
options: {
fields?: string[];
expand?: string[];
} = {}
): Promise<JiraIssue> {
const params = new URLSearchParams();
if (options.fields) params.set('fields', options.fields.join(','));
if (options.expand) params.set('expand', options.expand.join(','));
const query = params.toString() ? `?${params.toString()}` : '';
return client.request<JiraIssue>(`/issue/${issueKeyOrId}${query}`);
}interface UpdateIssueInput {
summary?: string;
description?: string;
assigneeAccountId?: string | null;
labels?: string[];
priority?: string;
}
async function updateIssue(
client: JiraClient,
issueKeyOrId: string,
input: UpdateIssueInput
): Promise<void> {
const body: any = { fields: {} };
if (input.summary) {
body.fields.summary = input.summary;
}
if (input.description !== undefined) {
body.fields.description = input.description
? {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: input.description }],
},
],
}
: null;
}
if (input.assigneeAccountId !== undefined) {
body.fields.assignee = input.assigneeAccountId
? { id: input.assigneeAccountId }
: null;
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
await client.request(`/issue/${issueKeyOrId}`, {
method: 'PUT',
body: JSON.stringify(body),
});
}async function deleteIssue(
client: JiraClient,
issueKeyOrId: string,
deleteSubtasks: boolean = false
): Promise<void> {
const query = deleteSubtasks ? '?deleteSubtasks=true' : '';
await client.request(`/issue/${issueKeyOrId}${query}`, {
method: 'DELETE',
});
}async function bulkCreateIssues(
client: JiraClient,
issues: CreateIssueInput[]
): Promise<Array<{ id: string; key: string; self: string }>> {
const results: Array<{ id: string; key: string; self: string }> = [];
// Jira doesn't have a native bulk create, so we batch with Promise.all
const batches = [];
const batchSize = 10;
for (let i = 0; i < issues.length; i += batchSize) {
batches.push(issues.slice(i, i + batchSize));
}
for (const batch of batches) {
const batchResults = await Promise.all(
batch.map((issue) => createIssue(client, issue))
);
results.push(...batchResults);
}
return results;
}curl -X POST "$JIRA_BASE_URL/rest/api/3/issue" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"project": { "key": "SCRUM" },
"summary": "New feature implementation",
"issuetype": { "name": "Story" },
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Description here" }]
}
]
}
}
}'curl -X GET "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Accept: application/json"curl -X PUT "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"summary": "Updated summary"
}
}'curl -X DELETE "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)"| Operation | Method | Path |
|---|---|---|
| Create issue | POST | /issue |
| Get issue | GET | /issue/{issueIdOrKey} |
| Update issue | PUT | /issue/{issueIdOrKey} |
| Delete issue | DELETE | /issue/{issueIdOrKey} |
project.key (required)summary (required)issuetype.name = "Story" (required)project.key (required)summary (required)issuetype.name = "Task" (required)project.key (required)summary (required)issuetype.name = "Bug" (required)description (recommended)Jira uses Atlassian Document Format for rich text:
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Normal text" }
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Bold text",
"marks": [{ "type": "strong" }]
}
]
}
]
}80215e3
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.