From 5437285451c6639c8d35f4977e59d4de04227d6e Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Tue, 19 May 2026 08:45:41 +0000 Subject: [PATCH] fix(mcp): drop orphan user-field keys + reject duplicate field_keys --- litellm/proxy/_types.py | 28 +++++++++++++++++++ .../mcp_management_endpoints.py | 3 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index c89e6ef0f35..a2b41095af0 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -1268,6 +1268,24 @@ class MCPUserField(LiteLLMPydanticObjectBase): env_var_name: Optional[str] = None +def _validate_unique_user_field_keys( + user_fields: List[MCPUserField], +) -> List[MCPUserField]: + seen: set = set() + duplicates: set = set() + for entry in user_fields: + key = entry.field_key + if key in seen: + duplicates.add(key) + else: + seen.add(key) + if duplicates: + raise ValueError( + f"user_fields contains duplicate field_key values: {sorted(duplicates)}" + ) + return user_fields + + class MCPUserFieldValuesRequest(LiteLLMPydanticObjectBase): """Body for storing the calling user's values for an MCP server's user fields.""" @@ -1368,6 +1386,11 @@ class NewMCPServerRequest(LiteLLMPydanticObjectBase): """ return values + @field_validator("user_fields") + @classmethod + def _user_fields_unique(cls, v: List[MCPUserField]) -> List[MCPUserField]: + return _validate_unique_user_field_keys(v) + class UpdateMCPServerRequest(LiteLLMPydanticObjectBase): server_id: str @@ -1427,6 +1450,11 @@ class UpdateMCPServerRequest(LiteLLMPydanticObjectBase): ) return values + @field_validator("user_fields") + @classmethod + def _user_fields_unique(cls, v: List[MCPUserField]) -> List[MCPUserField]: + return _validate_unique_user_field_keys(v) + class LiteLLM_MCPServerTable(LiteLLMPydanticObjectBase): """Represents a LiteLLM_MCPServerTable record""" diff --git a/litellm/proxy/management_endpoints/mcp_management_endpoints.py b/litellm/proxy/management_endpoints/mcp_management_endpoints.py index c6f7e65ebd6..010816db042 100644 --- a/litellm/proxy/management_endpoints/mcp_management_endpoints.py +++ b/litellm/proxy/management_endpoints/mcp_management_endpoints.py @@ -2166,8 +2166,9 @@ if MCP_AVAILABLE: user_fields.append(MCPUserField(**entry)) except Exception: # noqa: BLE001 — drop malformed entries silently continue + declared_keys = {f.field_key for f in user_fields} stored: Dict[str, str] = stored_values or {} - stored_keys = [k for k, v in stored.items() if v] + stored_keys = [k for k, v in stored.items() if v and k in declared_keys] missing_keys = [ f.field_key for f in user_fields