Full Report
Function Inventory
By Package
| Package |
Files |
Primary Purpose |
internal/auth |
1 |
Auth header parsing |
internal/cmd |
11 |
CLI (Cobra) commands & flags |
internal/config |
12 |
Config parsing, validation, guard policy |
internal/difc |
8 |
Decentralized Information Flow Control |
internal/envutil |
4 |
Environment variable utilities |
internal/guard |
10 |
Security guards (Noop, Wasm, WriteSink) |
internal/httputil |
2 |
Shared HTTP helpers |
internal/launcher |
4 |
Backend process management |
internal/logger |
14 |
Debug logging framework |
internal/mcp |
10 |
MCP protocol types & transport |
internal/middleware |
1 |
jq schema processing middleware |
internal/oidc |
1 |
GitHub Actions OIDC provider |
internal/proxy |
6 |
GitHub API filtering proxy |
internal/server |
17 |
HTTP server (routed/unified modes) |
internal/strutil |
4 |
String & formatting utilities |
internal/syncutil |
1 |
Concurrency utilities |
internal/sys |
2 |
System utilities |
internal/testutil/mcptest |
4 |
Test utilities |
internal/tracing |
2 |
OpenTelemetry tracing |
internal/tty |
1 |
Terminal detection |
internal/version |
1 |
Version management |
Identified Issues
1. Outlier: SessionSuffix in internal/logger/session_helpers.go
File: internal/logger/session_helpers.go
Function: SessionSuffix(sessionID string) string
Issue: This is a pure string formatting utility with no dependency on any logger types. It formats a session ID into a log suffix string (" for session '<id>'") and resides in the logger package only because it's used in log messages, but it has no logger-specific knowledge.
// Current location: internal/logger/session_helpers.go
func SessionSuffix(sessionID string) string {
if sessionID == "" {
return ""
}
return fmt.Sprintf(" for session '%s'", sessionID)
}
Callers (all in non-logger packages):
internal/mcp/errors.go
internal/launcher/log_helpers.go (3 usages)
Recommendation: Move SessionSuffix to internal/strutil/ as a general string formatting utility, or inline at the 4 call sites (the function body is trivial). If kept in logger, the file is appropriately named but callers outside the package create a cross-package dependency on a string-only utility.
Estimated Impact: Low — purely organizational, no functional change.
2. Near-Duplicate Domain: Rate-Limit Reset Parsing
Files:
internal/httputil/github_http.go — ParseRateLimitResetHeader(value string) time.Time
internal/server/circuit_breaker.go — parseRateLimitResetFromText(text string) time.Time
Issue: Rate-limit parsing logic is split across two packages. Both functions translate GitHub rate limit signals into time.Time values but handle different input formats:
// internal/httputil/github_http.go — parses Unix timestamp from HTTP header
func ParseRateLimitResetHeader(value string) time.Time { ... }
// internal/server/circuit_breaker.go — parses "rate reset in Ns" text pattern
func parseRateLimitResetFromText(text string) time.Time { ... }
Recommendation: Consider moving parseRateLimitResetFromText to internal/httputil/github_http.go (or a new internal/httputil/ratelimit.go) to centralize all rate limit time parsing in one place. They serve the same conceptual purpose and centralizing them improves discoverability.
Estimated Impact: Medium — improves cohesion of rate limit utilities.
3. Outlier: ensureTracingConfig in internal/cmd/root.go
File: internal/cmd/root.go
Function: ensureTracingConfig(cfg *config.Config) *config.TracingConfig
Issue: A tracing-specific helper living in root.go alongside CLI root command wiring. The cmd package already has internal/cmd/tracing.go specifically for tracing-related setup logic (initTracingProviderWithFallback, registerTracingFlags, shutdownTracingProviderWithTimeout).
// Current location: internal/cmd/root.go
func ensureTracingConfig(cfg *config.Config) *config.TracingConfig {
if cfg.Gateway.Tracing == nil {
cfg.Gateway.Tracing = &config.TracingConfig{}
}
return cfg.Gateway.Tracing
}
Recommendation: Move ensureTracingConfig to internal/cmd/tracing.go where the other tracing initialization functions reside.
Estimated Impact: Low — small organization improvement, no functional change.
4. Outlier: clientAddr in internal/cmd/proxy.go
File: internal/cmd/proxy.go
Function: clientAddr(addr string) string
Issue: A general-purpose address normalization utility (converts 0.0.0.0:port to localhost:port) embedded in the proxy command file. This is a network string utility with no inherent coupling to proxy command logic.
func clientAddr(addr string) string {
host, port, err := net.SplitHostPort(addr)
...
switch host {
case "", "0.0.0.0", "::", "[::]":
return net.JoinHostPort("localhost", port)
}
...
}
Recommendation: If the utility could be useful elsewhere, move to internal/httputil/httputil.go. If it's truly proxy-command-specific, it's acceptable where it is.
Estimated Impact: Low — minor organization concern.
Clustering Results
Well-Organized Clusters ✓
The following clusters are well-organized and require no changes:
- Validation cluster (
internal/config/validation*.go, guard_policy_validation.go): 27 validate* functions cleanly distributed across purpose-specific files.
- Parsing cluster (
internal/config/guard_policy_parse.go): Parse* functions for guard policies co-located.
- DIFC cluster (
internal/difc/): Labels, agents, evaluator, capabilities all in separate, clearly-named files.
- Strutil cluster (
internal/strutil/): Truncate, FormatDuration, DeduplicateStrings, RandomHex — each in its own file, all pure string utilities.
- Logger cluster (
internal/logger/): Extensive but well-separated: file_logger.go, jsonl_logger.go, markdown_logger.go, rpc_formatter.go, rpc_helpers.go, etc.
- Server cluster (
internal/server/): Clear purpose per file — auth.go, circuit_breaker.go, hmac.go, session.go, transport.go, etc.
No Significant Duplicates Detected
ParseRateLimitResetHeader and parseRateLimitResetFromText parse different input formats — near-duplicate in domain but not in implementation.
requireSession in internal/mcp/connection.go and internal/server/session.go serve different layers (MCP protocol vs. HTTP session management) — not duplicates.
Truncate* functions: strutil.Truncate (general), TruncateSessionID (auth-specific), TruncateSecret (sanitization) — each has a distinct concern.
- Multiple
init() functions (11 total) — idiomatic Go for flag registration; not an issue.
Refactoring Recommendations
Priority 1: Low Effort, Organizational Clarity
-
Move ensureTracingConfig from cmd/root.go → cmd/tracing.go
- All tracing lifecycle functions in one place
- Estimated effort: 5 minutes
-
Move parseRateLimitResetFromText from server/circuit_breaker.go → httputil/github_http.go
- Centralizes rate limit parsing utilities
- Estimated effort: 15 minutes
Priority 2: Evaluate and Decide
-
SessionSuffix location: Decide whether to keep in logger (acceptable if only used for logging), move to strutil, or inline at call sites.
-
clientAddr location: If proxy command is the only consumer, acceptable where it is. If useful elsewhere, move to httputil.
Implementation Checklist
Analysis Metadata
| Metric |
Value |
| Total Go Files Analyzed |
127 |
| Total Functions/Methods Cataloged |
801 |
| Packages Analyzed |
23 |
| Function Clusters Identified |
7 major clusters |
| Outliers Found |
4 |
| Duplicates Detected |
0 exact, 1 near-duplicate domain |
| Detection Method |
Naming pattern analysis + cross-package reference tracing |
| Analysis Date |
2026-05-08 |
Analysis of repository: github/gh-aw-mcpg
Executive Summary
Analyzed 127 non-test Go source files across 23 packages in
internal/, cataloging 801 functions and methods. The codebase is generally well-organized with clear separation of concerns. This analysis identified 4 notable outlier functions and 1 near-duplicate rate-limit parsing pattern. No major structural issues were found — the findings below are targeted, actionable improvements.Full Report
Function Inventory
By Package
internal/authinternal/cmdinternal/configinternal/difcinternal/envutilinternal/guardinternal/httputilinternal/launcherinternal/loggerinternal/mcpinternal/middlewareinternal/oidcinternal/proxyinternal/serverinternal/strutilinternal/syncutilinternal/sysinternal/testutil/mcptestinternal/tracinginternal/ttyinternal/versionIdentified Issues
1. Outlier:
SessionSuffixininternal/logger/session_helpers.goFile:
internal/logger/session_helpers.goFunction:
SessionSuffix(sessionID string) stringIssue: This is a pure string formatting utility with no dependency on any logger types. It formats a session ID into a log suffix string (
" for session '<id>'") and resides in theloggerpackage only because it's used in log messages, but it has no logger-specific knowledge.Callers (all in non-logger packages):
internal/mcp/errors.gointernal/launcher/log_helpers.go(3 usages)Recommendation: Move
SessionSuffixtointernal/strutil/as a general string formatting utility, or inline at the 4 call sites (the function body is trivial). If kept inlogger, the file is appropriately named but callers outside the package create a cross-package dependency on a string-only utility.Estimated Impact: Low — purely organizational, no functional change.
2. Near-Duplicate Domain: Rate-Limit Reset Parsing
Files:
internal/httputil/github_http.go—ParseRateLimitResetHeader(value string) time.Timeinternal/server/circuit_breaker.go—parseRateLimitResetFromText(text string) time.TimeIssue: Rate-limit parsing logic is split across two packages. Both functions translate GitHub rate limit signals into
time.Timevalues but handle different input formats:Recommendation: Consider moving
parseRateLimitResetFromTexttointernal/httputil/github_http.go(or a newinternal/httputil/ratelimit.go) to centralize all rate limit time parsing in one place. They serve the same conceptual purpose and centralizing them improves discoverability.Estimated Impact: Medium — improves cohesion of rate limit utilities.
3. Outlier:
ensureTracingConfigininternal/cmd/root.goFile:
internal/cmd/root.goFunction:
ensureTracingConfig(cfg *config.Config) *config.TracingConfigIssue: A tracing-specific helper living in
root.goalongside CLI root command wiring. Thecmdpackage already hasinternal/cmd/tracing.gospecifically for tracing-related setup logic (initTracingProviderWithFallback,registerTracingFlags,shutdownTracingProviderWithTimeout).Recommendation: Move
ensureTracingConfigtointernal/cmd/tracing.gowhere the other tracing initialization functions reside.Estimated Impact: Low — small organization improvement, no functional change.
4. Outlier:
clientAddrininternal/cmd/proxy.goFile:
internal/cmd/proxy.goFunction:
clientAddr(addr string) stringIssue: A general-purpose address normalization utility (converts
0.0.0.0:porttolocalhost:port) embedded in the proxy command file. This is a network string utility with no inherent coupling to proxy command logic.Recommendation: If the utility could be useful elsewhere, move to
internal/httputil/httputil.go. If it's truly proxy-command-specific, it's acceptable where it is.Estimated Impact: Low — minor organization concern.
Clustering Results
Well-Organized Clusters ✓
The following clusters are well-organized and require no changes:
internal/config/validation*.go,guard_policy_validation.go): 27validate*functions cleanly distributed across purpose-specific files.internal/config/guard_policy_parse.go):Parse*functions for guard policies co-located.internal/difc/): Labels, agents, evaluator, capabilities all in separate, clearly-named files.internal/strutil/):Truncate,FormatDuration,DeduplicateStrings,RandomHex— each in its own file, all pure string utilities.internal/logger/): Extensive but well-separated:file_logger.go,jsonl_logger.go,markdown_logger.go,rpc_formatter.go,rpc_helpers.go, etc.internal/server/): Clear purpose per file —auth.go,circuit_breaker.go,hmac.go,session.go,transport.go, etc.No Significant Duplicates Detected
ParseRateLimitResetHeaderandparseRateLimitResetFromTextparse different input formats — near-duplicate in domain but not in implementation.requireSessionininternal/mcp/connection.goandinternal/server/session.goserve different layers (MCP protocol vs. HTTP session management) — not duplicates.Truncate*functions:strutil.Truncate(general),TruncateSessionID(auth-specific),TruncateSecret(sanitization) — each has a distinct concern.init()functions (11 total) — idiomatic Go for flag registration; not an issue.Refactoring Recommendations
Priority 1: Low Effort, Organizational Clarity
Move
ensureTracingConfigfromcmd/root.go→cmd/tracing.goMove
parseRateLimitResetFromTextfromserver/circuit_breaker.go→httputil/github_http.goPriority 2: Evaluate and Decide
SessionSuffixlocation: Decide whether to keep inlogger(acceptable if only used for logging), move tostrutil, or inline at call sites.clientAddrlocation: If proxy command is the only consumer, acceptable where it is. If useful elsewhere, move tohttputil.Implementation Checklist
ensureTracingConfigtointernal/cmd/tracing.goparseRateLimitResetFromTexttointernal/httputil/github_http.go(or newratelimit.go)SessionSuffixplacement — inline, move to strutil, or accept in loggerclientAddrplacement — accept in proxy.go or move to httputilmake agent-finishedafter any changesAnalysis Metadata