agentscope-ai/agentscope · error · ValueError
MCPClient name '{self.name}' contains characters not allowed
Error message
MCPClient name '{self.name}' contains characters not allowed by LLM providers (only [a-zA-Z0-9_-] are permitted). Please rename it. What it means
MCPClient validates in model_post_init that its name matches ^[a-zA-Z0-9_-]+$ because the name is used to compose model-facing tool names (mcp__{name}__{tool}) that LLM providers restrict to that character set. Any space, dot, slash, unicode, or other symbol in the MCP server name triggers this ValueError at construction time.
Source
Thrown at src/agentscope/mcp/_mcp_client.py:123
_stack: AsyncExitStack | None = PrivateAttr(default=None)
_is_connected: bool = PrivateAttr(default=False)
_cached_tools: list[mcp.types.Tool] | None = PrivateAttr(default=None)
@property
def is_connected(self) -> bool:
"""Whether the client is currently connected.
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 "View on GitHub (pinned to e90f1c7592)
Solutions
- Rename the MCP client using only letters, digits, underscore, and hyphen (e.g. "github-api" instead of "github.com/api")
- If the name comes from a config file, sanitize it before constructing MCPClient
- Keep the display/description separate from the internal name if human-friendly naming is needed
Example fix
// before client = MCPClient(name="my search server", mcp_config=config) // after client = MCPClient(name="my-search-server", mcp_config=config)
Defensive patterns
Strategy: validation
Validate before calling
import re
assert re.fullmatch(r"[a-zA-Z0-9_-]+", name), f"invalid MCP name: {name!r}"
client = MCPClient(name=name, mcp_config=cfg) Try / catch
try:
MCPClient(name=name, mcp_config=cfg)
except ValueError as e:
if "not allowed by LLM providers" in str(e):
name = re.sub(r"[^a-zA-Z0-9_-]", "-", name) Prevention
- Derive MCP names with a sanitizer: re.sub(r'[^a-zA-Z0-9_-]', '-', raw_name)
- Keep a naming convention (kebab-case) for MCP servers in config files
- Add a config lint step before constructing clients
When it happens
Trigger: MCPClient(name="my mcp.server", mcp_config=...) or any name containing spaces, dots, colons, or non-ASCII characters; also names loaded from config files (YAML/JSON) where naming rules were not enforced.
Common situations: Naming an MCP server after a URL or path (e.g. "github.com/api"), using display names with spaces, copying server names from other tools (Claude Desktop config uses arbitrary names) into agentscope.
Related errors
- The injection template must contain the '{runtime_state}' pl
- 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}
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/b4721ad23c02457a.
Report an issue: GitHub.