Extract shared MCP content-slice normalization by Copilot · Pull Request #7325 · github/gh-aw-mcpg · GitHub
Skip to content

Extract shared MCP content-slice normalization#7325

Merged
lpcox merged 4 commits into
mainfrom
copilot/duplicate-code-content-slice-normalization
Jun 10, 2026
Merged

Extract shared MCP content-slice normalization#7325
lpcox merged 4 commits into
mainfrom
copilot/duplicate-code-content-slice-normalization

Conversation

Copilot AI commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

The MCP "content" field normalization logic was duplicated across mcp, mcpresult, and middleware, with behavior split between []interface{} and []map[string]interface{} inputs. This change centralizes that slice normalization while preserving each caller’s existing handling of invalid content items.

  • Shared normalization helper

    • Adds mcpresult.NormalizeContentItems(contentVal interface{}) ([]map[string]interface{}, bool) as the single normalization path for MCP content slices.
    • Supports both deserialized JSON slices ([]interface{}) and typed helper-produced slices ([]map[string]interface{}).
  • Call site refactor

    • Replaces local normalization switches in:
      • internal/mcp/tool_result.go
      • internal/mcpresult/text_content.go
      • internal/middleware/jqschema.go
    • Keeps caller-specific semantics unchanged:
      • ConvertToCallToolResult still rejects non-map items in []interface{}
      • ExtractTextContent still skips non-map items
      • middleware rewrite/fast-path logic still works for both slice forms
  • Coverage additions

    • Adds focused unit tests for the shared helper.
    • Adds middleware coverage for the typed []map[string]interface{} fast path, which was one of the duplicated branches called out in the issue.
  • Example

    items, ok := mcpresult.NormalizeContentItems(contentVal)
    if !ok {
        return nil, false
    }

Copilot AI changed the title [WIP] Fix duplicate code pattern for content slice normalization Extract shared MCP content-slice normalization Jun 10, 2026
Copilot finished work on behalf of lpcox June 10, 2026 18:09
Copilot AI requested a review from lpcox June 10, 2026 18:09
@lpcox lpcox marked this pull request as ready for review June 10, 2026 19:50
Copilot AI review requested due to automatic review settings June 10, 2026 19:50
@lpcox

lpcox commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

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.

Pull request overview

This PR centralizes MCP "content" slice normalization into mcpresult.NormalizeContentItems to remove duplicated handling of []interface{} vs []map[string]interface{} across MCP result conversion and middleware, while keeping each call site’s existing invalid-item semantics.

Changes:

  • Adds mcpresult.NormalizeContentItems(contentVal interface{}) to normalize "content" into []map[string]interface{}.
  • Refactors MCP result conversion, text extraction, and middleware fast-path/rewrite logic to use the shared helper.
  • Adds unit tests for the shared helper and a middleware fast-path test for typed []map[string]interface{} content slices.
Show a summary per file
File Description
internal/middleware/jqschema.go Uses shared content-slice normalization for envelope rewrite and fast-path checks.
internal/middleware/jqschema_test.go Adds coverage ensuring fast-path behavior works with typed []map[string]interface{} content.
internal/mcpresult/text_content.go Replaces local content normalization with NormalizeContentItems.
internal/mcpresult/content_items.go Introduces the shared NormalizeContentItems helper.
internal/mcpresult/content_items_test.go Adds focused unit tests for the new normalization helper.
internal/mcp/tool_result.go Refactors result conversion to use shared normalization while preserving strict rejection semantics.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 6/6 changed files
  • Comments generated: 1

Comment thread internal/mcp/tool_result.go Outdated
Comment on lines 62 to 71
items, ok := mcpresult.NormalizeContentItems(contentVal)
if !ok {
// content field exists but is not a recognizable slice type — wrap the whole map as text.
return marshalValueToTextContentResult(m)
}
if rawItems, ok := contentVal.([]interface{}); ok && len(items) != len(rawItems) {
for i, item := range rawItems {
if _, ok := item.(map[string]interface{}); !ok {
return nil, fmt.Errorf("content item %d: expected map, got %T", i, item)
}
…e-content-slice-normalization

# Conflicts:
#	internal/middleware/jqschema.go

Copilot AI commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Merge conflicts resolved in 7781dd1. The only conflict was in rewriteEnvelopeTextPayload in jqschema.goorigin/main had already refactored that section into the cleaner rewriteFirstContentItem/rewriteContentItemText helpers (commit 6f5d9b2), so the resolution takes that version. The NormalizeContentItems helper is still used for the fast-path logic further down in the same file, as well as in mcp/tool_result.go and mcpresult/text_content.go.

Copilot finished work on behalf of lpcox June 10, 2026 20:01
@lpcox

lpcox commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

Copilot AI commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Copilot finished work on behalf of lpcox June 10, 2026 20:22
@lpcox lpcox merged commit 81c876b into main Jun 10, 2026
26 checks passed
@lpcox lpcox deleted the copilot/duplicate-code-content-slice-normalization branch June 10, 2026 21:51
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.

[duplicate-code] Duplicate Code Pattern: Content Slice Normalization across mcp, mcpresult, and middleware

3 participants