feat(mcp): add list and get tools for row level security and plugins#40347
feat(mcp): add list and get tools for row level security and plugins#40347aminghadersohi wants to merge 5 commits into
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er roles to be returned RLS filter `roles` (which roles a filter applies to) are core RLS data, not user-directory metadata. Including 'roles' in USER_DIRECTORY_FIELDS caused filter_user_directory_columns() to strip it from any requested select_columns list, making it impossible to retrieve via list_rls_filters. No dashboard/chart/dataset schema defines a 'roles' field, so removing it from the block set has no privacy impact on other tools. Fixes test_list_rls_filters_returns_tables_and_roles.
…in RLS list tool 'roles' on a dashboard/chart exposes who has access to the resource and should be stripped by the USER_DIRECTORY_FIELDS privacy filter. 'roles' in an RLS filter is which roles the filter applies to — it is core filter data, not user-directory metadata. The RLS list tool now derives its column selection directly from ALL_RLS_COLUMNS (bypassing ModelListCore's USER_DIRECTORY_FIELDS filtering) so that RLS roles are selectable while dashboard roles remain hidden. Fixes three failing unit tests: - test_list_dashboards_omits_requested_user_directory_fields - test_get_allowed_fields_always_denies_user_directory_fields - test_filter_sensitive_data_strips_user_directory_fields_even_if_allowed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
geido
left a comment
There was a problem hiding this comment.
Reviewed carefully given the sensitivity of RLS data. class_permission_name="Row Level Security" is in ADMIN_ONLY_VIEW_MENUS, so non-admins cannot see filter clauses, tables, or associated roles. MCP_RBAC_ENABLED defaults to True and check_tool_permission enforces can_read at call time. The deliberate bypass of USER_DIRECTORY_FIELDS for the RLS roles column is correct — that field represents policy scope, not user directory metadata, and the bypass only applies after the Admin gate has passed. Plugin tools expose only non-sensitive metadata.
There was a problem hiding this comment.
Code Review Agent Run #f6e20e
Actionable Suggestions - 1
-
superset/mcp_service/plugin/tool/list_plugins.py - 1
- Type mismatch in serializer signature · Line 78-78
Additional Suggestions - 1
-
superset/mcp_service/rls/tool/list_rls_filters.py - 1
-
Serializer naming inconsistency · Line 78-78Rename the `_serialize` function to `_serialize_rls_filter` and update the `item_serializer` argument accordingly to match naming conventions used by other list tools.
-
Filtered by Review Rules
Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.
-
superset/mcp_service/rls/tool/get_rls_filter_info.py - 1
- Async/sync context manager mismatch · Line 69-78
-
superset/mcp_service/plugin/schemas.py - 1
- Missing filterable columns in schema · Line 62-62
Review Details
-
Files reviewed - 19 · Commit Range:
10ea6da..6e3a325- superset/mcp_service/app.py
- superset/mcp_service/plugin/__init__.py
- superset/mcp_service/plugin/dao.py
- superset/mcp_service/plugin/schemas.py
- superset/mcp_service/plugin/tool/__init__.py
- superset/mcp_service/plugin/tool/get_plugin_info.py
- superset/mcp_service/plugin/tool/list_plugins.py
- superset/mcp_service/privacy.py
- superset/mcp_service/rls/__init__.py
- superset/mcp_service/rls/schemas.py
- superset/mcp_service/rls/tool/__init__.py
- superset/mcp_service/rls/tool/get_rls_filter_info.py
- superset/mcp_service/rls/tool/list_rls_filters.py
- tests/unit_tests/mcp_service/plugin/__init__.py
- tests/unit_tests/mcp_service/plugin/tool/__init__.py
- tests/unit_tests/mcp_service/plugin/tool/test_plugin_tools.py
- tests/unit_tests/mcp_service/rls/__init__.py
- tests/unit_tests/mcp_service/rls/tool/__init__.py
- tests/unit_tests/mcp_service/rls/tool/test_rls_tools.py
-
Files skipped - 0
-
Tools
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
- MyPy (Static Code Analysis) - ✔︎ Successful
- Astral Ruff (Static Code Analysis) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers a full AI review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.
Documentation & Help
| try: | ||
| from superset.mcp_service.plugin.dao import DynamicPluginDAO | ||
|
|
||
| def _serialize(obj: object, cols: list[str] | None) -> PluginInfo | None: |
There was a problem hiding this comment.
The _serialize function has cols: list[str] | None but ModelListCore expects item_serializer: Callable[[T, List[str]], S | None] where the second argument is List[str] (non-optional). The cols parameter is also unused in the function body.
Code suggestion
Check the AI-generated fix before applying
--- a/superset/mcp_service/plugin/tool/list_plugins.py
+++ b/superset/mcp_service/plugin/tool/list_plugins.py
@@ -75,7 +75,7 @@ async def list_plugins(
from superset.mcp_service.plugin.dao import DynamicPluginDAO
- def _serialize(obj: object, cols: list[str] | None) -> PluginInfo | None:
+ def _serialize(obj: object, cols: list[str]) -> PluginInfo | None:
return serialize_plugin_object(obj)
list_tool = ModelListCore(
Code Review Run #f6e20e
Should Bito avoid suggestions like this for future reviews? (Manage Rules)
- Yes, avoid them
SUMMARY
Adds four new MCP (Model Context Protocol) tools to Apache Superset across two new domains:
Row Level Security (
superset/mcp_service/rls/):list_rls_filters— list RLS filters with filtering, search, column selection, sorting, and pagination. Requires admin access.get_rls_filter_info— get full RLS filter details by ID (name, type, tables, roles, clause, group key). Requires admin access.Dynamic Plugins (
superset/mcp_service/plugin/):list_plugins— list registered dynamic plugins with filtering, search, column selection, sorting, and pagination.get_plugin_info— get plugin details by ID (name, key, bundle_url, timestamps).Both domains follow the established MCP service patterns:
@tooldecorator withclass_permission_namefor RBAC ("Row Level Security","DynamicPlugin")ModelListCore/ModelGetInfoCorefrommcp_core.pyfor reusable list/get logicmodel_serializerfor column-filtered responsesColumnOperator/ColumnOperatorEnumfor structured filter objectsevent_loggerinstrumentation and FastMCPctxloggingThe
DynamicPluginDAOis co-located insuperset/mcp_service/plugin/dao.pysince no top-level DAO existed for theDynamicPluginmodel.The
DEFAULT_INSTRUCTIONSinapp.pyare updated to clarify thatget_schemacovers chart/dataset/dashboard/database resource types only; RLS and plugin tools document their filterable/sortable columns inline in their docstrings.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A — backend MCP tools only.
TESTING INSTRUCTIONS
list_rls_filters— returns paginated RLS filters with id, name, filter_type, clause by defaultlist_rls_filterswithselect_columns: ["id", "name", "tables", "roles"]— includes relationship dataget_rls_filter_infowith a valid RLS filter ID — returns full filter detailslist_plugins— returns paginated plugin list with id, name, key, bundle_url by defaultget_plugin_infowith a valid plugin ID — returns full plugin detailsUnit tests:
pytest tests/unit_tests/mcp_service/rls/ tests/unit_tests/mcp_service/plugin/ADDITIONAL INFORMATION