agentsclimarketplace

Pm tasks jira

Skill llodev/skills/skills/pm-tasks-jira

Collection of Agent Skills for Claude Code, Cursor, Codex, Windsurf, and any agent that speaks the open Skills spec. Ships via npm + plugin + skills add.

Install
npx -y skills add llodev/skills --skill pm-tasks-jira

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Jira adapter for the @llodev/pm-tasks-* family. Use when the user mentions Jira, asks to "create Jira issue", "publish to Jira", "log to Jira", "check subtask in Jira", or uses --publish-jira; OR for CRUD on existing issues (check subtask, close issue, change due-date, assign person, comment, set estimate, set parent); OR when invoked autonomously by another agent with [autonomous] / --auto sentinel. Jira model: team-managed, Kanban; issue → Subtask hierarchy (one level); transitions resolved at runtime by status category (locale-safe); estimate via story_points or timetracking field. Modes: paste-ready (no MCP), MCP publish (via Atlassian Remote MCP, Streamable-HTTP transport), autonomous (write-through with allowlist). Implements 9 verbs (task.create, task.move, checklist.check, task.close, task.due-date.set, task.assignee.add, task.comment.add, task.parent.set, task.estimate.set) from skills/pm-tasks-core/references/contract.md. F2 task.sprint.set is NOT supported — Atlassian MCP exposes no sprint API. Requires @llodev/pm-tasks-core installed.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

21.7 KB, as published. Nobody here has run it

pm-tasks-jira

Adapter for Jira within the @llodev/pm-tasks-* family. Use the core skill's extraction phases, then apply Jira formatting and optionally publish/operate via the Atlassian Remote MCP server.

Routing

