codeant-ai-for-open-source[bot] commented on code in PR #38641:
URL: https://github.com/apache/superset/pull/38641#discussion_r2935237586


##########
superset-core/src/superset_core/mcp/decorators.py:
##########
@@ -37,6 +37,8 @@ def another_tool(value: int) -> str:
 
 from typing import Any, Callable, TypeVar
 
+from mcp.types import ToolAnnotations

Review Comment:
   **Suggestion:** This introduces a hard runtime dependency on `mcp` in 
`apache-superset-core`, but `superset-core/pyproject.toml` does not include 
`mcp`/`fastmcp`. Importing this module will raise `ModuleNotFoundError` in 
environments without the MCP extra. Make the import optional and provide a 
fallback alias so the abstract decorators remain importable. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ README MCP tool example crashes on import.
   - ❌ `superset_core.mcp.decorators` unusable in core-only installs.
   - ⚠️ Extension authors blocked without optional MCP extras.
   ```
   </details>
   
   ```suggestion
   try:
       from mcp.types import ToolAnnotations
   except ImportError:  # MCP extras may not be installed in superset-core-only 
environments
       ToolAnnotations = Any  # type: ignore[assignment]
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Install only `apache-superset-core` as documented in 
`superset-core/README.md:30-32`
   (`pip install apache-superset-core`), which uses dependencies declared in
   `superset-core/pyproject.toml:44-51` and does not include `mcp`/`fastmcp`.
   
   2. Follow the documented MCP quick-start import in 
`superset-core/README.md:82` (`from
   superset_core.mcp.decorators import tool`) or `README.md:92` (`prompt`).
   
   3. Python imports `superset-core/src/superset_core/mcp/decorators.py`, which 
executes
   `from mcp.types import ToolAnnotations` at line 40 before any function call.
   
   4. In environments without MCP extras, import fails immediately with 
`ModuleNotFoundError:
   No module named 'mcp'`, preventing use of the abstract decorators that are 
intended to be
   importable from `superset_core`.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-core/src/superset_core/mcp/decorators.py
   **Line:** 40:40
   **Comment:**
        *Possible Bug: This introduces a hard runtime dependency on `mcp` in 
`apache-superset-core`, but `superset-core/pyproject.toml` does not include 
`mcp`/`fastmcp`. Importing this module will raise `ModuleNotFoundError` in 
environments without the MCP extra. Make the import optional and provide a 
fallback alias so the abstract decorators remain importable.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=a2b8a2e6a9965ed27249066d4a12586307ebee49e8d2173e0f877094611e223b&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=a2b8a2e6a9965ed27249066d4a12586307ebee49e8d2173e0f877094611e223b&reaction=dislike'>👎</a>



##########
superset/mcp_service/explore/tool/generate_explore_link.py:
##########
@@ -39,7 +39,15 @@
 from superset.mcp_service.utils.schema_utils import parse_request
 
 
