Skip to content

refactor(actions): type consolidated MCP tools - #3398

Merged
SamMorrowDrums merged 112 commits into
mainfrom
sammorrowdrums-typed-actions-tools
Oct 6, 2026
Merged

SamMorrowDrums merged 112 commits into
mainfrom
sammorrowdrums-typed-actions-tools

Conversation

@SamMorrowDrums

Copy link
Copy Markdown
Collaborator

Summary

Add concrete typed inputs and method-specific output unions to actions_list, actions_get, actions_run_trigger, and get_job_logs, with structured outputs advertised only for the recognized 2026-07-28 capability protocol.

Why

Part of #3385, stacked directly on #3397 at 4db5f54f982aa7c99c73321e99892f07f5f6445b. Actions tools need honest output contracts without changing legacy payloads or validation messages.

What changed

  • Typed workflow/run/job/artifact/usage responses, dispatch and run-operation responses, and content/URL/partial-error log variants. Arbitrary dispatch input echoes use json.RawMessage; runner billing maps retain their upstream typed values.
  • Preserve legacy coercions, ignored parameters, method-specific error precedence, response text, IFC labels, and scope/security annotations. Sparse upstream objects use anyOf where method shapes overlap.
  • Add real MCP wire tests across modern, legacy, empty, and literal unknown protocol versions, plus exact-parent golden comparisons, schema-negative checks, IFC and client-error precedence coverage, and typed snapshots.
  • Fix the tightly coupled shared output capability gate so malformed tokens and unsupported future dates cannot gain capabilities through lexical comparison. Minimum-protocol tool availability rules are unchanged.

MCP impact

  • No tool or API changes
  • Tool schema or behavior changed
  • New tool added
    Modern clients receive concrete output schemas and matching structured content. Legacy and unrecognized versions do not; descriptive input enum values remain documented rather than overriding legacy validation. As in the existing typed layers, SDK registration presents returned client-acquisition Go errors as IsError tool results with the same message; direct handler errors remain unchanged.

Prompts tested (tool changes only)

  • Automated MCP calls with mocked GitHub APIs cover “List workflows/runs/jobs/artifacts for owner/repo,” “Get a workflow/run/job/usage or download URL,” “Dispatch/re-run/cancel a workflow or delete its logs,” and “Get a single job's logs or all failed-job logs.” Natural-language/live-token end-to-end prompts were not run.

Security / limits

  • No security or limits impact
  • Auth / permissions considered
  • Data exposure, filtering, or token/size limits considered
    Existing read/write OAuth scopes, destructive annotations, repository-visibility IFC labels, log tail defaults, and content-window behavior are preserved. Public/private IFC labels and disabled-label behavior are tested. Unknown protocol versions no longer expose typed output capabilities.

Tool renaming

  • I am renaming tools as part of this PR (e.g. a part of a consolidation effort)
    • I have added the new tool aliases in deprecated_tool_aliases.go
  • I am not renaming tools as part of this PR

Note: 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/lint
  • Tested locally with ./script/test

Required final sequence, all passed in this order:

  1. UPDATE_TOOLSNAPS=true go test ./... — passed all packages.
  2. script/lint — passed, 0 issues.
  3. script/test — passed the complete race suite (pkg/github: 191.485s).
  4. script/generate-docs — passed.
  5. git diff --check — passed.

Additional verification: focused Actions/shared-gate tests passed; ACTIONS_LEGACY_BASELINE=true go test -overlay <exact-parent-actions-overlay.json> ./pkg/github -run TestTypedActions -count=1 passed against the Actions handlers extracted from the exact parent SHA. Live PAT-dependent E2E tests were not run. GitHub CI remains to be confirmed after publication.

Docs

  • Not needed
  • Updated (README / docs / examples)
    Generated README Actions parameter documentation; other generated documentation files were unchanged.

@SamMorrowDrums
SamMorrowDrums added this pull request to stack #3385 October 2, 2026 15:28
@SamMorrowDrums
SamMorrowDrums force-pushed the sammorrowdrums-typed-actions-tools branch from ce71882 to 20bfc4d Compare October 2, 2026 20:50
@SamMorrowDrums
SamMorrowDrums force-pushed the sammorrowdrums-typed-actions-tools branch from 20bfc4d to 4d1a88f Compare October 2, 2026 20:59
@SamMorrowDrums
SamMorrowDrums requested a balanced review from Copilot October 3, 2026 04:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Pagination validation regresses legacy behavior, documentation conflicts with the protocol gate, and generated license links are broken.

Review effort: Balanced
Findings: 1 Medium severity · 4 Low severity

Open (5)
What changed in this PR

Adds typed inputs and method-specific structured outputs for consolidated GitHub Actions tools while preserving legacy responses.

Changes:

  • Adds typed Actions DTOs, schemas, normalization, and protocol-aware outputs.
  • Restricts typed outputs to protocol 2026-07-28.
  • Adds wire tests, snapshots, generated documentation, and license-report updates.
File Description
README.md Updates generated Actions parameter documentation.
third-party-licenses.darwin.md Updates Darwin license report.
third-party-licenses.linux.md Updates Linux license report.
third-party-licenses.windows.md Updates Windows license report.
pkg/​inventory/​typed_output.go Tightens typed-output protocol gating.
pkg/​inventory/​typed_output_test.go Tests unknown and future protocol versions.
pkg/​github/​actions.go Migrates Actions handlers to typed inputs and outputs.
pkg/​github/​actions_types.go Defines Actions DTOs, schemas, and normalizers.
pkg/​github/​typed_actions_outputs_test.go Adds comprehensive typed Actions wire tests.
pkg/​github/​__toolsnaps__/​actions_get.snap Updates actions_get schema snapshot.
pkg/​github/​__toolsnaps__/​actions_get_typed.snap Adds typed actions_get snapshot.
pkg/​github/​__toolsnaps__/​actions_list.snap Updates actions_list schema snapshot.
pkg/​github/​__toolsnaps__/​actions_list_typed.snap Adds typed actions_list snapshot.
pkg/​github/​__toolsnaps__/​actions_run_trigger.snap Updates trigger schema snapshot.
pkg/​github/​__toolsnaps__/​actions_run_trigger_typed.snap Adds typed trigger snapshot.
pkg/​github/​__toolsnaps__/​get_job_logs_typed.snap Adds typed job-log snapshot.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pkg/github/actions_types.go Outdated
Comment thread pkg/inventory/typed_output.go Outdated
- [github.com/google/jsonschema-go/jsonschema](https://pkg.go.dev/github.com/google/jsonschema-go/jsonschema) ([MIT](https://github.com/google/jsonschema-go/blob/v0.4.3/LICENSE))
- [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE))
- [github.com/google/jsonschema-go/jsonschema](https://pkg.go.dev/github.com/google/jsonschema-go/jsonschema) ([MIT](https://github.com/google/jsonschema-go/blob/v0.4.3/LICENSE))
- [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE))
- [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE))
- [github.com/inconshreveable/mousetrap](https://pkg.go.dev/github.com/inconshreveable/mousetrap) ([Apache-2.0](https://github.com/inconshreveable/mousetrap/blob/v1.1.0/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/LICENSE))
- [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE))
SamMorrowDrums and others added 20 commits October 3, 2026 15:21
Use the MCP SDK's generic registration for concrete input/output types, with protocol-gated output schemas and structured results. Keep raw handlers compatible and apply shared middleware on both paths.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Auto-generated by license-check workflow
Exercise the typed array and object paths through an initialized 2025-11-25 MCP session. Verify CSV text is returned once without structured output or the SDK JSON fallback.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a raw JSON input normalizer that runs before SDK schema validation so migrated tools can retain legacy input coercions without widening their published schemas. Test case-folded issue states, numeric string IDs, validation failures and replacement registrations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Auto-generated by license-check workflow
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Exercise simultaneous legacy and modern sessions against one typed tool, plus stateless HTTP requests with modern, legacy, and absent protocol headers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cache immutable schema variants and enum overrides, preserve runtime input compatibility and request-era output behavior, and normalize dynamic scope challenges before dispatch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Avoid repeated canonical schema serialization and header annotation for cache-owned immutable pointers while retaining content-based lookup for caller-owned schemas. Run typed authorization and availability middleware before preflight and preserve tool-result error semantics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Advertise the SDK-compatible object schema for typed any input and deep-clone mutable JSON Schema metadata before caching or deriving runtime variants. Add legacy/modern registration and mutation isolation coverage.

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

Two Copilot findings on 431b7a2:

- CloneSchemas only deep-copies subschema nodes, so pointer-valued
  numeric validation keywords (Minimum, Maximum, MinLength, MinItems,
  etc.) remained aliased with the caller-owned schema after
  CloneSchema/CachedSchema. A caller mutating one of those pointers
  after caching could race with concurrent cached-schema
  serialization or silently change the cached validation bounds.
  Clone every *int/*float64 keyword explicitly alongside the existing
  collection/metadata cloning.

- CloneSchemaWithoutDefaults's removeSchemaDefaults visited every
  map/pointer child twice: once via two literal child-collection
  loops, and again via schemaChildren, which already covers the same
  fields. This doubled traversal at every nested level, making
  default removal exponential for deeply nested object/array schemas.
  Traverse only the single comprehensive schemaChildren list.

Add regression coverage across CloneSchema, CachedSchema, schema
inference option cloning, and CloneSchemaWithoutDefaults: every
*int/*float64 keyword is isolated from caller mutation (including
under concurrent marshaling), and a 48-level deep chain is used for
every schema-child field kind to confirm linear, non-exponential
default removal.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Select modern typed output for SDK-supported ISO-date protocol versions from 2026-07-28 onward. Missing, malformed, and unsupported future versions retain legacy behavior. Cover a later supported version through the selector list seam and verify the public path against the SDK supported set.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Match SDK input inference by unwrapping one pointer level before the cached input key and inference. Preserve nullable output pointer schemas. Cover both public constructors with actual modern and legacy discovery and calls, including structured null output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Key output encodings by their source definitions while preserving the SDK-registered schema guard. Keep header routing metadata available for legacy and unknown protocol clients.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Describe profile timestamps and validate null and empty team outputs against modern schemas while retaining exact legacy text.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
SamMorrowDrums and others added 21 commits October 7, 2026 00:11
Pin unchanged legacy profile/avatar fields separately from compact modern user projections and assert identical lockdown filtering and sanitization across protocols.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove added custom-field union constraints and sentinel enums from the advertised issue-write input. Preserve runtime exactly-one validation and private strict-schema tests. All three scoped input schemas compare exactly equal to main.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Auto-generated by license-check workflow
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

# Conflicts:
#	pkg/github/__toolsnaps__/add_sub_issue.snap
#	pkg/github/__toolsnaps__/remove_sub_issue.snap
#	pkg/github/__toolsnaps__/reprioritize_sub_issue.snap
#	pkg/github/granular_issue_types.go
#	pkg/github/issues_granular.go
#	pkg/github/typed_granular_issue_outputs_test.go

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 1973eee
# Last command done (1 command done):
#    pick 5b8f9d19 # refactor(issues): minimize granular structured outputs
# No commands remaining.
# You are currently rebasing.
#
# Changes to be committed:
#	modified:   pkg/github/__toolsnaps__/add_issue_comment_reaction.snap
#	modified:   pkg/github/__toolsnaps__/add_issue_reaction.snap
#	modified:   pkg/github/__toolsnaps__/add_sub_issue.snap
#	modified:   pkg/github/__toolsnaps__/create_issue.snap
#	modified:   pkg/github/__toolsnaps__/hide_issue_comment.snap
#	modified:   pkg/github/__toolsnaps__/remove_issue_comment_reaction.snap
#	modified:   pkg/github/__toolsnaps__/remove_issue_reaction.snap
#	modified:   pkg/github/__toolsnaps__/remove_sub_issue.snap
#	modified:   pkg/github/__toolsnaps__/reprioritize_sub_issue.snap
#	modified:   pkg/github/__toolsnaps__/set_issue_fields.snap
#	modified:   pkg/github/__toolsnaps__/unhide_issue_comment.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_assignees.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_body.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_labels.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_milestone.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_state.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_title.snap
#	modified:   pkg/github/__toolsnaps__/update_issue_type.snap
#	modified:   pkg/github/comment_minimize_test.go
#	new file:   pkg/github/granular_issue_types.go
#	modified:   pkg/github/granular_tools_test.go
#	modified:   pkg/github/issues_granular.go
#	new file:   pkg/github/typed_granular_issue_outputs_test.go
#
Preserve legacy text and search semantics while publishing protocol-gated concrete structured outputs. Cover modern, legacy, and unknown clients, full repository JSON unions, defaults, IFC labels, and errors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the full REST repository mirror with MinimalRepository-based
structured items plus purpose-built full-mode details. Legacy text remains
unchanged, and canonical snapshots now hold the modern output schema.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove the derivable node_id from compact full repository search output and
publish the visibility enum in the static output schema.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the modern text assertion aligned with structured content after the shared output wrapper change.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…s and outputs

Convert pull_request_read, create_pull_request, update_pull_request,
merge_pull_request, update_pull_request_branch, pull_request_review_write
(both feature variants), add_comment_to_pending_review and
add_reply_to_pull_request_comment to NewTool with concrete inputs and
output DTOs. Input normalizers replay legacy handler checks so legacy
coercions and error text are preserved.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use curated output DTOs for modern JSON text while preserving legacy serialization. Cover successful null responses, empty check runs, and Link-header page traversal.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replay parameter checks in handler order and scope cursor validation to review-thread reads. Keep commit message schema descriptions distinct from operation messages.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove normalization and test assertions that only pinned which invalid argument wins. Keep per-field validation, accepted coercions, and response-shape behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve exact legacy validation and response text while advertising concrete protocol-gated outputs for all granular PR mutations and both thread-resolution variants.

Make the inherited overflow assertion architecture-independent.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Auto-generated by license-check workflow
Keep advertised schemas exact while applying legacy-compatible runtime validation, and verify protocol-era output parity.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Auto-generated by license-check workflow
Treat required properties and enum values as unordered sets in the schema audit.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the original enum guidance in input descriptions while preserving actual JSON Schema enum constraints.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve legacy Actions payloads, validation ordering, coercions, IFC labels, and scope annotations while exposing concrete method-specific output unions to supported clients.

Reject unrecognized versions in the shared structured-output capability gate without changing tool availability rules.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Expose compact method-discriminated outputs for Actions tools while preserving legacy behavior, input coercions, and pagination forwarding.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@SamMorrowDrums
SamMorrowDrums dismissed kerobbi’s stale review October 6, 2026 22:11

The merge-base changed after approval.

@SamMorrowDrums
SamMorrowDrums force-pushed the sammorrowdrums-typed-actions-tools branch from 9f3bb5b to 719e8dd Compare October 6, 2026 22:11
Base automatically changed from sammorrowdrums-typed-granular-pr-tools to main October 6, 2026 22:23
SamMorrowDrums and others added 2 commits October 7, 2026 00:23
Fold the repository, project, governance, Copilot, and UI typed-output layers into the Actions tools pull request.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@SamMorrowDrums
SamMorrowDrums merged commit 2d5ad6e into main Oct 6, 2026
20 checks passed
@SamMorrowDrums
SamMorrowDrums deleted the sammorrowdrums-typed-actions-tools branch October 6, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants