Skip to content

Commit cca1292

Browse files
Merge pull request #69 from MarcSkovMadsen/enhancement/hvplot-apps
Enhancement/hvplot apps
2 parents b1edca3 + 7dc863b commit cca1292

11 files changed

Lines changed: 627 additions & 11 deletions
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
description: Generate an implementation plan for a new HoloViz Panel app or feature.
3+
name: Panel App Planner
4+
tools: ['holoviz/*', 'read/readFile', 'read/problems', 'agent/runSubagent', 'web/fetch']
5+
handoffs:
6+
- label: Implement Plan
7+
agent: agent
8+
prompt: Implement the plan outlined above.
9+
send: false
10+
---
11+
# Planning instructions
12+
13+
You are in planning mode. Your task is to generate an implementation plan for a Panel app, a new feature or for refactoring existing code.
14+
15+
Don't make any code edits, just generate a plan.
16+
17+
The plan consists of a Markdown document that describes the implementation plan, including the following sections:
18+
19+
* Overview: A brief description of the feature or refactoring task.
20+
* Requirements: A list of requirements for the feature or refactoring task.
21+
* Implementation Steps: A detailed list of steps to implement the feature or refactoring task.
22+
* Testing: A list of tests that need to be implemented to verify the feature or refactoring task.
23+
24+
Please always adhere to the panel and panel-material-ui best practices.

docs/explanation/tools.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ Tools for searching and accessing HoloViz documentation.
182182

183183
Tools for working with hvPlot plotting functionality.
184184

185-
### list_plot_types
185+
### hvplot_list_plot_types
186186

187187
**Purpose**: List all available hvPlot plot types.
188188

@@ -192,7 +192,9 @@ Tools for working with hvPlot plotting functionality.
192192

193193
**Example Query**: *"What plot types does hvPlot support?"*
194194

195-
### get_docstring
195+
**Demo**: [https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_list_plot_types](https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_list_plot_types)
196+
197+
### hvplot_get_docstring
196198

197199
**Purpose**: Get the docstring for a specific hvPlot plot type.
198200

@@ -205,7 +207,9 @@ Tools for working with hvPlot plotting functionality.
205207

206208
**Example Query**: *"How do I use hvPlot's scatter plot?"*
207209

208-
### get_signature
210+
**Demo**: [https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_get_docstring](https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_get_docstring)
211+
212+
### hvplot_get_signature
209213

210214
**Purpose**: Get the function signature for a specific hvPlot plot type.
211215

@@ -216,6 +220,8 @@ Tools for working with hvPlot plotting functionality.
216220

217221
**Returns**: Function signature with parameter information.
218222

