Skip to content

update_issue / update_epic: missing Status widget support (and list_workitem_statuses companion) #41

@Hakihiro

Description

@Hakihiro

Context

GitLab 17+ introduced a native Status widget on Work Items, with a custom per-group taxonomy (e.g. Refine, Ready, In progress, Review, QA, Feedback, Done, Won't do, Duplicate on our project). This widget is distinct from:

  • GitLab's open/closed state (state)
  • health_status (onTrack / needsAttention / atRisk)
  • Legacy Workflow::* labels

It is the canonical state axis on the Work Items board. The MCP update_issue / update_epic tools currently do not expose this widget, which forces a fallback to raw GraphQL workItemUpdate(statusWidget: { ... }) with hard-coded gid://gitlab/WorkItems::Statuses::Custom::Status/<n> IDs.

Encountered on 2026-04-23 during a MR review session: after creating a refactor issue (#814) and an in-review issue (#810), setting the board-visible Status (Refine / Review) was not possible via MCP — had to shell out to glab api graphql.

Impact

Medium–High. Status is the primary state axis surfaced on boards; every issue/epic status update currently requires raw GraphQL. The Workflow::* labels convention duplicates the widget and creates inconsistency when applied to issues.

Proposed fix

Extend two existing tools and add one helper:

1. update_issue / update_epic — add status param

Accept either the status name ("Review") or the full global ID ("gid://gitlab/WorkItems::Statuses::Custom::Status/42"). If a name is passed, resolve it against the group's custom statuses for the target work-item type.

Write-side mutation:

mutation {
  workItemUpdate(input: {
    id: "gid://gitlab/WorkItem/$WI_ID",
    statusWidget: { status: "gid://gitlab/WorkItems::Statuses::Custom::Status/$STATUS_ID" }
  }) {
    workItem { id }
    errors
  }
}

2. New companion tool list_workitem_statuses

Group-scoped, returns the allowed statuses for a given work-item type (ISSUE / EPIC / ...). Needed so callers can resolve names → IDs without hard-coding.

Read-side query:

query {
  workItem(id: "gid://gitlab/WorkItem/$ANY_WI_ID") {
    workItemType {
      widgetDefinitions {
        type
        ... on WorkItemWidgetDefinitionStatus {
          allowedStatuses { id name iconName color }
        }
      }
    }
  }
}

Or, if GitLab exposes a group-level endpoint for allowed statuses per type, prefer that (no sample work item needed).

Suggested tool shape:

list_workitem_statuses(group_id: string, work_item_type: 'issue' | 'epic') → [{ id, name, iconName, color }]

Ergonomic note

To avoid hammering the group every call, the resolved name → ID map can be cached on the client side (same pattern as other gap-fills). But the server should still accept both forms so callers don't have to cache to use the tool at all.

Version

@wanadev/mcp-gitlab latest (as of 2026-04-23), running against GitLab 18.x.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions