Skip to content

fix: return object-shaped structuredContent from list tools - #3574

Open
gdut4140 wants to merge 4 commits into
github:mainfrom
gdut4140:fix/structured-content-object-envelope
Open

gdut4140 wants to merge 4 commits into
github:mainfrom
gdut4140:fix/structured-content-object-envelope

Conversation

@gdut4140

Copy link
Copy Markdown

Summary

Wrap the array results of list_commits and the pull_request_read list methods in a named object field, so structuredContent is always a JSON object as the MCP schema requires.

Why

Fixes #3559

For protocol era 2026-07-28, both tools advertise an outputSchema and returned structuredContent as a top-level JSON array. Strict clients reject that payload (expected record, received array) because MCP defines structuredContent as an object.

What changed

  • list_commits now returns {"commits": [...]}; handler error paths return an empty ListCommitsOutput.
  • pull_request_read now returns {"files": [...]}, {"commits": [...]}, {"reviews": [...]}, or {"comments": [...]} depending on method, and its output schema offers one required-key object variant per list method instead of a single top-level array variant.
  • Older and unknown protocol versions keep the exact bare-array text and receive no outputSchema, as before. Modern JSON text serializes the same enveloped object as structuredContent.
  • Updated typed-output tests, compatibility tests, and the list_commits / pull_request_read tool snapshots.
  • Documented the object-envelope rule in README.md and docs/typed-tool-schemas.md.

MCP impact

  • Tool schema or behavior changed

Only the supported 2026-07-28 era changes shape; 2025-11-25 and unknown versions are unchanged. The returned data is the same, just enveloped.

Prompts tested (tool changes only)

Exercised through in-process MCP sessions in typed_repository_commit_outputs_test.go, typed_consolidated_pull_request_outputs_test.go, and typed_compatibility_test.go:

  • list_commits with and without fields, plus empty and null GitHub responses
  • pull_request_read with method: get_files, get_commits, get_reviews, get_comments, including after pagination and empty results

Each case asserts that modern structuredContent is an object, validates it against the advertised outputSchema, and leaves legacy text byte-identical.

Security / limits

  • No security or limits impact
  • Data exposure, filtering, or token/size limits considered — payload contents and fields projections are unchanged; only the JSON envelope changes.

Tool renaming

  • I am not renaming tools as part of this PR

Lint & tests

  • Linted locally with ./script/lint
  • Tested locally with ./script/test

go test ./... passes locally. -race needs a C compiler that this Windows checkout does not have, so CI will be the first -race run.

Docs

  • Updated (README / docs / examples)

MCP requires structuredContent to be a JSON object; list_commits returned a
top-level array and pull_request_read returned its files/commits/reviews/
comments arrays directly, so strict clients rejected the payload (expected
record, received array). Wrap both in named object fields.

Tests are being updated in follow-up commits.
pull_request_read list methods and list_commits now return their arrays under a
named key in structuredContent, so update the typed-output expectations. Legacy
text keeps the bare array, and the schema samples now include the enveloped
objects (and reject bare arrays).
@gdut4140
gdut4140 requested a review from a team as a code owner October 24, 2026 04:24
Copilot AI max review requested due to automatic review settings October 24, 2026 04:24

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 was unable to review this pull request because the user who requested the review has insufficient remaining quota.

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.

Bug: list_commits and pull_request_read return top-level JSON array violating MCP schema specifications

2 participants