The Problem
The mcp__neo-mjs-github-workflow__manage_issue_labels MCP tool fails when invoked with a PR number, returning:
Tool Error: GraphQL API request failed. Message: GitHub API error: Could not resolve to an Issue with the number of {N}.
Reproduced during PR #10076 creation (session 62d6f155-e57f-4279-9b59-36c9e4ecbc5e, 2026-04-19): labels ai, ai-generated, enhancement could not be applied via MCP immediately after gh pr create. Fallback to gh pr edit --add-label succeeded.
The tool schema advertises "issue OR pull request" support (issue_number: "The number of the issue or pull request" per openapi.yaml), so this is a contract violation — the documented capability does not match runtime behavior.
Root Cause
ai/mcp/server/github-workflow/services/IssueService.mjs — manageIssueLabels() method (around line 509) unconditionally runs the GET_ISSUE_AND_LABEL_IDS GraphQL query and extracts data.repository.issue.id. GitHub's GraphQL schema treats Issues and PullRequests as distinct types, so repository.issue(number: N) returns null when N is a PR number, yielding the observed error.
The Pattern Already Exists in the Codebase
manageIssueComment() in the same file (lines 187–193) correctly handles the dual-type case:
const query = isPR ? GET_PULL_REQUEST_ID : GET_ISSUE_ID;
const idData = await GraphqlService.query(query, idVariables);
const subjectId = isPR
? idData.repository.pullRequest.id
: idData.repository.issue.id;
This is the template manageIssueLabels should follow. Both Issue and PullRequest implement the Labelable GraphQL interface, so the downstream mutations (addLabelsToLabelable / removeLabelsFromLabelable) are already generic — only the ID-lookup query needs to branch.
Proposed Fix
- Add an
isPR detection (same mechanism manageIssueComment uses — check parent issue/PR type or probe both queries).
- Conditionally query
GET_PULL_REQUEST_ID vs GET_ISSUE_AND_LABEL_IDS (or split the latter: one query for the labelable ID, one for the repo label IDs).
- Extract
data.repository.pullRequest.id or data.repository.issue.id accordingly.
- Pass the unified
labelableId to the shared label mutations — no changes needed downstream.
Test Plan
- Playwright unit test under
test/playwright/unit/ai/mcp/server/github-workflow/ covering:
- Adding labels to an Issue (existing behavior, regression guard)
- Adding labels to a PR (new)
- Removing labels from a PR (new)
- Error case: non-existent number (PR and Issue both not found)
- Manual verification: open a fresh PR via
gh pr create, then immediately call manage_issue_labels via MCP — the specific reproduction vector from PR #10076.
Secondary Observation (Separate Hypothesis)
During the original failure, manage_issue_labels also failed for the fresh PR number before GitHub's local sync caught up. That could be a second bug (local-cache miss handling) or a symptom of this same bug (the Issue-only lookup fails identically whether the PR exists or not). The fix above likely resolves both observed symptoms, but if the cache-miss concern persists after the fix, consider a follow-up ticket.
Scope
Investigation ticket parked for a future session. Not in scope for the current session (focused on #10030 next).
Origin Session ID
62d6f155-e57f-4279-9b59-36c9e4ecbc5e
Related
- PR #10076 — reproduction;
[TOOLING_GAP] tag in the self-review documents this case
- #10075 — the ticket whose PR surfaced the failure
ai/mcp/server/github-workflow/services/IssueService.mjs — location of the fix
ai/mcp/server/github-workflow/openapi.yaml — schema claims dual-type support
The Problem
The
mcp__neo-mjs-github-workflow__manage_issue_labelsMCP tool fails when invoked with a PR number, returning:Reproduced during PR #10076 creation (session
62d6f155-e57f-4279-9b59-36c9e4ecbc5e, 2026-04-19): labelsai,ai-generated,enhancementcould not be applied via MCP immediately aftergh pr create. Fallback togh pr edit --add-labelsucceeded.The tool schema advertises "issue OR pull request" support (
issue_number: "The number of the issue or pull request"peropenapi.yaml), so this is a contract violation — the documented capability does not match runtime behavior.Root Cause
ai/mcp/server/github-workflow/services/IssueService.mjs—manageIssueLabels()method (around line 509) unconditionally runs theGET_ISSUE_AND_LABEL_IDSGraphQL query and extractsdata.repository.issue.id. GitHub's GraphQL schema treats Issues and PullRequests as distinct types, sorepository.issue(number: N)returns null whenNis a PR number, yielding the observed error.The Pattern Already Exists in the Codebase
manageIssueComment()in the same file (lines 187–193) correctly handles the dual-type case:const query = isPR ? GET_PULL_REQUEST_ID : GET_ISSUE_ID; const idData = await GraphqlService.query(query, idVariables); const subjectId = isPR ? idData.repository.pullRequest.id : idData.repository.issue.id;This is the template
manageIssueLabelsshould follow. BothIssueandPullRequestimplement theLabelableGraphQL interface, so the downstream mutations (addLabelsToLabelable/removeLabelsFromLabelable) are already generic — only the ID-lookup query needs to branch.Proposed Fix
isPRdetection (same mechanismmanageIssueCommentuses — check parent issue/PR type or probe both queries).GET_PULL_REQUEST_IDvsGET_ISSUE_AND_LABEL_IDS(or split the latter: one query for the labelable ID, one for the repo label IDs).data.repository.pullRequest.idordata.repository.issue.idaccordingly.labelableIdto the shared label mutations — no changes needed downstream.Test Plan
test/playwright/unit/ai/mcp/server/github-workflow/covering:gh pr create, then immediately callmanage_issue_labelsvia MCP — the specific reproduction vector from PR #10076.Secondary Observation (Separate Hypothesis)
During the original failure,
manage_issue_labelsalso failed for the fresh PR number before GitHub's local sync caught up. That could be a second bug (local-cache miss handling) or a symptom of this same bug (the Issue-only lookup fails identically whether the PR exists or not). The fix above likely resolves both observed symptoms, but if the cache-miss concern persists after the fix, consider a follow-up ticket.Scope
Investigation ticket parked for a future session. Not in scope for the current session (focused on #10030 next).
Origin Session ID
62d6f155-e57f-4279-9b59-36c9e4ecbc5eRelated
[TOOLING_GAP]tag in the self-review documents this caseai/mcp/server/github-workflow/services/IssueService.mjs— location of the fixai/mcp/server/github-workflow/openapi.yaml— schema claims dual-type support