feat: add labels support to create_pull_request tool#2413
Conversation
Add optional 'labels' parameter to the create_pull_request tool,
enabling users to apply labels during PR creation.
Since the GitHub REST API doesn't support labels in the PR creation
endpoint, labels are applied in a second step via the Issues API
(POST /repos/{owner}/{repo}/issues/{issue_number}/labels).
Changes:
- Add 'labels' array property to CreatePullRequest InputSchema
- Add post-creation AddLabelsToIssue call in the handler
- Add labels input field to pr-write MCP App UI
- Add test cases for label success and failure scenarios
- Update toolsnap snapshot and README documentation
jluocsa
left a comment
There was a problem hiding this comment.
Nice feature — labels on creation saves a follow-up add_issue_labels round-trip for agents.
Two things worth considering before merge:
1. Partial-success surfaced as full failure. In pullrequests.go:
if labelsErr != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx,
fmt.Sprintf("pull request created (#%d) but failed to add labels", pr.GetNumber()),
labelsResp,
labelsErr,
), nil, nil
}The PR has already been created at this point, but the tool returns an MCP error result. An LLM caller seeing isError: true is very likely to treat the whole operation as failed and retry — which will either create a duplicate PR or hit the "head branch already has an open PR" error and get confused. The string "pull request created (#%d) but failed to add labels" is good context for a human reader, but agents key off the error flag first.
Two options that avoid the retry hazard:
- Return a successful
CallToolResultwhose content includes the PR JSON plus a_warnings: ["could not add labels: ..."]field, mirroring how some other partial-success endpoints in this server are structured. - Or: roll back by calling Issues.Edit to close the PR, then return the error. (Probably worse — silently closes a PR the user wanted.)
The first option seems cleanest. Whatever path you pick, it's worth a comment explaining the chosen semantics.
2. Test mocks a 404 but GitHub returns 422 for "label does not exist". In pullrequests_test.go, the failure-mode test does:
PostReposIssuesLabelsByOwnerByRepoByIssueNumber: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusNotFound)
_, _ = w.Write([]byte(`{"message": "Label does not exist"}`))
}),The real API behavior for unknown label names is 422 Validation Failed, not 404 (404 is only returned when the issue/PR number itself is unreachable). The mock works for asserting that the error path runs, but a future maintainer reading the test will get a misleading impression of the GitHub contract. Consider switching the status to 422 and the response body to a validation_failed shape.
3. Minor: description doesn't note labels-must-exist. The POST /issues/{n}/labels endpoint does not auto-create labels; passing a non-existent label name fails the whole add call. Worth adding a sentence to the param description so agents don't try labels: ["fix-this"] against repos that don't have that label defined.
Toolsnap + README + UI changes all look consistent. Test coverage of the happy path is great.
Summary
Add optional
labelsparameter to thecreate_pull_requesttool, enabling users to apply labels during PR creation in a single step.Why
Fixes #2417
The
create_pull_requesttool currently doesn't support adding labels. Users in agentic workflows must make a separateadd_labeltool call after creating a PR, which is inefficient and unintuitive. Developers naturally think of PR creation as: title + description + labels together.What changed
pkg/github/pullrequests.go: Addedlabels(string array) toCreatePullRequestInputSchema. After PR creation, callsclient.Issues.AddLabelsToIssueto apply labels. If label application fails, returns error with PR number so users know the PR was created.pkg/github/helper_test.go: AddedPostReposIssuesLabelsByOwnerByRepoByIssueNumberendpoint constant for mocking.pkg/github/pullrequests_test.go: Added 2 test cases — successful PR creation with labels, and label failure after PR creation.pkg/github/__toolsnaps__/create_pull_request.snap: Updated schema snapshot to includelabels.ui/src/apps/pr-write/App.tsx: Added labels state, comma-separated input field, prefill fromtoolInput, and array conversion on submit.README.md: Auto-generated viascript/generate-docs.MCP impact
labelsarray parameter tocreate_pull_requestPrompts tested (tool changes only)
Security / limits
Tool renaming
deprecated_tool_aliases.goNote: if you're renaming tools, you must add the tool aliases. For more information on how to do so, please refer to the official docs.
Lint & tests
./script/lint./script/testDocs