Skip to content

Add protocol-gated structured outputs to read tools - #3360

Draft
SamMorrowDrums wants to merge 6 commits into
mainfrom
sammorrowdrums-protocol-gated-output-schemas
Draft

SamMorrowDrums wants to merge 6 commits into
mainfrom
sammorrowdrums-protocol-gated-output-schemas

Conversation

@SamMorrowDrums

@SamMorrowDrums SamMorrowDrums commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds typed output schemas and structured results to read tools, exposing them only to MCP clients negotiated on protocol 2026-07-28 or later. Older and unknown-version clients keep the tools and text results, without outputSchema or structuredContent.

Why

Modern MCP clients use output schemas for programmatic tool calling / Code Mode. Protocol 2025-11-25 required output schema roots to be objects, while SEP-2106 in 2026-07-28 allows the nullable/union roots emitted by Go-inferred schemas; gating avoids advertising incompatible schemas to older clients.
Fixes: N/A

What changed

  • Added typed output schemas for read tools covering user/repository reads, projected issue and pull-request search/list results, security findings, notifications, and discussions.
  • Added protocol-version gating that strips outputSchema from tools/list and structuredContent from tools/call results for pre-2026-07-28 or unknown protocol versions, preserving text content and the tool listing.
  • Version detection uses the negotiated request version and falls back to stateless per-request metadata when the SDK request version is unavailable; missing version information is treated as legacy.
  • Preserved existing scope controls and rich body-content sanitization. The project-planning schema slice was dropped because it conflicted across multiple current tool implementations; follow-up work can add it.

MCP impact

  • No tool or API changes
  • Tool schema or behavior changed
    Read tools now advertise output schemas to modern clients and return structuredContent; older clients retain text-only responses.
  • New tool added

Prompts tested (tool changes only)

  • No live GitHub prompts run; protocol-era schema and call-result behavior is covered by Go tests.

Security / limits

  • No security or limits impact
  • Auth / permissions considered
    Existing tool scopes are preserved.
  • Data exposure, filtering, or token/size limits considered
    Structured output mirrors existing tool responses and does not widen authorization; projected search output remains compact and honors field selection.

