Skip to content

[duplicate-code] Duplicate Code Pattern: StreamableHTTP Handler + Middleware Chain #5072

@github-actions

Description

@github-actions

Part of duplicate code analysis: #5070

Summary

Both internal/server/transport.go (unified mode) and internal/server/routed.go (routed mode) implement the same three-step handler construction sequence:

  1. sdk.NewStreamableHTTPHandler(...) with StreamableHTTPOptions{Stateless: false, Logger: ..., SessionTimeout: ...}
  2. WrapWithSessionAutoInit(handler)
  3. wrapWithMiddleware(handler, tag, unifiedServer, apiKey, hmacSecret)

The only differences are the session-factory callback, the logger variable, the log tag, and the SessionTimeout source.

Duplication Details

Pattern: StreamableHTTP handler + middleware chain

  • Severity: Medium
  • Occurrences: 2
  • Locations:
    • internal/server/transport.go (lines 28–54) — unified mode
    • internal/server/routed.go (lines 163–186) — routed mode (once per backend, inside a loop)
  • Code Sample:
// Both files follow this identical structure:
handler := sdk.NewStreamableHTTPHandler(serverFactory, &sdk.StreamableHTTPOptions{
    Stateless:      false,
    Logger:         logger.NewSlogLoggerWithHandler(logXxx),
    SessionTimeout: <session timeout>,
})
autoInitHandler := WrapWithSessionAutoInit(handler)
finalHandler := wrapWithMiddleware(autoInitHandler, logTag, unifiedServer, apiKey, hmacSecret)

Impact Analysis

  • Maintainability: Medium — any change to the middleware chain (e.g. adding a new wrapper) must be applied in both files.
  • Bug Risk: Medium — it is easy to apply a fix to one mode but forget the other.
  • Code Bloat: Low — ~12 duplicated lines per occurrence.

Refactoring Recommendations

  1. Extract a buildMCPHandler helper in internal/server/http_helpers.go (or a new server/handler_factory.go):
    // buildMCPHandler constructs the standard streamable HTTP handler stack.
    func buildMCPHandler(
        serverFactory func(*http.Request) *sdk.Server,
        log *logger.Logger,
        sessionTimeout time.Duration,
        logTag string,
        unifiedServer *UnifiedServer,
        apiKey, hmacSecret string,
    ) http.Handler {
        h := sdk.NewStreamableHTTPHandler(serverFactory, &sdk.StreamableHTTPOptions{
            Stateless:      false,
            Logger:         logger.NewSlogLoggerWithHandler(log),
            SessionTimeout: sessionTimeout,
        })
        return wrapWithMiddleware(WrapWithSessionAutoInit(h), logTag, unifiedServer, apiKey, hmacSecret)
    }
    • Estimated effort: ~1 hour
    • Benefits: middleware chain changes need one edit; both modes stay in sync automatically.

Implementation Checklist

  • Create buildMCPHandler helper in internal/server/
  • Refactor transport.go to use the helper
  • Refactor routed.go to use the helper
  • Run make test-all to verify no regressions

Parent Issue

See parent analysis report: #5070
Related to #5070

Generated by Duplicate Code Detector · ● 960.3K ·

  • expires on May 11, 2026, 6:28 AM UTC

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions