Issue tracking — four providers, one interface.
Connect Claude tasks to your tracker. Import an issue and the task file is created; complete the task and the issue closes, the MR ships, the label flips — all driven by MCP tools, the same way across every provider.
The four providers
| Provider | issue_tracking.provider | Notes |
|---|---|---|
| GitLab | gitlab | Issues + merge-request workflow. |
| Jira | jira | Jira API with markdown-to-wiki conversion. |
| GitHub | github | Issues + pull-request workflow. |
| Gitea | github | Same key — auto-detected from the base URL (/api/v1 path or a gitea host); uses label IDs, not names. |
| None | disabled | Completion shows a 4-option menu instead of a provider flow (see Completion dispatch). |
Import, create, sync
issue_read takes an ID or full URL and writes a task file under team-management/tasks/; pass update mode to re-fetch and overwrite an existing one. issue_create goes the other way — pushes a task's title and description to a new provider issue. issue_sync pushes the current task status to the linked issue, and auto_sync does it automatically on task-lifecycle events.
Linking an existing ticket
Work does not always start from the tracker. When a task already exists locally, issue_link attaches a provider ID to it and issue_unlink detaches it again — useful when something was filed twice, or filed in the wrong project.
From there the rest of the surface is ordinary tracker work, done without leaving the session: issue_update for title, description, status or labels; issue_comment to leave a note; issue_set_status to transition with an optional comment; and issue_push to send the task file’s own content back into the description. When something is not covered, issue_api makes a raw authenticated call to the active provider.
One tool is not universal. issue_dependency declares that one piece of work blocks another, and it runs on the github key only — GitHub inside a single repository, and Gitea, which shares that key and can also link across repositories. On GitLab it returns an error rather than guessing, and Jira is not supported.
What happens without being asked
Two engine functions do the routine bookkeeping, and both check first. create_issue_if_enabled files a new ticket when a task starts; update_issue_status closes it out at completion. Each one skips quietly unless a provider is actually configured — the default is disabled, and a configured provider can still be switched off with its own issue_tracking_enabled flag. Set one up and the tracker keeps pace with the work without anyone remembering to update it.
Completion dispatch
With a provider configured, the completion step merges the branch, opens the MR/PR, and transitions the issue. With provider: "disabled", it instead offers a four-option menu — merge_local / push_pr / keep / discard. push_pr uses gh pr create with an idempotency precheck; discard is gated behind a typed confirmation (friction, not security). Either way, HEAD must match the task's feature branch before any local flow runs.
All of this is exposed through the issue_* tools on the MCP reference.