Commit Graph

881 Commits

Author SHA1 Message Date
Kelsey Myers 546a66a754 clean up verbose comments on IssueWrite and LegacyIssueWrite
Build and Test Go Project / build (ubuntu-latest) (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Build and Test Go Project / build (macos-latest) (push) Has been cancelled
Build and Test Go Project / build (windows-latest) (push) Has been cancelled
2026-05-27 16:25:26 +02:00
Kelsey Myers 865c9623f9 always clear raw IssueFieldValues from get_issue response 2026-05-27 16:25:26 +02:00
Kelsey Myers 0d5d9514a8 address comments 2026-05-27 16:25:26 +02:00
Kelsey Myers ba9930f328 feat: gate issue_write and get_issue behind remote_mcp_issue_fields flag
- Extend FeatureFlagEnable/Disable fields from string to []string (AND
  semantics for enable, OR semantics for disable) so a tool can require
  multiple flags simultaneously.

- Add LegacyIssueWrite: the FeatureFlagIssueFields-disabled variant of
  issue_write. It exposes the pre-issue-fields schema (no issue_fields
  parameter) and skips the custom field value resolution. Both this and
  IssueWrite register under the tool name 'issue_write'; exactly one is
  active at a time via mutually exclusive flag annotations.

- Gate IssueWrite (the flag-enabled variant) with FeatureFlagEnable so
  it is only served when remote_mcp_issue_fields is on.

- Gate the get_issue field_values enrichment with a runtime
  IsFeatureEnabled check so the GraphQL round-trip is skipped when the
  flag is off.

- Add issue_write.snap (legacy) and
  issue_write_ff_remote_mcp_issue_fields.snap (flag-enabled) toolsnaps
  following the convention established by PR #2520.

- Modernise featureFlagAllowed disableFlags loop to slices.ContainsFunc.
2026-05-27 16:25:26 +02:00
Kelsey Myers 15192ca84e schema: strict additionalProperties and typed value in issue_fields items 2026-05-26 10:32:33 -07:00
Kelsey Myers d63407cfa7 docs: regenerate after issue_fields schema update 2026-05-26 09:59:58 -07:00
Kelsey Myers 89d1847026 refactor(issue-fields): unexport IssueWriteFieldInput, fix issue_fields schema with oneOf 2026-05-26 09:58:26 -07:00
Kelsey Myers 7b1b06c849 docs update 2026-05-26 09:44:22 -07:00
Kelsey Myers b97207f25e Fix field_option_name to pass option name to REST API, not DB ID - return minimal fields 2026-05-26 09:44:22 -07:00
Iulia B c0a1d1d6a0 feat(issue-fields): support issue_fields in issue_write using fullDatabaseId
- Expose fullDatabaseId (BigInt) in list_issue_fields
- Add issue_fields parameter to issue_write for setting field values
- Support single-select fields via field_option_name resolution
- Add REST API field value extraction in get_issue responses
- Update minimal types with IssueFieldValue for REST responses

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 09:44:22 -07:00
Boaz Reicher 57f4df4728 Adding suggest bool flag to suggest type changes to an issue (#2548) 2026-05-26 17:19:15 +02:00
Sam Morrow 1add5fe231 docs: auto-generate per-flag tool lists for insiders and feature flags (#2521)
Adds two auto-generated documentation sections that describe how
feature flags shape the tool surface:

- docs/insiders-features.md gets a per-flag block under its existing
  hand-written prose. Each Insiders flag whose tools differ from the
  default surface is listed with the full tool schema rendered through
  the same writer used for README, so contributors can see exactly what
  Insiders Mode adds or changes.
- docs/feature-flags.md is new and gives the same treatment to every
  flag in AllowedFeatureFlags (user-controllable flags). It links back
  to the Insiders doc for the auto-enabled subset.

Both sections are produced by a single generator that diffs the
flag-on inventory against the default-flagged inventory and reports any
tool that is new or has a different InputSchema/Meta. No reason
classification - just tools and their schemas, kept intentionally
simple so contributors don't have to update the generator when adding
a new flag.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 00:31:39 +02:00
Sam Morrow 0b644d7b74 ci(mcp-diff): build UI artifacts available to baseline checkout (#2523)
The mcp-server-diff action checks the baseline ref out into a separate
working directory and runs install_command there. Without prebuilt UI
artifacts, pkg/github/ui_dist/ is empty on the baseline side and
UIAssetsAvailable() returns false, producing a false-positive diff that
"adds" _meta.ui to MCP Apps tools on every PR.

Stash the artifacts to RUNNER_TEMP after the workflow's build-ui step,
then restore them from install_command so both the baseline and PR
checkouts register identical MCP Apps UI metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 23:18:55 +02:00
Sam Morrow 6fd9d070ba chore(gitignore): anchor binary names to repo root (#2522)
The bare `github-mcp-server`, `mcpcurl`, and `e2e.test` rules matched
those names anywhere in the tree, which silently ignored new files
created under `cmd/github-mcp-server/` (the rule treats the directory
component as a match). The intent was to ignore the binaries produced
by `go build` at repo root, so anchor each rule with a leading slash.

The existing `cmd/github-mcp-server/github-mcp-server` rule on line 2
continues to ignore the binary when built inside the cmd directory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 23:02:07 +02:00
Sam Morrow f5e26a8540 feat(issues): gate issue-fields features behind remote_mcp_issue_fields flag (#2520)
* feat(issues): gate issue-fields features behind remote_mcp_issue_fields flag

Gates the recently merged issue-fields work (list_issue_fields tool,
field_values enrichment on list_issues/search_issues, and field_filters
input on list_issues) behind a new feature flag, also enabled in
insiders mode.

- list_issues splits into two same-named registrations: the field-aware
  variant requires the flag, while LegacyListIssues (FeatureFlagDisable)
  preserves the prior schema and GraphQL selection set so disabled
  callers don't pay the extra wire/server cost.
- search_issues skips the field-values lookup when the flag is off.
- list_issue_fields requires the flag to be registered at all.
- Adopts <tool>_ff_<flag>.snap naming for flagged toolsnap variants so
  same-named duplicates each get a distinct snapshot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address PR review on issue-fields gating

- docs generator: install a no-flags feature checker so README reflects
  the default user experience (tools enabled with no special flags),
  fixing duplicate `list_issues` and removing granular/flagged-only
  tools that were never meant to appear in the default docs.
- csv_output: drop the FeatureFlagEnable/Disable exclusion in
  isCSVOutputTool. Wrapping happens before the per-request flag filter
  picks the live variant, so flag-gated list_* tools wrap safely; this
  restores CSV conversion for `list_issues` and enables it for
  `list_issue_fields` when both flags are on.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 23:01:19 +02:00
Ross Tarrant f929c58c6b feat: Add CSV output format for default list tools under insiders mode (#2450)
* Add CSV output for list tools under insiders mode

* fix: resolve rebase feature flag conflicts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Simplify feature-flag handling: collapse CSV dual-variant + skip filtering when no checker (#2516)

* refactor: generic toolset+name sort, clarify feature flag intent

Address review feedback on #2450:

- Collapse the three near-identical sort helpers in pkg/inventory/filters.go
  into a generic sortByToolsetThenName so adding new inventory item types
  doesn't require copying the comparator.
- Expand the doc comments on the three *WithoutFeatureFiltering helpers to
  spell out why they exist: HTTP mode builds a static (process-wide)
  inventory as an upper bound, but per-request feature flags from headers
  (X-MCP-Features, X-MCP-Insiders) are evaluated later, so feature-flagged
  variants must be preserved here.
- Strengthen the doc comment on ResolveFeatureFlags to make the contract
  explicit: user-supplied flags are validated against AllowedFeatureFlags,
  but insiders expansion deliberately is not — InsidersFeatureFlags may
  include server-controlled flags that are not user-toggleable.

CORS comments are intentionally left for the PR author.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(feature-flags): clarify allowed and insiders sets are independent

Also add tests covering:
- a user-toggleable flag (FeatureFlagIssuesGranular) that insiders does
  not turn on automatically
- insiders mode not turning on user-only allowed flags

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor(inventory): collapse three *WithoutFeatureFiltering helpers into StaticUpperBound

The three parallel methods (AvailableToolsWithoutFeatureFiltering,
AvailableResourceTemplatesWithoutFeatureFiltering,
AvailablePromptsWithoutFeatureFiltering) were always called as a triple
in exactly two places: HTTP buildStaticInventory and its test mirror.
They exist because the dual-variant pattern (sibling tools with mirrored
FeatureFlagEnable / FeatureFlagDisable on the same name, e.g. CSV output)
makes feature filtering at static-build time impossible — both variants
must be kept and resolved per-request.

Replace the three with one method, Inventory.StaticUpperBound(ctx), that
returns (tools, resources, prompts) and carries the rationale in its
doc comment. Reduces API surface, eliminates the triplication, and makes
the single "skip feature filtering" concept obvious to readers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: simplify feature-flag handling

Two related simplifications, both about treating insiders as a meta flag
that expands once at startup and then stops mattering:

- Collapse CSV's dual-variant pattern into a single tool whose handler
  performs a runtime feature-flag check via deps.IsFeatureEnabled. CSV
  is a pure response-format toggle, not a schema change, so it does not
  need the dual-name pattern that genuine schema variants (granular
  issues/PRs) still use.

- When no feature checker is installed, skip feature-flag filtering and
  return the full upper bound. The static HTTP inventory now uses plain
  AvailableTools/Resources/Prompts; the per-request inventory always
  installs a checker, so MCP registration (which serves a tool name once)
  always sees a deduplicated set. The bespoke StaticUpperBound helper and
  the isToolEnabledWithFeatureFlags split go away.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci(mcp-diff): add insiders + per-feature configs

The mcp-diff matrix now includes:
  - --insiders (and --insiders --read-only)
  - one config per github.AllowedFeatureFlags entry, generated by
    script/print-mcp-diff-configs so new user-controllable flags get
    diffed automatically without editing the workflow

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(insiders): explain feature-flag resolution for contributors

Adds a 'How feature flags are resolved' section covering:
  - Insiders is a meta flag, like 'all'/'default' for toolsets
  - User input -> allowlist filter -> insiders expansion ->
    server-side fallback (remote only)
  - AllowedFeatureFlags vs InsidersFeatureFlags are independent
  - How to add a new feature flag, including the
    TestGitHubPackageDoesNotReadInsidersMode guard

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor(inventory): make feature-flag gating a regular ToolFilter

Move tool feature-flag evaluation out of isToolEnabled and into a
ToolFilter installed at the head of the pipeline by Build() when
WithFeatureChecker received a non-nil checker. The 'no checker = no
filtering' contract is now expressed structurally (the filter isn't
installed) instead of by a runtime nil check inside the helper.

Resources and prompts have no filter pipeline, so they call the now-pure
featureFlagAllowed helper behind an explicit r.featureChecker != nil
guard at the iteration site.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* perf(inventory): cache extracted toolset IDs in sort comparator

Avoid evaluating the extractor closures up to three times per comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: correct MCP features header in cors

* docs: regenerate README for CSV output toolset

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove duplicate MCPFeaturesHeader from CORS headers

* ci(mcp-diff): add streamable-http job with header-based configs

Adds a sibling mcp-diff-http job that exercises the streamable-http
transport against a shared HTTP server, with per-config settings supplied
via X-MCP-* request headers — mirroring how the remote server is invoked
in production (server-side defaults + per-user header overrides).

The config generator gains a -transport flag:
- stdio (default, unchanged behaviour)
- http-headers (emits headers-only configs targeting a shared server)

Two new combined entries layer multiple headers together as a smoke test
for header-merging regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: regenerate after merging main

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Sam Morrow <info@sam-morrow.com>
Co-authored-by: sammorrowdrums <sammorrowdrums@github.com>
2026-05-21 16:50:55 +02:00
Tim Rogers f39f758d6f Remove trailing periods from tool title annotations (#2518)
Tool title annotations should be consistent with the rest of the tool catalog and render cleanly in agent UIs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Sam Morrow <info@sam-morrow.com>
2026-05-21 16:41:21 +02:00
Kelsey Myers 13e7f10fc8 Add custom field filtering to list_issues (#2480)
* Add custom field filtering to list_issues

* Flatten schema

* add repo fields flag

* test fix

---------

Co-authored-by: Sam Morrow <sammorrowdrums@github.com>
2026-05-21 16:36:17 +02:00
Kelsey Myers 8f6050a5b8 Add list_issue_fields tool (#2445)
* Add list_org_issue_fields tool

* Clean up code

* complete struct fields & rename option type

* Drop created_at/updated_at from IssueField and IssueSingleSelectFieldOption

* Address feedback

* Address Copilot review: close resp.Body, set expectError=true for missing org test

* Adjust to list_issue_fields

* Add feature flag

* Allow tool to support read:org or repo

* Docs

* address comments

* Add repo_issue_fields flag

---------

Co-authored-by: Michael Jacholke <46944669+michaeljacholke@users.noreply.github.com>
2026-05-21 16:19:49 +02:00
Jui Desai 805ad75c62 Fix return Thread node ID in get_review_comments response (#2515)
* fix return Thread ID in get_review_comments response

* Fix syntax error in convertToMinimalReviewThread

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Jui Desai <juidesai@MacBook-Pro.local>
Co-authored-by: Sam Morrow <info@sam-morrow.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 14:33:28 +02:00
Dhananjay Mishra 6b4ca78505 feat: Add search commit tool (#2284)
* add `SearchCommits` tool

* run test

* run script/generate-docs

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* refactor(search_commits): share commit conversion, surface repo, tighten query docs

- Extract newMinimalCommitFromCore to share field mapping between
  convertToMinimalCommit (RepositoryCommit) and the new
  convertCommitResultToMinimalCommit (CommitResult), removing ~50
  lines of duplicated logic from the search_commits handler.
- Add MinimalRepoRef and a search-only MinimalCommitSearchItem type
  (embedding MinimalCommit) so cross-repo commit search results
  identify the repo each commit came from. Keeping the field off
  MinimalCommit avoids paying for a never-populated field on the
  get_commit/list_commits output types.
- Rewrite the query description to teach the model the actual
  commit-search qualifier surface (repo:/org:/user: scoping, author/
  committer/date qualifiers, hash/tree/parent, merge:, is:public)
  and reword the sort description to drop redundancy with the enum.
- Extend tests to assert the repository field is surfaced and to
  cover commits with no resolved GitHub user (nil Author/Committer).
- Refresh README and toolsnap.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sam Morrow <info@sam-morrow.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 16:24:00 +02:00
Dvir Arad 0bd0bf0818 feat: add pagination to list GHAS alerts tools (#2451)
* feat(code_scanning): add pagination to list_code_scanning_alerts (#2363)

* feat(dependabot): add pagination to list_dependabot_alerts (#2363)

* feat(secret_scanning): add pagination to list_secret_scanning_alerts (#2363)

* test(code_scanning): pagination expectations + new test case (#2363)

* test(dependabot): pagination expectations + new test case (#2363)

* test(secret_scanning): pagination expectations + new test case (#2363)

* test(toolsnaps): refresh list_code_scanning_alerts with page/perPage (#2363)

* test(toolsnaps): refresh list_dependabot_alerts with page/perPage (#2363)

* test(toolsnaps): refresh list_secret_scanning_alerts with page/perPage (#2363)

* docs: regenerate README for new pagination params

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Sam Morrow <info@sam-morrow.com>
Co-authored-by: sammorrowdrums <sam.morrowdrums@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 15:27:04 +02:00
Kelsey Myers 8f4680b90a Add field_values to search_issues results (#2474)
* Add field_values to search_issues results

* remove dupe keys

* Fix advanced search not enabled for fields

---------

Co-authored-by: Sam Morrow <info@sam-morrow.com>
2026-05-20 14:59:56 +02:00
Sam Morrow e9533330b0 fix(search_code): tighten query description for accurate model guidance (#2513)
The current `search_code` query description is hand-wavy and gives the
model little usable guidance on GitHub code search syntax, which (per
analysis in #2390 across thousands of agent sessions) leads to repeated
422 ERROR_TYPE_QUERY_PARSING_FATAL responses from agents that guess at
plausible-but-invalid syntax.

Re-applies the spirit of #2442 by @jluocsa, originally suggested by
@danmoseley in #2390, but corrected against the actual endpoint this
tool calls.

Critically, this tool uses go-github's `client.Search.Code`, which hits
the legacy REST `/search/code` endpoint — NOT the new code search
("Blackbird"). Verified against the live API:

  symbol:WithContext repo:github/github-mcp-server  -> 0
  /Get|Set/ repo:github/github-mcp-server           -> 0
  path:**/*.go func repo:github/github-mcp-server   -> 0
  filename:*.md repo:github/github-mcp-server       -> 0
  (Foo OR Bar) -path:vendor language:go             -> 422

So `symbol:`, `/regex/`, path globs, filename globs, and parenthesized
boolean groups — features the proposal in #2442 listed — silently
return zero or fail. Documenting them would teach the model syntax
that doesn't work on this endpoint.

The new description focuses on what's actually supported by legacy
code search and the real bugs observed in #2390:

- `path:dir` is a prefix, NOT a glob (displaces `path:**/*.ts` guesses).
- `filename:exact.ext` is exact, NOT a glob (displaces `filename:*.md`).
- `/regex/` and `\|` inside quotes don't work — call this out so the
  model stops generating them.
- `symbol:` doesn't work on this endpoint — call this out.
- Parenthesized boolean groups 422 — call this out so the model
  stops wrapping `OR` chains in parens.
- Adds `extension:`, `in:file`, `in:path`, `size:`, `filename:`, `user:`
  qualifiers that the previous text omitted.
- Implicit AND, `OR`, `NOT`, and `"quoted phrase"` for exact match are
  documented positively.
- 256-char query limit.

All four examples in the new description are verified against the live
GitHub API and return non-zero results.

Co-authored-by: jluocsa <103165870+jluocsa@users.noreply.github.com>
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 12:30:38 +02:00
Kelsey Myers cc2a95725a Include custom issue field values in list_issues response (#2466)
* Include custom issue field values in list_issues response

Adds Issues 2.0 custom field values to each issue returned by the
list_issues GraphQL query, exposed on MinimalIssue as field_values:
[{field, value}]. Filtering by field is a separate concern (needs the
GraphQL IssueFilters input updated upstream) and is not included here.

shurcooL/graphql's response decoder walks every inline fragment of a
union regardless of __typename, so IssueFieldNumberValue.value is
aliased to valueNumber to avoid a Float-vs-String type clash when the
runtime variant is, e.g., a SingleSelectValue.

* Extend list_issues tests to cover Date/Number/Text field value variants

---------

Co-authored-by: Sam Morrow <info@sam-morrow.com>
2026-05-20 11:18:42 +02:00
Boaz Reicher b2b49361fd Adding rationale for fields and labels in issues_granular (#2505)
* Adding rationle for fields and labels in issues_granular

Co-authored-by: Copilot <copilot@github.com>

* removed descriptions

* test: update update_issue_labels toolsnap schema text

* removed descriptions

Co-authored-by: Copilot <copilot@github.com>

* fixed snaps

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Sam Morrow <info@sam-morrow.com>
2026-05-20 11:00:19 +02:00
Sam Morrow 0f0506d2fd refactor: remove dynamic toolsets and deprecated closure constructor (#2512)
Dynamic toolset discovery (the meta-tools enable_toolset, list_available_toolsets,
get_toolset_tools and the --dynamic-toolsets / GITHUB_DYNAMIC_TOOLSETS switch)
was a local-only feature never offered by the remote server. Removing it
deletes a meaningful chunk of branching, configuration surface and tests
for a path no longer in active use.

The deprecated closure-based NewServerToolWithDeps generic constructor was
only kept around for the dynamic tool registration path and is removed
together with it. Going forward there are exactly two constructors:

- NewServerTool — raw mcp.ToolHandler, no closure, no unmarshalling
- NewServerToolWithContextHandler[In, Out] — typed handler, deps via context

Inventory methods that only existed for the dynamic path
(ToolsForToolset, IsToolsetEnabled, EnableToolset, EnabledToolsetIDs)
are removed. ResolvedEnabledToolsets loses its dynamic flag.

Also strips dynamic references from the README, server configuration
docs, copilot-instructions, mcp-diff workflow, and conformance-test
script.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 10:51:47 +02:00
Sam Morrow 272d160512 fix: return isError for argument validation failures (#2511)
* refactor: simplify NewServerTool naming

- Rename NewServerToolWithRawContextHandler -> NewServerTool. This is the
  preferred constructor for raw mcp.ToolHandler tools because it avoids
  creating closures at registration time, which matters for per-request
  servers that re-register all tools on every request.
- Rename deprecated generic NewServerTool[In, Out] -> NewServerToolWithDeps
  to free up the simpler name and make its closure-based nature explicit.
  The dynamic tools package is the only legitimate user of this constructor
  because DynamicToolDependencies differs from the standard ToolDependencies.
- Remove deprecated NewServerToolFromHandler. Its only callers can use the
  new NewServerTool directly via context-injected deps.
- Update all call sites in dependencies.go, dynamic_tools.go, and
  registry_test.go.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: return isError for argument validation failures

When tool argument unmarshalling fails (wrong types, malformed JSON),
return a CallToolResult with IsError: true instead of a Go error.
Returning a Go error is converted by the SDK into a JSON-RPC protocol
error (-32603), which is invisible to agents and prevents self-correction.
Returning IsError: true with the validation message lets agents see the
problem and retry with corrected arguments.

Affects:
- NewServerToolWithDeps (was NewServerTool prior to the rename in #2510)
- NewServerToolWithContextHandler

Fixes #1952.
Re-applies #2488 by @blackwell-systems on top of the NewServerTool rename.

Co-authored-by: blackwell-systems <236632453+blackwell-systems@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: blackwell-systems <236632453+blackwell-systems@users.noreply.github.com>
2026-05-20 10:19:36 +02:00
Sam Morrow 970155ad64 refactor: simplify NewServerTool naming (#2510)
- Rename NewServerToolWithRawContextHandler -> NewServerTool. This is the
  preferred constructor for raw mcp.ToolHandler tools because it avoids
  creating closures at registration time, which matters for per-request
  servers that re-register all tools on every request.
- Rename deprecated generic NewServerTool[In, Out] -> NewServerToolWithDeps
  to free up the simpler name and make its closure-based nature explicit.
  The dynamic tools package is the only legitimate user of this constructor
  because DynamicToolDependencies differs from the standard ToolDependencies.
- Remove deprecated NewServerToolFromHandler. Its only callers can use the
  new NewServerTool directly via context-injected deps.
- Update all call sites in dependencies.go, dynamic_tools.go, and
  registry_test.go.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 10:14:40 +02:00
John CSA bafcaf57c3 fix(pull_request_read): expose after cursor parameter in input schema (#2489)
The `pull_request_read` tool description tells clients that
`get_review_comments` uses cursor-based pagination (`perPage`, `after`),
and the handler does plumb `after` through to the GraphQL query, but the
input schema only declared `page` and `perPage` (via `WithPagination`).
Because `after` was not advertised in `inputSchema`, MCP clients had
no way to request it, leaving cursor pagination effectively broken:
`perPage: 1` returned only the first thread with no way to advance, and
`page` was silently ignored by the GraphQL path.

This change adds `after` to the schema (string, optional) with a
description making clear it only applies to `get_review_comments`. All
other methods continue to ignore it. No handler behavior is changed.

- Add `after` schema property after `WithPagination` in `PullRequestRead`
- Regenerate `__toolsnaps__/pull_request_read.snap` and update README
- Add a regression test asserting `after` is in the schema and a new
  table-driven case verifying the cursor is forwarded to the GraphQL query

Fixes #2122 (for the `get_review_comments` pagination part). The
remaining concerns in #2122 about unbounded response sizes for `get`,
`get_diff`, and `get_reviews` are deferred to follow-up design.

Co-authored-by: Sam Morrow <info@sam-morrow.com>
2026-05-19 19:40:19 +02:00
Sam Morrow f21dcd38ab fix(ui): advertise get_me as an app via _meta.ui.visibility (#2503) 2026-05-19 12:19:30 +02:00
Sam Morrow c88d2ecdd3 fix: guard CompletionsHandler against nil params/ref (#2502)
* fix: guard CompletionsHandler against nil params/ref

A malformed completion/complete request with missing or empty
parameters caused a nil pointer dereference in CompletionsHandler,
panicking the process. Reject such requests with a clear error
before dispatching on Ref.Type.

Reported by @manthanghasadiya (GHSA-w4q6-qw23-4rg7).

Co-authored-by: manthanghasadiya <68530736+manthanghasadiya@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align error wording with repo convention

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: manthanghasadiya <68530736+manthanghasadiya@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 11:55:44 +02:00
Sam Morrow 7e394af647 chore(ui): migrate vite 6 → 8, plugin-react 4 → 6; cache UI build in CI (#2501)
* 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>
2026-05-19 11:52:24 +02:00
dependabot[bot] d4e1231cf7 build(deps): bump github.com/modelcontextprotocol/go-sdk from 1.5.1-0.20260403154220-27f29c1cef3b to 1.6.0 (#2498)
* build(deps): bump github.com/modelcontextprotocol/go-sdk

Bumps [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) from 1.5.1-0.20260403154220-27f29c1cef3b to 1.6.0.
- [Release notes](https://github.com/modelcontextprotocol/go-sdk/releases)
- [Commits](https://github.com/modelcontextprotocol/go-sdk/commits/v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/modelcontextprotocol/go-sdk
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: regenerate license files

Auto-generated by license-check workflow

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-05-19 09:58:34 +02:00
dependabot[bot] 66ec0763cc build(deps): bump goreleaser/goreleaser-action from 7.2.1 to 7.2.2 (#2499)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 7.2.1 to 7.2.2.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8...5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 7.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 09:19:12 +02:00
dependabot[bot] de2f17390c build(deps): bump reproducible-containers/buildkit-cache-dance (#2500)
Bumps [reproducible-containers/buildkit-cache-dance](https://github.com/reproducible-containers/buildkit-cache-dance) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/reproducible-containers/buildkit-cache-dance/releases)
- [Commits](https://github.com/reproducible-containers/buildkit-cache-dance/compare/1b8ab18fbda5ad3646e3fcc9ed9dd41ce2f297b4...5422eac04292c961a382e0f584ea0f03ad9da723)

---
updated-dependencies:
- dependency-name: reproducible-containers/buildkit-cache-dance
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 09:12:42 +02:00
dependabot[bot] 91336dc982 build(deps): bump distroless/base-debian12 from 9dce90e to 58695f4 (#2497)
Bumps distroless/base-debian12 from `9dce90e` to `58695f4`.

---
updated-dependencies:
- dependency-name: distroless/base-debian12
  dependency-version: 58695f439f772a00009c8f6be4c183f824c1f556d74b313c30900f167e4772f8
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 09:05:58 +02:00
Sam Morrow 0ef8f9724a feat(ui): opt into ext-apps autoResize and dev-mode strict
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>
2026-05-18 21:38:03 +02:00
sammorrowdrums 6c56224bc7 build(deps): declare Node >=20 engine requirement for /ui
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 21:38:03 +02:00
sammorrowdrums 2a6229f45c build(deps): bump ui dependencies to clear security advisories
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>
2026-05-18 21:38:03 +02:00
dependabot[bot] ea9d0c81a2 build(deps): bump hono (#2097)
Bumps the npm_and_yarn group with 1 update in the /ui directory: [hono](https://github.com/honojs/hono).


Updates `hono` from 4.12.0 to 4.12.19
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.12.0...v4.12.19)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 18:10:01 +02:00
dependabot[bot] fb8d48b7af build(deps): bump node from 20-alpine to 26-alpine (#2013)
Bumps node from 20-alpine to 26-alpine.

---
updated-dependencies:
- dependency-name: node
  dependency-version: 25-alpine
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 17:56:34 +02:00
dependabot[bot] 0725cd953c build(deps): bump actions/setup-node from 4 to 6 (#2015)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 17:48:44 +02:00
dependabot[bot] 0d560e75e3 build(deps): bump actions/attest-build-provenance from 3 to 4 (#2123)
Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 3 to 4.
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest-build-provenance/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 17:40:57 +02:00
dependabot[bot] 07a12f03ff build(deps): bump github.com/google/jsonschema-go from 0.4.2 to 0.4.3 (#2393)
* build(deps): bump github.com/google/jsonschema-go from 0.4.2 to 0.4.3

Bumps [github.com/google/jsonschema-go](https://github.com/google/jsonschema-go) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/google/jsonschema-go/releases)
- [Commits](https://github.com/google/jsonschema-go/compare/v0.4.2...0.4.3)

---
updated-dependencies:
- dependency-name: github.com/google/jsonschema-go
  dependency-version: 0.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: regenerate license files

Auto-generated by license-check workflow

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-05-18 17:33:07 +02:00
dependabot[bot] c471ae94bb build(deps): bump sigstore/cosign-installer from 4.1.0 to 4.1.2 (#2394)
MCP Server Diff / mcp-diff (push) Has been cancelled
Build and Test Go Project / build (macos-latest) (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docker / build (push) Has been cancelled
Build and Test Go Project / build (ubuntu-latest) (push) Has been cancelled
Build and Test Go Project / build (windows-latest) (push) Has been cancelled
GoReleaser Release / release (push) Has been cancelled
Publish to MCP Registry / publish (push) Has been cancelled
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.1.0 to 4.1.2.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/ba7bc0a3fef59531c69a25acd34668d6d3fe6f22...6f9f17788090df1f26f669e9d70d6ae9567deba6)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
v1.0.5
2026-05-18 16:54:16 +02:00
dependabot[bot] 8af3431ed4 build(deps): bump docker/login-action from 4.0.0 to 4.1.0 (#2395)
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/b45d80f862d83dbcd57f89517bcf500b2ab88fb2...4907a6ddec9925e35a0a9e82d7399ccc52663121)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 16:45:49 +02:00
dependabot[bot] 8d81376a59 build(deps): bump goreleaser/goreleaser-action from 6.4.0 to 7.2.1 (#2396)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 6.4.0 to 7.2.1.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/e435ccd777264be153ace6237001ef4d979d3a7a...1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 7.2.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 16:38:27 +02:00
dependabot[bot] f4b95e6acc build(deps): bump golang from 1.25.9-alpine to 1.25.10-alpine (#2455)
Bumps golang from 1.25.9-alpine to 1.25.10-alpine.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.10-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 16:28:19 +02:00
Iulia Bejan 1861a351f8 Upgrade go-github from v82 to v87 (#2452)
Breaking changes addressed:
- raw.NewClient: Use WithHTTPClient/WithEnterpriseURLs options, pass ctx to
  NewRequest, return (*Client, error)
- internal/ghmcp/server.go: Use functional options for REST client creation,
  replace UserAgent field mutation with UserAgentTransport wrapper, add
  restUATransp field to githubClients struct
- pkg/github/dependencies.go: Use functional options for REST client creation,
  handle raw.NewClient error return
- pkg/github/actions.go: Handle new WorkflowDispatchRunDetails return value
  from CreateWorkflowDispatchEventByID/ByFileName
- pkg/github/issues.go: Replace IssueListOptions with ListOptions for
  SubIssue.ListByIssue
- pkg/github/notifications.go: MarkThreadDone now takes string instead of
  int64; remove ParseInt and strconv import
- pkg/github/projects.go: Remove pointer indirection from
  ListProjectsPaginationOptions and ListProjectsOptions fields
- pkg/github/issues_granular.go: Pass ctx to NewRequest, remove ctx from Do
- Test files: Add mustNewGHClient helper, replace all NewClient calls,
  fix stubClientFnFromHTTP signature, fix lockdown_test.go BaseURL handling,
  fix raw_test.go, remove invalid threadID test case

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 14:36:23 +02:00