langchain-ai/deepagents · error · ValueError

Invalid MCP server name {server_name!r}: token storage names

Error message

Invalid MCP server name {server_name!r}: token storage names must match [A-Za-z0-9_-]+ to keep the on-disk path inside {tokens_dir}.

What it means

The MCP token-store wrapper validates the server name at construction because the server name becomes a file name under the tokens directory. Names containing path separators or other unsafe characters could escape the token directory, so only [A-Za-z0-9_-]+ is allowed. This is a fail-fast guard in TokenStore.__init__ (mcp_auth.py:324).

Source

Thrown at libs/code/deepagents_code/mcp_auth.py:324

class FileTokenStorage(TokenStorage):
    """File-backed `TokenStorage` under the selected profile's state directory."""

    def __init__(self, server_name: str, *, server_url: str | None = None) -> None:
        """Bind this storage to a configured MCP server identity.

        Raises:
            ValueError: If `server_name` contains characters that would let
                it escape the MCP token-store directory when used as the
                token-file basename.
        """
        if not _SAFE_SERVER_NAME_RE.fullmatch(server_name):
            tokens_dir = PATHS.display(token_store_dir())
            msg = (
                f"Invalid MCP server name {server_name!r}: token storage "
                "names must match [A-Za-z0-9_-]+ to keep the on-disk path "
                f"inside {tokens_dir}."
            )
            raise ValueError(msg)
        self._server_name = server_name
        self._server_url = server_url

    @property
    def path(self) -> Path:
        """On-disk token file path for this server."""
        stem = _token_file_stem(self._server_name, self._server_url)
        return token_store_dir() / f"{stem}.json"

    @property
    def refresh_lock_path(self) -> Path:
        """Sibling lock file that serializes token refreshes across processes.

        A dedicated `.lock` file (never the token file itself) lets `filelock`
        coordinate refreshes between dcode processes and provider instances
        without ever holding an exclusive lock on the credential file. It holds
        no token material.
        """

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Rename the MCP server entry to a simple identifier using only letters, digits, underscores, or hyphens (e.g. 'github-mcp').
  2. Strip whitespace and transliterate/replace special characters in the name before constructing the store.
  3. If generating names programmatically, pass them through re.sub(r'[^A-Za-z0-9_-]', '-', name) first.

Example fix

// before
store = McpTokenStore(server_name="https://mcp.example.com/sse", url=...)
// after
import re
name = re.sub(r"[^A-Za-z0-9_-]", "-", "https://mcp.example.com/sse")  # e.g. 'https---mcp-example-com-sse'
store = McpTokenStore(server_name=name, url=...)
Defensive patterns

Strategy: validation

Validate before calling

import re
def valid_server_name(name: str) -> bool:
    return bool(re.fullmatch(r"[A-Za-z0-9_-]+", name))

if not valid_server_name(server_name):
    server_name = re.sub(r"[^A-Za-z0-9_-]", "-", server_name)

Type guard

import re
def is_safe_token_name(name: object) -> TypeGuard[str]:
    return isinstance(name, str) and re.fullmatch(r"[A-Za-z0-9_-]+", name) is not None

Prevention

When it happens

Trigger: Constructing the token store (directly or via `mcp login`/auth flows) with a server name that is empty or contains characters outside [A-Za-z0-9_-], e.g. slashes, spaces, dots, or unicode.

Common situations: MCP server entries in config with URLs or paths used as names (e.g. 'https://mcp.example.com/v1'), names copied from docs containing spaces or slashes, or a typo'd/whitespace-padded server key in .mcp.json.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/d8fc21c4ab3652ed. Report an issue: GitHub.