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

Reply via email to