ModeTriggerPath
Paste-only"format as Jira issue" without MCP intentPhase 3 (core) → Phase 4 (this skill, format only) → output paste blocks
MCP publish"publish to Jira", "create on Jira", "--publish-jira"Phase 3 → Phase 4 → Phase 5 (publish via MCP)
Autonomous[autonomous] or --auto in prompt OR LLODEV_PM_TASKS_AUTONOMOUS=1Phase 3 → Phase 4 → Phase 5b (write-through, no preview)
CRUD ops"check subtask N on KAN-1", "close KAN-2", "assign Alice to KAN-3", "comment on KAN-4", "set estimate on KAN-5"Phase 6 (operations, direct verb dispatch)
Plan-executionPlan file path in prompt (docs/plans/*.md), OR --plan-exec flag, OR plan reference paired with .jira.jsonPhase 7 (discover existing issues via discoverPlanTasks; calling agent dispatches per-task verbs at task boundaries)

Jira model

Jira issues have:

  • Summary (title, ≤255 chars; aim for ≤80 for board readability).
  • Description (Atlassian Document Format / ADF; transport sends markdown with markdown: true; do NOT attempt raw ADF construction).
  • Issue type — resolved from .jira.json issueTypes{}. Keys are canonical (task, story, bug, epic, subtask); each value is { id, name } where name is the locale-specific type name verbatim (e.g. { id: "10003", name: "Tarefa" } in pt-BR workspaces) and id is the stable reference. NEVER hard-code type names — always read from config.
  • Subtasks — one level deep. A Subtask requires a parent issue key at create time. Subtasks have reduced fields: duedate and priority are NOT applicable; task.due-date.set returns NOT_APPLICABLE on Subtasks.
  • Transitions — resolved at runtime via getTransitionsForJiraIssue, matched by to.statusCategory.key ("new" / "indeterminate" / "done"). NEVER match by transition name — names are locale-dependent and change with workflow customization.
  • Labels — plain strings; robust and searchable. Used to preserve human-readable estimates as est:<slug>.
  • Assignee — single account; editJiraIssue { assignee: { accountId } }. Jira does not support multi-assignee at the API level.

MCP transport: Atlassian Remote MCP at Streamable-HTTP endpoint https://mcp.atlassian.com/v1/mcp. The SSE endpoint (/events) was retired 2026-06-30. All mcp__atlassian__* tools are unchanged; only the transport layer differs.

F2 sprint: task.sprint.set is NOT supported. The Atlassian MCP exposes no agile/sprint API. The core factory returns UNSUPPORTED_VERB for this verb. Capacity and sprint planning are roadmapped for v1.12.0.

Phase 4 — Jira formatting

Apply the generic card from core's ../pm-tasks-core/references/generic-card.md. Then map to Jira:

  • Title → issue summary.
  • Sections of the generic card → markdown headings in description (ADF handles them when sent with markdown: true).
  • "Implementation Checklist" + "Verification Checklist" → Subtask summaries (one Subtask per item; Jira supports one level only; Subtask parent = parent issue key).
  • Labels → labels[] array. Resolve from .jira.json labels[] or pass through raw.
  • Due date → duedate (YYYY-MM-DD; sliced from ISO 8601). Not applicable for Subtasks — omit silently. The typed transport taskCreate also maps the core TaskCreateRequest.dueDate to duedate — see references/operations.md § Temporal handling for the create/start/close split.
  • Assignee → lookupJiraAccountId by display name or email; editJiraIssue { assignee: { accountId } }.
  • Issue type → v1 maps all created cards to the configured issueTypes.task (Subtasks use issueTypes.subtask). Per-type override is not yet supported — TaskCreateRequest carries no type field.

Phase 5 — MCP publish

Prerequisites: Atlassian Remote MCP connected in your agent. Configure with Streamable-HTTP transport https://mcp.atlassian.com/v1/mcp. The MCP handles OAuth; the adapter never sees tokens.

  • Claude Code: claude mcp add atlassian -s project -- npx -y @anthropic-ai/mcp-server-atlassian (or follow Atlassian's Remote MCP setup guide for your site).
  • Cursor / Windsurf / Cline / Roo Code: add an MCP entry in that agent's settings JSON pointing at the same endpoint and credentials.
  • Codex: TOML entry under [mcp_servers.atlassian] in ~/.codex/config.toml.

Strict order: 5.1 read .jira.json (full file) → 5.2 preview & approval → 5.3 publish via MCP → 5.4 error handling.

MCP publish sequence:

  1. Parent issuecreateJiraIssue with cloudId, projectKey, issueTypeName (from issueTypes.task), summary, description (markdown; clientToken embedded as [ct:<token>] in description body).
  2. SubtaskscreateJiraIssue per subtask with issueTypeName (from issueTypes.subtask), summary, parent: <parentKey>. No duedate or priority.
  3. Confirm — display parent issue key + URL (https://<site>/browse/<KEY>) and each subtask key.

Attribution (opt-in)

Before calling the MCP create tool, read config.attribution. If enabled === true, prefix the comment with the commentPrefix returned by getAttribution() and append the descriptionFooter to the end of description. In autonomous mode ([autonomous] sentinel), the commentPrefix automatically becomes the autonomousCommentPrefix. See references/attribution.md in pm-tasks-core (added in v1.2.0).

Phase 5b — Autonomous

Skip 5.2 preview & approval. Apply autonomous-mode contract from ../pm-tasks-core/references/autonomous-mode.md. Audit log entries per ../pm-tasks-core/references/audit-log-format.md.

Jira-specific autonomous scope: autonomous.scope.projectKey must match the target project in .jira.json. Issue transitions must be to categories already accessible in the board's workflow.

Continuous operation in multi-task loops

Mandatory when the controller executes a plan with multiple tasks autonomously. Mirror each task transition on the corresponding Jira issue in real time — NEVER batch state updates at end-of-loop. See ../pm-tasks-core/references/autonomous-mode.md § Continuous operation across multi-task loops.

Jira-specific verb mapping:

TransitionCanonical verb + MCP call(s)
Task starttask.move(key, "indeterminate")getTransitionsForJiraIssue → match statusCategory.key == "indeterminate"transitionJiraIssue
Step complete (subtask)checklist.checktransitionJiraIssue(subtaskKey, "done")
Task complete (full)task.move(key, "done")transitionJiraIssue to done category, then task.comment.addaddCommentToJiraIssue(body: "Task complete. Commit: <SHA>.", markdown: true), then task.closetransitionJiraIssue to done category again (idempotent)
Task failedtask.comment.addaddCommentToJiraIssue with failure mode + task.assignee.add to reassign for human escalation. Do NOT call task.move(_, "done") or task.close.

Close preserves the plan (lifecycle fidelity): transitioning to done lets Jira auto-stamp resolutiondate (the real completion). Leave duedate = the original plan — never overwrite it at close. Jira has no wired start-date field (optional custom-field increment, not implemented). See references/operations.md § Temporal handling and ../pm-tasks-core/references/lifecycle-fidelity.md.

Jira caveat (per anti-patterns/jira.md): getJiraIssue returns field values but not the full changelog. Verify lifecycle in the Jira UI activity feed when auditing — the UI is the human's audit log.

Phase 6 — CRUD operations (existing issues)

For verbs other than task.create, jump directly to the operation. Verb → MCP tool mapping:

Core verbJira MCP tool (mcp__atlassian__*)Notes
task.createcreateJiraIssueparent + subtasks per Phase 5; type from issueTypes; clientToken embedded in description as [ct:<token>]
task.movegetTransitionsForJiraIssuetransitionJiraIssuereq.targetListOrSectionId = status category key ("new" / "indeterminate" / "done"); locale-safe via category matching; previousListOrSectionId = null
checklist.checkcreateJiraIssue(Subtask) + transitionJiraIssuecomplete: create Subtask with parent=taskId, then transition to "done"; incomplete: transition existing subtask key to "new"
task.closegetTransitionsForJiraIssuetransitionJiraIssuetransitions to "done" category; same engine as task.move; movedToListOrSectionId = resulting status id
task.due-date.seteditJiraIssuefields: { duedate: "YYYY-MM-DD" } (sliced from req.dueAt ISO 8601); Subtask → NOT_APPLICABLE error (error-driven detection, no pre-read)
task.assignee.addlookupJiraAccountId (if needed) + editJiraIssuereq.userId: if matches accountId pattern → fast-path skip lookup; else lookupJiraAccountId { query: userId }editJiraIssue { assignee: { accountId } }
task.comment.addaddCommentToJiraIssuebody: req.text, markdown: true (load-bearing — omitting markdown: true causes ADF rendering failure); apply attribution prefix if enabled
task.parent.set (F3)editJiraIssuefields: { parent: { key: req.parentId } }; req.parentId must be a valid issue key (KAN-12); previousParentId always null
task.estimate.set (F7)getJiraIssue (read labels) + editJiraIssuenormalize via core normalizeEstimate; write native field + idempotent est:<slug> label in one call; see § Estimation below

<task-ref> resolution: Jira permalink (https://<site>/browse/KEY-N) → bare issue key (KAN-42) → alias from .jira.json taskAliases[].

Estimation (task.estimate.set detail)

Estimation records effort — never a calendar deadline. The request carries { taskId, input: EstimateInput, config: EstimationConfig }.

Flow:

  1. normalizeEstimate(req.input, req.config) (core helper, never throws) → NormalizedEstimate.
  2. Guard: if jiraTarget === "story_points" and req.config.fieldId is absent or empty → return INVALID_REQUEST with hint to enable Story Points in Board settings and re-run pm-tasks-jira init. No MCP calls made.
  3. getJiraIssue({ cloudId, issueKey, fields: ["labels"] }) — read current labels.
  4. Strip all prior est:* labels; append est:<slug> where slug = slugify(normalized.humanReadable).
  5. Build native field patch:
    • jiraTarget === "story_points"{ [req.config.fieldId]: n.points }
    • jiraTarget === "time"{ timetracking: { originalEstimate: n.timeString } }
    • jiraTarget === "none" → no native field (labels-only write)
  6. editJiraIssue({ fields: { ...nativeFieldPatch, labels: newLabels } }) — ONE call.
  7. Return { ok: true, data: { normalized, fieldWritten } }.

The est:<slug> label is the durable human-readable record — not a description footer. Jira descriptions are ADF; modifying them is fragile and not attempted. See references/estimation.md for full strategy taxonomy and jiraTarget mapping.

Phase 7 — Plan-execution mode

When the calling agent passes a plan reference (a path to a markdown plan file, a plan slug, or an explicit list of expected issue summaries), this skill loads .jira.json via requireConfig and uses discoverPlanTasks (from @llodev/pm-tasks-core) to triage which tasks in the plan already exist as issues in scope. The skill returns { found, missing, ambiguous } — the calling agent decides how to act on each bucket (create missing issues via Phase 4 + 5; disambiguate by picking the right ambiguous issue; proceed with existing).

The skill does not assume any particular implementation strategy. It does not drive the calling agent's task loop, does not depend on any specific orchestration framework, and does not require any markup beyond what is already documented for task.create and the autonomous-mode contract. When the calling agent finishes a task and asks the skill to record progress, it invokes the standard verbs (task.move, checklist.check, task.comment.add, task.close) directly — the same path used by Phase 5b autonomous mode.

Full contract: skills/pm-tasks-core/references/plan-execution.md (added in v1.9.0). Jira note: use searchJiraIssuesUsingJql for scope queries (replaces Asana search_tasks).

Result envelope

Every verb returns the core contract shape (see ../pm-tasks-core/references/contract.md §Result envelope):

{
  "ok": true,
  "verb": "task.create",
  "tool": "jira",
  "ref": { "id": "KAN-42", "url": "https://<site>/browse/KAN-42", "alias": null },
  "details": {/* Jira-specific (see table below) */}
}

