Documentation
¶
Overview ¶
Package sessionmanager provides session lifecycle management for sessionManagementV2.
This package implements the two-phase session creation pattern that bridges the MCP SDK's session management with the vMCP server's backend lifecycle:
- Phase 1 (Generate): Creates a placeholder session with no context
- Phase 2 (CreateSession): Replaces placeholder with fully-initialized MultiSession
The Manager type implements the server.SessionManager interface and is used by the server package when SessionManagementV2 is enabled.
Index ¶
- Constants
- type Manager
- func (sm *Manager) CreateSession(ctx context.Context, sessionID string) (vmcpsession.MultiSession, error)
- func (sm *Manager) Generate() string
- func (sm *Manager) GetAdaptedTools(sessionID string) ([]mcpserver.ServerTool, error)
- func (sm *Manager) GetMultiSession(sessionID string) (vmcpsession.MultiSession, bool)
- func (sm *Manager) Terminate(sessionID string) (isNotAllowed bool, err error)
- func (sm *Manager) Validate(sessionID string) (isTerminated bool, err error)
Constants ¶
const ( // MetadataKeyTerminated is the session metadata key that marks a placeholder // session as explicitly terminated by the client. MetadataKeyTerminated = "terminated" // MetadataValTrue is the string value stored under MetadataKeyTerminated // when a session has been terminated. MetadataValTrue = "true" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager bridges the domain session lifecycle (MultiSession / MultiSessionFactory) to the mark3labs SDK's SessionIdManager interface.
It implements a two-phase session-creation pattern:
- Generate(): called by SDK during initialize without context; stores an empty placeholder via transportsession.Manager.
- CreateSession(): called from OnRegisterSession hook once context is available; calls factory.MakeSessionWithID(), then replaces the placeholder with the fully-formed MultiSession.
All session storage is delegated to transportsession.Manager — no separate sync.Map or secondary store is maintained. The MultiSession itself implements transportsession.Session and is stored directly in the transport Manager.
Storage backend scope: the transportsession.Manager's pluggable backend (including Redis if configured) handles session metadata and TTL lifecycle. However, MultiSession holds live in-process state (backend HTTP connections, routing table) that cannot be serialized or transferred across processes. Sessions are therefore node-local: pluggable backends provide metadata durability, but a session can only be served by the process that created it. Horizontal scaling requires sticky routing (e.g., session-affinity load balancing) — cross-node reconstruction is not implemented.
func New ¶
func New( storage *transportsession.Manager, factory vmcpsession.MultiSessionFactory, backendRegistry vmcp.BackendRegistry, ) *Manager
New creates a Manager backed by the given transport manager, session factory, and backend registry.
func (*Manager) CreateSession ¶
func (sm *Manager) CreateSession( ctx context.Context, sessionID string, ) (vmcpsession.MultiSession, error)
CreateSession is Phase 2 of the two-phase creation pattern.
It is called from the OnRegisterSession hook once the request context is available. It:
- Resolves the caller identity from the context.
- Lists available backends from the registry.
- Calls MultiSessionFactory.MakeSessionWithID() to build a fully-formed MultiSession (which opens real HTTP connections to each backend).
- Replaces the placeholder stored by Generate() with the new MultiSession.
The returned MultiSession can be retrieved later via GetMultiSession().
func (*Manager) Generate ¶
Generate implements the SDK's SessionIdManager.Generate().
Phase 1 of the two-phase creation pattern: creates a unique session ID, stores an empty placeholder via transportsession.Manager.AddWithID(), and returns the ID to the SDK. No context is available at this point.
The placeholder is replaced by CreateSession() in Phase 2 once context is available via the OnRegisterSession hook.
func (*Manager) GetAdaptedTools ¶
func (sm *Manager) GetAdaptedTools(sessionID string) ([]mcpserver.ServerTool, error)
GetAdaptedTools returns SDK-format tools for the given session, with handlers that delegate tool invocations directly to the session's CallTool() method.
This enables session-scoped routing: each tool call goes through the session's backend connections rather than the global router.
func (*Manager) GetMultiSession ¶
func (sm *Manager) GetMultiSession(sessionID string) (vmcpsession.MultiSession, bool)
GetMultiSession retrieves the fully-formed MultiSession for a given SDK session ID. Returns (nil, false) if the session does not exist or has not yet been upgraded from placeholder to MultiSession.
func (*Manager) Terminate ¶
Terminate implements the SDK's SessionIdManager.Terminate().
The two session types are handled asymmetrically to prevent a race condition where client termination during the Phase 1→Phase 2 window could resurrect sessions with open backend connections:
MultiSession (Phase 2): Close() releases backend connections, then the session is deleted from storage immediately. After deletion Validate() returns (false, error) — the same response as "never existed". This is intentional: a terminated MultiSession has no resources to preserve, so immediate removal is cleaner than marking and waiting for TTL.
Placeholder (Phase 1): the session is marked terminated=true and left for TTL cleanup. This prevents CreateSession() from opening backend connections for an already-terminated session (see fast-fail check in CreateSession at lines 142-147). The terminated flag also lets Validate() return (isTerminated=true, nil) during the window between termination and TTL expiry, allowing the SDK to distinguish "actively terminated" from "never existed".
Returns (isNotAllowed=false, nil) on success; client termination is always permitted.
func (*Manager) Validate ¶
Validate implements the SDK's SessionIdManager.Validate().
Returns (isTerminated=true, nil) for explicitly terminated sessions. Returns (false, error) for unknown sessions — per the SDK interface contract, a lookup failure is signalled via err, not via isTerminated. Returns (false, nil) for valid, active sessions.