agentscope-ai/agentscope · error · RuntimeError

MCP '{self.name}' is already connected. Call close() before

Error message

MCP '{self.name}' is already connected. Call close() before reconnecting.

What it means

For stateful MCP connections, connect() refuses to run twice without an intervening close(), because the underlying transport/session resources (an AsyncExitStack of one-shot transports) are already allocated. This prevents leaking sessions and duplicated subprocesses/connections.

Source

Thrown at src/agentscope/mcp/_mcp_client.py:230

        )

    async def connect(self) -> None:
        """Connect to the MCP server (for stateful connections only).

        For stateless connections, this method does nothing.

        Raises:
            RuntimeError: If already connected.
        """
        if not self.is_stateful:
            logger.debug(
                "Stateless MCP '%s' does not require explicit connect.",
                self.name,
            )
            return

        if self._is_connected:
            raise RuntimeError(
                f"MCP '{self.name}' is already connected. "
                "Call close() before reconnecting.",
            )

        # Transports are one-shot context managers. Recreate them before every
        # connection so connect() -> close() -> connect() starts a fresh one.
        if self._client is None:
            if self.mcp_config.type == "http_mcp":
                self._client = self._create_http_client()
            else:
                self._initialize_client()

        assert self._client is not None
        self._stack = AsyncExitStack()

        try:
            context = await self._stack.enter_async_context(self._client)
            read_stream, write_stream = context[0], context[1]

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Call await client.close() before reconnecting, ideally in a finally block after the first connect
  2. Guard with if client._is_connected / a wrapper that checks connection state before connect()
  3. Reuse a single connected client instead of reconnecting per operation

Example fix

// before
await client.connect()
try:
    ...
except Exception:
    await client.connect()  # RuntimeError 226

// after
try:
    await client.connect()
    ...
finally:
    await client.close()
await client.connect()  # fresh one-shot transport, OK
Defensive patterns

Strategy: try-catch

Validate before calling

if getattr(client, "_is_connected", False):
    await client.close()
await client.connect()

Try / catch

try:
    await client.connect()
except RuntimeError as e:
    if "already connected" in str(e):
        await client.close()
        await client.connect()
    else:
        raise

Prevention

When it happens

Trigger: Calling await client.connect() a second time on a stateful MCPClient (e.g. in a retry loop or after an exception that left the client connected), typically via agent.add_mcp(...) reconnect logic.

Common situations: Retrying initialization on transient failures without closing first; framework restart/reload handlers that re-run setup code; multiple components each trying to register/connect the same shared MCPClient.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/5e0a48cd2de288e4. Report an issue: GitHub.