Repository navigation
Conversation
Pull the Users.Get account type lookup out of detectOwnerType so issue metadata can reuse it to tell a user owner from an organization. The project probe fallback is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48ff87e1-24bb-49f1-887f-9f2576ab0c2d
Issue types and issue fields are available on user accounts as well as organizations. list_issue_types, list_issue_fields, and the ui_get issue_types method assumed the owner was an organization when repo was omitted, so they failed or came back empty for user-owned repositories. Introduce issueMetadataScope (repository, organization, or the authenticated user) and resolve it once per call. With repo, the repository path is unchanged. Without repo, the owner's account type picks the organization endpoints or, when the owner is the authenticated user, GET /user/issue-types and GraphQL user(login:).issueFields. GitHub lists a user's definitions only to that user, so any other user owner gets a tool error asking for repo instead of a raw FORBIDDEN. The issue-write app now passes repo to ui_get issue_types, which reads the repository endpoint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48ff87e1-24bb-49f1-887f-9f2576ab0c2d
Owner-level list_issue_types, list_issue_fields, and ui_get issue_types calls challenged for read:org because the owner was assumed to be an organization. A user owner needs no extra scope, and the arguments alone cannot tell a user from an organization, so the challenge would ask user callers for a scope they do not need. Rename repositoryOrOrganizationScopeAccess to optionalRepositoryScopeAccess, which challenges for repo only when repo is passed, and treat ui_get issue_types like the other repository methods. An organization caller without read:org now gets the API error instead of a step-up prompt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48ff87e1-24bb-49f1-887f-9f2576ab0c2d
Tool descriptions, toolset instructions, the README, and toolsnaps said issue types and fields belong to an organization. Describe the owner as a user or organization, and note that ui_get takes an optional repo for issue_types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 48ff87e1-24bb-49f1-887f-9f2576ab0c2d
dewski
force-pushed
the
dewski/owner-agnostic-issue-types-fields
branch
from
November 12, 2026 19:39
9ec3a65 to
001cf21
Compare
resolveIssueMetadataScope put the raw owner argument into the tool error
it returns for another user's account. owner comes from the model, and
go-github doesn't escape it in the users/{owner} path, so a value like
"octocat?x=..." still resolves to a real user and its extra text would
reach the model verbatim. Refer to "the owner" instead, since the model
already knows what it passed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 48ff87e1-24bb-49f1-887f-9f2576ab0c2d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR makes
list_issue_types,list_issue_fields, and theui_getissue_typesmethod work for user-owned repositories the same way they work for organizations. It's stacked on #3831.Important
This PR changes one OAuth behavior. Calls to
list_issue_typesandlist_issue_fieldswithoutrepono longer challenge forread:org. The challenge only sees the arguments and the token's scopes, so it can't tell a user owner from an organization, and a user owner doesn't needread:org. An organization caller whose token lacksread:orgnow gets the GitHub API error at call time instead of an OAuth step-up prompt.read:orgis in the default OAuth scopes, so I expect that to be rare.ui_getissue_typesalso stops challenging forread:org, and challenges forrepowhen one is named, like the other repository-scopedui_getmethods.Why
Issue types and issue fields are generally available on user accounts as well as organizations, but the server still assumed the owner was an organization whenever
repowas omitted. For a user-owned repository, that meantlist_issue_typesandlist_issue_fieldsfailed againstorgs/{owner}ororganization(login:). It also meant the issue-write app's type picker came back empty, since it calledui_getissue_typeswithoutrepo.There isn't a public issue tracking this.
What changed
reporepo, organization ownerorgs/{owner}/issue-types,organization(login:)repo, owner is the authenticated userGET /user/issue-types,user(login:)issueFieldsrepo, any other user ownerFORBIDDENor not foundrepo, since GitHub only lists a user's definitions to that userissueMetadataScopeinpkg/github/issue_metadata_scope.go, which is the repository, organization, or authenticated user whose issue types and fields a call lists.list_issue_types,list_issue_fields, andui_getissue_typesall resolve it once per call throughresolveIssueMetadataScope.ListIssueTypesdrops its non-200 body-reading branches, since go-github already returns an error for any non-2xx response.ownerAccountTypefromdetectOwnerTypeinpkg/github/projects.goso the projects tools and the new scope share one owner lookup.detectOwnerTypebehaves the same.issue_writetypeandfield_nameparams, theset_issue_fieldsdescription, and the issues toolset instructions to describe the owner as a user or organization.Reviewing this PR
I'd review this commit by commit. Each commit builds and passes
go test ./...on its own, and the generated README and toolsnaps match the code at every step.ownerAccountTypefromdetectOwnerType. This is a refactor ofpkg/github/projects.gowith no behavior change.issueMetadataScopeinpkg/github/issue_metadata_scope.go, then the call sites inissues.go,issue_fields.go,ui_tools.go, andui/src/apps/issue-write/App.tsx, with the tests. The fixture tweaks intyped_issue_outputs_test.goandtyped_copilot_ui_outputs_test.goadd an owner lookup mock or arepoargument.read:orgfor owner-level issue metadata. This is the behavior change called out above, isolated inpkg/github/tool_scopes.goand its tests, plus the two regenerated scope lines in the README.ownerargument back to the model, so the message now says "the owner" instead.MCP impact
Tool names and input shapes are unchanged.
list_issue_typesandlist_issue_fieldsnow succeed for user owners who are the authenticated user,ui_gettakes an optionalrepoforissue_types, and the descriptions and OAuth challenge scopes changed as described above.Prompts tested (tool changes only)
I didn't run these against a live MCP client. The tool tests exercise each scenario end to end against mocked REST and GraphQL responses:
octocat/hello-world?" (repo path, user-owned repository)OctoCat(GET /user/issue-types)user(login:)issueFields)hubot" whenhubotis a different user (error asking forrepo)testorgorganization" (organization path, unchanged)ui_getissue_typeswithrepo)Security / limits
See the
read:orgnote at the top. The user path only lists definitions for the authenticated user, and other user owners get a clear error rather than a request on their behalf. Repository results keep the repo visibility IFC label, and owner-level results keep the conservative private label.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
Linted locally with
./script/lintTested locally with
./script/testgo build ./...passed.script/testpassed.script/lintpassed with 0 issues.UPDATE_TOOLSNAPS=true go test ./...passed, and the toolsnap updates are committed.script/generate-docspassed, and the README update is committed.In
ui/,npm testpassed locally (11 tests). CI'sbuildjob runsscript/build-ui, which runsnpm testandnpm run build, and it passed on all three platforms. Neither CI nor I rannpm run typecheck. The UI change only addsrepoto onecallToolargument object.I also checked the new tests catch regressions. Each of these changes made the named tests fail:
Test_ListIssueTypesandTest_ListIssueFields.orgs/{owner}/issue-typesfailed the authenticated-user case inTest_ListIssueTypes.read:orgchallenge for owner-level calls failedTestConditionalToolScopeChecks.ui_getignorerepofailed the repository case inTest_UIGet.Docs
The generated README now describes the owner as a user or organization and lists
repoas the only OAuth challenge scope forlist_issue_typesandlist_issue_fields.