This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 409cdad264 fix(mcp): prevent MCP service from corrupting shared
appbuilder singleton (#37252)
409cdad264 is described below
commit 409cdad2648c7476cf1769196e970149cbecf800
Author: Michael S. Molina <[email protected]>
AuthorDate: Mon Jan 19 13:03:37 2026 -0300
fix(mcp): prevent MCP service from corrupting shared appbuilder singleton
(#37252)
---
superset/mcp_service/flask_singleton.py | 82 ++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 28 deletions(-)
diff --git a/superset/mcp_service/flask_singleton.py
b/superset/mcp_service/flask_singleton.py
index 055883cd5b..d508943e86 100644
--- a/superset/mcp_service/flask_singleton.py
+++ b/superset/mcp_service/flask_singleton.py
@@ -25,6 +25,7 @@ Following the Stack Overflow recommendation:
"""
import logging
+import os
from flask import Flask
@@ -33,34 +34,59 @@ logger = logging.getLogger(__name__)
logger.info("Creating Flask app instance for MCP service")
try:
- from superset.app import create_app
- from superset.mcp_service.mcp_config import get_mcp_config
-
- # Create a temporary context to avoid
- # "Working outside of application context" errors.
- _temp_app = create_app()
-
- # Push an application context and initialize core dependencies and
extensions
- with _temp_app.app_context():
- # Apply MCP configuration - reads from app.config first, falls back to
defaults
- mcp_config = get_mcp_config(_temp_app.config)
- _temp_app.config.update(mcp_config)
- try:
- from superset.initialization import SupersetAppInitializer
-
- # Create initializer and run only dependency injection
- # NOT the full init_app_in_ctx which includes web views
- initializer = SupersetAppInitializer(_temp_app)
- initializer.init_all_dependencies_and_extensions()
-
- logger.info("Core dependencies and extensions initialized for MCP
service")
- except Exception as e:
- logger.warning("Failed to initialize dependencies for MCP service:
%s", e)
-
- # Store the app instance for later use
- app = _temp_app
-
- logger.info("Minimal Flask app instance created successfully for MCP
service")
+ from superset.extensions import appbuilder
+
+ # Check if appbuilder is already initialized (main Superset app is
running).
+ # If so, reuse that app to avoid corrupting the shared appbuilder
singleton.
+ # Calling create_app() again would re-initialize appbuilder and break
views.
+ if appbuilder.app is not None:
+ logger.info("Reusing existing Flask app from appbuilder for MCP
service")
+ app = appbuilder.app
+ else:
+ # Create a minimal Flask app for standalone MCP server.
+ # We avoid calling create_app() which would run full FAB initialization
+ # and could corrupt the shared appbuilder singleton if main app starts.
+ from superset.app import SupersetApp
+ from superset.mcp_service.mcp_config import get_mcp_config
+
+ # Disable debug mode to avoid side-effects like file watchers
+ _mcp_app = SupersetApp(__name__)
+ _mcp_app.debug = False
+
+ # Load configuration
+ config_module = os.environ.get("SUPERSET_CONFIG", "superset.config")
+ _mcp_app.config.from_object(config_module)
+
+ # Apply MCP-specific configuration
+ mcp_config = get_mcp_config(_mcp_app.config)
+ _mcp_app.config.update(mcp_config)
+
+ # Initialize only the minimal dependencies needed for MCP service
+ with _mcp_app.app_context():
+ try:
+ from superset.extensions import db
+
+ db.init_app(_mcp_app)
+
+ # Initialize only MCP-specific dependencies
+ # MCP tools import directly from superset.daos/models, so we
only need
+ # the MCP decorator injection, not the full superset_core
abstraction
+ from superset.core.mcp.core_mcp_injection import (
+ initialize_core_mcp_dependencies,
+ )
+
+ initialize_core_mcp_dependencies()
+
+ logger.info(
+ "Minimal MCP dependencies initialized for standalone MCP
service"
+ )
+ except Exception as e:
+ logger.warning(
+ "Failed to initialize dependencies for MCP service: %s", e
+ )
+
+ app = _mcp_app
+ logger.info("Minimal Flask app instance created successfully for MCP
service")
except Exception as e:
logger.error("Failed to create Flask app: %s", e)