-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Analysis of repository: githubnext/gh-aw-mcpg
Executive Summary
Analyzed 48 non-test Go files across 14 packages containing approximately 362 functions/methods (both exported and unexported). The codebase demonstrates excellent organization with strong use of Go generics, clear separation of concerns, and well-structured packages. Identified 3 actionable refactoring opportunities that can improve code organization and reduce duplication.
Key Findings:
- ✅ Well-organized areas: Logger package (exemplary generics usage), Config package (clear validation separation), DIFC package (modular design)
⚠️ 1 critical duplicate: Shutdown middleware duplicated across 2 files (~95% identical, 13 duplicate lines)- 🔧 2 organizational improvements: Session truncation utility in wrong package, deprecated function still in use (3 call sites)
Function Inventory Summary
By Package
| Package | Files | Functions | Primary Purpose |
|---|---|---|---|
internal/auth |
1 | 4 | Authentication header parsing |
internal/cmd |
2 | 11 | CLI commands (Cobra) |
internal/config |
5 | 45 | Configuration parsing & validation |
internal/difc |
5 | 66 | DIFC security labels |
internal/guard |
4 | 18 | Security guards |
internal/launcher |
2 | 18 | Backend process management |
internal/logger |
11 | 69 | Logging framework |
internal/mcp |
2 | 30 | MCP protocol types |
internal/middleware |
1 | 6 | Request middleware |
internal/server |
9 | 63 | HTTP server |
internal/sys |
1 | 6 | System utilities |
internal/testutil |
4 | 22 | Testing utilities |
internal/timeutil |
1 | 1 | Time formatting |
internal/tty |
2 | 3 | TTY detection |
Total: 48 files, 362 functions/methods
Semantic Clustering Results
Major Function Patterns Identified:
| Pattern | Count | Observation |
|---|---|---|
New* constructors |
25+ | Consistent constructor naming ✓ |
Validation functions (validate*) |
10 | Well-organized in config package ✓ |
Close() methods |
8 | Standard Go interface pattern ✓ |
Logging functions (Log*) |
12 | Properly centralized in logger package ✓ |
Format functions (format*) |
6 | Appropriately distributed by purpose ✓ |
Parse functions (parse*) |
3 | Appropriately distributed ✓ |
| Middleware functions | 6 | In server package, one duplication found |
Identified Issues
1. 🔴 Duplicate Shutdown Middleware (Critical - High Impact)
Issue: Two nearly identical functions for shutdown rejection middleware
Occurrences:
- File 1:
internal/server/routed.go:21-33-rejectIfShutdown() - File 2:
internal/server/transport.go:18-30-rejectIfShutdownUnified()
Code Comparison:
// routed.go:21
func rejectIfShutdown(unifiedServer *UnifiedServer, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if unifiedServer.IsShutdown() {
logRouted.Printf("Rejecting request during shutdown: remote=%s, method=%s, path=%s",
r.RemoteAddr, r.Method, r.URL.Path)
logger.LogWarn("shutdown", "Request rejected during shutdown, remote=%s, path=%s",
r.RemoteAddr, r.URL.Path)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(shutdownErrorJSON))
return
}
next.ServeHTTP(w, r)
})
}
// transport.go:18 - NEARLY IDENTICAL (only debug logger differs: logTransport vs logRouted)
func rejectIfShutdownUnified(unifiedServer *UnifiedServer, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if unifiedServer.IsShutdown() {
logTransport.Printf("Rejecting request during shutdown: remote=%s, method=%s, path=%s",
r.RemoteAddr, r.Method, r.URL.Path)
logger.LogWarn("shutdown", "Request rejected during shutdown, remote=%s, path=%s",
r.RemoteAddr, r.URL.Path)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(shutdownErrorJSON))
return
}
next.ServeHTTP(w, r)
})
}Analysis:
- Similarity: ~95% identical (13 duplicate lines)
- Only difference: Debug logger variable name (
logRoutedvslogTransport) - Both functions: Check shutdown state, return HTTP 503, use same error JSON
- Impact: Code duplication, double maintenance burden
Recommendation:
- Consolidate into single function with logger namespace parameter
- Remove one function and update call sites
- Optional: Create
internal/server/middleware.gofor shared middleware
Implementation Approach:
// Option 1: Single function with logger parameter in routed.go
func rejectIfShutdown(unifiedServer *UnifiedServer, next http.Handler, logNamespace string) http.Handler {
log := logger.New(logNamespace)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if unifiedServer.IsShutdown() {
log.Printf("Rejecting request during shutdown: remote=%s, method=%s, path=%s",
r.RemoteAddr, r.Method, r.URL.Path)
logger.LogWarn("shutdown", "Request rejected during shutdown, remote=%s, path=%s",
r.RemoteAddr, r.URL.Path)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(shutdownErrorJSON))
return
}
next.ServeHTTP(w, r)
})
}
// Update call sites:
// In routed.go: rejectIfShutdown(unifiedServer, handler, "server:routed")
// In transport.go: rejectIfShutdown(unifiedServer, handler, "server:transport")Estimated Impact:
- Eliminates 13 lines of duplicate code
- Single point of maintenance for shutdown logic
- Effort: 20-30 minutes
2. 🟡 Session Truncation Utility in Wrong Package (Medium Priority)
Issue: Session ID truncation utility is in server package but should be in auth package
Occurrence:
- File:
internal/server/sdk_logging.go:144-153 - Function:
truncateSession() - Current usage: Only used within
sdk_logging.go(7 call sites)
Code:
// truncateSession returns a truncated session ID for logging (first 8 chars)
func truncateSession(s string) string {
if s == "" {
return "(none)"
}
if len(s) <= 8 {
return s
}
return s[:8] + "..."
}Problem:
- Session manipulation utility is in server/logging file
- Not reusable by other packages
- Auth package already contains session handling (
ExtractSessionID,ExtractAgentID) - Violates "one file per feature" principle - auth concerns in server package
Recommendation:
- Move to
internal/auth/header.goas public functionTruncateSessionID(sessionID string) string - Update import in
sdk_logging.goto useauth.TruncateSessionID() - Make it exportable for reuse across packages
Implementation:
// In internal/auth/header.go - add new exported function
// TruncateSessionID returns a truncated session ID for safe logging (first 8 chars).
// Returns "(none)" for empty session IDs, and appends "..." for truncated values.
func TruncateSessionID(sessionID string) string {
if sessionID == "" {
return "(none)"
}
if len(sessionID) <= 8 {
return sessionID
}
return sessionID[:8] + "..."
}
// In internal/server/sdk_logging.go - update all 7 usages:
// Before: truncateSession(sessionID)
// After: auth.TruncateSessionID(sessionID)Benefits:
- Centralizes all session-related operations in auth package
- Makes utility discoverable and reusable
- Follows Go best practice of grouping related functionality
- Effort: 15-20 minutes
3. 🟢 Deprecated Function Still In Use (Low Priority - Technical Debt)
Issue: Function marked as deprecated but still actively used in 3 locations
Deprecated Function:
- File:
internal/server/auth.go:45-53 - Function:
extractSessionFromAuth() - Status: Marked deprecated, delegating to
auth.ExtractSessionID()
Code:
// extractSessionFromAuth extracts session ID from Authorization header.
// This function delegates to auth.ExtractSessionID for consistent session ID extraction.
// Per spec 7.1: When API key is configured, Authorization contains plain API key.
// When API key is not configured, supports Bearer token for backward compatibility.
//
// Deprecated: Use auth.ExtractSessionID directly instead.
func extractSessionFromAuth(authHeader string) string {
return auth.ExtractSessionID(authHeader)
}Current Usages:
internal/server/sdk_logging.go:48-sessionID := extractSessionFromAuth(authHeader)internal/server/routed.go:112-sessionID := extractSessionFromAuth(authHeader)internal/server/transport.go:94-sessionID := extractSessionFromAuth(authHeader)
Recommendation:
- Replace all 3 usages with direct calls to
auth.ExtractSessionID(authHeader) - Remove deprecated wrapper function from
auth.go - Verify no other usages exist
Implementation:
// Replace in sdk_logging.go:48, routed.go:112, transport.go:94:
- sessionID := extractSessionFromAuth(authHeader)
+ sessionID := auth.ExtractSessionID(authHeader)
// Then delete the deprecated function from internal/server/auth.go:45-53Benefits:
- Removes technical debt
- Simplifies codebase (eliminates unnecessary indirection)
- Follows deprecation best practice
- Effort: 10-15 minutes
Well-Organized Areas ✅
Logger Package - Exemplary Use of Go Generics
Files: internal/logger/global_helpers.go, internal/logger/common.go
The logger package demonstrates excellent use of Go 1.18+ generics to eliminate code duplication:
// Generic helper for initializing any logger type
func initGlobalLogger[T closableLogger](mu *sync.RWMutex, current *T, newLogger T) {
mu.Lock()
defer mu.Unlock()
if *current != nil {
(*current).Close()
}
*current = newLogger
}
// Generic helper for closing any logger type
func closeGlobalLogger[T closableLogger](mu *sync.RWMutex, logger *T) error {
mu.Lock()
defer mu.Unlock()
if *logger != nil {
err := (*logger).Close()
var zero T
*logger = zero
return err
}
return nil
}
// Constraint that works with FileLogger, JSONLLogger, MarkdownLogger
type closableLogger interface {
*FileLogger | *JSONLLogger | *MarkdownLogger
Close() error
}Impact: Eliminates duplication across 3 logger types with type-safe generics ✅
Note: This is an excellent example of modern Go best practices and should serve as a model for similar patterns elsewhere in the codebase.
Config Package - Clear Separation of Concerns
Files:
internal/config/validation.go- General validation logic (10 functions)internal/config/validation_env.go- Environment-specific validation (13 functions)internal/config/validation_schema.go- JSON schema validation (8 functions)internal/config/rules/rules.go- Validation error rules (8 functions)
Organization: Well-structured with clear boundaries between:
- General validation (server config, mounts, custom schemas)
- Environment validation (Docker, container detection, port mapping)
- Schema validation (JSON schema, string patterns)
- Error formatting (consistent error messages with JSON paths)
Impact: Clear file organization makes validation logic easy to find and maintain ✅
DIFC Package - Excellent Modular Design
Files:
internal/difc/agent.go- Agent label management (4 functions)internal/difc/capabilities.go- Capability operations (1 function)internal/difc/evaluator.go- Flow evaluation (2 functions)internal/difc/labels.go- Label operations (5 functions)internal/difc/resource.go- Resource labeling (3 functions)
Organization: Clear separation by responsibility, each file has a single, well-defined purpose ✅
Analysis of Function Name Patterns
Analyzed common function name patterns to distinguish between appropriate interface usage vs. problematic duplication:
Standard Go Interface Methods (Expected) ✅
| Method/Pattern | Occurrences | Explanation |
|---|---|---|
Close() |
8 different types | Standard io.Closer interface - proper pattern |
New* constructors |
25+ | Standard Go constructor pattern - proper pattern |
| HTTP handlers | 6 | Standard http.Handler interface - proper pattern |
| Validation functions | 10 | All in config package - proper organization |
| Logging functions | 12 | All in logger package - proper centralization |
Conclusion: These are appropriate uses of Go's type system and interface patterns, not problematic duplication. The codebase correctly implements Go idioms.
Additional Observations
Positive Patterns Identified
- Consistent Constructor Naming: All packages use
New*pattern for constructors (25+ instances) - Proper Interface Implementation: Standard Go interfaces (
Close(),http.Handler) correctly implemented - Clear Package Boundaries: Each package has a well-defined responsibility
- Modern Go Features: Excellent use of generics in logger package
- Test Coverage: Comprehensive test files for all packages
No Issues Found
- ❌ No scattered helper functions - utilities are properly centralized
- ❌ No misplaced validation logic - all validation in config package
- ❌ No format/parse duplication - each serves a specific purpose
- ❌ No generic opportunities missed - already using generics effectively in logger
Refactoring Recommendations
Priority 1: Quick Wins (45-70 minutes total)
-
✅ Consolidate Duplicate Shutdown Middleware (20-30 min)
- Merge
rejectIfShutdownandrejectIfShutdownUnifiedinto single function - Add logger namespace parameter to distinguish call sites
- Update 2 call sites in
routed.goandtransport.go - Benefits: Eliminates 13 lines of duplicate code, single maintenance point
- Risk: Low - pure refactoring with no logic changes
- Merge
-
✅ Move Session Truncation to Auth Package (15-20 min)
- Move
truncateSessiontointernal/auth/header.goasTruncateSessionID() - Update 7 call sites in
sdk_logging.go - Add proper godoc comment
- Benefits: Better organization, reusable utility, follows Go conventions
- Risk: Low - simple function move
- Move
-
✅ Remove Deprecated Wrapper (10-15 min)
- Replace 3 usages of
extractSessionFromAuthwith directauth.ExtractSessionIDcalls - Remove deprecated function from
auth.go - Benefits: Removes technical debt, simplifies code
- Risk: Low - already marked deprecated
- Replace 3 usages of
Total Estimated Effort: 45-70 minutes
Priority 2: Optional Enhancements (Future Consideration)
- Consider Creating Dedicated Middleware File (optional, 1-2 hours)
- If more middleware functions are added in the future, consider creating
internal/server/middleware.go - Would contain:
rejectIfShutdown,authMiddleware,withResponseLogging - Benefits: Clearer organization, all middleware in one place
- Note: Not necessary at current scale (only 3 middleware functions)
- If more middleware functions are added in the future, consider creating
Implementation Checklist
Priority 1 Tasks (Recommended)
-
Issue Configure as a Go CLI tool #1: Consolidate shutdown middleware
- Create unified
rejectIfShutdownfunction with logger parameter - Update call site in
routed.go:CreateHTTPServerForRoutedMode - Update call site in
transport.go:CreateHTTPServerForMCP - Remove duplicate
rejectIfShutdownUnifiedfunction - Run
make test-allto verify
- Create unified
-
Issue Lpcox/initial implementation #2: Move session truncation to auth package
- Add
TruncateSessionID()tointernal/auth/header.go - Update 7 usages in
sdk_logging.go - Remove private
truncateSessionfunction - Run
make test-allto verify
- Add
-
Issue Lpcox/initial implementation #3: Remove deprecated wrapper
- Replace usage in
sdk_logging.go:48 - Replace usage in
routed.go:112 - Replace usage in
transport.go:94 - Delete deprecated function from
auth.go:45-53 - Run
make test-allto verify
- Replace usage in
Verification
- Run full test suite:
make test-all - Verify no functionality broken
- Run linting:
make lint - Check formatting:
make format - Final verification:
make agent-finished
Priority 2 Tasks (Optional - Future)
- Monitor for additional middleware functions
- Consider creating
middleware.goif 5+ middleware functions exist
Analysis Metadata
- Repository: githubnext/gh-aw-mcpg
- Total Go Files Analyzed: 48 (excluding test files)
- Total Functions Cataloged: 362 (both exported and unexported)
- Packages Analyzed: 14 (
auth,cmd,config,difc,guard,launcher,logger,mcp,middleware,server,sys,testutil,timeutil,tty) - Duplicate Code Issues: 1 (shutdown middleware - 13 duplicate lines)
- Organizational Issues: 2 (session truncation placement, deprecated wrapper usage)
- Well-Organized Packages: Logger (exemplary generics), Config (clear separation), DIFC (modular)
- Detection Method: Static code analysis + manual semantic review + function inventory
- Analysis Date: 2026-01-26
- Overall Assessment: 🟢 Excellent - Minor improvements available, codebase is well-structured
- Estimated Total Refactoring Time: 45-70 minutes for Priority 1 items
Conclusion
This codebase demonstrates strong engineering practices with:
- ✅ Excellent use of Go generics to eliminate duplication (logger package)
- ✅ Clear separation of concerns (config validation, DIFC security)
- ✅ Appropriate interface patterns (Close methods, constructors, HTTP handlers)
- ✅ Well-organized package structure (14 packages with clear responsibilities)
- ✅ Consistent naming conventions (
New*,validate*,Log*)
The identified refactoring opportunities are minor organizational improvements rather than critical issues. All 3 issues are low-risk, high-value changes that can be completed in under an hour. The code is already in excellent shape.
Recommendation: Implement Priority 1 items (45-70 minutes total effort) for immediate code quality improvements. Priority 2 items are optional and only needed if the codebase grows significantly.
References:
- Workflow Run: §21359589137
- Configuration Reference: MCP Gateway Configuration
AI generated by Semantic Function Refactoring