Skip to content

Eliminate duplicate code patterns in JSON-RPC parsing and config initialization#1022

Merged
lpcox merged 4 commits intomainfrom
copilot/remove-duplicate-code-patterns
Feb 17, 2026
Merged

Eliminate duplicate code patterns in JSON-RPC parsing and config initialization#1022
lpcox merged 4 commits intomainfrom
copilot/remove-duplicate-code-patterns

Conversation

Copy link
Contributor

Copilot AI commented Feb 17, 2026

Automated analysis identified 3 duplication patterns totaling ~150 lines across critical MCP protocol handling and configuration code. This refactoring extracts helper functions to eliminate the duplication.

Changes

JSON-RPC Response Parsing (118+ lines → 1 helper)

  • Extracted parseJSONRPCResponseWithSSE() consolidating SSE format fallback logic
  • Used in initializeHTTPSession() and sendHTTPRequest()
  • Reduces each call site from 45+ lines to 2 lines

Optional Config Field Assignment (9 lines → 1 helper)

  • Extracted intPtrOrDefault() for pointer dereferencing with defaults
  • Replaces repeated if ptr != nil { cfg.Field = *ptr } pattern
  • Used inline in struct initialization

Gateway Default Initialization (duplicate assignments → 1 helper)

  • Extracted applyGatewayDefaults() centralizing Port/StartupTimeout/ToolTimeout defaults
  • Single source of truth for TOML and JSON config loading

Example

Before:

if err := json.Unmarshal(result.ResponseBody, &rpcResponse); err != nil {
    sseData, sseErr := parseSSEResponse(result.ResponseBody)
    if sseErr != nil {
        if result.StatusCode != http.StatusOK {
            return &Response{JSONRPC: "2.0", Error: &ResponseError{...}}, nil
        }
        bodyPreview := string(result.ResponseBody)
        if len(bodyPreview) > 500 {
            bodyPreview = bodyPreview[:500] + "... (truncated)"
        }
        return nil, fmt.Errorf("failed to parse...")
    }
    // ... 30+ more lines of duplicate error handling
}

After:

rpcResponse, err := parseJSONRPCResponseWithSSE(result.ResponseBody, result.StatusCode, "JSON-RPC response")
if err != nil {
    return nil, err
}

