Skip to content

Add configurable idle timeout for persistent named sessions #311

Description

@0xdevalias

Problem

Named @sessions are persistent: each keeps a bridge (and, for stdio, the MCP server child process) alive until the session is explicitly closed. This is useful for repeated calls, but it can leave one idle MCP process running for every consumer context.

One concrete use case is Codex skills that invoke an MCP server on demand through mcpc. Calls often arrive in short bursts, so keeping the connection warm briefly is useful; keeping one MCP process alive indefinitely for every Codex thread is not.

The existing --timeout is a per-request timeout, so this should use distinct terminology.

Proposed interface

mcpc connect <server> @session --idle-timeout 600

--idle-timeout is expressed in seconds and is persisted with the named session, like other connection settings that survive bridge restart/reconnect.

  • Omission or --idle-timeout 0: preserve the current unlimited lifetime.
  • A positive value: after that many seconds without user-issued MCP activity, gracefully close the MCP transport and any stdio server child process, then exit the bridge.
  • Retain the named session and its configuration after idle shutdown. Mark it as intentionally idle/stopped rather than crashed so background crash recovery does not immediately restart it; the next user operation should start its bridge on demand.

Activity semantics

  • Count user-issued MCP operations as activity, including an explicit user ping.
  • Do not count internal keepalive/health pings, passive server notifications, notification-triggered cache refreshes or resource sync, or other housekeeping traffic.
  • Never expire while one or more user operations are in flight. Once the last active operation completes, start a fresh idle period.

This likely needs a user-activity timestamp separate from lastSeenAt, because lastSeenAt currently records successful keepalive pings as well as commands.

Flag placement

connect seems like the natural public entry point because it creates/configures a named session, and the timeout belongs to that persisted session configuration. Restart and automatic reconnect should reuse the saved value without requiring the flag again. If there is a better internal configuration boundary, the important behavior is that the value is set when creating/configuring the named session and persists with it.

Suggested acceptance matrix

Case Expected result
Flag omitted Existing unlimited-lifetime behavior
--idle-timeout 0 Same unlimited-lifetime behavior
Positive timeout, no user activity Transport and child process close gracefully after the timeout; named session remains available for on-demand reuse
User operation before deadline Idle deadline resets after the operation completes
Operation runs past deadline Session stays alive until the operation completes, then receives a fresh full idle period
Concurrent operations Session cannot expire until all user operations have completed
Internal keepalive ping Does not reset the idle deadline
Passive notification / housekeeping refresh Does not reset the idle deadline
Explicit user ping Does reset the idle deadline
Bridge restart/reconnect Persisted timeout is retained
Next command after idle shutdown Bridge/transport starts on demand and the command succeeds
HTTP and stdio transports HTTP closes cleanly; stdio also terminates its server child process

Drafted by Codex (GPT 5.6 Sol Medium) at my request, and reviewed by me before posting

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions