module documentation

Worker-side MCP activities and a pooled-connection subsystem.

The Gemini SDK's automatic-function-calling loop runs inside the workflow, where it would otherwise call McpClientSession.list_tools / call_tool directly (network I/O — forbidden in a workflow). The workflow-side TemporalMcpClientSession shim redirects those two methods to the {server}-list-tools / {server}-call-tool activities defined here, so the real mcp.ClientSession lives only on the worker.

A single live session per server is held open in the worker process and reused across activity invocations, with idle eviction — modeled on the strands plugin's _temporal_mcp_client. The MCP transport and ClientSession are anyio context managers whose cancel scope is bound to the task that enters them, so a dedicated owner task (_ConnectionRecord._run) holds them open for the connection's lifetime while concurrent activities on the same event loop call through the shared session.

Function build_call_tool_activity Return the per-server {server}-call-tool activity for registration.
Function build_list_tools_activity Return the per-server {server}-list-tools activity for registration.
Function build_mcp_activities Build the list-tools and call-tool activities for every registered server.
Async Function get_connection Return the cached session for server, opening one lazily if needed.
Type Alias McpSessionFactory Undocumented
Class _ConnectionRecord A single MCP session held open by a dedicated owner task.
Async Function _evict_connection Undocumented
Constant _CONNECTIONS Undocumented
Constant _MCP_CONNECTION_IDLE Undocumented
def build_call_tool_activity(server: str, factory: McpSessionFactory, idle_timeout: timedelta | None = None) -> Callable: (source)

Return the per-server {server}-call-tool activity for registration.

Reuses the same lazily-opened, idle-evicted worker-process MCP session as {server}-list-tools. Returns the raw mcp.types.CallToolResult — including tool-level error results (isError=True), which the model is meant to see; only transport/protocol failures raise (and evict).

def build_list_tools_activity(server: str, factory: McpSessionFactory, idle_timeout: timedelta | None = None) -> Callable: (source)

Return the per-server {server}-list-tools activity for registration.

Reuses a lazily-opened, idle-evicted worker-process MCP session. Returns the raw mcp.types.ListToolsResult so the workflow-side shim can hand it to the Gemini SDK exactly as a live session would (preserving the full tool parameter schema).

def build_mcp_activities(mcp_servers: dict[str, McpSessionFactory], idle_timeout: timedelta | None = None) -> list[Callable]: (source)

Build the list-tools and call-tool activities for every registered server.

async def get_connection(server: str, factory: McpSessionFactory, idle_timeout: timedelta) -> tuple[ClientSession, _ConnectionRecord]: (source)

Return the cached session for server, opening one lazily if needed.

Concurrent first-callers dedupe onto a single connect handshake by awaiting the same record. The returned record is acquired; the caller must release() it once the call completes so idle eviction can resume.

McpSessionFactory = (source)

Undocumented

Value
Callable[[], AbstractAsyncContextManager[ClientSession]]
async def _evict_connection(server: str): (source)

Undocumented

Undocumented

Value
{}
_MCP_CONNECTION_IDLE = (source)

Undocumented

Value
timedelta(minutes=5)