Skip to content

[Repo Assist] feat(envutil): add GetEnvDuration + configurable MCP_GATEWAY_SESSION_TIMEOUT#3068

Merged
lpcox merged 1 commit intomainfrom
repo-assist/feat-session-timeout-configurable-2026-04-02-444de2699857cab5
Apr 3, 2026
Merged

[Repo Assist] feat(envutil): add GetEnvDuration + configurable MCP_GATEWAY_SESSION_TIMEOUT#3068
lpcox merged 1 commit intomainfrom
repo-assist/feat-session-timeout-configurable-2026-04-02-444de2699857cab5

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 2, 2026

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Adds GetEnvDuration to internal/envutil (consistent with existing GetEnvString/GetEnvInt/GetEnvBool), and uses it to make the unified-mode MCP session timeout configurable via the MCP_GATEWAY_SESSION_TIMEOUT environment variable.

Motivation

The session timeout in server/transport.go was hardcoded at 2 hours with a comment "2h accommodates long-running workflows with idle periods". While the default is good, operators may need to:

  • Shorten it for tighter security postures or faster-cycling workflows
  • Lengthen it for unusually long-running agentic sessions

This was identified as a best-practice alignment item in the go-sdk module review (#3054).

Changes

internal/envutil/envutil.go

// GetEnvDuration returns the time.Duration value of the environment variable specified by envKey.
// If the environment variable is not set, is empty, or cannot be parsed by time.ParseDuration,
// it returns the defaultValue. Accepts any string valid for time.ParseDuration (e.g. "2h", "30m", "90s").
func GetEnvDuration(envKey string, defaultValue time.Duration) time.Duration {
    if envValue := os.Getenv(envKey); envValue != "" {
        if d, err := time.ParseDuration(envValue); err == nil && d > 0 {
            return d
        }
    }
    return defaultValue
}

internal/server/transport.go

SessionTimeout: envutil.GetEnvDuration("MCP_GATEWAY_SESSION_TIMEOUT", 2*time.Hour),

internal/envutil/envutil_test.go

9 table-driven test cases covering: valid durations ("2h", "30m", "90s", "1h30m"), missing env var, empty string, invalid string, zero duration, and negative duration. Plus a real-world scenario test for MCP_GATEWAY_SESSION_TIMEOUT.

Usage

# Shorten session timeout to 30 minutes
MCP_GATEWAY_SESSION_TIMEOUT=30m ./awmg --config config.toml

# Extend to 4 hours for long-running workflows
MCP_GATEWAY_SESSION_TIMEOUT=4h ./awmg --config config.toml

# Default (2h) - no change in behavior if env var is unset
./awmg --config config.toml

Invalid, zero, or negative values fall back to the 2h default silently.

Test Status

⚠️ Infrastructure limitation: The CI build environment cannot download Go modules (network proxy access is blocked), so make agent-finished could not be run. The changes are:

  • Syntactically valid (gofmt clean on all changed files)
  • The GetEnvDuration implementation follows the identical pattern as GetEnvInt (which is well-tested and in production use)
  • Tests are table-driven and follow the same structure as existing envutil tests

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@851905c06e905bf362a9f6cc54f912e3df747d55

Add GetEnvDuration to envutil, consistent with GetEnvString/GetEnvInt/GetEnvBool.
Use it in server/transport.go to make the unified-mode session timeout
configurable via MCP_GATEWAY_SESSION_TIMEOUT (default: 2h).

Previously the 2h timeout was hardcoded. Operators with tighter security
requirements or faster workflows can now shorten it without recompiling.

Format: any string accepted by time.ParseDuration, e.g. '30m', '1h', '4h'.
Invalid/zero/negative values fall back to the 2h default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lpcox lpcox marked this pull request as ready for review April 3, 2026 03:57
Copilot AI review requested due to automatic review settings April 3, 2026 03:57
@lpcox lpcox merged commit 27f4460 into main Apr 3, 2026
3 checks passed
@lpcox lpcox deleted the repo-assist/feat-session-timeout-configurable-2026-04-02-444de2699857cab5 branch April 3, 2026 03:57
Copy link
Copy Markdown
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

Adds a new environment helper to parse time.Duration values and uses it to make the MCP Streamable HTTP session timeout configurable via MCP_GATEWAY_SESSION_TIMEOUT (default remains 2h).

Changes:

  • Add envutil.GetEnvDuration (patterned after existing envutil helpers).
  • Wire MCP_GATEWAY_SESSION_TIMEOUT into sdk.StreamableHTTPOptions.SessionTimeout.
  • Add table-driven unit tests for duration parsing and fallback behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
internal/envutil/envutil.go Introduces GetEnvDuration for parsing positive durations from env vars.
internal/server/transport.go Uses GetEnvDuration to configure MCP session timeout via MCP_GATEWAY_SESSION_TIMEOUT.
internal/envutil/envutil_test.go Adds unit tests covering valid/invalid duration env values and a session-timeout scenario.

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

Comment on lines +32 to +38
// GetEnvDuration returns the time.Duration value of the environment variable specified by envKey.
// If the environment variable is not set, is empty, or cannot be parsed by time.ParseDuration,
// it returns the defaultValue. Accepts any string valid for time.ParseDuration (e.g. "2h", "30m", "90s").
func GetEnvDuration(envKey string, defaultValue time.Duration) time.Duration {
if envValue := os.Getenv(envKey); envValue != "" {
if d, err := time.ParseDuration(envValue); err == nil && d > 0 {
return d
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The docstring says this falls back only when the env var is unset/empty or cannot be parsed, but the implementation also falls back when the parsed duration is non-positive (d <= 0). Please update the comment to mention the > 0 requirement (similar to GetEnvInt) so behavior and docs match.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +101
t.Run(tt.name, func(t *testing.T) {
os.Unsetenv(tt.envKey)
defer os.Unsetenv(tt.envKey)

if tt.setEnv {
os.Setenv(tt.envKey, tt.envValue)
}

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

Tests are manually setting/unsetting environment variables via os.Unsetenv/os.Setenv. The repo frequently uses testing.T.Setenv for this (e.g., internal/sys/container_test.go:12-68), which automatically restores env vars via t.Cleanup and is safer if tests ever become parallelized. Consider switching these cases to t.Setenv (and avoiding manual Unsetenv/defer).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants