Repository navigation
Conversation
Expose list, upsert, and delete operations behind the pull_request_artifacts MCP feature flag, with repository rollout enforced by the GitHub API. Include commit-aware pagination, lockdown handling, tool snapshots, regression tests, and documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7bc67675-583d-4ef1-9b2a-25ae850acee2
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The artifact name transformation loses addressing information, so passing a listed name to upsert or delete can overwrite or delete a different artifact.
1 open issue
What changed in this PR
Adds experimental pull request artifact management to the GitHub MCP Server’s pull_requests toolset, following the existing issue-artifact pattern.
Changes:
- Introduces typed tools for listing artifacts and upserting or deleting them by name, with commit selection and pagination.
- Requires explicit feature opt-in, separate from GitHub’s repository rollout gate, and supports read-only and lockdown restrictions.
- Adds validation, sanitization, security labels, regression tests, schema snapshots, and documentation.
| File | Description |
|---|---|
pkg/skills/catalog/availability_test.go |
Adds reasoned skill-coverage exemptions for both tools. |
pkg/github/tools.go |
Registers the artifact tools. |
pkg/github/pull_request_artifacts.go |
Implements tool schemas, API operations, validation, and result handling. |
pkg/github/pull_request_artifacts_test.go |
Covers discovery, requests, pagination, errors, and safety behavior. |
pkg/github/pull_request_artifact_types.go |
Defines exported artifact input and output types. |
pkg/github/feature_flags.go |
Adds the explicit artifact-tool exposure flag. |
pkg/github/__toolsnaps__/pull_request_artifact_write_ff_pull_request_artifacts.snap |
Records the write tool’s schema. |
pkg/github/__toolsnaps__/pull_request_artifact_read_ff_pull_request_artifacts.snap |
Records the read tool’s schema. |
docs/feature-flags.md |
Documents opt-in setup, operations, outputs, and constraints. |
Review effort: Max (dynamic)
Add target-bound, expiring MCP confirmation for pull request artifact deletion and lossless name keys for safe read-to-write round trips. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7bc67675-583d-4ef1-9b2a-25ae850acee2
BigDadBear
approved these changes
Nov 13, 2026
BigDadBear
left a comment
Member
There was a problem hiding this comment.
Zero experience with this repo but lgtm!
| func pullRequestArtifactResult(ctx context.Context, deps ToolDependencies, repository *gogithub.Repository, output any) *mcp.CallToolResult { | ||
| result := MarshalledTextResult(output) | ||
| if shouldAttachIFCLabel(ctx, deps, result) && repository.Private != nil { | ||
| setIFCLabel(result, ifc.LabelRepoUserContent(*repository.Private)) |
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
Add experimental pull request artifact tools for listing, upserting, and deleting artifacts, following the issue-artifact tool pattern. Tool exposure requires the explicit MCP feature flag
pull_request_artifacts; GitHub separately enforcespull_request_artifacts_apifor the target repository.Why
Enable clients to read and write PR artifacts through MCP without treating a user-level tool-exposure flag as repository rollout authorization.
What changed
pull_request_artifact_read(method: list) andpull_request_artifact_write(method: upsert | delete) in thepull_requeststoolset, with exported typed inputs and outputs.next_pagefrom REST Link headers.pull_request_artifactsMCP flag, off by default and excluded from Insiders. Each API request remains subject to GitHub's repository/organization-awarepull_request_artifacts_apigate.MCP impact
Two new experimental tools; existing issue-artifact tools are unchanged. Read-only mode exposes only the read tool. Clients opt in with
--features=pull_request_artifacts,GITHUB_FEATURES=pull_request_artifacts, or the supported HTTP feature configuration.Prompts tested (tool changes only)
github-artifacts-localserver. The prompt sequence is recorded below. Manualmcpcurlschema discovery was also confirmed after exportingGITHUB_PERSONAL_ACCESS_TOKEN; the write tool advertises--method,--name, and--body.mcp-teston github/pull-request-review-testing#1885. Enabled-versus-disabled repository rollout toggling was not exercised.Manual prompt sequence
To repeat the manual prompt testing, connect
github-artifacts-localusing the setup below and use these prompts in order. Create/update/delete modify the scratch artifact; substitute a different test PR or artifact name if needed.Create
Read
Update
Delete
Verify deletion
Security / limits
Both tools declare the existing
repoOAuth scope policy. GitHub's API enforces operation-specific authorization and the per-repository rollout flag; exact fine-grained permission mappings were not independently verified. All operations reject lockdown mode before making network requests.Artifact names and creator logins use plain-text sanitization; bodies use the existing content sanitizer. List returns one page, defaulting to 30 and capped at 100. Writes are not automatically retried; conflicts, permission errors, throttling, and storage failures are returned explicitly. A 404 is not interpreted as definitive evidence of a disabled rollout flag.
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.
No existing tools are renamed.
Lint & tests
./script/lint./script/testCompleted verification:
go test ./pkg/github ./pkg/skills/catalog -run '^(TestPullRequestArtifact|TestIssueArtifact|TestResolveFeatureFlags|TestCatalogToolRequirementsAreRegistered|TestCatalogAvailabilityModes)' -count=1UPDATE_TOOLSNAPS=true go test ./...script/lintscript/testgo test -race ./...suitescript/generate-docsdocs/feature-flags.mdgit diff --checkThe required lint, race-test, and documentation commands passed in that order. Regression coverage includes create/update upsert statuses, delete, commit selection, Link-based pagination, escaped paths, invalid inputs, legacy/modern output, sanitization/IFC labels, lockdown, API errors/no retries, and mocked enabled/disabled repository responses under the same request context. The automated live E2E suite was not run, and repository rollout flags were not changed.
Reproducing locally
Use Go 1.27.3 or later. Run the following from the repository root, keeping authentication and invocation commands in the same terminal.
Build and automated tests
Authentication and discovery
The target repository must have the API rollout flag
pull_request_artifacts_apienabled, and the token must have access to the target PR. The current MCP scope policy requiresrepofor classic PATs. The separate MCP exposure flag ispull_request_artifacts; passing it does not enable the repository's API rollout.Discovery should advertise both artifact tools, and write-tool help should include
--method. Ifmcpcurlreportsunknown flag: --method, runschemadirectly: startup/discovery failures can otherwise surface as misleading unknown-flag errors. In particular, having a PAT configured inghis not sufficient unless the server receivesGITHUB_PERSONAL_ACCESS_TOKEN. A 404 from an artifact operation may indicate disabled repository rollout, missing resources, or insufficient access.Direct MCP operation tests
These commands mutate only the named scratch artifact
mcp-teston github/pull-request-review-testing#1885. Substitute a repository/PR you are authorized to test.Expected results: create/update return an
artifact; list returns alistwith bodies and optionalnext_page; delete returns adeletedconfirmation; the final list should no longer include the scratch artifact. Omitcommit_oidor usecurrentto test current-head selection; use a fixed commit OID for stable selection across pages.Connect the local build to Copilot CLI
Configure the token explicitly on the MCP server rather than relying on environment inheritance. Run this from the repository root in the shell where the token was exported:
--envsaves the token in the local Copilot configuration (~/.copilot/mcp-config.json, or underCOPILOT_HOMEwhen overridden). Do not share or commit that file or include token values in test reports.Start
copilot, or in an existing session reload and inspect the server:Use the manual prompt sequence above and confirm the tool calls target
github-artifacts-local. After future code changes, rebuild the server binary and run/mcp reloadbefore retesting; the existing process does not pick up a newly built binary automatically.Docs
Updated
docs/feature-flags.mdwith experimental opt-in behavior, the distinction between the two feature flags, operations, pagination, output, and safety constraints.Skills
PR artifact management is outside the current bundled workflows. Added explicit exemptions for both tools in
pkg/skills/catalog/availability_test.go, following the issue-artifact precedent; catalog coverage checks passed.