agentscope-ai/agentscope · error · ValueError
STDIO MCP must be stateful (is_stateful=True).
Error message
STDIO MCP must be stateful (is_stateful=True).
What it means
STDIO-based MCP servers run as a local subprocess whose process state persists across tool calls, so they cannot operate statelessly. MCPClient's post-init validation enforces that a stdio_mcp configuration requires is_stateful=True.
Source
Thrown at src/agentscope/mcp/_mcp_client.py:131
Returns:
True if connected, False otherwise.
"""
return self._is_connected
def model_post_init(self, __context: Any) -> None:
"""Validate configuration and initialize client."""
# MCP name is used to compose model-facing tool names
# (mcp__{name}__{tool}), which must match ^[a-zA-Z0-9_-]+$.
if not re.fullmatch(r"[a-zA-Z0-9_-]+", self.name):
raise ValueError(
f"MCPClient name '{self.name}' contains characters not "
f"allowed by LLM providers (only [a-zA-Z0-9_-] are "
f"permitted). Please rename it.",
)
# STDIO MCP must be stateful
if self.mcp_config.type == "stdio_mcp" and not self.is_stateful:
raise ValueError(
"STDIO MCP must be stateful (is_stateful=True).",
)
# Check arguments for self.enable_tools and disable_tools
if self.enable_tools is not None:
if not isinstance(self.enable_tools, list) or any(
not isinstance(_, str) for _ in self.enable_tools
):
raise ValueError(
"Enable tools should be a list of strings, but got "
f"{self.enable_tools}.",
)
if self.disable_tools is not None:
if not isinstance(self.disable_tools, list) or any(
not isinstance(_, str) for _ in self.disable_tools
):
raise ValueError(View on GitHub (pinned to e90f1c7592)
Solutions
- Set is_stateful=True (or omit it if the default is True for stdio) for stdio_mcp configs
- If you intended stateless operation, use an HTTP/SSE/streamable transport type instead of stdio_mcp
Example fix
// before
client = MCPClient(
name="fs",
mcp_config=MCPConfig(type="stdio_mcp", command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]),
is_stateful=False,
)
// after
client = MCPClient(
name="fs",
mcp_config=MCPConfig(type="stdio_mcp", command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]),
is_stateful=True,
) Defensive patterns
Strategy: validation
Validate before calling
if cfg.type == "stdio_mcp":
is_stateful = True # forced
client = MCPClient(name=n, mcp_config=cfg, is_stateful=is_stateful) Try / catch
try:
MCPClient(name=n, mcp_config=cfg, is_stateful=False)
except ValueError as e:
if "must be stateful" in str(e):
client = MCPClient(name=n, mcp_config=cfg, is_stateful=True) Prevention
- Remember the transport/statefulness matrix: stdio implies stateful
- Write a helper that infers is_stateful from the transport type
- Document the constraint next to stdio MCP examples in your codebase
When it happens
Trigger: MCPClient(mcp_config=MCPConfig(type="stdio_mcp", ...), is_stateful=False) — explicitly setting is_stateful=False or using a stateless preset/template with a stdio transport.
Common situations: Copying a stateless HTTP/SSE MCPClient configuration and swapping in a stdio command without flipping is_stateful; library examples defaulting to stateless for simplicity.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- STDIO MCP does not support ephemeral mode. Use 'shared' or '
- Invalid values for MCP {card.name!r}: {e.message}
- MCP {card.name!r} needs a value for: {', '.join(sorted(missi
- MCP {card.name!r} produced an invalid client: {e}
- MCPClient name '{self.name}' contains characters not allowed
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/073463f6b3af133d.
Report an issue: GitHub.