No exact duplicate implementations were found. The patterns below are near-duplicates or misplaced functions — the kind of low-risk, high-clarity refactors.
Full Report
1. Three ResponseWriter Wrapper Types With Overlapping Purpose
Severity: Medium | Estimated effort: 1–2 hours
There are three separate http.ResponseWriter wrapper structs that capture HTTP status codes:
| Type |
File |
Purpose |
BaseResponseWriter |
internal/httputil/response_writer.go |
Embeddable base: captures status, buffers implicit 200 |
responseWriter |
internal/server/response_writer.go |
Extends BaseResponseWriter to also buffer body bytes for debug logging |
statusResponseWriter |
internal/tracing/http.go |
Extends BaseResponseWriter for OTel span status |
The server and tracing variants already embed httputil.BaseResponseWriter, so the core duplication is resolved. However, statusResponseWriter in internal/tracing/http.go is an unnamed, unexported struct defined inline in the file. For clarity it should either be documented or folded into BaseResponseWriter if its sole behaviour is identical (it is: no additional methods beyond the embedding).
Recommendation: Document the design intent at the top of httputil/response_writer.go stating it is the canonical base. Confirm statusResponseWriter adds no behaviour beyond the embed (it doesn't) and consider whether it can be replaced with a direct BaseResponseWriter embed at the call site in tracing/http.go.
2. TLS Helper Functions Scattered Across Four Packages
Severity: Medium | Estimated effort: 2–3 hours
TLS-related helper functions are spread across four distinct locations:
internal/httputil/tls.go
NewServerTLSConfig(cert tls.Certificate) *tls.Config
NewClientTLSConfig() *tls.Config
internal/server/gateway_tls.go
LoadGatewayTLS(certPath, keyPath, caPath string) (*tls.Config, error)
internal/proxy/tls.go
GenerateSelfSignedTLS(dir string) (*TLSConfig, error)
writePEM(path, blockType string, derBytes []byte, perm os.FileMode) error
internal/cmd/proxy.go
configureTLSTrustEnvironment(caCertPath string) error
The four locations have distinct concerns (generic config builders, gateway-level loading, self-signed cert generation, trust store configuration) but a developer looking for "where does TLS live?" will need to check four packages. The writePEM helper in proxy/tls.go is an implementation detail of GenerateSelfSignedTLS and does not belong in a shared location — that's fine. The concern is discoverability.
Recommendation: Add a package-level comment to internal/httputil/tls.go pointing to server/gateway_tls.go and proxy/tls.go for the higher-level functions. Alternatively, consider whether GenerateSelfSignedTLS belongs in httputil since it's a generic TLS utility that happens to be used by the proxy. No move is strictly required; documentation is sufficient.
3. FormatSessionIDForLog Lives in a Separate One-Function File
Severity: Low | Estimated effort: 30 minutes
internal/util/session.go contains a single function:
func FormatSessionIDForLog(sessionID string) string
This function calls Truncate from the same package. It is a formatting utility and fits naturally into internal/util/format_duration.go (which already houses FormatFutureTime and FormatDuration) or a new internal/util/format.go. Having a file with a single 10-line function creates unnecessary file-count overhead.
Recommendation: Move FormatSessionIDForLog into internal/util/format_duration.go (or rename that file to format.go to reflect its broader formatting scope) and delete session.go.
4. config/config_env.go Partially Duplicates envutil.GetEnvInt
Severity: Low | Estimated effort: 1 hour
internal/config/config_env.go defines a package-private helper:
func parseAndValidateIntEnv(envKey string, validate func(int) *ValidationError) (int, bool, error)
This is a thin wrapper over envutil.GetEnvIntRaw that adds domain-specific validation. The pattern is sound (config validation belongs in the config package). However, the function name and shape are very similar to envutil.GetEnvInt, envutil.GetEnvIntRaw, and envutil.GetEnvDuration. A developer new to the codebase may implement a fourth version elsewhere.
Recommendation: Add a comment to parseAndValidateIntEnv (and its sibling GetGatewayPortFromEnv etc.) explaining that the config-level functions intentionally wrap envutil with domain validation. This is a documentation-only change.
5. cmd/proxy.go::configureTLSTrustEnvironment Is an Outlier in a Command File
Severity: Low | Estimated effort: 30 minutes
internal/cmd/proxy.go contains:
func configureTLSTrustEnvironment(caCertPath string) error
This function manipulates the system TLS trust store — it's an infrastructure utility, not a CLI-command-handler concern. It does not depend on any cobra.Command state. It would be more discoverable in internal/httputil/tls.go or internal/proxy/tls.go.
Recommendation: Move configureTLSTrustEnvironment to internal/httputil/tls.go and update the call site in cmd/proxy.go. This improves discoverability and keeps the command file focused on wiring flags to behavior.
6. logger/fileutil.go::atomicWriteFile Could Be Shared More Broadly
Severity: Low | Estimated effort: 1 hour
internal/logger/fileutil.go defines:
func atomicWriteFile(filePath string, data []byte, perm os.FileMode) error
func writeJSONToFile(logDir, fileName string, data any, perm os.FileMode) error
These are currently unexported logger internals, but atomicWriteFile is a general-purpose utility. It is only used within the logger package. If any future package needs atomic file writes, it would either duplicate the logic or depend on internal/logger (creating an awkward dependency). Consider exporting or relocating it.
Recommendation: Export atomicWriteFile as logger.AtomicWriteFile or move it to a new internal/fileutil package if/when a second consumer appears. No immediate action required; flag for the next new use case.
The following packages demonstrate excellent single-responsibility organization and are explicitly highlighted to confirm no action is needed:
🔧 Semantic Function Clustering Analysis
Analysis of repository: github/gh-aw-mcpg
Run: §29209100965
Date: 2026-07-12
Executive Summary
Analysis of 140 non-test Go source files across 22 packages catalogued 964 exported and unexported functions. The codebase is generally well-organized with clear package boundaries. This report highlights three meaningful areas for improvement: (1) parallel
ResponseWriterwrapper types across packages that partially duplicate each other, (2) TLS-helper functions spread across four packages, and (3) small utility functions (FormatSessionIDForLog,Truncate) that live outside the package most likely to want them.No exact duplicate implementations were found. The patterns below are near-duplicates or misplaced functions — the kind of low-risk, high-clarity refactors.
Function Inventory
internal/serverinternal/configinternal/difcinternal/loggerinternal/guardinternal/mcpinternal/proxyinternal/launcherinternal/tracinginternal/cmdinternal/middlewareinternal/utilinternal/httputilinternal/envutilTotal: 964 functions across 140 files
Identified Issues
Full Report
1. Three
ResponseWriterWrapper Types With Overlapping PurposeSeverity: Medium | Estimated effort: 1–2 hours
There are three separate
http.ResponseWriterwrapper structs that capture HTTP status codes:BaseResponseWriterinternal/httputil/response_writer.goresponseWriterinternal/server/response_writer.goBaseResponseWriterto also buffer body bytes for debug loggingstatusResponseWriterinternal/tracing/http.goBaseResponseWriterfor OTel span statusThe
serverandtracingvariants already embedhttputil.BaseResponseWriter, so the core duplication is resolved. However,statusResponseWriterininternal/tracing/http.gois an unnamed, unexported struct defined inline in the file. For clarity it should either be documented or folded intoBaseResponseWriterif its sole behaviour is identical (it is: no additional methods beyond the embedding).Recommendation: Document the design intent at the top of
httputil/response_writer.gostating it is the canonical base. ConfirmstatusResponseWriteradds no behaviour beyond the embed (it doesn't) and consider whether it can be replaced with a directBaseResponseWriterembed at the call site intracing/http.go.2. TLS Helper Functions Scattered Across Four Packages
Severity: Medium | Estimated effort: 2–3 hours
TLS-related helper functions are spread across four distinct locations:
The four locations have distinct concerns (generic config builders, gateway-level loading, self-signed cert generation, trust store configuration) but a developer looking for "where does TLS live?" will need to check four packages. The
writePEMhelper inproxy/tls.gois an implementation detail ofGenerateSelfSignedTLSand does not belong in a shared location — that's fine. The concern is discoverability.Recommendation: Add a package-level comment to
internal/httputil/tls.gopointing toserver/gateway_tls.goandproxy/tls.gofor the higher-level functions. Alternatively, consider whetherGenerateSelfSignedTLSbelongs inhttputilsince it's a generic TLS utility that happens to be used by the proxy. No move is strictly required; documentation is sufficient.3.
FormatSessionIDForLogLives in a Separate One-Function FileSeverity: Low | Estimated effort: 30 minutes
internal/util/session.gocontains a single function:This function calls
Truncatefrom the same package. It is a formatting utility and fits naturally intointernal/util/format_duration.go(which already housesFormatFutureTimeandFormatDuration) or a newinternal/util/format.go. Having a file with a single 10-line function creates unnecessary file-count overhead.Recommendation: Move
FormatSessionIDForLogintointernal/util/format_duration.go(or rename that file toformat.goto reflect its broader formatting scope) and deletesession.go.4.
config/config_env.goPartially Duplicatesenvutil.GetEnvIntSeverity: Low | Estimated effort: 1 hour
internal/config/config_env.godefines a package-private helper:This is a thin wrapper over
envutil.GetEnvIntRawthat adds domain-specific validation. The pattern is sound (config validation belongs in the config package). However, the function name and shape are very similar toenvutil.GetEnvInt,envutil.GetEnvIntRaw, andenvutil.GetEnvDuration. A developer new to the codebase may implement a fourth version elsewhere.Recommendation: Add a comment to
parseAndValidateIntEnv(and its siblingGetGatewayPortFromEnvetc.) explaining that the config-level functions intentionally wrapenvutilwith domain validation. This is a documentation-only change.5.
cmd/proxy.go::configureTLSTrustEnvironmentIs an Outlier in a Command FileSeverity: Low | Estimated effort: 30 minutes
internal/cmd/proxy.gocontains:This function manipulates the system TLS trust store — it's an infrastructure utility, not a CLI-command-handler concern. It does not depend on any
cobra.Commandstate. It would be more discoverable ininternal/httputil/tls.goorinternal/proxy/tls.go.Recommendation: Move
configureTLSTrustEnvironmenttointernal/httputil/tls.goand update the call site incmd/proxy.go. This improves discoverability and keeps the command file focused on wiring flags to behavior.6.
logger/fileutil.go::atomicWriteFileCould Be Shared More BroadlySeverity: Low | Estimated effort: 1 hour
internal/logger/fileutil.godefines:These are currently unexported logger internals, but
atomicWriteFileis a general-purpose utility. It is only used within the logger package. If any future package needs atomic file writes, it would either duplicate the logic or depend oninternal/logger(creating an awkward dependency). Consider exporting or relocating it.Recommendation: Export
atomicWriteFileaslogger.AtomicWriteFileor move it to a newinternal/fileutilpackage if/when a second consumer appears. No immediate action required; flag for the next new use case.Clustering Results: What's Well-Organized ✅
The following packages demonstrate excellent single-responsibility organization and are explicitly highlighted to confirm no action is needed:
internal/sanitize: All 7 functions (SanitizeString,SanitizeJSON,RedactSecret,RedactSecretMap,RedactURL,SanitizeArgs,MarshalAndSanitize) are cohesively scoped to data redaction.internal/auth: 8 functions all directly related to authentication header parsing and session ID extraction.internal/envutil: Clean separation betweenenvutil.go(typed env getters),envfile.go(file loading),expand_env_args.go(Docker arg expansion), andgithub.go(GitHub token lookup).internal/config/expand.go: Variable expansion functions are cleanly isolated from validation.internal/jqutil/secure.go: Correctly factors out sharedgojqcompiler options to prevent theinternal/configandinternal/middlewarepackages from independently defining identical options — a good example of proactive de-duplication.internal/util: Reasonable split acrossutil.go(map/JSON helpers),collections.go(slice helpers),format_duration.go(time formatting),random.go(random bytes),truncate.go(string truncation),session.go(session ID formatting — though see Issue Lpcox/initial implementation #3 above).Refactoring Recommendations by Priority
Priority 1 (High Impact)
GenerateSelfSignedTLStohttputil.configureTLSTrustEnvironmentfromcmd/proxy.go→httputil/tls.go.Priority 2 (Medium Impact)
BaseResponseWriteras the canonical embed base; verifystatusResponseWriterintracing/http.goadds no unique behaviour.Priority 3 (Low / Housekeeping)
util/session.go(single function) intoutil/format_duration.goor a newutil/format.go.config_env.gohelpers explaining the intentional layering overenvutil.atomicWriteFilefor export/relocation when a second consumer emerges.Implementation Checklist
configureTLSTrustEnvironmenttohttputil/tls.go(Priority 1)statusResponseWriteris a pure embed and documentBaseResponseWriterintent (Priority 2)util/session.gointoutil/format_duration.go(Priority 3)config_env.go(Priority 3)atomicWriteFileas a future export candidate (Priority 3)Analysis Metadata
configureTLSTrustEnvironment,FormatSessionIDForLog)statusResponseWritervsBaseResponseWriter)References:
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
awmgmcpgSee Network Configuration for more information.