223+
**Demo**: [https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_get_signature](https://awesome-panel-holoviz-mcp-ui.hf.space/hvplot_get_signature)
224+
219225
## Tool Categories by Use Case
220226

221227
### Discovery

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@ dependencies = [
4242
"chromadb",
4343
"fastmcp",
4444
"GitPython",
45+
"matplotlib",
4546
"nbconvert",
4647
"packaging",
4748
"panel-material-ui",
4849
"panel",
50+
"plotly",
4951
"pydantic>=2.0",
5052
"PyYAML",
5153
"watchfiles",
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
"""An app to retrieve hvPlot docstring documentation for plot types.
2+
3+
An interactive version of the holoviz_mcp.hvplot_mcp.server.get_docstring tool.
4+
"""
5+
6+
import panel as pn
7+
import panel_material_ui as pmui
8+
import param
9+
10+
from holoviz_mcp.client import call_tool
11+
12+
pn.extension()
13+
14+
pn.pane.Markdown.disable_anchors = True
15+
16+
ABOUT = """
17+
## hvPlot Get Docstring Tool
18+
19+
Get comprehensive documentation for any hvPlot plot type, equivalent to calling `hvplot.help(plot_type)` in Python.
20+
21+
### How to Use This Tool
22+
23+
1. **Plot Type**: Select the type of plot you want documentation for (e.g., "line", "scatter", "bar")
24+
2. **Configuration Options**: Adjust what content to include:
25+
- **Include Docstring**: Main documentation and examples
26+
- **Include Generic Options**: Options shared by all plot types
27+
- **Style Backend**: Get options specific to matplotlib, bokeh, plotly, or auto-detect
28+
29+
### Use Cases
30+
31+
**Learn hvPlot plotting**:
32+
33+
- Understand available parameters for customization
34+
- Explore examples and usage patterns
35+
- Compare options across different backends
36+
- Get quick reference while coding
37+
38+
**Plot Development**:
39+
40+
- Check parameter names and types before coding
41+
- Discover advanced customization options
42+
- Learn best practices from examples
43+
- Understand backend differences
44+
45+
### Configuration Options
46+
47+
- **Plot Type**: Choose from all available hvPlot plot types
48+
- **Include Docstring**: Toggle main documentation (default: True)
49+
- **Include Generic Options**: Toggle shared plotting options (default: True)
50+
- **Style Backend**: Select specific backend or auto-detect (default: auto)
51+
52+
### Learn More
53+
54+
For more information visit: [hvPlot Documentation](https://hvplot.holoviz.org/) and [HoloViz MCP](https://marcskovmadsen.github.io/holoviz-mcp/).
55+
"""
56+
57+
58+
class GetDocstringConfiguration(param.Parameterized):
59+
"""Configuration for hvPlot get_docstring tool."""
60+
61+
plot_type = param.Selector(default="line", objects=["line"], label="Plot Type")
62+
docstring = param.Boolean(default=True, label="Include Docstring")
63+
generic = param.Boolean(default=True, label="Include Generic Options")
64+
style = param.Selector(default=True, objects=[True, "matplotlib", "bokeh", "plotly"], label="Style Backend")
65+
66+
result = param.String(default="", doc="Docstring result")
67+
loading = param.Boolean(default=False, doc="Loading state")
68+
error_message = param.String(default="", doc="Error message if request fails")
69+
70+
def __init__(self, **params):
71+
super().__init__(**params)
72+
if pn.state.location:
73+
pn.state.location.sync(self, ["plot_type", "docstring", "generic", "style"])
74+
# Initialize with available plot types
75+
pn.state.execute(self._update_plot_types)
76+
# Load default docstring on startup
77+
pn.state.execute(self._update_result)
78+
79+
async def _update_plot_types(self):
80+
"""Update the available plot types."""
81+
try:
82+
result = await call_tool("hvplot_list_plot_types", {})
83+
plot_types = sorted(result.data)
84+
self.param.plot_type.objects = plot_types
85+
except Exception as e:
86+
self.error_message = f"Failed to load plot types: {str(e)}"
87+
88+
@param.depends("plot_type", "docstring", "generic", "style", watch=True)
89+
async def _update_result(self):
90+
"""Execute tool and update result."""
91+
self.loading = True
92+
self.error_message = ""
93+
self.result = ""
94+
95+
params = {"plot_type": self.plot_type, "docstring": self.docstring, "generic": self.generic, "style": self.style}
96+
97+
try:
98+
result = await call_tool("hvplot_get_docstring", params)
99+
if result and hasattr(result, "structured_content"):
100+
if result.data:
101+
self.result = result.data.replace("``", "`")
102+
else:
103+
self.error_message = "No docstring returned for the specified plot type"
104+
else:
105+
self.error_message = "Request returned no data"
106+
107+
except Exception as e:
108+
error_str = str(e)
109+
self.error_message = f"Request failed: {error_str}"
110+
finally:
111+
self.loading = False
112+
113+
114+
class DocstringViewer(pn.viewable.Viewer):
115+
"""Viewer for displaying hvPlot docstring."""
116+
117+
result = param.String(default="", allow_refs=True, doc="Docstring content")
118+
119+
def __init__(self, **params):
120+
super().__init__(**params)
121+
122+
raw_view = pn.pane.Str(
123+
self.param.result,
124+
name="Raw Response",
125+
sizing_mode="stretch_width",
126+
styles={"font-family": "monospace", "white-space": "pre-wrap"},
127+
)
128+
129+
self._layout = raw_view
130+
131+
def __panel__(self):
132+
"""Return the Panel layout."""
133+
return self._layout
134+
135+
136+
class HvplotGetDocstringApp(pn.viewable.Viewer):
137+
"""Main application for retrieving hvPlot docstrings."""
138+
139+
title = param.String(default="HoloViz MCP - hvplot_get_docstring Tool Demo")
140+
141+
def __init__(self, **params):
142+
super().__init__(**params)
143+
144+
# Create configuration and viewer
145+
self._config = GetDocstringConfiguration()
146+
self._docstring_viewer = DocstringViewer(result=self._config.param.result)
147+
148+
with pn.config.set(sizing_mode="stretch_width"):
149+
self._plot_type_select = pmui.Select.from_param(
150+
self._config.param.plot_type,
151+
label="Plot Type",
152+
variant="outlined",
153+
sx={"width": "100%"},
154+
)
155+
156+
self._docstring_switch = pmui.Switch.from_param(
157+
self._config.param.docstring,
158+
label="Include Docstring",
159+
)
160+
161+
self._generic_switch = pmui.Switch.from_param(
162+
self._config.param.generic,
163+
label="Include Generic Options",
164+
)
165+
166+
self._style_select = pmui.Select.from_param(
167+
self._config.param.style,
168+
label="Style Backend",
169+
variant="outlined",
170+
sx={"width": "100%"},
171+
)
172+
173+
# Status indicators
174+
self._status_pane = pn.pane.Markdown(self._status_text, sizing_mode="stretch_width")
175+
self._error_pane = pmui.Alert(
176+
self._error_text,
177+
alert_type="error",
178+
visible=pn.rx(bool)(self._config.param.error_message),
179+
sizing_mode="stretch_width",
180+
)
181+
182+
# Quick access buttons for common plot types
183+
# Create static layout structure
184+
self._sidebar = pn.Column(
185+
pmui.Typography("## Documentation Lookup", variant="h6"),
186+
self._plot_type_select,
187+
pmui.Typography("### Options", variant="subtitle2", margin=(15, 0, 5, 0)),
188+
self._docstring_switch,
189+
self._generic_switch,
190+
self._style_select,
191+
self._error_pane,
192+
self._status_pane,
193+
sizing_mode="stretch_width",
194+
)
195+
196+
self._main = pmui.Container(self._docstring_viewer, width_option="xl", margin=10)
197+
198+
@param.depends("_config.loading", "_config.result")
199+
def _status_text(self):
200+
"""Generate status message."""
201+
if self._config.loading:
202+
return "_Loading docstring..._"
203+
elif self._config.result.strip():
204+
char_count = len(self._config.result)
205+
plot_type = self._config.plot_type
206+
return f"_Successfully loaded **{char_count} characters** of documentation for **{plot_type}** plot_"
207+
return ""
208+
209+
@param.depends("_config.error_message")
210+
def _error_text(self):
211+
"""Get error message."""
212+
return self._config.error_message
213+
214+
def __panel__(self):
215+
"""Return the main page layout."""
216+
with pn.config.set(sizing_mode="stretch_width"):
217+
# About button and dialog
218+
about_button = pmui.IconButton(
219+
label="About",
220+
icon="info",
221+
description="Click to learn about the hvPlot Get Docstring Tool.",
222+
sizing_mode="fixed",
223+
width=40,
224+
height=40,
225+
color="light",
226+
margin=(10, 0),
227+
)
228+
about = pmui.Dialog(ABOUT, close_on_click=True, width=0)
229+
about_button.js_on_click(args={"about": about}, code="about.data.open = true")
230+
231+
# GitHub button
232+
github_button = pmui.IconButton(
233+
label="Github",
234+
icon="star",
235+
description="Give HoloViz-MCP a star on GitHub",
236+
sizing_mode="fixed",
237+
width=40,
238+
height=40,
239+
color="light",
240+
margin=(10, 0),
241+
href="https://github.com/MarcSkovMadsen/holoviz-mcp",
242+
target="_blank",
243+
)
244+
245+
return pmui.Page(
246+
title=self.title,
247+
site_url="./",
248+
sidebar=[self._sidebar],
249+
header=[pn.Row(pn.Spacer(), about_button, github_button, align="end")],
250+
main=[about, self._main],
251+
)
252+
253+
254+
if pn.state.served:
255+
HvplotGetDocstringApp().servable()

0 commit comments

Comments
 (0)