forgejo create_issue should accept labels so issue creation is one call, not two #53

Closed
opened 2026-08-13 00:05:21 +00:00 by coilyco-ops · 1 comment
Member

Request

create_issue on the forgejo MCP exposes only owner, repo, title, body. Forgejo's own API accepts labels (an array of label ids) on issue creation. Please project it through.

Why

Filing a batch of issues currently costs 2N calls: create, then add_issue-label per issue. During a 23-issue QA batch on coilyco-gaming/eco-app#240 that is 23 extra round trips to do something the upstream API does atomically, and it leaves a window where issues exist unlabelled — visible to anyone watching the tracker, and to any automation that filters on labels.

Not a capability gap: add_issue-label and set_issue-label are both exposed and work. This is purely about atomicity and call count.

Likely shape

labels is a repeated/array field, so this may depend on the same machinery as #33 (typed repeated query inputs). If array-valued body fields are already supported, this should be an allowlist addition in the forgejo spec rather than new plumbing.

Also worth considering

milestone and assignees have the same shape and the same argument. Not requesting them, just flagging that a fix here probably generalises.

## Request `create_issue` on the forgejo MCP exposes only `owner`, `repo`, `title`, `body`. Forgejo's own API accepts `labels` (an array of label ids) on issue creation. Please project it through. ## Why Filing a batch of issues currently costs 2N calls: create, then `add_issue-label` per issue. During a 23-issue QA batch on https://forgejo.coilysiren.me/coilyco-gaming/eco-app/issues/240 that is 23 extra round trips to do something the upstream API does atomically, and it leaves a window where issues exist unlabelled — visible to anyone watching the tracker, and to any automation that filters on labels. Not a capability gap: `add_issue-label` and `set_issue-label` are both exposed and work. This is purely about atomicity and call count. ## Likely shape `labels` is a repeated/array field, so this may depend on the same machinery as https://forgejo.coilysiren.me/coilyco-flight-deck/mcp-beaver/issues/33 (typed repeated query inputs). If array-valued body fields are already supported, this should be an allowlist addition in the forgejo spec rather than new plumbing. ## Also worth considering `milestone` and `assignees` have the same shape and the same argument. Not requesting them, just flagging that a fix here probably generalises.
Author
Member

No runtime change needed - this already works. Verified and pinned with a test in c61a7f2. Leaving open because the actual edit is deploy's.

Your guess that this might depend on the same machinery as #33 was the right question, and the answer is that array-valued body fields are already supported and already tested (internal/mcpserver/structured_body_test.go covers array "labels" items="string"). What blocks it is the flat shorthand, not the plumbing: body "title" "body" mints optional strings and cannot express anything else. The block form can.

The deploy-side edit, which is the whole remaining change:

can create issue {
    path "/repos/{owner}/{repo}/issues"
    body {
        field "title" type="string" required=#true
        field "body" type="string"
        array "labels" items="integer"
    }
}

items="integer", not "string" - this matters and it would be easy to get wrong. Forgejo's CreateIssueOption takes label IDs. Your own add issue-label grant in deploy/services/forgejo-mcp/forgejo.mcp.kdl already carries the note: "Forgejo's IssueLabelsOption is an integer-id array. Declaring strings caused numeric ids to arrive quoted and mutate nothing." Repeating that here would ship a labels parameter that silently labels nothing - worse than the two-call sequence, because it looks like it worked.

TestCreateIssueAcceptsLabelArray asserts the ids reach the upstream as JSON numbers, so the runtime side is guarded against that regression.

Also updated examples/forgejo-issues.mcp.kdl to show the shape, since "supported but no example exists" is the same reason #58 sat open on a feature that already worked.

milestone (integer) and assignees (string array) have the same shape if you want them in the same pass.

**No runtime change needed - this already works.** Verified and pinned with a test in c61a7f2. Leaving open because the actual edit is deploy's. Your guess that this might depend on the same machinery as #33 was the right question, and the answer is that array-valued body fields are already supported and already tested (`internal/mcpserver/structured_body_test.go` covers `array "labels" items="string"`). What blocks it is the **flat shorthand**, not the plumbing: `body "title" "body"` mints optional strings and cannot express anything else. The block form can. The deploy-side edit, which is the whole remaining change: ```kdl can create issue { path "/repos/{owner}/{repo}/issues" body { field "title" type="string" required=#true field "body" type="string" array "labels" items="integer" } } ``` **`items="integer"`, not `"string"` - this matters and it would be easy to get wrong.** Forgejo's `CreateIssueOption` takes label **IDs**. Your own `add issue-label` grant in `deploy/services/forgejo-mcp/forgejo.mcp.kdl` already carries the note: *"Forgejo's IssueLabelsOption is an integer-id array. Declaring strings caused numeric ids to arrive quoted and mutate nothing."* Repeating that here would ship a `labels` parameter that silently labels nothing - worse than the two-call sequence, because it looks like it worked. `TestCreateIssueAcceptsLabelArray` asserts the ids reach the upstream as JSON numbers, so the runtime side is guarded against that regression. Also updated `examples/forgejo-issues.mcp.kdl` to show the shape, since "supported but no example exists" is the same reason #58 sat open on a feature that already worked. `milestone` (integer) and `assignees` (string array) have the same shape if you want them in the same pass.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/mcp-beaver#53
No description provided.