Jira-specific details per verb:

Verbdetails fields
task.create{ id: "KAN-42", url?: string } (url present when MCP returns it)
task.move{ previousListOrSectionId: null, newListOrSectionId: "<statusId>" }
checklist.check{ previousState, newState } ("complete" / "incomplete")
task.close{ closed: true, movedToListOrSectionId: "<statusId>" }
task.due-date.set{ previousDueAt: null, newDueAt: "YYYY-MM-DD" } — or NOT_APPLICABLE on Subtask
task.assignee.add{ added: true, currentAssigneeIds: ["<accountId>"] }
task.comment.add{ commentId: "<id>", postedAt: "<ISO8601>" }
task.parent.set (F3){ previousParentId: null, newParentId: "<issueKey>" }
task.estimate.set (F7){ normalized: NormalizedEstimate, fieldWritten: <fieldId> or "timetracking" or null }

On failure: { ok: false, code: "<CODE>", details: { message, ... } }. Stable error codes: UNSUPPORTED_VERB, INVALID_REQUEST, NOT_APPLICABLE, NOT_FOUND, AUTH_ERROR, RATE_LIMITED, MCP_ERROR. UNSUPPORTED_VERB is returned by the core factory for verbs not in the adapter's manifest (e.g. task.sprint.set).

Anti-patterns

