agentscope-ai/agentscope · error · ValueError
An MCP named {mcp_record.name!r} already exists for this use
Error message
An MCP named {mcp_record.name!r} already exists for this user. What it means
Raised by SQLStorage.upsert_mcp when creating or updating an installed-MCP record whose name is already taken by a different MCP record owned by the same user. Names are unique per user, so the check compares the existing record's id with the incoming mcp_record.id; a mismatch means a name collision with another record.
Source
Thrown at src/agentscope/app/storage/_sql/_storage.py:838
return result.rowcount > 0
# ------------------------------------------------------------------
# Installed MCPs and skills
#
# ``(user_id, name)`` is unique on both tables. The pre-write lookup
# below turns the common case into the same ``ValueError`` the Redis
# backend raises; the constraint is the backstop that closes the
# read-then-write window between concurrent writers.
# ------------------------------------------------------------------
async def upsert_mcp(self, user_id: str, mcp_record: MCPRecord) -> str:
"""Create or update an installed-MCP record for *user_id*.
Same contract as :meth:`RedisStorage.upsert_mcp`.
"""
holder = await self.get_mcp_by_name(user_id, mcp_record.name)
if holder is not None and holder.id != mcp_record.id:
raise ValueError(
f"An MCP named {mcp_record.name!r} already exists for "
f"this user.",
)
mcp_record.user_id = user_id
await self._write_row(MCPRow, mcp_record)
return mcp_record.id
async def list_mcps(self, user_id: str) -> list[MCPRecord]:
"""Return every installed-MCP record for *user_id*."""
from sqlalchemy import select
async with self._session() as sess:
rows = (
(
await sess.execute(
select(MCPRow).where(MCPRow.user_id == user_id),
)
)View on GitHub (pinned to e90f1c7592)
Solutions
- Choose a unique name for the MCP record before upserting
- If updating an existing MCP, load it first (get_mcp_by_name) and reuse its id and mutate fields instead of creating a new record
- Delete the conflicting record (delete_mcp) before re-registering with the same name
Example fix
// before
await storage.upsert_mcp(user_id, MCPRecord(id=new_id, name="fs")) # name clash
// after
existing = await storage.get_mcp_by_name(user_id, "fs")
if existing:
existing.command = new_cmd
await storage.upsert_mcp(user_id, existing) # same id -> update
else:
await storage.upsert_mcp(user_id, MCPRecord(name="fs", ...)) Defensive patterns
Strategy: validation
Validate before calling
existing = await storage.get_mcp_by_name(user_id, record.name)
if existing is not None and existing.id != record.id:
record.name = f"{record.name}-{uuid4().hex[:6]}" # or merge into existing Try / catch
try:\n await storage.upsert_mcp(user_id, rec)\nexcept ValueError as e:\n if \"already exists\" in str(e): handle_name_collision(rec)\n else: raise
Prevention
- Keep a registry of installed MCP names per user
- Reuse existing record ids when updating
When it happens
Trigger: Calling upsert_mcp(user_id, record) where record.name matches an existing MCP for that user but record.id differs (e.g. a new record reusing an existing name, or an update that changed the id).
Common situations: Re-installing an MCP under a name already registered for the user; copying MCP config between environments without preserving record ids; concurrent installs racing on the same name.
Related errors
- A skill named {skill_record.name!r} already exists for this
- Bot {platform_bot_id!r} already drives channel {holder!r}.
- 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
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/8d0e93358589f79f.
Report an issue: GitHub.