Skip to content

Commit 4a2dc4e

Browse files
fix(mcp): move search/filters mutual exclusion check from schema to tool layer
Pydantic model_validators in ListRolesRequest and ListUsersRequest fired during fastmcp parameter deserialization, producing a raw ToolError with "1 validation error for call[list_roles]" text that the StructuredContent- StripperMiddleware wrapped as non-JSON content. Tests that called json.loads() on the result then raised JSONDecodeError instead of seeing the expected error dict. Removes the model_validators from both schemas and moves the mutual exclusion check into the tool functions' try blocks, returning a proper RoleError/UserError JSON object so tests can assert "error" in data. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b8ba7a7 commit 4a2dc4e

4 files changed

Lines changed: 20 additions & 24 deletions

File tree

superset/mcp_service/role/schemas.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
Field,
2929
field_validator,
3030
model_serializer,
31-
model_validator,
3231
PositiveInt,
3332
)
3433

@@ -184,17 +183,6 @@ def parse_columns(cls, v: Any) -> List[str]:
184183
"""Accept JSON array, list, or comma-separated string."""
185184
return parse_json_or_list(v, "select_columns")
186185

187-
@model_validator(mode="after")
188-
def validate_search_and_filters(self) -> "ListRolesRequest":
189-
"""Prevent using both search and filters simultaneously."""
190-
if self.search and self.filters:
191-
raise ValueError(
192-
"Cannot use both 'search' and 'filters' parameters simultaneously. "
193-
"Use either 'search' for text-based searching or 'filters' for "
194-
"precise column-based filtering, but not both."
195-
)
196-
return self
197-
198186

199187
class RoleError(BaseModel):
200188
error: str = Field(..., description="Error message")

superset/mcp_service/role/tool/list_roles.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ async def list_roles(
7676
)
7777

7878
try:
79+
if request.search and request.filters:
80+
return RoleError.create(
81+
error=(
82+
"Cannot use both 'search' and 'filters' parameters simultaneously. "
83+
"Use either 'search' for text-based searching or 'filters' for "
84+
"precise column-based filtering, but not both."
85+
),
86+
error_type="validation_error",
87+
).model_dump(mode="json")
88+
7989
from superset.daos.role import RoleDAO
8090

8191
def _serialize_role(obj: Any, cols: list[str] | None) -> RoleInfo | None:

superset/mcp_service/user/schemas.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
Field,
2929
field_validator,
3030
model_serializer,
31-
model_validator,
3231
PositiveInt,
3332
)
3433

@@ -215,17 +214,6 @@ def parse_columns(cls, v: Any) -> List[str]:
215214
"""Accept JSON array, list, or comma-separated string."""
216215
return parse_json_or_list(v, "select_columns")
217216

218-
@model_validator(mode="after")
219-
def validate_search_and_filters(self) -> "ListUsersRequest":
220-
"""Prevent using both search and filters simultaneously."""
221-
if self.search and self.filters:
222-
raise ValueError(
223-
"Cannot use both 'search' and 'filters' parameters simultaneously. "
224-
"Use either 'search' for text-based searching or 'filters' for "
225-
"precise column-based filtering, but not both."
226-
)
227-
return self
228-
229217

230218
class UserError(BaseModel):
231219
error: str = Field(..., description="Error message")

superset/mcp_service/user/tool/list_users.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ async def list_users(
7979
)
8080

8181
try:
82+
if request.search and request.filters:
83+
return UserError.create(
84+
error=(
85+
"Cannot use both 'search' and 'filters' parameters simultaneously. "
86+
"Use either 'search' for text-based searching or 'filters' for "
87+
"precise column-based filtering, but not both."
88+
),
89+
error_type="validation_error",
90+
).model_dump(mode="json")
91+
8292
from superset.daos.user import UserDAO
8393

8494
can_view_sensitive = user_can_view_data_model_metadata()

0 commit comments

Comments
 (0)