Skip to content

Commit b3b5b0c

Browse files
feat(mcp): add instance info tool, prompts, and resources
Add comprehensive MCP features for instance metadata, user guidance, and resource templates: **New Tools (1):** - get_superset_instance_info: Detailed instance statistics with dashboards, charts, datasets, activity metrics, and database breakdowns **New Prompts (2):** - superset_quickstart: Interactive onboarding guide for new users - create_chart_guided: AI-powered chart creation workflow with business context **New Resources (2):** - chart_configs: Example chart configuration templates for common visualizations - instance_metadata: Real-time instance metadata and statistics **Infrastructure Added:** - InstanceInfoCore: Configurable base class for comprehensive instance reporting with custom metric calculators - Added 7 new schemas to system/schemas.py: InstanceInfo, InstanceSummary, RecentActivity, DashboardBreakdown, DatabaseBreakdown, PopularContent, GetSupersetInstanceInfoRequest Changes: - Added get_superset_instance_info.py tool (268 lines) with detailed breakdown calculations - Added InstanceInfoCore class to mcp_core.py (173 lines) - Added quickstart.py prompt (94 lines) for user onboarding - Added create_chart_guided.py prompt (195 lines) for AI-assisted chart creation - Added chart_configs.py resource (362 lines) with example configurations - Added instance_metadata.py resource (107 lines) for real-time instance stats - Updated system/tool/__init__.py to export new instance info tool - Added placeholder __init__.py files for dashboard/dataset prompts and resources - Added 7 new Pydantic schemas for instance information responses Statistics: - 17 files changed (16 new, 2 modified) - ~1,200 lines of production code added - All pre-commit hooks passing fix(mcp): convert timestamp to ISO string in InstanceInfo schema Fixed Pydantic validation error where timestamp field was receiving a datetime object instead of the expected string type. The InstanceInfo schema requires timestamp as a string, so now we convert it using .isoformat(). fix(mcp): use BaseDAO instead of DAO Protocol in instance_metadata Replace DAO Protocol casts with BaseDAO[Any] to match InstanceInfoCore type signature. This fixes mypy type checking errors. feat(mcp): register prompts and resources in app.py and document in CLAUDE.md Add imports for chart and system prompts/resources to ensure they are registered with the MCP instance on startup. Update CLAUDE.md with comprehensive instructions for adding new prompts and resources. Changes to app.py: - Import chart.prompts module to register create_chart_guided prompt - Import chart.resources module to register chart_configs resource - Import system.prompts module to register superset_quickstart prompt - Import system.resources module to register instance_metadata resource - Add clear comment explaining prompt/resource registration pattern Changes to CLAUDE.md: - Update section title to include prompts and resources - Add "How to Add a New Prompt" section with complete workflow - Add "How to Add a New Resource" section with complete workflow - Add Quick Checklist for New Prompts - Add Quick Checklist for New Resources - Update line number references (210-242 for tools, 244-253 for prompts/resources) - Explain two-level import pattern (module __init__.py + app.py) This ensures all prompts and resources are available to MCP clients and provides clear documentation for future contributors.
1 parent dff5f80 commit b3b5b0c

File tree

17 files changed

+1315
-6
lines changed

17 files changed

+1315
-6
lines changed