Tool renaming

  • I am renaming tools as part of this PR (e.g. as 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 — attempted, but the repository-pinned golangci-lint v2.9.0 cannot decode Go 1.27.1 export data (internal/goarch, export data version 4; max supported version 2). Compatible golangci-lint v2.14.0 change-only check passed: /tmp/golangci-lint/golangci-lint run --new-from-rev=origin/main (0 issues).
  • Tested locally with ./script/test — passed (go test -race ./...). Also passed UPDATE_TOOLSNAPS=true go test ./....

Docs

  • Not needed
  • Updated (README / docs / examples)

Ran script/generate-docs; it produced no documentation diff.

SamMorrowDrums and others added 6 commits October 2, 2026 00:12
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3821743d-3aec-42d3-8fa3-66ff925f1cf1
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3821743d-3aec-42d3-8fa3-66ff925f1cf1
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3821743d-3aec-42d3-8fa3-66ff925f1cf1
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3821743d-3aec-42d3-8fa3-66ff925f1cf1
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@SamMorrowDrums SamMorrowDrums changed the title Add structured output schemas to read tools Add protocol-gated structured outputs to read tools Oct 1, 2026
@SamMorrowDrums
SamMorrowDrums marked this pull request as ready for review October 1, 2026 22:27
@SamMorrowDrums
SamMorrowDrums requested a review from a team as a code owner October 1, 2026 22:27
Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:27

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

Typed registration changes existing input validation, and legacy CSV calls retain an unintended JSON fallback.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Adds protocol-gated structured outputs to read tools while retaining text fallbacks for older MCP clients.

Changes:

  • Adds typed output registration and protocol-version gating.
  • Introduces projected DTOs for read, search, security, notification, and discussion tools.
  • Updates structured-output tests and tool snapshots.
File Description
pkg/​inventory/​tool_availability.go Gates schemas and structured content by protocol.
pkg/​inventory/​tool_availability_test.go Tests protocol gating.
pkg/​inventory/​server_tool.go Adds typed registration and middleware support.
pkg/​inventory/​server_tool_test.go Tests typed outputs and middleware.
pkg/​github/​tools_validation_test.go Validates structured-output coverage.
pkg/​github/​security_advisories.go Returns typed advisory outputs.
pkg/​github/​secret_scanning.go Returns typed secret-alert outputs.
pkg/​github/​search.go Adds projected code-search output.
pkg/​github/​search_utils.go Adds typed issue/PR search results.
pkg/​github/​search_test.go Updates code-search assertions.
pkg/​github/​sanitize_coverage_test.go Tests projected-output sanitization.
pkg/​github/​repositories.go Types branch and tag outputs.
pkg/​github/​pullrequests.go Adds projected PR outputs.
pkg/​github/​projected_outputs.go Defines projection-aware DTOs.
pkg/​github/​notifications.go Returns typed notification outputs.
pkg/​github/​notification_outputs.go Defines notification DTOs.
pkg/​github/​notification_outputs_test.go Tests notification output contracts.
pkg/​github/​minimal_types.go Adds typed projection helpers.
pkg/​github/​discussions.go Returns typed discussion outputs.
pkg/​github/​discussion_outputs.go Defines discussion DTOs.
pkg/​github/​dependabot.go Returns typed Dependabot outputs.
pkg/​github/​csv_output.go Integrates CSV as handler middleware.
pkg/​github/​csv_output_test.go Tests CSV with structured output.
pkg/​github/​context_tools.go Types user and team outputs.
pkg/​github/​context_tools_test.go Tests get_me structured output.
pkg/​github/​code_scanning.go Returns typed code-scanning outputs.
pkg/​github/​code_quality.go Returns typed quality findings.
pkg/​github/​__toolsnaps__/​search_pull_requests.snap Records PR-search output schema.
pkg/​github/​__toolsnaps__/​search_issues.snap Records issue-search output schema.
pkg/​github/​__toolsnaps__/​search_code.snap Records code-search output schema.
pkg/​github/​__toolsnaps__/​list_tags.snap Records tag-list output schema.
pkg/​github/​__toolsnaps__/​list_secret_scanning_alerts.snap Records secret-alert list schema.
pkg/​github/​__toolsnaps__/​list_repository_security_advisories.snap Records repository-advisory schema.
pkg/​github/​__toolsnaps__/​list_pull_requests.snap Records PR-list output schema.
pkg/​github/​__toolsnaps__/​list_org_repository_security_advisories.snap Records organization-advisory schema.
pkg/​github/​__toolsnaps__/​list_notifications.snap Records notification-list schema.
pkg/​github/​__toolsnaps__/​list_issues.snap Records issue-list output schema.
pkg/​github/​__toolsnaps__/​list_discussions.snap Records discussion-list schema.
pkg/​github/​__toolsnaps__/​list_discussion_categories.snap Records category-list schema.
pkg/​github/​__toolsnaps__/​list_dependabot_alerts.snap Records Dependabot-list schema.
pkg/​github/​__toolsnaps__/​list_code_scanning_alerts.snap Records code-alert list schema.
pkg/​github/​__toolsnaps__/​list_branches.snap Records branch-list output schema.
pkg/​github/​__toolsnaps__/​get_teams.snap Records team output schema.
pkg/​github/​__toolsnaps__/​get_team_members.snap Records member output schema.
pkg/​github/​__toolsnaps__/​get_secret_scanning_alert.snap Records secret-alert schema.
pkg/​github/​__toolsnaps__/​get_notification_details.snap Records notification-detail schema.
pkg/​github/​__toolsnaps__/​get_me.snap Records current-user schema.
pkg/​github/​__toolsnaps__/​get_discussion.snap Records discussion-detail schema.
pkg/​github/​__toolsnaps__/​get_discussion_comments.snap Records discussion-comment schema.
pkg/​github/​__toolsnaps__/​get_dependabot_alert.snap Records Dependabot-alert schema.
pkg/​github/​__toolsnaps__/​get_code_scanning_alert.snap Records code-alert schema.
pkg/​github/​__toolsnaps__/​get_code_quality_finding.snap Records quality-finding schema.

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

Comment on lines +320 to +322
typedRegisterFunc = func(s *mcp.Server, tool *mcp.Tool, middleware ...ToolHandlerMiddleware) {
mcp.AddTool(s, tool, toTypedHandler(handler, middleware...))
}
Comment on lines +145 to +148
if callResult, ok := result.(*mcp.CallToolResult); ok && callResult.StructuredContent != nil {
resultCopy := *callResult
resultCopy.StructuredContent = nil
return &resultCopy, nil
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.

2 participants