-@tool(tags=["explore"], class_permission_name="Explore")
+@tool(
+    tags=["explore"],
+    class_permission_name="Explore",
+    annotations=ToolAnnotations(
+        title="Generate explore link",
+        readOnlyHint=True,
+        destructiveHint=False,
+    ),

Review Comment:
   **Suggestion:** The tool is marked as read-only, but it calls logic that 
creates a new `form_data_key` cache entry (`MCPCreateFormDataCommand.run()`), 
which is a state mutation. This incorrect annotation can cause MCP 
clients/directories to treat a mutating tool as safe read-only behavior. Set 
`readOnlyHint` to `False` to match actual side effects. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ MCP metadata mislabels mutating `generate_explore_link` behavior.
   - ⚠️ Clients may treat cache-writing tool as read-only.
   - ⚠️ Directory safety profile for explore tool becomes inaccurate.
   ```
   </details>
   
   ```suggestion
       annotations=ToolAnnotations(
           title="Generate explore link",
           readOnlyHint=False,
           destructiveHint=False,
       ),
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start MCP service and invoke `generate_explore_link` through MCP client 
exactly like
   unit tests do at
   
`tests/unit_tests/mcp_service/explore/tool/test_generate_explore_link.py:119-122`
   (`client.call_tool("generate_explore_link", ...)`).
   
   2. Request enters tool function `generate_explore_link()` in
   `superset/mcp_service/explore/tool/generate_explore_link.py:52`; decorator 
metadata
   currently marks `readOnlyHint=True` at `:47`.
   
   3. The tool calls `generate_url(...)` at
   `superset/mcp_service/explore/tool/generate_explore_link.py:141-143`, which 
resolves to
   `chart_utils.generate_explore_link()` at 
`superset/mcp_service/chart/chart_utils.py:152`.
   
   4. `chart_utils.generate_explore_link()` executes
   `MCPCreateFormDataCommand(cmd_params).run()` at
   `superset/mcp_service/chart/chart_utils.py:205`; underlying 
`CreateFormDataCommand.run()`
   writes cache entries via `cache_manager.explore_form_data_cache.set(...)` at
   `superset/commands/explore/form_data/create.py:67-68`, proving server-side 
state mutation
   despite read-only annotation.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/mcp_service/explore/tool/generate_explore_link.py
   **Line:** 45:49
   **Comment:**
        *Logic Error: The tool is marked as read-only, but it calls logic that 
creates a new `form_data_key` cache entry (`MCPCreateFormDataCommand.run()`), 
which is a state mutation. This incorrect annotation can cause MCP 
clients/directories to treat a mutating tool as safe read-only behavior. Set 
`readOnlyHint` to `False` to match actual side effects.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=254f0be6597885d9fb69f71d780904c652371b2f6b3c05f1118b0c9ca3f828df&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=254f0be6597885d9fb69f71d780904c652371b2f6b3c05f1118b0c9ca3f828df&reaction=dislike'>👎</a>



##########
superset/core/mcp/core_mcp_injection.py:
##########
@@ -25,6 +25,8 @@
 import logging
 from typing import Any, Callable, Optional, TypeVar
 
+from mcp.types import ToolAnnotations

Review Comment:
   **Suggestion:** This unconditional import introduces a hard runtime 
dependency on `mcp` during normal Superset startup, but MCP support is optional 
(`fastmcp` extra). Since this module is imported from core initialization even 
when MCP extras are not installed, `ModuleNotFoundError` can crash app 
initialization before the existing fastmcp availability guard runs. Make the 
import optional with a fallback type alias so startup still works without MCP 
packages. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ create_app() fails without optional MCP dependencies.
   - ❌ Celery bootstrap fails via superset/tasks/celery_app.py:32.
   - ⚠️ fastmcp guard never executes due earlier import crash.
   ```
   </details>
   
   ```suggestion
   try:
       from mcp.types import ToolAnnotations
   except ImportError:
       ToolAnnotations = Any  # type: ignore[assignment]
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start Superset through normal app bootstrap (`superset/app.py:47-55`), 
which always
   calls `app_initializer.init_app()`.
   
   2. During initialization, `SupersetAppInitializer.init_app()` enters 
app-context init
   (`superset/initialization/__init__.py:728-740`) and calls
   `init_all_dependencies_and_extensions()` (`:626`), which always calls
   `init_core_dependencies()` (`:543-554`).
   
   3. `init_core_dependencies()` unconditionally imports 
`initialize_core_mcp_dependencies`
   from `superset.core.mcp.core_mcp_injection`
   (`superset/initialization/__init__.py:547-549`), so Python evaluates module 
top-level
   imports first.
   
   4. In environments without MCP packages installed, top-level `from mcp.types 
import
   ToolAnnotations` at `superset/core/mcp/core_mcp_injection.py:28` raises
   `ModuleNotFoundError` before the internal `fastmcp` guard
   (`core_mcp_injection.py:281-288`) can run, aborting startup.
   
   5. This is realistic because MCP is optional (`pyproject.toml:147` defines 
`fastmcp` as an
   extra), so non-MCP deployments can hit this on standard startup paths.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/core/mcp/core_mcp_injection.py
   **Line:** 28:28
   **Comment:**
        *Possible Bug: This unconditional import introduces a hard runtime 
dependency on `mcp` during normal Superset startup, but MCP support is optional 
(`fastmcp` extra). Since this module is imported from core initialization even 
when MCP extras are not installed, `ModuleNotFoundError` can crash app 
initialization before the existing fastmcp availability guard runs. Make the 
import optional with a fallback type alias so startup still works without MCP 
packages.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=bb7d97f0b6037f45a6a6b0f5f5282635af7082eb8c054b5890932ffd3330a596&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=bb7d97f0b6037f45a6a6b0f5f5282635af7082eb8c054b5890932ffd3330a596&reaction=dislike'>👎</a>



##########
superset/mcp_service/sql_lab/tool/save_sql_query.py:
##########
@@ -43,7 +43,14 @@
 logger = logging.getLogger(__name__)
 
 
-@tool(tags=["mutate"])
+@tool(
+    tags=["mutate"],
+    annotations=ToolAnnotations(

Review Comment:
   **Suggestion:** This tool is registered without `class_permission_name`, so 
MCP RBAC defaults to allow and skips Superset view-level permission checks. As 
a result, any authenticated user who can access a database can invoke this 
mutating endpoint even if they do not have SQL Lab permissions. Add SQL Lab 
RBAC metadata to the decorator so permission checks are enforced consistently 
with other SQL Lab tools. [security]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ SQL Lab RBAC can be bypassed for save_sql_query.
   - ❌ Unauthorized users may create persisted SavedQuery records.
   - ⚠️ Inconsistent authorization versus execute_sql SQLLab tool.
   ```
   </details>
   
   ```suggestion
       class_permission_name="SQLLab",
       method_permission_name="write",
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start MCP server initialization; `superset/mcp_service/app.py:418-421` 
imports
   `save_sql_query`, so the decorator in
   `superset/mcp_service/sql_lab/tool/save_sql_query.py:46-53` is executed 
during tool
   registration.
   
   2. In `superset/core/mcp/core_mcp_injection.py:110-121`, RBAC attributes are 
only attached
   when `class_permission_name` is provided; this tool omits it, so no
   `_class_permission_name`/`_method_permission_name` gets set.
   
   3. Invoke MCP `save_sql_query` (documented as a normal workflow tool in
   `superset/mcp_service/app.py:73,109`); execution enters `mcp_auth_hook` at
   `superset/mcp_service/auth.py:55`.
   
   4. `check_tool_permission()` at `superset/mcp_service/auth.py:103-106` 
returns
   allow-by-default when class permission metadata is missing (also validated by
   `tests/unit_tests/mcp_service/test_auth_rbac.py:103-108`), so SQL Lab 
view-level RBAC is
   skipped.
   
   5. The function then only enforces database access (`save_sql_query.py:91`) 
and proceeds
   to mutate state with `SavedQueryDAO.create(...)` at 
`save_sql_query.py:102-113`, allowing
   saved-query creation without explicit SQLLab permission checks.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/mcp_service/sql_lab/tool/save_sql_query.py
   **Line:** 48:48
   **Comment:**
        *Security: This tool is registered without `class_permission_name`, so 
MCP RBAC defaults to allow and skips Superset view-level permission checks. As 
a result, any authenticated user who can access a database can invoke this 
mutating endpoint even if they do not have SQL Lab permissions. Add SQL Lab 
RBAC metadata to the decorator so permission checks are enforced consistently 
with other SQL Lab tools.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=6fb90b4b5f82a067fad9c3564e6b7f8c596b663ab2358d809f35ef063be17ef6&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38641&comment_hash=6fb90b4b5f82a067fad9c3564e6b7f8c596b663ab2358d809f35ef063be17ef6&reaction=dislike'>👎</a>



-- 
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