superset/mcp_service/CLAUDE.md

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ superset/mcp_service/
6767
└── tool/
6868
```
6969

70-
## Critical Convention: Tool Registration
70+
## Critical Convention: Tool, Prompt, and Resource Registration
7171

72-
**IMPORTANT**: When creating new MCP tools, you MUST add their imports to `app.py` for auto-registration. Do NOT add them to `server.py` - that approach doesn't work properly.
72+
**IMPORTANT**: When creating new MCP tools, prompts, or resources, you MUST add their imports to `app.py` for auto-registration. Do NOT add them to `server.py` - that approach doesn't work properly.
7373

7474
### How to Add a New Tool
7575

7676
1. **Create the tool file** in the appropriate directory (e.g., `chart/tool/my_new_tool.py`)
7777
2. **Decorate with `@mcp.tool`** to register it with FastMCP
78-
3. **Add import to `app.py`** at the bottom of the file where other tools are imported (around line 207-224)
78+
3. **Add import to `app.py`** at the bottom of the file where other tools are imported (around line 210-242)
7979

8080
**Example**:
8181
```python
@@ -102,6 +102,74 @@ from superset.mcp_service.chart.tool import ( # noqa: F401, E402
102102

103103
**Why this matters**: Tools use `@mcp.tool` decorators and register automatically on import. The import MUST be in `app.py` at the bottom of the file (after the `mcp` instance is created). If you don't import the tool in `app.py`, it won't be available to MCP clients. DO NOT add imports to `server.py` - that file is for running the server only.
104104

105+
### How to Add a New Prompt
106+
107+
1. **Create the prompt file** in the appropriate directory (e.g., `chart/prompts/my_new_prompt.py`)
108+
2. **Decorate with `@mcp.prompt`** to register it with FastMCP
109+
3. **Add import to module's `__init__.py`** (e.g., `chart/prompts/__init__.py`)
110+
4. **Ensure module is imported in `app.py`** (around line 244-253)
111+
112+
**Example**:
113+
```python
114+
# superset/mcp_service/chart/prompts/my_new_prompt.py
115+
from superset.mcp_service.app import mcp
116+
from superset.mcp_service.auth import mcp_auth_hook
117+
118+
@mcp.prompt("my_new_prompt")
119+
@mcp_auth_hook
120+
async def my_new_prompt_handler(ctx: Context) -> str:
121+
"""Interactive prompt for doing something."""
122+
return "Prompt instructions here..."
123+
```
124+
125+
**Then add to `chart/prompts/__init__.py`**:
126+
```python
127+
# superset/mcp_service/chart/prompts/__init__.py
128+
from . import create_chart_guided # existing
129+
from . import my_new_prompt # ADD YOUR PROMPT HERE
130+
```
131+
132+
**Verify module import exists in `app.py`** (around line 248):
133+
```python
134+
# superset/mcp_service/app.py
135+
from superset.mcp_service.chart import prompts as chart_prompts # This imports all prompts
136+
```
137+
138+
### How to Add a New Resource
139+
140+
1. **Create the resource file** in the appropriate directory (e.g., `chart/resources/my_new_resource.py`)
141+
2. **Decorate with `@mcp.resource`** to register it with FastMCP
142+
3. **Add import to module's `__init__.py`** (e.g., `chart/resources/__init__.py`)
143+
4. **Ensure module is imported in `app.py`** (around line 244-253)
144+
145+
**Example**:
146+
```python
147+
# superset/mcp_service/chart/resources/my_new_resource.py
148+
from superset.mcp_service.app import mcp
149+
from superset.mcp_service.auth import mcp_auth_hook
150+
151+
@mcp.resource("superset://chart/my_resource")
152+
@mcp_auth_hook
153+
def get_my_resource() -> str:
154+
"""Resource description for LLMs."""
155+
return "Resource data here..."
156+
```
157+
158+
**Then add to `chart/resources/__init__.py`**:
159+
```python
160+
# superset/mcp_service/chart/resources/__init__.py
161+
from . import chart_configs # existing
162+
from . import my_new_resource # ADD YOUR RESOURCE HERE
163+
```
164+
165+
**Verify module import exists in `app.py`** (around line 249):
166+
```python
167+
# superset/mcp_service/app.py
168+
from superset.mcp_service.chart import resources as chart_resources # This imports all resources
169+
```
170+
171+
**Why this matters**: Prompts and resources work similarly to tools - they use decorators and register on import. The module-level imports (`chart/prompts/__init__.py`, `chart/resources/__init__.py`) ensure individual files are imported when the module is imported. The `app.py` imports ensure the modules are loaded when the MCP service starts.
172+
105173
## Tool Development Patterns
106174

107175
### 1. Use Core Classes for Reusability
@@ -417,12 +485,36 @@ MCP clients discover tools via:
417485
- [ ] Added `@mcp_auth_hook` decorator
418486
- [ ] Created Pydantic request/response schemas in `{module}/schemas.py`
419487
- [ ] Used DAO classes instead of direct queries
420-
- [ ] Added tool import to `app.py` (around line 207-224)
488+
- [ ] Added tool import to `app.py` (around line 210-242)
421489
- [ ] Added Apache license header to new files
422490
- [ ] Created unit tests in `tests/unit_tests/mcp_service/{module}/tool/test_{tool_name}.py`
423491
- [ ] Updated `DEFAULT_INSTRUCTIONS` in `app.py` if adding new capability
424492
- [ ] Tested locally with MCP client (e.g., Claude Desktop)
425493

494+
## Quick Checklist for New Prompts
495+
496+
- [ ] Created prompt file in `{module}/prompts/{prompt_name}.py`
497+
- [ ] Added `@mcp.prompt("prompt_name")` decorator
498+
- [ ] Added `@mcp_auth_hook` decorator
499+
- [ ] Made function async: `async def prompt_handler(ctx: Context) -> str`
500+
- [ ] Added import to `{module}/prompts/__init__.py`
501+
- [ ] Verified module import exists in `app.py` (around line 244-253)
502+
- [ ] Added Apache license header to new file
503+
- [ ] Updated `DEFAULT_INSTRUCTIONS` in `app.py` to list the new prompt
504+
- [ ] Tested locally with MCP client (e.g., Claude Desktop)
505+
506+
## Quick Checklist for New Resources
507+
508+
- [ ] Created resource file in `{module}/resources/{resource_name}.py`
509+
- [ ] Added `@mcp.resource("superset://{path}")` decorator with unique URI
510+
- [ ] Added `@mcp_auth_hook` decorator
511+
- [ ] Implemented resource data retrieval logic
512+
- [ ] Added import to `{module}/resources/__init__.py`
513+
- [ ] Verified module import exists in `app.py` (around line 244-253)
514+
- [ ] Added Apache license header to new file
515+
- [ ] Updated `DEFAULT_INSTRUCTIONS` in `app.py` to list the new resource
516+
- [ ] Tested locally with MCP client (e.g., Claude Desktop)
517+
426518
## Getting Help
427519

428520
- Check existing tool implementations for patterns (chart/tool/, dashboard/tool/)

superset/mcp_service/app.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ def create_mcp_app(
207207
# Import all MCP tools to register them with the mcp instance
208208
# NOTE: Always add new tool imports here when creating new MCP tools.
209209
# Tools use @mcp.tool decorators and register automatically on import.
210+
# Import prompts and resources to register them with the mcp instance
211+
# NOTE: Always add new prompt/resource imports here when creating new prompts/resources.
212+
# Prompts use @mcp.prompt decorators and resources use @mcp.resource decorators.
213+
# They register automatically on import, similar to tools.
214+
from superset.mcp_service.chart import ( # noqa: F401, E402
215+
prompts as chart_prompts,
216+
resources as chart_resources,
217+
)
210218
from superset.mcp_service.chart.tool import ( # noqa: F401, E402
211219
generate_chart,
212220
get_chart_available_filters,
@@ -236,7 +244,14 @@ def create_mcp_app(
236244
execute_sql,
237245
open_sql_lab_with_context,
238246
)
239-
from superset.mcp_service.system.tool import health_check # noqa: F401, E402
247+
from superset.mcp_service.system import ( # noqa: F401, E402
248+
prompts as system_prompts,
249+
resources as system_resources,
250+
)
251+
from superset.mcp_service.system.tool import ( # noqa: F401, E402
252+
get_superset_instance_info,
253+
health_check,
254+
)
240255

241256

242257
def init_fastmcp_server(
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
"""Chart prompts for Superset MCP service"""
19+
20+
# Import to register prompts when module is imported
21+
from . import create_chart_guided # noqa: F401
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
"""
19+
Chart prompts for visualization guidance
20+
"""
21+
22+
import logging
23+
24+
from superset.mcp_service.app import mcp
25+
from superset.mcp_service.auth import mcp_auth_hook
26+
27+
logger = logging.getLogger(__name__)
28+
29+
30+
@mcp.prompt("create_chart_guided")
31+
@mcp_auth_hook
32+
async def create_chart_guided_prompt(
33+
chart_type: str = "auto", business_goal: str = "exploration"
34+
) -> str:
35+
"""
36+
AI-powered chart creation guide following Anthropic's agent design principles.
37+
38+
This prompt implements:
39+
- Transparency: Clear reasoning at each step
40+
- Proactive Intelligence: Suggests insights before being asked
41+
- Context Awareness: Maintains conversational flow
42+
- Business Focus: Translates data into actionable insights
43+
- Validation: Verifies choices before proceeding
44+
- Natural Interaction: Conversational, not configuration-driven
45+
46+
Args:
47+
chart_type: Preferred chart type (auto, line, bar, pie, table, scatter, area)
48+
business_goal: Purpose (exploration, reporting, monitoring, presentation)
49+
"""
50+
51+
# Enhanced chart intelligence with business context
52+
chart_intelligence = {
53+
"line": {
54+
"description": "Time series visualization for trend analysis",
55+
"best_for": "Tracking performance over time, identifying patterns",
56+
"business_value": "Reveals growth trends, seasonality, and patterns",
57+
"data_requirements": "Temporal column + continuous metrics",
58+
},
59+
"bar": {
60+
"description": "Category comparison visualization",
61+
"best_for": "Ranking, comparisons, and performance by category",
62+
"business_value": "Identifies top performers, bottlenecks, and gaps",
63+
"data_requirements": "Categorical dimensions + aggregatable metrics",
64+
},
65+
"scatter": {
66+
"description": "Correlation and relationship analysis",
67+
"best_for": "Finding relationships, outlier detection, clustering",
68+
"business_value": "Uncovers hidden correlations and identifies anomalies",
69+
"data_requirements": "Two continuous variables, optional grouping",
70+
},
71+
"table": {
72+
"description": "Detailed data exploration and exact values",
73+
"best_for": "Detailed analysis, data validation, precise values",
74+
"business_value": "Provides granular insights and detailed reporting",
75+
"data_requirements": "Any combination of dimensions and metrics",
76+
},
77+
"area": {
78+
"description": "Volume and composition over time",
79+
"best_for": "Showing cumulative effects, stacked comparisons",
80+
"business_value": "Visualizes contribution and total volume trends",
81+
"data_requirements": "Temporal dimension + stackable metrics",
82+
},
83+
"auto": {
84+
"description": "AI-powered visualization recommendation",
85+
"best_for": "When you're not sure what chart type to use",
86+
"business_value": "Optimizes chart choice based on data characteristics",
87+
"data_requirements": "I'll analyze your data and recommend the best type",
88+
},
89+
}
90+
91+
# Business context intelligence
92+
goal_intelligence = {
93+
"exploration": {
94+
"approach": "Interactive discovery and pattern finding",
95+
"features": "Filters, drill-downs, multiple perspectives",
96+
"outcome": "Uncover hidden insights and generate hypotheses",
97+
},
98+
"reporting": {
99+
"approach": "Clear, professional, and consistent presentation",
100+
"features": "Clean design, appropriate aggregation, clear labels",
101+
"outcome": "Reliable, repeatable business reporting",
102+
},
103+
"monitoring": {
104+
"approach": "Real-time tracking with clear thresholds",
105+
"features": "Alert conditions, trend indicators, key metrics",
106+
"outcome": "Proactive issue detection and performance tracking",
107+
},
108+
"presentation": {
109+
"approach": "Compelling visual storytelling",
110+
"features": "Engaging colors, clear messaging, audience-appropriate detail",
111+
"outcome": "Persuasive data-driven presentations for stakeholders",
112+
},
113+
}
114+
115+
selected_chart = chart_intelligence.get(chart_type, chart_intelligence["auto"])
116+
selected_goal = goal_intelligence.get(
117+
business_goal, goal_intelligence["exploration"]
118+
)
119+
120+
return f"""🎯 **AI-Powered Chart Creation Assistant**
121+
122+
I'm your intelligent data visualization partner! Let me help you create charts.
123+
124+
**Your Visualization Goal:**
125+
📊 **Chart Focus**: {chart_type.title()} - {selected_chart["description"]}
126+
🎯 **Business Purpose**: {business_goal.title()} - {selected_goal["approach"]}
127+
💡 **Expected Value**: {selected_chart["business_value"]}
128+
129+
---
130+
131+
## 🚀 My Intelligent Approach
132+
133+
### **Phase 1: Data Intelligence** 📊
134+
I'll automatically analyze your dataset to understand:
135+
- **Data characteristics** (types, distributions, quality)
136+
- **Business relationships** (correlations, hierarchies, trends)
137+
- **Visualization opportunities** (what stories your data can tell)
138+
- **Performance considerations** (size, complexity, aggregation needs)
139+
140+
*Why this matters: The right chart depends on your data's unique characteristics*
141+
142+
### **Phase 2: Smart Recommendations** 🧠
143+
Based on your data analysis, I'll:
144+
- **Recommend optimal chart types** with confidence scores and reasoning
145+
- **Suggest meaningful metrics** that align with your business goal
146+
- **Identify interesting patterns** you might want to highlight
147+
- **Propose filters** to focus on what matters most
148+
149+
*Why this matters: I'll spot opportunities you might miss and save you time*
150+
151+
### **Phase 3: Intelligent Configuration** ⚙️
152+
I'll configure your chart with:
153+
- **Business-appropriate aggregations** (daily, weekly, monthly for time series)
154+
- **Meaningful labels and formatting** (currency, percentages, readable names)
155+
- **Performance optimizations** (appropriate limits, caching strategies)
156+
- **Visual best practices** (colors, scales, legends that enhance understanding)
157+
158+
*Why this matters: Proper configuration makes charts both beautiful and actionable*
159+
160+
### **Phase 4: Validation & Refinement** 🎯
161+
Before finalizing, I'll:
162+
- **Verify the chart answers your business question**
163+
- **Check data quality and completeness**
164+
- **Suggest improvements** based on visualization best practices
165+
- **Provide preview** so you can see exactly what you're getting
166+
167+
*Why this matters: Great charts require iteration and validation*
168+
169+
---
170+
171+
## 🎬 Let's Begin Your Data Story
172+
173+
I'm ready to be your proactive data exploration partner. Here's how we can start:
174+
175+
**Option 1: Quick Start** ⚡
176+
Tell me: *"What business question are you trying to answer?"*
177+
(e.g., "How are our sales trending?" or "Which products perform best?")
178+
179+
**Option 2: Dataset Exploration** 🔍
180+
I can show you available datasets: `list_datasets`
181+
Or explore a specific one: `get_dataset_info [dataset_id]`
182+
183+
**Option 3: Visual Inspiration** 🎨
184+
Browse pre-built chart configurations: `superset://chart/configs` resource
185+
Perfect for when you want to see examples of great charts!
186+
187+
**Option 4: Autonomous Discovery** 🤖
188+
Just point me to a dataset and say *"Find something interesting"*
189+
I'll explore autonomously and surface the most compelling insights!
190+
191+
---
192+
193+
💡 **Pro Tip**: Great charts combine business intuition with data analysis!
194+
195+
**What's your data challenge today?** 🚀"""

0 commit comments

Comments
 (0)