* build: require Go 1.25.12
Ensure setup-go and GoReleaser use the patched Go toolchain for release binaries.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0b2aa497-b47d-464a-b132-af0dcaf2b621
* build(ui): update fast-uri to 3.1.4
Resolve the high-severity host-confusion advisories reported by npm audit.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0b2aa497-b47d-464a-b132-af0dcaf2b621
---------
Co-authored-by: Ross Tarrant <rosstarrant@github.com>
* fix(ui): render success view when an MCP App tool executed up-front
The create_pull_request / issue_write / update_pull_request Views decided
form-vs-success from in-app submit state only, ignoring the tool-result the
host delivers on render. Per the MCP Apps 2026-01-26 spec the host renders a
View whenever the tool carries _meta.ui.resourceUri — independent of whether
the server deferred or executed. So when the server executed up-front (e.g.
show_ui=false, or parameters the form can't represent) the View still showed
its "Create pull request" input form over an already-created PR, which reads
as a bug (it even shows a PR number).
Drive the Views off the result instead: a new shared completedToolResult()
helper returns parsed data only for a genuine completed success, and returns
null for the awaiting_user_submission deferral sentinel, errors, or no result.
Each write View now shows its success card when that completed result is
present, so the form is only ever shown while the action is genuinely deferred.
Reconciles the show/defer state machine at the View (decision layer that the
host result feeds). See github/copilot-mcp-core#1864.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(ui): scope tool-result to the current invocation
Address review feedback: the write Views derive their success card from
`toolResult`, but it wasn't cleared when a new invocation arrived (only the
in-app `successPR`/`successIssue` was reset on `toolInput` change). A completed
result from a previous invocation could briefly render a stale success card
over the next, still-deferred form.
Clear `toolResult` whenever a new `tool-input` notification arrives. The spec
guarantees `tool-input` precedes that invocation's `tool-result`, so this scopes
the result to the current invocation centrally in the hook — fixing all three
Views without per-app invocation keys.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(mcp-apps): remove show_ui — it can't suppress app rendering
show_ui promised "skip the form and execute directly", but it can't deliver:
the host renders an MCP App for any tool that carries _meta.ui.resourceUri, and
the 2026-01-26 MCP Apps spec has no per-call/per-result way to opt out of
rendering. show_ui only flipped the server's defer decision, so show_ui=false
created the PR/issue up-front yet the host still rendered the app — exactly the
contradiction this work set out to fix. And show_ui is only ever exposed to
clients that support UI, i.e. precisely the clients that always render the app.
Remove it entirely:
- Drop the show_ui schema property, the form-param allowlist entry, and the
showUI term from the defer predicate in create_pull_request and issue_write.
The gate is now FF && clientSupportsUI && !_ui_submitted && !hasNonFormParams.
- Delete the now-unused UI-only schema-property strip machinery in
pkg/inventory (uiOnlySchemaProperties, stripUIOnlySchemaProperties,
stripSchemaProperties) and the exported ConditionalSchemaPropertyDescriptions,
which existed solely to surface show_ui to UI-capable clients. _meta.ui
stripping is untouched.
- Drop the conditional-property annotation from the docs generator.
- Update toolsnaps, generated docs, and tests.
With the up-front-execution Views now rendering the result (success card), the
remaining contract is simple: when MCP Apps are enabled the form is the path,
and the form is only shown while the action is genuinely deferred.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(mcp-apps): centralize the show/defer decision (single source of truth)
The defer-to-form predicate was triplicated across create_pull_request,
update_pull_request, and issue_write, each with its own near-identical
*HasNonFormParams function. As more MCP App tools are added this duplication
would grow and the copies could silently drift.
Extract one shared gate in ui_capability.go:
- shouldDeferToForm(ctx, deps, req, args, formParams) — the single show/defer
decision (MCP Apps enabled, client supports UI, not a form submission, and no
non-form params).
- hasNonFormParams(args, formParams) — one generic helper replacing the three
per-tool functions.
- uiSubmitted(args) — small shared predicate.
Each handler is now a one-line `if shouldDeferToForm(...) { return awaiting }`.
The per-tool form-parameter allowlists and the user-facing messages stay
per-tool (that is the genuine per-tool config). Pure refactor — behavior
unchanged; existing tests now exercise the generic helper.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* PoC full flow (hello world example)
* add avatar resource domain
* add postmessage logic and richer UI
* add create issue ui
* update ui for issue creatioon
* fix
* ignore banner
* update docs after rebase
* update toolsnap for get_me
* new UI changes
* update docs
* update workflows that need ui build
* add UI diff
* fix build ui step for windows runners to use git bash
* fix UI diff
* refactor issue creation UI
* add AvatarWithFallback component and update UserCard to use it; enhance CreateIssueApp to manage existing issue data
* fix formatting of button labels
* add create pull request functionality with UI support and insiders
* update docs
* add test for insiders mode handling in ServerTool schema
* remove `show_ui` param for now
* make insiders mode metadata stripping generic
* remove ui diff
* fix CI
* remove redundant mention of old app name
* add node types to fix ide issues for ts code
* remove unused TriangleDownIcon import
* update @primer/behaviors and electron-to-chromium versions in package-lock.json
* add check to ensure base and head are not the same when creating a new PR
* remove old show_ui
* fix gitignore for dist so builds dont break
* add tests for insiders mode handling and metadata stripping in ServerTool
* remove unused state and components from CreatePRApp
* fix ui build
* update docker build to fix npm issue
* remove reference to show_ui
* allow insiders to work for non-ui features
* formalise insiders inventory support
* update docs
* fix overflow issues and replace pull request dropdown with matching UI from dotcom
* fix createpullrequest test
* consolidate fetching tools under `ui_get` tool to remove toolset deps
* fix issue data prefill in issue_write form
* fix link component when updating issue
* fix avatar URL
* fix broken issue update logic
* remove dbg
* fix for new GetFlags
* revert to original required fields for create_pull_request
* fix for UI form submission
* Simplify MCP App UIs for basic branch
Remove advanced features to be kept in mcp-ui-apps-advanced:
- Strip labels, assignees, milestones, issue types, repo picker from issue-write
- Strip repo picker, branch selectors from pr-write
- Delete ui_get tool (ui_tools.go, ui_tools_test.go, ui_get.snap)
- Remove UIGet registration from tools.go
Basic forms retain: title, body, submit with _ui_submitted,
draft/regular split button (PR), MarkdownEditor, and SuccessView.
* Fix header spacing in issue-write and pr-write UIs
Add proper spacing between icon, title text, and repo name in the
header bar for both issue-write and create-pull-request forms.
* fix UI spacing
* Revert "Simplify MCP App UIs for basic branch"
This reverts commit 24174b91e222e45b47913ff6b760db809f48660b.
* Undo dependency downgrades in ui/package-lock.json
* Update ui/src/apps/pr-write/App.tsx
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update ui/src/apps/issue-write/App.tsx
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Implement pagination for uiGetBranches (#2012)
* Initial plan
* Implement pagination for uiGetBranches function
Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com>
* update to new insiders feature flag func
* ensure transient state is reset on successive tool calls
* Mark ui_get as app-only visibility
ui_get backs only the MCP App views and has no business in the agent's
tool list. Per the MCP Apps 2026-01-26 spec, omitting _meta.ui.visibility
defaults to ["model","app"], which exposes the tool to the model. Declare
visibility ["app"] so the host hides it from tools/list while the views can
still invoke it via tools/call.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update ui_get toolsnap for app-only visibility
Regenerated via UPDATE_TOOLSNAPS to capture the new _meta.ui.visibility.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Assert ui_get declares app-only visibility
Locks in the _meta.ui.visibility ["app"] contract so a future edit can't
silently re-expose the UI data tool to the model.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add ui_get to insiders feature docs
Regenerated docs/feature-flags.md and docs/insiders-features.md to include
the ui_get tool entry.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address ui_get review feedback
- Paginate the labels GraphQL query (cursor-based) so repos with more than
100 labels return a complete list instead of silently truncating.
- Emit an empty due_on for milestones without a due date instead of
formatting the zero time as "0001-01-01".
- Use NewGitHubAPIErrorResponse in uiGetIssueTypes to preserve GitHub
response context, matching the other REST-backed methods.
- Extend tests to cover the labels (GraphQL), milestones (including the
no-due-date case) and issue_types methods, plus the issue_types error path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix repo reset and stale base-branch in MCP App views
- Re-initialize selectedRepo from toolInput inside the reset-on-invocation
effect instead of a separate effect. The two effects both depended on
toolInput and ran in declaration order, so the reset wiped the just-
initialized repo and the picker never reflected the invocation's owner/repo.
- Set the default base branch with a functional update in pr-write so a base
prefilled from toolInput.base (or chosen by the user) isn't overwritten by
a stale baseBranch value captured before the branches request resolved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Fix issue-write repo owner mapping and clear stale UI state on reset
- issue-write: derive owner/name from full_name since search_repositories
minimal output omits the owner object (mirrors pr-write)
- pr-write/issue-write: clear available branch/label/assignee/milestone/type
lists and filters in the toolInput reset effect so prefill effects can't
match against the previous repo's stale data
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Merge remote-tracking branch 'origin/main' into mcp-ui-apps-advanced
* feat: add pull request editing functionality with reviewers support
* feat: implement interactive form handling for issue and pull request creation and updates
* Close response body per page in ui_get pagination loops
Avoids leaking HTTP connections when paging through assignees,
milestones, branches, collaborators, and teams.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Cache pr-edit.html in build-ui action
The build-ui cache only saved get-me/issue-write/pr-write HTML, so once a
cache entry was stored it restored an incomplete ui_dist on later runs and
skipped the rebuild, leaving pr-edit.html absent and panicking the tests.
Add pr-edit.html to the cached paths and bump the cache key to v2 to evict
the incomplete entries.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: tommaso-moro <tommaso-moro@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Open created issue/PR link via host open-link capability
The success views for issue-write and pr-write rendered a plain anchor
to the created/updated issue or PR. MCP Apps run in a sandboxed iframe
where target="_blank" navigation may be blocked, so clicking the link
did nothing in some hosts.
Route the click through the host's ui/open-link capability (already
exposed by useMcpApp as openLink), which asks the host to open the URL
in the user's browser. The hook now also falls back to window.open when
the host denies the request, in addition to the existing no-app
fallback. The href is retained so right-click/copy and native fallback
still work.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Prevent default anchor navigation before URL check
When the success-view link URL was unavailable ("#"), the click handler
returned before calling e.preventDefault(), so the anchor's default
target="_blank" navigation still ran and could open a stray blank tab.
Call preventDefault() first, then no-op when the URL is unavailable.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Skip MCP App form when issue/PR write carries non-form params
When MCP Apps are enabled and the client supports UI, issue_write and
create_pull_request route the call to an interactive form. The form only
collects a subset of fields and rebuilds the submit payload from scratch,
so any parameter it cannot represent was silently dropped — e.g. labels,
assignees, milestone, type, state and issue_fields (priority) for
issue_write.
Skip the form and execute directly whenever the call carries a parameter
outside the set the form collects and re-sends. This generalizes the
previous state-only guard and is robust to future parameter additions
(an unrecognized param now bypasses the form rather than being lost).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Forward original tool params on MCP App form submit
The issue-write and pr-write forms rebuilt their submit payload from
scratch, so any parameter the form does not render was dropped on submit.
Spread the original toolInput first and override only the edited fields,
so unsupported params (e.g. issue_fields, labels, state) are preserved
when the user submits the form.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Declare appCapabilities.availableDisplayModes (defaults to ["inline"])
during initialization, as required by the new spec.
* Track McpUiHostContext (and its updates via onhostcontextchanged) and
thread it into AppProvider, which now picks up host-supplied
theme + CSS style variables and projects them onto the root element so
Primer components inherit host theming.
* Add setModelContext and openLink helpers to useMcpApp. issue-write and
pr-write call setModelContext on a successful submission so the agent
has the new entity in its next-turn context; get-me uses openLink for
the profile's external blog link.
The pinned @modelcontextprotocol/ext-apps ^1.7.2 was already resolved to
1.7.2 in the lockfile, so no dependency bump is required for the new
HostContext / openLink / updateModelContext APIs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(ui): migrate vite 6 -> 8 and plugin-react 4 -> 6
Supersedes the auto-generated bump in #2496, which only updated vite and
left @vitejs/plugin-react on a peer range that excludes vite 8, breaking
the UI build (and every Go job that embeds the UI assets) with ERESOLVE.
- vite ^6.0.0 -> ^8.0.13
- @vitejs/plugin-react ^4.3.0 -> ^6.0.2 (peers vite ^8.0.0 only)
- vite-plugin-singlefile ^2.0.0 -> ^2.3.3 (peers already allowed v8)
- engines.node >=20 -> ^20.19.0 || >=22.12.0 (Vite 7+ requirement)
Vite 8 ships Rolldown instead of Rollup, which rejects bundle mutation in
generateBundle. The rename-output plugin was doing exactly that to flatten
the singlefile-inlined HTML from src/apps/<app>/index.html down to
<app>.html. Refactored it to hoist the file in closeBundle (post-write)
and renamed it to flatten-output to reflect what it actually does.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(ui): give flatten-output a clearer error when the HTML is missing
Addresses Copilot review feedback on #2501: if the singlefile-inlined HTML
isn't where we expect it (e.g. because a future Vite/Rolldown change alters
the output path), throw with the app name and expected path instead of
letting renameSync surface a bare ENOENT.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* perf(ui+ci): cache build artifacts and run vite in single process
Introduce a content-addressable cache for the embedded UI HTML and refactor
the build script to invoke vite once per Node process instead of three
times.
* New ui/scripts/build.mjs runs vite build() in a loop within one process,
removing the cross-env dev dependency and avoiding redundant plugin/JIT
warm-up. Local build time drops from ~2.4s to ~1.5s.
* New .github/actions/build-ui composite action restores
pkg/github/ui_dist/{get-me,issue-write,pr-write}.html from cache keyed on
hashes of ui/ sources and the lockfile. On cache hit it skips Node setup
and the build entirely; on miss it sets up Node and runs script/build-ui
as before. Saves ~6s per workflow on Go-only PRs, which is the common
case across seven workflows.
* Replace the duplicated setup-node + Build UI pair in seven workflows
(go, lint, docs-check, license-check, goreleaser, mcp-diff, code-scanning)
with a single uses: ./.github/actions/build-ui line. code-scanning keeps
a dedicated setup-node for the JavaScript CodeQL path.
Output files are byte-identical to the pre-refactor build.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* perf(ci): share UI artifact cache across runner OSes
The cached HTML output is platform-independent, so set
enableCrossOsArchive on the cache step. With this any OS can restore
the cache populated by any other OS — one shared cache instead of three.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the v1.7.0 useApp options to:
- autoResize iframes to content height (helps issue-write/pr-write/get-me
surfaces which all render variable-height forms and result cards)
- enable strict handshake-ordering checks in development builds so any
out-of-order handler registration surfaces immediately
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bumps @modelcontextprotocol/ext-apps from ^1.0.0 to ^1.7.2 (which pulls
in newer @modelcontextprotocol/sdk and hono), and runs npm audit fix to
update the transitive vite/rollup/postcss/picomatch/lodash chain.
Closes the following GHSAs (all reachable only through /ui build deps):
- hono: GHSA-xh87-mx6m-69f3, and the SSR/cookie/serveStatic family
- fast-uri: GHSA path-traversal/host-confusion
- ip-address, express-rate-limit, path-to-regexp, picomatch
- vite path-traversal + dev-server WebSocket file-read
- rollup arbitrary file write, postcss XSS, lodash prototype pollution
No source changes required: the ext-apps React API we consume
(useApp / App / ontoolresult / ontoolinput) is unchanged; typecheck
and the full vite build pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* PoC full flow (hello world example)
* add avatar resource domain
* add postmessage logic and richer UI
* add create issue ui
* update ui for issue creatioon
* fix
* ignore banner
* update docs after rebase
* update toolsnap for get_me
* new UI changes
* update docs
* update workflows that need ui build
* add UI diff
* fix build ui step for windows runners to use git bash
* fix UI diff
* refactor issue creation UI
* add AvatarWithFallback component and update UserCard to use it; enhance CreateIssueApp to manage existing issue data
* fix formatting of button labels
* add create pull request functionality with UI support and insiders
* update docs
* add test for insiders mode handling in ServerTool schema
* remove `show_ui` param for now
* make insiders mode metadata stripping generic
* remove ui diff
* fix CI
* remove redundant mention of old app name
* add node types to fix ide issues for ts code
* remove unused TriangleDownIcon import
* update @primer/behaviors and electron-to-chromium versions in package-lock.json
* add check to ensure base and head are not the same when creating a new PR
* remove old show_ui
* fix gitignore for dist so builds dont break
* add tests for insiders mode handling and metadata stripping in ServerTool
* remove unused state and components from CreatePRApp
* fix ui build
* update docker build to fix npm issue
* remove reference to show_ui
* allow insiders to work for non-ui features
* formalise insiders inventory support
* update docs
* fix overflow issues and replace pull request dropdown with matching UI from dotcom
* fix createpullrequest test
* consolidate fetching tools under `ui_get` tool to remove toolset deps
* fix issue data prefill in issue_write form
* fix link component when updating issue
* fix avatar URL
* fix broken issue update logic
* remove dbg
* fix for new GetFlags
* revert to original required fields for create_pull_request
* fix for UI form submission
* Simplify MCP App UIs for basic branch
Remove advanced features to be kept in mcp-ui-apps-advanced:
- Strip labels, assignees, milestones, issue types, repo picker from issue-write
- Strip repo picker, branch selectors from pr-write
- Delete ui_get tool (ui_tools.go, ui_tools_test.go, ui_get.snap)
- Remove UIGet registration from tools.go
Basic forms retain: title, body, submit with _ui_submitted,
draft/regular split button (PR), MarkdownEditor, and SuccessView.
* Fix header spacing in issue-write and pr-write UIs
Add proper spacing between icon, title text, and repo name in the
header bar for both issue-write and create-pull-request forms.
* fix UI spacing
* Add insiders flag to User-Agent header
When InsidersMode is enabled, append '(insiders)' to the User-Agent
string sent with GitHub API requests, enabling server-side adoption
tracking.
* address ui feedback
* added ui/no-ui support
* improve active state UI for write and preview button. make padding consistent in textarea
* return to prev non ui check
* use hardcoded client name check for ui support
* linter fixes
* merge fix
* linter fix 2
---------
Co-authored-by: tommaso-moro <tommaso-moro@github.com>