See anti-patterns/jira.md — transition-by-name pitfall, Subtask field restrictions, locale type-name anti-pattern, SSE endpoint retirement, description-footer anti-pattern for estimates.

Standalone fallback

If @llodev/pm-tasks-core is not installed: ask the user for minimum input (title + subtask names) and produce a paste-ready Jira issue body from this content alone. Quality is degraded — no scope/audience/fidelity inference. Print: "Install @llodev/pm-tasks-core for the full flow."

Config

Lookup order: <git-root>/.jira.json~/.config/llodev/pm-tasks/jira.json → abort with init instructions. Schema: schemas/config.json. Secrets NEVER in JSON — Atlassian MCP holds OAuth; init uses mcp__atlassian__atlassianUserInfo to discover the site and project via MCP.

Key fields written by init:

  • project{ key, id, style } (id is the numeric project id; style is team-managed / company-managed).
  • issueTypes{ id, name } per canonical key (epic, story, task, subtask, bug); name is the account-localized type name verbatim.
  • statuses — board statuses (≈ move/close targets), each { id, name, category } with categorynew / indeterminate / done.
  • fieldsByType — valid field keys per canonical type (lets the agent avoid writing unsupported fields).
  • locale — chosen at init (prompted); used for narration.

Init

npx @llodev/pm-tasks-jira init

See ../pm-tasks-core/references/init-ux.md for the shared flow. Jira init uses:

  • atlassianUserInfo — verify MCP connection and get user email.
  • getAccessibleAtlassianResources — list sites; select cloudId.
  • getVisibleJiraProjects — select project by key + id.
  • getJiraIssueTypeMetaWithFields — discover issue types (builds issueTypes{} as {id,name} via structural flags + locale aliases), the valid fields per type (fieldsByType), and the Story Points field for estimation (fieldId, matched by name; default customfield_10016). Absent on basic boards → time tracking is used instead.
  • project statuses — discover board statuses (move/close targets) with their stable category.
  • locale is prompted; estimation strategy + write target stay coherent (point strategies never target time, time strategies never target story points).

Writes all resolved values (including fieldId if found) to .jira.json.

Pass --doctor to run workspace health checks:

npx @llodev/pm-tasks-jira init --doctor

Runs core checks (C-FS-1..3, C-CFG-1..4) plus Jira-specific probes (C-JIR-1, C-JIR-2, gated on MCP connectivity). Full check matrix: skills/pm-tasks-core/references/doctor.md.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.