This is an automated email from the ASF dual-hosted git repository. aminghadersohi pushed a commit to branch mcp-rbac-tool-visibility in repository https://gitbox.apache.org/repos/asf/superset.git
commit f97e70ccdb09327293e5c14d51e9e52926521614 Author: Amin Ghadersohi <[email protected]> AuthorDate: Wed May 20 16:02:38 2026 +0000 refactor(mcp): promote local imports to module level in RBAC middleware Move contextlib, flask, and auth imports from function bodies to module level in auth.py and middleware.py. The only remaining local import is get_flask_app in _get_app_context_manager, which is deferred because importing it at module level would trigger create_app() before Superset is fully initialised (e.g. during unit-test collection). Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- superset/mcp_service/auth.py | 9 ++++----- superset/mcp_service/middleware.py | 17 +++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/superset/mcp_service/auth.py b/superset/mcp_service/auth.py index e91d25fe414..e8cb675228a 100644 --- a/superset/mcp_service/auth.py +++ b/superset/mcp_service/auth.py @@ -44,11 +44,12 @@ Configuration: - MCP_DEV_USERNAME: Fallback username for development """ +import contextlib import logging from contextlib import AbstractContextManager from typing import Any, Callable, TYPE_CHECKING, TypeVar -from flask import g, has_request_context +from flask import current_app, g, has_app_context, has_request_context from flask_appbuilder.security.sqla.models import Group, User if TYPE_CHECKING: @@ -657,16 +658,14 @@ def _get_app_context_manager() -> AbstractContextManager[None]: from both ``mcp_auth_hook`` (tool execution) and ``RBACToolVisibilityMiddleware`` (tools/list filtering). """ - import contextlib - - from flask import current_app, has_app_context, has_request_context - if has_request_context(): return contextlib.nullcontext() if has_app_context(): # Push a new context for the CURRENT app (not get_flask_app() # which may return a different instance in test environments). return current_app._get_current_object().app_context() + # Deferred: importing at module level would trigger create_app() before + # Superset is fully initialised (e.g. during unit-test collection). from superset.mcp_service.flask_singleton import get_flask_app return get_flask_app().app_context() diff --git a/superset/mcp_service/middleware.py b/superset/mcp_service/middleware.py index f22fd4cf673..c26c699a7e7 100644 --- a/superset/mcp_service/middleware.py +++ b/superset/mcp_service/middleware.py @@ -26,7 +26,7 @@ from fastmcp.exceptions import ToolError from fastmcp.server.middleware import Middleware, MiddlewareContext from fastmcp.server.middleware.middleware import CallNext from fastmcp.tools.tool import Tool, ToolResult -from flask import has_app_context +from flask import g, has_app_context from pydantic import ValidationError from sqlalchemy.exc import OperationalError, TimeoutError from starlette.exceptions import HTTPException @@ -38,7 +38,12 @@ from superset.commands.exceptions import ( ) from superset.exceptions import SupersetException, SupersetSecurityException from superset.extensions import event_logger -from superset.mcp_service.auth import MCPPermissionDeniedError +from superset.mcp_service.auth import ( + MCPPermissionDeniedError, + _get_app_context_manager, + get_user_from_request, + is_tool_visible_to_current_user, +) from superset.mcp_service.constants import ( DEFAULT_TOKEN_LIMIT, DEFAULT_WARN_THRESHOLD_PCT, @@ -438,14 +443,6 @@ class RBACToolVisibilityMiddleware(Middleware): tools = await call_next(context) try: - from flask import g - - from superset.mcp_service.auth import ( - _get_app_context_manager, - get_user_from_request, - is_tool_visible_to_current_user, - ) - with _get_app_context_manager(): # Use get_user_from_request directly rather than # _setup_user_context, which carries per-call execution
