mirror of
https://github.com/apache/superset.git
synced 2026-08-12 11:11:01 +00:00
feat(mcp): Add tool annotations for MCP directory compliance (#38641)
This commit is contained in:
@@ -37,6 +37,13 @@ Usage:
|
||||
|
||||
from typing import Any, Callable, TypeVar
|
||||
|
||||
try:
|
||||
from mcp.types import ToolAnnotations
|
||||
except (
|
||||
ImportError
|
||||
): # MCP extras may not be installed in superset-core-only environments
|
||||
ToolAnnotations = dict
|
||||
|
||||
# Type variable for decorated functions
|
||||
F = TypeVar("F", bound=Callable[..., Any])
|
||||
|
||||
@@ -50,6 +57,7 @@ def tool(
|
||||
protect: bool = True,
|
||||
class_permission_name: str | None = None,
|
||||
method_permission_name: str | None = None,
|
||||
annotations: ToolAnnotations | None = None,
|
||||
) -> Any: # Use Any to avoid mypy issues with dependency injection
|
||||
"""
|
||||
Decorator to register an MCP tool with optional authentication.
|
||||
@@ -77,6 +85,8 @@ def tool(
|
||||
permission checking via security_manager.can_access().
|
||||
method_permission_name: FAB action name (e.g., "read", "write").
|
||||
Defaults to "write" if tags includes "mutate", else "read".
|
||||
annotations: MCP tool annotations (title, readOnlyHint, destructiveHint, etc.)
|
||||
These hints help MCP clients understand tool behavior and safety.
|
||||
|
||||
Returns:
|
||||
Decorator function that registers and wraps the tool, or the wrapped function
|
||||
@@ -178,4 +188,5 @@ def prompt(
|
||||
__all__ = [
|
||||
"tool",
|
||||
"prompt",
|
||||
"ToolAnnotations",
|
||||
]
|
||||
|
||||
@@ -25,6 +25,11 @@ that replaces the abstract functions in superset-core during initialization.
|
||||
import logging
|
||||
from typing import Any, Callable, Optional, TypeVar
|
||||
|
||||
try:
|
||||
from mcp.types import ToolAnnotations
|
||||
except ImportError:
|
||||
ToolAnnotations = dict
|
||||
|
||||
from superset.extensions.context import get_current_extension_context
|
||||
|
||||
# Type variable for decorated functions
|
||||
@@ -62,6 +67,7 @@ def create_tool_decorator(
|
||||
protect: bool = True,
|
||||
class_permission_name: Optional[str] = None,
|
||||
method_permission_name: Optional[str] = None,
|
||||
annotations: ToolAnnotations | None = None,
|
||||
) -> Callable[[F], F] | F:
|
||||
"""
|
||||
Create the concrete MCP tool decorator implementation.
|
||||
@@ -82,6 +88,7 @@ def create_tool_decorator(
|
||||
(e.g., "Chart", "Dashboard", "SQLLab"). Enables permission checking.
|
||||
method_permission_name: FAB action name (e.g., "read", "write").
|
||||
Defaults to "write" if tags has "mutate", else "read".
|
||||
annotations: MCP tool annotations (title, readOnlyHint, destructiveHint, etc.)
|
||||
|
||||
Returns:
|
||||
Decorator that registers and wraps the tool with optional authentication,
|
||||
@@ -130,6 +137,7 @@ def create_tool_decorator(
|
||||
name=tool_name,
|
||||
description=tool_description,
|
||||
tags=tool_tags,
|
||||
annotations=annotations,
|
||||
)
|
||||
mcp.add_tool(tool)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ from typing import Any, Dict, List
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.commands.exceptions import CommandException
|
||||
from superset.extensions import event_logger
|
||||
@@ -119,7 +119,15 @@ def _compile_chart(
|
||||
return CompileResult(success=False, error=str(exc))
|
||||
|
||||
|
||||
@tool(tags=["mutate"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="Create chart",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GenerateChartRequest)
|
||||
async def generate_chart( # noqa: C901
|
||||
request: GenerateChartRequest, ctx: Context
|
||||
|
||||
@@ -25,7 +25,7 @@ from typing import Any, Dict, List, TYPE_CHECKING
|
||||
|
||||
from fastmcp import Context
|
||||
from flask import current_app
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset.models.slice import Slice
|
||||
@@ -74,7 +74,15 @@ def _get_cached_form_data(form_data_key: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
@tool(tags=["data"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["data"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="Get chart data",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetChartDataRequest)
|
||||
async def get_chart_data( # noqa: C901
|
||||
request: GetChartDataRequest, ctx: Context
|
||||
|
||||
@@ -23,7 +23,7 @@ import logging
|
||||
|
||||
from fastmcp import Context
|
||||
from sqlalchemy.orm import subqueryload
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.commands.exceptions import CommandException
|
||||
from superset.commands.explore.form_data.parameters import CommandParameters
|
||||
@@ -115,7 +115,15 @@ def _apply_unsaved_state_override(result: ChartInfo, form_data_key: str) -> None
|
||||
)
|
||||
|
||||
|
||||
@tool(tags=["discovery"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["discovery"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="Get chart info",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetChartInfoRequest)
|
||||
async def get_chart_info(
|
||||
request: GetChartInfoRequest, ctx: Context
|
||||
|
||||
@@ -23,7 +23,7 @@ import logging
|
||||
from typing import Any, Dict, List, Protocol
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.commands.exceptions import CommandException
|
||||
from superset.exceptions import SupersetException
|
||||
@@ -2177,7 +2177,15 @@ async def _get_chart_preview_internal( # noqa: C901
|
||||
)
|
||||
|
||||
|
||||
@tool(tags=["data"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["data"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="Get chart preview",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetChartPreviewRequest)
|
||||
async def get_chart_preview(
|
||||
request: GetChartPreviewRequest, ctx: Context
|
||||
|
||||
@@ -23,7 +23,7 @@ import logging
|
||||
from typing import cast, TYPE_CHECKING
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset.models.slice import Slice
|
||||
@@ -62,7 +62,15 @@ SORTABLE_CHART_COLUMNS = [
|
||||
]
|
||||
|
||||
|
||||
@tool(tags=["core"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["core"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="List charts",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(ListChartsRequest)
|
||||
async def list_charts(request: ListChartsRequest, ctx: Context) -> ChartList:
|
||||
"""List charts with filtering and search.
|
||||
|
||||
@@ -23,7 +23,7 @@ import logging
|
||||
import time
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.chart.chart_utils import (
|
||||
@@ -45,7 +45,15 @@ from superset.utils import json
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool(tags=["mutate"], class_permission_name="Chart")
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="Chart",
|
||||
annotations=ToolAnnotations(
|
||||
title="Update chart",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=True,
|
||||
),
|
||||
)
|
||||
@parse_request(UpdateChartRequest)
|
||||
async def update_chart(
|
||||
request: UpdateChartRequest, ctx: Context
|
||||
|
||||
@@ -24,7 +24,7 @@ import time
|
||||
from typing import Any, Dict
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.chart.chart_utils import (
|
||||
@@ -44,7 +44,16 @@ from superset.mcp_service.utils.schema_utils import parse_request
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool(tags=["mutate"], class_permission_name="Chart", method_permission_name="write")
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="Chart",
|
||||
method_permission_name="write",
|
||||
annotations=ToolAnnotations(
|
||||
title="Update chart preview",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=True,
|
||||
),
|
||||
)
|
||||
@parse_request(UpdateChartPreviewRequest)
|
||||
def update_chart_preview(
|
||||
request: UpdateChartPreviewRequest, ctx: Context
|
||||
|
||||
@@ -26,7 +26,7 @@ import re
|
||||
from typing import Any, Dict
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.chart.schemas import serialize_chart_object
|
||||
@@ -305,7 +305,15 @@ def _ensure_layout_structure(
|
||||
layout["DASHBOARD_VERSION_KEY"] = "v2"
|
||||
|
||||
|
||||
@tool(tags=["mutate"], class_permission_name="Dashboard")
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="Dashboard",
|
||||
annotations=ToolAnnotations(
|
||||
title="Add chart to dashboard",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(AddChartToDashboardRequest)
|
||||
def add_chart_to_existing_dashboard(
|
||||
request: AddChartToDashboardRequest, ctx: Context
|
||||
|
||||
@@ -25,7 +25,7 @@ import logging
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.chart.schemas import serialize_chart_object
|
||||
@@ -178,7 +178,15 @@ def _generate_title_from_charts(chart_objects: List[Any]) -> str:
|
||||
return title
|
||||
|
||||
|
||||
@tool(tags=["mutate"], class_permission_name="Dashboard")
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="Dashboard",
|
||||
annotations=ToolAnnotations(
|
||||
title="Create dashboard",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GenerateDashboardRequest)
|
||||
def generate_dashboard(
|
||||
request: GenerateDashboardRequest, ctx: Context
|
||||
|
||||
@@ -27,7 +27,7 @@ from datetime import datetime, timezone
|
||||
|
||||
from fastmcp import Context
|
||||
from sqlalchemy.orm import subqueryload
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.dashboards.permalink.exceptions import DashboardPermalinkGetFailedError
|
||||
from superset.dashboards.permalink.types import DashboardPermalinkValue
|
||||
@@ -59,7 +59,15 @@ def _get_permalink_state(permalink_key: str) -> DashboardPermalinkValue | None:
|
||||
return None
|
||||
|
||||
|
||||
@tool(tags=["discovery"], class_permission_name="Dashboard")
|
||||
@tool(
|
||||
tags=["discovery"],
|
||||
class_permission_name="Dashboard",
|
||||
annotations=ToolAnnotations(
|
||||
title="Get dashboard info",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetDashboardInfoRequest)
|
||||
async def get_dashboard_info(
|
||||
request: GetDashboardInfoRequest, ctx: Context
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset.models.dashboard import Dashboard
|
||||
@@ -63,7 +63,15 @@ SORTABLE_DASHBOARD_COLUMNS = [
|
||||
]
|
||||
|
||||
|
||||
@tool(tags=["core"], class_permission_name="Dashboard")
|
||||
@tool(
|
||||
tags=["core"],
|
||||
class_permission_name="Dashboard",
|
||||
annotations=ToolAnnotations(
|
||||
title="List dashboards",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(ListDashboardsRequest)
|
||||
async def list_dashboards(
|
||||
request: ListDashboardsRequest, ctx: Context
|
||||
|
||||
@@ -27,7 +27,7 @@ from datetime import datetime, timezone
|
||||
|
||||
from fastmcp import Context
|
||||
from sqlalchemy.orm import joinedload, subqueryload
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.dataset.schemas import (
|
||||
@@ -42,7 +42,15 @@ from superset.mcp_service.utils.schema_utils import parse_request
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool(tags=["discovery"], class_permission_name="Dataset")
|
||||
@tool(
|
||||
tags=["discovery"],
|
||||
class_permission_name="Dataset",
|
||||
annotations=ToolAnnotations(
|
||||
title="Get dataset info",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetDatasetInfoRequest)
|
||||
async def get_dataset_info(
|
||||
request: GetDatasetInfoRequest, ctx: Context
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
@@ -61,7 +61,15 @@ SORTABLE_DATASET_COLUMNS = [
|
||||
]
|
||||
|
||||
|
||||
@tool(tags=["core"], class_permission_name="Dataset")
|
||||
@tool(
|
||||
tags=["core"],
|
||||
class_permission_name="Dataset",
|
||||
annotations=ToolAnnotations(
|
||||
title="List datasets",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(ListDatasetsRequest)
|
||||
async def list_datasets(request: ListDatasetsRequest, ctx: Context) -> DatasetList:
|
||||
"""List datasets with filtering and search.
|
||||
|
||||
@@ -26,7 +26,7 @@ from typing import Any, Dict
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.chart.chart_utils import (
|
||||
@@ -39,7 +39,15 @@ from superset.mcp_service.chart.schemas import (
|
||||
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=False,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GenerateExploreLinkRequest)
|
||||
async def generate_explore_link(
|
||||
request: GenerateExploreLinkRequest, ctx: Context
|
||||
|
||||
@@ -28,7 +28,7 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
from superset_core.queries.types import (
|
||||
CacheOptions,
|
||||
QueryOptions,
|
||||
@@ -55,6 +55,11 @@ logger = logging.getLogger(__name__)
|
||||
tags=["mutate"],
|
||||
class_permission_name="SQLLab",
|
||||
method_permission_name="execute_sql_query",
|
||||
annotations=ToolAnnotations(
|
||||
title="Execute SQL query",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=True,
|
||||
),
|
||||
)
|
||||
@parse_request(ExecuteSqlRequest)
|
||||
async def execute_sql(request: ExecuteSqlRequest, ctx: Context) -> ExecuteSqlResponse:
|
||||
|
||||
@@ -25,7 +25,7 @@ import logging
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.sql_lab.schemas import (
|
||||
@@ -38,7 +38,16 @@ from superset.mcp_service.utils.url_utils import get_superset_base_url
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool(tags=["explore"], class_permission_name="SQLLab", method_permission_name="read")
|
||||
@tool(
|
||||
tags=["explore"],
|
||||
class_permission_name="SQLLab",
|
||||
method_permission_name="read",
|
||||
annotations=ToolAnnotations(
|
||||
title="Open SQL Lab with context",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(OpenSqlLabRequest)
|
||||
def open_sql_lab_with_context(
|
||||
request: OpenSqlLabRequest, ctx: Context
|
||||
|
||||
@@ -29,7 +29,7 @@ import logging
|
||||
|
||||
from fastmcp import Context
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
from superset.exceptions import SupersetErrorException, SupersetSecurityException
|
||||
@@ -43,7 +43,16 @@ from superset.mcp_service.utils.schema_utils import parse_request
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool(tags=["mutate"])
|
||||
@tool(
|
||||
tags=["mutate"],
|
||||
class_permission_name="SQLLab",
|
||||
method_permission_name="write",
|
||||
annotations=ToolAnnotations(
|
||||
title="Save SQL query",
|
||||
readOnlyHint=False,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(SaveSqlQueryRequest)
|
||||
async def save_sql_query(
|
||||
request: SaveSqlQueryRequest, ctx: Context
|
||||
@@ -129,7 +138,7 @@ async def save_sql_query(
|
||||
except SQLAlchemyError as e:
|
||||
from superset import db
|
||||
|
||||
db.session.rollback()
|
||||
db.session.rollback() # pylint: disable=consider-using-transaction
|
||||
await ctx.error(
|
||||
"Failed to save SQL query: error=%s, database_id=%s"
|
||||
% (str(e), request.database_id)
|
||||
|
||||
@@ -23,7 +23,7 @@ InstanceInfoCore for flexible, extensible metrics calculation.
|
||||
import logging
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.mcp_core import InstanceInfoCore
|
||||
@@ -73,7 +73,14 @@ _instance_info_core = InstanceInfoCore(
|
||||
)
|
||||
|
||||
|
||||
@tool(tags=["core"])
|
||||
@tool(
|
||||
tags=["core"],
|
||||
annotations=ToolAnnotations(
|
||||
title="Get instance info",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetSupersetInstanceInfoRequest)
|
||||
def get_instance_info(
|
||||
request: GetSupersetInstanceInfoRequest, ctx: Context
|
||||
|
||||
@@ -27,7 +27,7 @@ import logging
|
||||
from typing import Callable, Literal
|
||||
|
||||
from fastmcp import Context
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.common.schema_discovery import (
|
||||
@@ -121,7 +121,14 @@ _SCHEMA_CORE_FACTORIES: dict[
|
||||
}
|
||||
|
||||
|
||||
@tool(tags=["discovery"])
|
||||
@tool(
|
||||
tags=["discovery"],
|
||||
annotations=ToolAnnotations(
|
||||
title="Get schema",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
@parse_request(GetSchemaRequest)
|
||||
async def get_schema(request: GetSchemaRequest, ctx: Context) -> GetSchemaResponse:
|
||||
"""
|
||||
|
||||
@@ -23,7 +23,7 @@ import platform
|
||||
import time
|
||||
|
||||
from flask import current_app
|
||||
from superset_core.mcp.decorators import tool
|
||||
from superset_core.mcp.decorators import tool, ToolAnnotations
|
||||
|
||||
from superset.extensions import event_logger
|
||||
from superset.mcp_service.system.schemas import HealthCheckResponse
|
||||
@@ -34,7 +34,14 @@ logger = logging.getLogger(__name__)
|
||||
_start_time = time.monotonic()
|
||||
|
||||
|
||||
@tool(tags=["core"])
|
||||
@tool(
|
||||
tags=["core"],
|
||||
annotations=ToolAnnotations(
|
||||
title="Health check",
|
||||
readOnlyHint=True,
|
||||
destructiveHint=False,
|
||||
),
|
||||
)
|
||||
async def health_check() -> HealthCheckResponse:
|
||||
"""
|
||||
Simple health check tool for testing the MCP service.
|
||||
|
||||
Reference in New Issue
Block a user