No behavioral changes. All tests passing.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /tmp/go-build4017383299/b275/launcher.test /tmp/go-build4017383299/b275/launcher.test -test.testlogfile=/tmp/go-build4017383299/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true go pull.rebase 64/pkg/tool/linu-o (dns block)
    • Triggering command: /tmp/go-build3792116991/b275/launcher.test /tmp/go-build3792116991/b275/launcher.test -test.testlogfile=/tmp/go-build3792116991/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true p/go-build kP-l/WrPb7ILNcQOx2pc8kP-l x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build2064399090/b275/launcher.test /tmp/go-build2064399090/b275/launcher.test -test.testlogfile=/tmp/go-build2064399090/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true submodules | head -n 10 thored-by: lpcox <15877973+lpcox@users.noreply.github.com> ker/cli-plugins/docker-buildx go /exp.go 64/pkg/tool/linu--64 ker/cli-plugins/docker-buildx n-me�� (create|run) 64/pkg/tool/linu/tmp/go-build4017383299/b065/vet.cfg ker/cli-plugins/docker-compose go +lpcox@users.nor-c 64/pkg/tool/linugit status --porcelain --ignore-submodules | head -n 10 ker/cli-plugins/docker-compose (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build4017383299/b260/config.test /tmp/go-build4017383299/b260/config.test -test.testlogfile=/tmp/go-build4017383299/b260/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true go ternal/randutil/--64 64/pkg/tool/linu-o (dns block)
    • Triggering command: /tmp/go-build807840348/b001/config.test /tmp/go-build807840348/b001/config.test -test.testlogfile=/tmp/go-build807840348/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net -trimpath 64/pkg/tool/linux_amd64/vet -p ions =0 64/pkg/tool/linux_amd64/vet (dns block)
    • Triggering command: `/tmp/go-build1630895575/b001/config.test /tmp/go-build1630895575/b001/config.test -test.testlogfile=/tmp/go-build1630895575/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true se 7383299/b122/vet.cfg ache/go/1.25.7/x64/pkg/tool/linux_amd64/vet . --gdwarf2 --64 ache/go/1.25.7/x64/pkg/tool/linuExtract parseJSONRPCResponseWithSSE helper to eliminate duplicate parsing logic

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> -W -I /tmp/go-build4017383299/b165/ test.test . --gdwarf2 --64 test.test` (dns block)

  • nonexistent.local
    • Triggering command: /tmp/go-build4017383299/b275/launcher.test /tmp/go-build4017383299/b275/launcher.test -test.testlogfile=/tmp/go-build4017383299/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true go pull.rebase 64/pkg/tool/linu-o (dns block)
    • Triggering command: /tmp/go-build3792116991/b275/launcher.test /tmp/go-build3792116991/b275/launcher.test -test.testlogfile=/tmp/go-build3792116991/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true p/go-build kP-l/WrPb7ILNcQOx2pc8kP-l x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build2064399090/b275/launcher.test /tmp/go-build2064399090/b275/launcher.test -test.testlogfile=/tmp/go-build2064399090/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true submodules | head -n 10 thored-by: lpcox &lt;15877973&#43;lpcox@users.noreply.github.com&gt; ker/cli-plugins/docker-buildx go /exp.go 64/pkg/tool/linu--64 ker/cli-plugins/docker-buildx n-me�� (create|run) 64/pkg/tool/linu/tmp/go-build4017383299/b065/vet.cfg ker/cli-plugins/docker-compose go &#43;lpcox@users.nor-c 64/pkg/tool/linugit status --porcelain --ignore-submodules | head -n 10 ker/cli-plugins/docker-compose (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build4017383299/b275/launcher.test /tmp/go-build4017383299/b275/launcher.test -test.testlogfile=/tmp/go-build4017383299/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true go pull.rebase 64/pkg/tool/linu-o (dns block)
    • Triggering command: /tmp/go-build3792116991/b275/launcher.test /tmp/go-build3792116991/b275/launcher.test -test.testlogfile=/tmp/go-build3792116991/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true p/go-build kP-l/WrPb7ILNcQOx2pc8kP-l x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build2064399090/b275/launcher.test /tmp/go-build2064399090/b275/launcher.test -test.testlogfile=/tmp/go-build2064399090/b275/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true submodules | head -n 10 thored-by: lpcox &lt;15877973&#43;lpcox@users.noreply.github.com&gt; ker/cli-plugins/docker-buildx go /exp.go 64/pkg/tool/linu--64 ker/cli-plugins/docker-buildx n-me�� (create|run) 64/pkg/tool/linu/tmp/go-build4017383299/b065/vet.cfg ker/cli-plugins/docker-compose go &#43;lpcox@users.nor-c 64/pkg/tool/linugit status --porcelain --ignore-submodules | head -n 10 ker/cli-plugins/docker-compose (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build4017383299/b284/mcp.test /tmp/go-build4017383299/b284/mcp.test -test.testlogfile=/tmp/go-build4017383299/b284/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true unset NvYQykAA8 /usr/local/sbin/git user.email go (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>[duplicate-code] 🔍 Duplicate Code Analysis Report - 3 Significant Patterns Detected</issue_title>
<issue_description>Analysis of commit bb96a20

Summary

This automated analysis identified 3 significant duplication patterns in the Go codebase that impact maintainability and present refactoring opportunities. The patterns span critical areas including JSON-RPC response handling, configuration management, and optional field assignment.

Detected Patterns

This analysis found 3 significant duplication patterns requiring attention:

  1. JSON-RPC Response Parsing - Severity: CRITICAL - See sub-issue [duplicate-code] 🔍 Duplicate Code Pattern: JSON-RPC Response Parsing with SSE Fallback #1008

    • 118+ lines of nearly identical code duplicated across 2 locations
    • Affects MCP protocol communication reliability
  2. Optional Gateway Config Assignment - Severity: HIGH - See sub-issue [duplicate-code] 🔍 Duplicate Code Pattern: Optional Gateway Config Pointer Dereferencing #1007

    • Repeated pointer dereferencing pattern (3 instances in single function)
    • Affects configuration parsing robustness
  3. Default Gateway Initialization - Severity: MEDIUM - See sub-issue [duplicate-code] 🔍 Duplicate Code Pattern: Default Gateway Configuration Initialization #1009

    • Duplicated default value assignments across 2+ locations
    • Affects configuration initialization consistency

Overall Impact

  • Total Duplicated Lines: ~150 lines across all patterns
  • Affected Files: 3 critical files (connection.go, config_core.go, config_stdin.go)
  • Maintainability Risk: HIGH - Critical protocol handling code is duplicated
  • Refactoring Priority: HIGH - JSON-RPC parsing duplication poses bug synchronization risk

Next Steps

  1. Review individual pattern sub-issues for detailed analysis
  2. Prioritize Pattern Configure as a Go CLI tool #1 (JSON-RPC parsing) - highest risk and impact
  3. Extract helper functions for each pattern
  4. Update tests to verify refactored behavior

Analysis Metadata

  • Analyzed Files: 62 Go files from latest commit
  • Detection Method: Serena semantic code analysis + manual pattern verification
  • Commit: bb96a20
  • Triggered by: @lpcox
  • Analysis Date: 2026-02-17T02:57:15Z</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits February 17, 2026 13:18
…sing logic

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
…ncing

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
…tion

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix duplicate code issues in Go codebase Eliminate duplicate code patterns in JSON-RPC parsing and config initialization Feb 17, 2026
Copilot AI requested a review from lpcox February 17, 2026 13:24
@lpcox lpcox marked this pull request as ready for review February 17, 2026 13:32
Copilot AI review requested due to automatic review settings February 17, 2026 13:32
@lpcox lpcox merged commit d530244 into main Feb 17, 2026
8 checks passed
@lpcox lpcox deleted the copilot/remove-duplicate-code-patterns branch February 17, 2026 13:32
Copy link
Contributor

Copilot AI left a comment

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 refactors duplicated logic across MCP HTTP JSON-RPC handling and configuration loading by extracting small helper functions, reducing repeated code paths and centralizing defaulting/parsing behavior.

Changes:

  • Added parseJSONRPCResponseWithSSE() to consolidate JSON-RPC response parsing with SSE fallback, used by both initializeHTTPSession() and sendHTTPRequest().
  • Added intPtrOrDefault() to simplify optional integer field handling in stdin JSON config conversion.
  • Added applyGatewayDefaults() to centralize gateway default initialization across TOML and stdin JSON config loading.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
internal/mcp/connection.go Extracts shared JSON-RPC parsing (with SSE fallback) and updates HTTP call sites to use it.
internal/config/config_stdin.go Introduces intPtrOrDefault() and uses applyGatewayDefaults() to reduce duplication in stdin config conversion.
internal/config/config_core.go Introduces applyGatewayDefaults() and uses it during TOML config loading.
Comments suppressed due to low confidence (1)

internal/mcp/connection.go:111

  • Same issue as above: in the non-OK status branch after SSE extraction succeeds but JSON unmarshal fails, ResponseError.Data is set to json.RawMessage(body) even though body may be SSE/plain text. Ensure Data is always valid JSON (e.g., JSON-string/object wrapper) so encoding/marshalling the Response cannot fail.
			if statusCode != http.StatusOK {
				logConn.Printf("HTTP error status=%d, SSE data cannot be parsed as JSON-RPC", statusCode)
				return &Response{
					JSONRPC: "2.0",
					Error: &ResponseError{
						Code:    -32603, // Internal error
						Message: fmt.Sprintf("HTTP %d: %s", statusCode, http.StatusText(statusCode)),
						Data:    json.RawMessage(body),
					},

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

Comment on lines +82 to +87
return &Response{
JSONRPC: "2.0",
Error: &ResponseError{
Code: -32603, // Internal error
Message: fmt.Sprintf("HTTP %d: %s", statusCode, http.StatusText(statusCode)),
Data: json.RawMessage(body),
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

ResponseError.Data is assigned json.RawMessage(body) in the branch where the body is known to be non-JSON (json.Unmarshal failed and SSE extraction failed). json.RawMessage must contain valid JSON bytes; otherwise json.Marshal / json.Encoder will fail (e.g., when proxying this Response back to clients or logging it). Consider wrapping the raw body as a JSON string (or an object with a base64/string field) so the response can always be encoded safely.

This issue also appears on line 103 of the same file.

Suggested change
return &Response{
JSONRPC: "2.0",
Error: &ResponseError{
Code: -32603, // Internal error
Message: fmt.Sprintf("HTTP %d: %s", statusCode, http.StatusText(statusCode)),
Data: json.RawMessage(body),
rawBodyJSON, marshalErr := json.Marshal(string(body))
if marshalErr != nil {
// Fall back to an empty JSON string to ensure ResponseError.Data is always valid JSON.
logConn.Printf("failed to marshal HTTP error body as JSON string: %v", marshalErr)
rawBodyJSON = []byte(`""`)
}
return &Response{
JSONRPC: "2.0",
Error: &ResponseError{
Code: -32603, // Internal error
Message: fmt.Sprintf("HTTP %d: %s", statusCode, http.StatusText(statusCode)),
Data: json.RawMessage(rawBodyJSON),

Copilot uses AI. Check for mistakes.
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 Analysis Report - 3 Significant Patterns Detected

3 participants