Antonio-RiveroMartnez commented on code in PR #37216:
URL: https://github.com/apache/superset/pull/37216#discussion_r2702252384


##########
superset/mcp_service/auth.py:
##########
@@ -212,6 +220,15 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
             with _get_app_context_manager():
                 user = _setup_user_context()
 
+                # If no Flask context, execute without user context
+                # (middleware will provide context later for tools)
+                if user is None:

Review Comment:
   If the middleware will provide the context later, why not relying on it 
entirely for such things and stop trying to set it here? That way we only one 
place when it's set



##########
superset/mcp_service/server.py:
##########
@@ -55,21 +65,79 @@ def configure_logging(debug: bool = False) -> None:
         logging.info("🔍 SQL Debug logging enabled")
 
 
+def create_event_store(config: dict[str, Any] | None = None) -> Any | None:
+    """
+    Create an EventStore for MCP session management.
+
+    For multi-pod deployments, uses Redis-backed storage to share session state
+    across pods. For single-pod deployments, returns None (uses in-memory).
+
+    Args:
+        config: Optional config dict. If None, reads from MCP_STORE_CONFIG.
+
+    Returns:
+        EventStore instance if Redis URL is configured, None otherwise.
+    """
+    if config is None:
+        config = MCP_STORE_CONFIG
+
+    redis_url = config.get("CACHE_REDIS_URL")
+    if not redis_url:
+        logging.info("EventStore: Using in-memory storage (single-pod mode)")
+        return None
+
+    try:
+        from fastmcp.server.event_store import EventStore
+
+        # Reuse _create_redis_store with wrap=False for raw RedisStore
+        redis_store = _create_redis_store(config, wrap=False)

Review Comment:
   Wouldn't wrap=false skip prefixes and fernet encryption like we are using 
for cache for example?



##########
superset/mcp_service/auth.py:
##########
@@ -235,6 +252,15 @@ def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
             with _get_app_context_manager():
                 user = _setup_user_context()
 
+                # If no Flask context, execute without user context
+                # (middleware will provide context later for tools)
+                if user is None:

Review Comment:
   Same as above, if we set it on the middleware we wouldn't need to repeat 
this block



##########
superset/mcp_service/auth.py:
##########
@@ -127,14 +127,22 @@ def has_dataset_access(dataset: "SqlaTable") -> bool:
         return False  # Deny access on error
 
 
-def _setup_user_context() -> User:
+def _setup_user_context() -> User | None:
     """
     Set up user context for MCP tool execution.
 
     Returns:
-        User object with roles and groups loaded
+        User object with roles and groups loaded, or None if no Flask context
     """
-    user = get_user_from_request()
+    try:
+        user = get_user_from_request()
+    except RuntimeError as e:
+        # No Flask application context (e.g., prompts before middleware runs)
+        # This is expected for some FastMCP operations - return None gracefully
+        if "application context" in str(e):

Review Comment:
   Cannot we catch the exact exception class being returned or is it just a 
RuntimeError? With a message?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to