holoviz-mcp 0.0.1a0__py3-none-any.whl → 0.0.1a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of holoviz-mcp might be problematic. Click here for more details.
- holoviz_mcp/__init__.py +18 -0
- holoviz_mcp/apps/__init__.py +1 -0
- holoviz_mcp/apps/configuration_viewer.py +116 -0
- holoviz_mcp/apps/search.py +314 -0
- holoviz_mcp/config/__init__.py +31 -0
- holoviz_mcp/config/config.yaml +167 -0
- holoviz_mcp/config/loader.py +308 -0
- holoviz_mcp/config/models.py +216 -0
- holoviz_mcp/config/resources/best-practices/hvplot.md +62 -0
- holoviz_mcp/config/resources/best-practices/panel-material-ui.md +318 -0
- holoviz_mcp/config/resources/best-practices/panel.md +294 -0
- holoviz_mcp/config/schema.json +203 -0
- holoviz_mcp/docs_mcp/__init__.py +1 -0
- holoviz_mcp/docs_mcp/data.py +963 -0
- holoviz_mcp/docs_mcp/models.py +21 -0
- holoviz_mcp/docs_mcp/pages_design.md +407 -0
- holoviz_mcp/docs_mcp/server.py +220 -0
- holoviz_mcp/hvplot_mcp/__init__.py +1 -0
- holoviz_mcp/hvplot_mcp/server.py +152 -0
- holoviz_mcp/panel_mcp/__init__.py +17 -0
- holoviz_mcp/panel_mcp/data.py +316 -0
- holoviz_mcp/panel_mcp/models.py +124 -0
- holoviz_mcp/panel_mcp/server.py +650 -0
- holoviz_mcp/py.typed +0 -0
- holoviz_mcp/serve.py +34 -0
- holoviz_mcp/server.py +77 -0
- holoviz_mcp/shared/__init__.py +1 -0
- holoviz_mcp/shared/extract_tools.py +74 -0
- holoviz_mcp-0.0.1a2.dist-info/METADATA +641 -0
- holoviz_mcp-0.0.1a2.dist-info/RECORD +33 -0
- {holoviz_mcp-0.0.1a0.dist-info → holoviz_mcp-0.0.1a2.dist-info}/WHEEL +1 -2
- holoviz_mcp-0.0.1a2.dist-info/entry_points.txt +4 -0
- holoviz_mcp-0.0.1a2.dist-info/licenses/LICENSE.txt +30 -0
- holoviz_mcp-0.0.1a0.dist-info/METADATA +0 -6
- holoviz_mcp-0.0.1a0.dist-info/RECORD +0 -5
- holoviz_mcp-0.0.1a0.dist-info/top_level.txt +0 -1
- main.py +0 -6
holoviz_mcp/__init__.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Accessible imports for the holoviz_mcp package."""
|
|
2
|
+
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
from holoviz_mcp.server import main
|
|
7
|
+
from holoviz_mcp.server import mcp
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
__version__ = importlib.metadata.version(__name__)
|
|
11
|
+
except importlib.metadata.PackageNotFoundError as e: # pragma: no cover
|
|
12
|
+
warnings.warn(f"Could not determine version of {__name__}\n{e!s}", stacklevel=2)
|
|
13
|
+
__version__ = "unknown"
|
|
14
|
+
|
|
15
|
+
__all__: list[str] = ["mcp"]
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Here for technical reasons."""
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""An app to view the holoviz-mcp configuration using Panel and Panel Material UI best practices.
|
|
2
|
+
|
|
3
|
+
- Uses parameter-driven architecture for reactivity and maintainability
|
|
4
|
+
- Uses a Panel template for layout and branding
|
|
5
|
+
- Uses only Panel Material UI components for UI widgets
|
|
6
|
+
- Separates config loading logic from UI logic
|
|
7
|
+
- Responsive and modern design
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
import panel as pn
|
|
13
|
+
import panel_material_ui as pmui
|
|
14
|
+
import param
|
|
15
|
+
|
|
16
|
+
from holoviz_mcp.config.loader import HoloVizMCPConfig
|
|
17
|
+
from holoviz_mcp.config.loader import get_config
|
|
18
|
+
from holoviz_mcp.config.loader import get_config_loader
|
|
19
|
+
|
|
20
|
+
pn.extension("jsoneditor")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ConfigViewer(param.Parameterized):
|
|
24
|
+
"""
|
|
25
|
+
A Panel Material UI app for viewing holoviz-mcp configuration.
|
|
26
|
+
|
|
27
|
+
Features:
|
|
28
|
+
- Parameter-driven reactivity
|
|
29
|
+
- Modern, responsive UI using Panel Material UI
|
|
30
|
+
- Separation of config loading and UI logic
|
|
31
|
+
- Supports dark and light themes
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
config_source = param.Selector(objects=["Combined", "Default", "User"], default="Combined", doc="Which configuration to show")
|
|
35
|
+
dark_theme = param.Boolean(default=False, doc="Use dark theme for the JSON editor", allow_refs=True)
|
|
36
|
+
|
|
37
|
+
def __init__(self, **params):
|
|
38
|
+
"""
|
|
39
|
+
Initialize the ConfigViewer.
|
|
40
|
+
|
|
41
|
+
Loads environment config and config loader.
|
|
42
|
+
"""
|
|
43
|
+
super().__init__(**params)
|
|
44
|
+
self._env_config = HoloVizMCPConfig()
|
|
45
|
+
self._loader = get_config_loader()
|
|
46
|
+
|
|
47
|
+
@param.depends("config_source")
|
|
48
|
+
def _config_json(self):
|
|
49
|
+
"""Get the selected configuration as a JSON string."""
|
|
50
|
+
if self.config_source == "Combined":
|
|
51
|
+
return get_config().model_dump_json(indent=2)
|
|
52
|
+
elif self.config_source == "Default":
|
|
53
|
+
default_config_file = self._env_config.default_dir / "config.yaml"
|
|
54
|
+
default_config = self._loader._load_yaml_file(default_config_file)
|
|
55
|
+
return json.dumps(default_config, indent=2)
|
|
56
|
+
elif self.config_source == "User":
|
|
57
|
+
user_config_file = self._env_config.user_dir / "config.yaml"
|
|
58
|
+
user_config = self._loader._load_yaml_file(user_config_file)
|
|
59
|
+
return json.dumps(user_config, indent=2)
|
|
60
|
+
return json.dumps({"error": "Unknown config source"}, indent=2)
|
|
61
|
+
|
|
62
|
+
@param.depends("dark_theme")
|
|
63
|
+
def _theme(self):
|
|
64
|
+
"""Get the theme for the JSON editor ('dark' or 'light')."""
|
|
65
|
+
return "dark" if self.dark_theme else "light"
|
|
66
|
+
|
|
67
|
+
def view(self):
|
|
68
|
+
"""Get the main view for the configuration viewer app."""
|
|
69
|
+
selector = pmui.RadioButtonGroup.from_param(
|
|
70
|
+
self.param.config_source,
|
|
71
|
+
color="primary",
|
|
72
|
+
orientation="horizontal",
|
|
73
|
+
sx={"mb": 2},
|
|
74
|
+
)
|
|
75
|
+
json_pane = pn.pane.JSON(
|
|
76
|
+
self._config_json,
|
|
77
|
+
name="holoviz-mcp config",
|
|
78
|
+
theme=self._theme,
|
|
79
|
+
sizing_mode="stretch_width",
|
|
80
|
+
)
|
|
81
|
+
card = pmui.Paper(
|
|
82
|
+
pmui.Column(
|
|
83
|
+
pmui.Typography(
|
|
84
|
+
"HoloViz MCP Configuration Viewer",
|
|
85
|
+
variant="h5",
|
|
86
|
+
sx={"fontWeight": 700, "mb": 2},
|
|
87
|
+
),
|
|
88
|
+
selector,
|
|
89
|
+
json_pane,
|
|
90
|
+
),
|
|
91
|
+
elevation=3,
|
|
92
|
+
sx={"maxWidth": "900px", "margin": "auto", "padding": "32px"},
|
|
93
|
+
)
|
|
94
|
+
return pmui.Container(card)
|
|
95
|
+
|
|
96
|
+
def _update_source(self, selector):
|
|
97
|
+
"""Update the config source from the selector widget."""
|
|
98
|
+
self.config_source = selector.value
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def create_app(cls):
|
|
102
|
+
"""Create and return the Panel Material UI app page."""
|
|
103
|
+
viewer = cls()
|
|
104
|
+
page = pmui.Page(
|
|
105
|
+
title="HoloViz MCP Configuration Viewer",
|
|
106
|
+
main=[viewer.view()],
|
|
107
|
+
site_url="./",
|
|
108
|
+
)
|
|
109
|
+
viewer.dark_theme = page.param.dark_theme
|
|
110
|
+
return page
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
ConfigViewer.create_app().show(port=5007, open=True, dev=True)
|
|
115
|
+
elif pn.state.served:
|
|
116
|
+
ConfigViewer.create_app().servable()
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""A search application for exploring the HoloViz MCP docs_search tool."""
|
|
2
|
+
|
|
3
|
+
import panel as pn
|
|
4
|
+
import panel_material_ui as pmui
|
|
5
|
+
import param
|
|
6
|
+
|
|
7
|
+
from holoviz_mcp.docs_mcp.data import DocumentationIndexer
|
|
8
|
+
from holoviz_mcp.docs_mcp.models import Document
|
|
9
|
+
|
|
10
|
+
URL_CSS = """
|
|
11
|
+
#url, .url {
|
|
12
|
+
display: inline-block;
|
|
13
|
+
margin-bottom: 8px;
|
|
14
|
+
border: 1.5px solid #e0e0e0;
|
|
15
|
+
border-radius: 10px;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
padding: 10px;
|
|
18
|
+
width: 100%;
|
|
19
|
+
margin-top: 10px;
|
|
20
|
+
}
|
|
21
|
+
#iframe {
|
|
22
|
+
height: calc(100% - 100px);
|
|
23
|
+
width: 100%;
|
|
24
|
+
border: 1.5px solid #e0e0e0;
|
|
25
|
+
border-radius: 10px;
|
|
26
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.07);
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
}
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
ALL = "ALL"
|
|
32
|
+
|
|
33
|
+
ABOUT = """
|
|
34
|
+
## Documentation Search Tool
|
|
35
|
+
|
|
36
|
+
This tool provides powerful semantic search capabilities across the extended HoloViz documentation.
|
|
37
|
+
|
|
38
|
+
### Search Parameters
|
|
39
|
+
|
|
40
|
+
- **`query`**: Your search text - the tool uses semantic similarity to find the most relevant documents
|
|
41
|
+
- **`project`**: Filter results by specific project (e.g., "panel", "hvplot", "datashader") or search across all projects
|
|
42
|
+
- **`max_results`**: Control the number of results returned (1-50 documents)
|
|
43
|
+
- **`content`**: Choose whether to include full document content or just metadata for faster responses
|
|
44
|
+
|
|
45
|
+
### What's Indexed
|
|
46
|
+
|
|
47
|
+
By default, the complete HoloViz ecosystem documentation is indexed and searchable, including:
|
|
48
|
+
|
|
49
|
+
- [Panel](https://panel.holoviz.org), [HvPlot](https://hvplot.holoviz.org), [Datashader](https://datashader.holoviz.org), [HoloViews](https://holoviews.org), [GeoViews](https://geoviews.org)
|
|
50
|
+
- [Param](https://param.holoviz.org), [Colorcet](https://colorcet.holoviz.org), and core HoloViz guides
|
|
51
|
+
|
|
52
|
+
The system is extensible and can be configured to include additional projects like Altair, Bokeh, Pandas, Plotly, Polars or even your own custom documentation.
|
|
53
|
+
|
|
54
|
+
### Why Use This Tool?
|
|
55
|
+
|
|
56
|
+
Unlike simple keyword search, this tool understands context and meaning, helping you discover relevant information even when you don't know the exact terminology used in the documentation.
|
|
57
|
+
|
|
58
|
+
For LLMs this tool provides a structured way to access and retrieve relevant documentation, when using the HoloViz ecosystem.
|
|
59
|
+
|
|
60
|
+
### Learn More
|
|
61
|
+
|
|
62
|
+
For more information about this project, including setup instructions and advanced configuration options, visit: [HoloViz MCP](https://github.com/MarcSkovMadsen/holoviz-mcp).
|
|
63
|
+
""" # noqa: E501
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@pn.cache
|
|
67
|
+
def _get_indexer() -> DocumentationIndexer:
|
|
68
|
+
"""Get or create the global DocumentationIndexer instance."""
|
|
69
|
+
return DocumentationIndexer()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SearchConfiguration(param.Parameterized):
|
|
73
|
+
"""
|
|
74
|
+
Configuration for the search application.
|
|
75
|
+
|
|
76
|
+
Parameters correspond to the arguments of the search_documentation function.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
query = param.String(default="What is HoloViz?", doc="Search text for semantic similarity search across the documentation")
|
|
80
|
+
|
|
81
|
+
project = param.Selector(
|
|
82
|
+
default=ALL,
|
|
83
|
+
objects=[ALL, "panel", "hvplot", "datashader", "holoviews", "geoviews", "param", "colorcet", "holoviz"],
|
|
84
|
+
doc="Filter results to a specific project. Select 'all' for all projects.",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
max_results = param.Integer(default=5, bounds=(1, 50), doc="Maximum number of search results to return")
|
|
88
|
+
|
|
89
|
+
content = param.Boolean(
|
|
90
|
+
default=True, label="Include Full Content", doc="Include full document content in results. Disable for faster and simpler responses with metadata only."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
search = param.Event(doc="Event to trigger search when parameters change")
|
|
94
|
+
|
|
95
|
+
results = param.List(item_type=Document, doc="Search results as a list of Documents", precedence=-1)
|
|
96
|
+
|
|
97
|
+
def __init__(self, **params):
|
|
98
|
+
"""Initialize the SearchConfiguration with default values."""
|
|
99
|
+
super().__init__(**params)
|
|
100
|
+
|
|
101
|
+
if pn.state.location:
|
|
102
|
+
pn.state.location.sync(self, parameters=["query", "project", "content", "max_results"])
|
|
103
|
+
|
|
104
|
+
if self.query:
|
|
105
|
+
self.param.trigger("search")
|
|
106
|
+
|
|
107
|
+
@param.depends("search", watch=True)
|
|
108
|
+
async def _update_results(self):
|
|
109
|
+
indexer = _get_indexer()
|
|
110
|
+
project = self.project if self.project != ALL else None
|
|
111
|
+
self.results = await indexer.search(self.query, project=project, content=self.content, max_results=self.max_results)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
async def _update_projects(self):
|
|
115
|
+
self.config.param.project.objects = [ALL] + await _get_indexer().list_projects() # Ensure indexer is initialized
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class DocumentsMenuList(pn.viewable.Viewer):
|
|
119
|
+
"""
|
|
120
|
+
A Menu for selecting a Document.
|
|
121
|
+
|
|
122
|
+
This menu allows users to select a Document from a list of Documents.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
value = param.ClassSelector(
|
|
126
|
+
default=None,
|
|
127
|
+
class_=Document,
|
|
128
|
+
allow_None=True,
|
|
129
|
+
doc="""
|
|
130
|
+
Last clicked Document.""",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
documents = param.List(item_type=Document, doc="List of Documents to display in the menu", allow_refs=True)
|
|
134
|
+
|
|
135
|
+
def __panel__(self):
|
|
136
|
+
"""Create the Panel layout."""
|
|
137
|
+
menu = pmui.MenuList(items=self._items)
|
|
138
|
+
pn.bind(self._update_value, menu.param.active, watch=True)
|
|
139
|
+
return menu
|
|
140
|
+
|
|
141
|
+
@param.depends("documents", watch=True)
|
|
142
|
+
def _reset_value(self):
|
|
143
|
+
"""Reset the value when the documents change."""
|
|
144
|
+
if self.documents:
|
|
145
|
+
self.value = self.documents[0]
|
|
146
|
+
else:
|
|
147
|
+
self.value = None
|
|
148
|
+
|
|
149
|
+
def _update_value(self, event):
|
|
150
|
+
if event and self.documents:
|
|
151
|
+
index = event[0]
|
|
152
|
+
self.value = self.documents[index]
|
|
153
|
+
else:
|
|
154
|
+
self.value = None
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def _to_secondary(document: Document):
|
|
158
|
+
"""Convert a Document to a secondary text for the menu item."""
|
|
159
|
+
return f"""{document.description}
|
|
160
|
+
|
|
161
|
+
Relevance Score: {document.relevance_score or 'N/A':0.2f}
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
@param.depends("documents")
|
|
165
|
+
def _items(self):
|
|
166
|
+
return [
|
|
167
|
+
{"label": f"{index+1}. {document.project}: {document.title}", "icon": None, "secondary": self._to_secondary(document)}
|
|
168
|
+
for index, document in enumerate(self.documents)
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class DocumentView(pn.viewable.Viewer):
|
|
173
|
+
"""
|
|
174
|
+
A Panel Material UI view for displaying a single Document.
|
|
175
|
+
|
|
176
|
+
This view renders the content of a Document in a tabbed interface.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
document = param.ClassSelector(class_=Document, doc="Document to display", allow_refs=True)
|
|
180
|
+
|
|
181
|
+
def __panel__(self):
|
|
182
|
+
"""Create the Panel layout."""
|
|
183
|
+
return pmui.Tabs(
|
|
184
|
+
("URL", pn.pane.HTML(self._url_view, sizing_mode="stretch_both", stylesheets=[URL_CSS])),
|
|
185
|
+
# Hack Column Scroll
|
|
186
|
+
("CONTENT", pn.Column(pn.pane.Markdown(self._source_view, sizing_mode="stretch_width", stylesheets=[URL_CSS]), sizing_mode="stretch_both", scroll=True)),
|
|
187
|
+
("DOCUMENT", pn.Column(pn.pane.JSON(self._json_view, sizing_mode="stretch_both"), scroll=True)),
|
|
188
|
+
dynamic=True,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
@param.depends("document")
|
|
192
|
+
def _js_copy_url_to_clipboard(self):
|
|
193
|
+
return f"navigator.clipboard.writeText('{self._url()}');"
|
|
194
|
+
|
|
195
|
+
@param.depends("document")
|
|
196
|
+
def _url(self):
|
|
197
|
+
"""Get the URL of the document."""
|
|
198
|
+
if not self.document:
|
|
199
|
+
return ""
|
|
200
|
+
url = self.document.url
|
|
201
|
+
return f"[{url}]({url})"
|
|
202
|
+
|
|
203
|
+
@param.depends("document")
|
|
204
|
+
def _source_url(self):
|
|
205
|
+
"""Get the source URL of the document."""
|
|
206
|
+
if not self.document:
|
|
207
|
+
return ""
|
|
208
|
+
return f"[{self.document.source_url}]({self.document.source_url})"
|
|
209
|
+
|
|
210
|
+
@param.depends("document")
|
|
211
|
+
def _json_view(self):
|
|
212
|
+
"""Create a JSON view for the document."""
|
|
213
|
+
if not self.document:
|
|
214
|
+
return None
|
|
215
|
+
return self.document.model_dump_json()
|
|
216
|
+
|
|
217
|
+
@param.depends("document")
|
|
218
|
+
def _source_view(self):
|
|
219
|
+
"""Create a source view for the document."""
|
|
220
|
+
if not self.document:
|
|
221
|
+
return "No document selected."
|
|
222
|
+
if not self.document.content:
|
|
223
|
+
return "No content available for this document."
|
|
224
|
+
if self.document.source_path.endswith(".rst"):
|
|
225
|
+
language = "restructuredtext"
|
|
226
|
+
else:
|
|
227
|
+
language = "markdown"
|
|
228
|
+
|
|
229
|
+
return f"""
|
|
230
|
+
<a class="url" href="{self.document.source_url}" target="_blank">{self.document.source_url}</a>
|
|
231
|
+
|
|
232
|
+
`````{language}
|
|
233
|
+
{self.document.content}
|
|
234
|
+
`````
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
@param.depends("document")
|
|
238
|
+
def _url_view(self):
|
|
239
|
+
"""Create a URL view for the document."""
|
|
240
|
+
if not self.document:
|
|
241
|
+
return "No document selected."
|
|
242
|
+
if not self.document.url:
|
|
243
|
+
return "No URL available for this document."
|
|
244
|
+
|
|
245
|
+
return f"""\
|
|
246
|
+
<a id="url" href="{self.document.url}" target="_blank">{self.document.url}</a>
|
|
247
|
+
<iframe id="iframe" src="{self.document.url}"></iframe>
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class SearchApp(pn.viewable.Viewer):
|
|
252
|
+
"""
|
|
253
|
+
A Panel Material UI app for searching HoloViz MCP documentation.
|
|
254
|
+
|
|
255
|
+
Features:
|
|
256
|
+
- Parameter-driven reactivity
|
|
257
|
+
- Modern, responsive UI using Panel Material UI
|
|
258
|
+
- Integration with HoloViz MCP docs_search tool
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
title = param.String(default="HoloViz MCP Search Tool", doc="Title of the search app")
|
|
262
|
+
config = param.ClassSelector(class_=SearchConfiguration, doc="Configuration for the search app")
|
|
263
|
+
|
|
264
|
+
def __init__(self, **params):
|
|
265
|
+
"""Initialize the SearchApp with default configuration."""
|
|
266
|
+
params["config"] = params.get("config", SearchConfiguration())
|
|
267
|
+
super().__init__(**params)
|
|
268
|
+
|
|
269
|
+
async def _config(self):
|
|
270
|
+
await _update_projects(self)
|
|
271
|
+
|
|
272
|
+
with pn.config.set(sizing_mode="stretch_width"):
|
|
273
|
+
return pn.Param(
|
|
274
|
+
self.config,
|
|
275
|
+
name="Search",
|
|
276
|
+
widgets={
|
|
277
|
+
"query": {"type": pmui.TextAreaInput, "rows": 3, "placeholder": "Enter search query ..."},
|
|
278
|
+
"search": {"type": pmui.Button, "label": "Search", "button_type": "primary"},
|
|
279
|
+
},
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
def __panel__(self):
|
|
283
|
+
"""Create the Panel layout for the search app."""
|
|
284
|
+
with pn.config.set(sizing_mode="stretch_width"):
|
|
285
|
+
menu = DocumentsMenuList(documents=self.config.param.results)
|
|
286
|
+
|
|
287
|
+
about_button = pmui.IconButton(
|
|
288
|
+
label="About", icon="info", description="Click to learn about the Search Tool.", sizing_mode="fixed", color="light", margin=(10, 0)
|
|
289
|
+
)
|
|
290
|
+
about = pmui.Dialog(ABOUT, close_on_click=True, width=0)
|
|
291
|
+
about_button.js_on_click(args={"about": about}, code="about.data.open = true")
|
|
292
|
+
|
|
293
|
+
github_button = pmui.IconButton(
|
|
294
|
+
label="Github", icon="star", description="Give HoloViz-MCP a star on GitHub", sizing_mode="fixed", color="light", margin=(10, 0)
|
|
295
|
+
)
|
|
296
|
+
href = "https://github.com/MarcSkovMadsen/holoviz-mcp"
|
|
297
|
+
js_code_to_open_holoviz_mcp = f"window.open('{href}', '_blank')"
|
|
298
|
+
github_button.js_on_click(code=js_code_to_open_holoviz_mcp)
|
|
299
|
+
|
|
300
|
+
return pmui.Page(
|
|
301
|
+
title=self.title,
|
|
302
|
+
site_url="./",
|
|
303
|
+
sidebar=[self._config, menu],
|
|
304
|
+
sidebar_width=400,
|
|
305
|
+
header=[pn.Row(about, about_button, github_button, align="end")],
|
|
306
|
+
main=[pmui.Container(DocumentView(document=menu.param.value), width_option="xl", sizing_mode="stretch_both")],
|
|
307
|
+
# logo="https://holoviz.org/_static/holoviz-logo-unstacked.svg",
|
|
308
|
+
# stylesheets=[".logo {background: white;border-radius: 5px;margin: 15px 15px 5px 10px;padding:7px}"],
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
if pn.state.served:
|
|
313
|
+
pn.extension("codeeditor")
|
|
314
|
+
SearchApp().servable()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Configuration package for HoloViz MCP server."""
|
|
2
|
+
|
|
3
|
+
from .loader import ConfigLoader
|
|
4
|
+
from .loader import ConfigurationError
|
|
5
|
+
from .loader import get_config
|
|
6
|
+
from .loader import get_config_loader
|
|
7
|
+
from .loader import reload_config
|
|
8
|
+
from .models import DocsConfig
|
|
9
|
+
from .models import GitRepository
|
|
10
|
+
from .models import HoloVizMCPConfig
|
|
11
|
+
from .models import PromptConfig
|
|
12
|
+
from .models import ResourceConfig
|
|
13
|
+
from .models import SecurityConfig
|
|
14
|
+
from .models import ServerConfig
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
# Loader
|
|
18
|
+
"ConfigLoader",
|
|
19
|
+
"ConfigurationError",
|
|
20
|
+
"get_config",
|
|
21
|
+
"get_config_loader",
|
|
22
|
+
"reload_config",
|
|
23
|
+
# Models
|
|
24
|
+
"DocsConfig",
|
|
25
|
+
"GitRepository",
|
|
26
|
+
"HoloVizMCPConfig",
|
|
27
|
+
"PromptConfig",
|
|
28
|
+
"ResourceConfig",
|
|
29
|
+
"SecurityConfig",
|
|
30
|
+
"ServerConfig",
|
|
31
|
+
]
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Default configuration for HoloViz MCP server
|
|
2
|
+
# This file provides the default settings that are used when no user configuration is provided.
|
|
3
|
+
|
|
4
|
+
server:
|
|
5
|
+
name: holoviz-mcp
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
description: "Model Context Protocol server for HoloViz ecosystem"
|
|
8
|
+
log_level: INFO
|
|
9
|
+
transport: stdio
|
|
10
|
+
anonymized_telemetry: false
|
|
11
|
+
jupyter_server_proxy_url: ""
|
|
12
|
+
security:
|
|
13
|
+
allow_code_execution: True
|
|
14
|
+
|
|
15
|
+
docs:
|
|
16
|
+
repositories:
|
|
17
|
+
panel:
|
|
18
|
+
url: https://github.com/holoviz/panel.git
|
|
19
|
+
branch: main
|
|
20
|
+
folders:
|
|
21
|
+
doc:
|
|
22
|
+
url_path: ""
|
|
23
|
+
examples/reference:
|
|
24
|
+
url_path: "/reference"
|
|
25
|
+
base_url: https://panel.holoviz.org
|
|
26
|
+
reference_patterns:
|
|
27
|
+
- "examples/reference/**/*.md"
|
|
28
|
+
- "examples/reference/**/*.ipynb"
|
|
29
|
+
- "examples/reference/**/*.rst"
|
|
30
|
+
panel-material-ui:
|
|
31
|
+
url: https://github.com/panel-extensions/panel-material-ui.git
|
|
32
|
+
branch: main
|
|
33
|
+
folders:
|
|
34
|
+
doc:
|
|
35
|
+
url_path: ""
|
|
36
|
+
examples/reference:
|
|
37
|
+
url_path: "/reference"
|
|
38
|
+
base_url: https://panel-material-ui.holoviz.org/
|
|
39
|
+
reference_patterns:
|
|
40
|
+
- "examples/reference/**/*.md"
|
|
41
|
+
- "examples/reference/**/*.ipynb"
|
|
42
|
+
- "examples/reference/**/*.rst"
|
|
43
|
+
hvplot:
|
|
44
|
+
url: https://github.com/holoviz/hvplot.git
|
|
45
|
+
branch: main
|
|
46
|
+
folders:
|
|
47
|
+
doc:
|
|
48
|
+
url_path: ""
|
|
49
|
+
base_url: https://hvplot.holoviz.org
|
|
50
|
+
reference_patterns:
|
|
51
|
+
- "doc/reference/**/*.md"
|
|
52
|
+
- "doc/reference/**/*.ipynb"
|
|
53
|
+
- "doc/reference/**/*.rst"
|
|
54
|
+
param:
|
|
55
|
+
url: https://github.com/holoviz/param.git
|
|
56
|
+
branch: main
|
|
57
|
+
folders:
|
|
58
|
+
doc:
|
|
59
|
+
url_path: ""
|
|
60
|
+
base_url: https://param.holoviz.org
|
|
61
|
+
reference_patterns:
|
|
62
|
+
- "doc/reference/**/*.md"
|
|
63
|
+
- "doc/reference/**/*.ipynb"
|
|
64
|
+
- "doc/reference/**/*.rst"
|
|
65
|
+
holoviews:
|
|
66
|
+
url: https://github.com/holoviz/holoviews.git
|
|
67
|
+
branch: main
|
|
68
|
+
folders:
|
|
69
|
+
doc:
|
|
70
|
+
url_path: ""
|
|
71
|
+
examples:
|
|
72
|
+
url_path: ""
|
|
73
|
+
base_url: https://holoviews.org
|
|
74
|
+
reference_patterns:
|
|
75
|
+
- "examples/reference/**/*.md"
|
|
76
|
+
- "examples/reference/**/*.ipynb"
|
|
77
|
+
- "examples/reference/**/*.rst"
|
|
78
|
+
holoviz:
|
|
79
|
+
url: https://github.com/holoviz/holoviz.git
|
|
80
|
+
branch: main
|
|
81
|
+
folders:
|
|
82
|
+
doc:
|
|
83
|
+
url_path: ""
|
|
84
|
+
examples/tutorial:
|
|
85
|
+
url_path: "/tutorial"
|
|
86
|
+
base_url: https://holoviz.org
|
|
87
|
+
url_transform: "datashader"
|
|
88
|
+
reference_patterns:
|
|
89
|
+
- "doc/reference/**/*.md"
|
|
90
|
+
- "doc/reference/**/*.ipynb"
|
|
91
|
+
- "doc/reference/**/*.rst"
|
|
92
|
+
datashader:
|
|
93
|
+
url: https://github.com/holoviz/datashader.git
|
|
94
|
+
branch: main
|
|
95
|
+
folders:
|
|
96
|
+
doc:
|
|
97
|
+
url_path: ""
|
|
98
|
+
examples:
|
|
99
|
+
url_path: ""
|
|
100
|
+
base_url: https://datashader.org
|
|
101
|
+
url_transform: "datashader"
|
|
102
|
+
reference_patterns:
|
|
103
|
+
- "doc/reference/**/*.md"
|
|
104
|
+
- "doc/reference/**/*.ipynb"
|
|
105
|
+
- "doc/reference/**/*.rst"
|
|
106
|
+
geoviews:
|
|
107
|
+
url: https://github.com/holoviz/geoviews.git
|
|
108
|
+
branch: main
|
|
109
|
+
folders:
|
|
110
|
+
doc:
|
|
111
|
+
url_path: ""
|
|
112
|
+
examples:
|
|
113
|
+
url_path: "/"
|
|
114
|
+
base_url: https://geoviews.org
|
|
115
|
+
reference_patterns:
|
|
116
|
+
- "doc/reference/**/*.md"
|
|
117
|
+
- "doc/reference/**/*.ipynb"
|
|
118
|
+
- "doc/reference/**/*.rst"
|
|
119
|
+
colorcet:
|
|
120
|
+
url: https://github.com/holoviz/colorcet.git
|
|
121
|
+
branch: main
|
|
122
|
+
folders:
|
|
123
|
+
doc:
|
|
124
|
+
url_path: ""
|
|
125
|
+
base_url: https://colorcet.holoviz.org
|
|
126
|
+
reference_patterns:
|
|
127
|
+
- "doc/reference/**/*.md"
|
|
128
|
+
- "doc/reference/**/*.ipynb"
|
|
129
|
+
- "doc/reference/**/*.rst"
|
|
130
|
+
lumen:
|
|
131
|
+
url: https://github.com/holoviz/lumen.git
|
|
132
|
+
branch: main
|
|
133
|
+
folders:
|
|
134
|
+
doc:
|
|
135
|
+
url_path: ""
|
|
136
|
+
base_url: https://lumen.holoviz.org
|
|
137
|
+
reference_patterns:
|
|
138
|
+
- "doc/reference/**/*.md"
|
|
139
|
+
- "doc/reference/**/*.ipynb"
|
|
140
|
+
- "doc/reference/**/*.rst"
|
|
141
|
+
|
|
142
|
+
index_patterns:
|
|
143
|
+
- "**/*.md"
|
|
144
|
+
- "**/*.ipynb"
|
|
145
|
+
- "**/*.rst"
|
|
146
|
+
|
|
147
|
+
exclude_patterns:
|
|
148
|
+
- "**/node_modules/**"
|
|
149
|
+
- "**/.git/**"
|
|
150
|
+
- "**/build/**"
|
|
151
|
+
- "**/__pycache__/**"
|
|
152
|
+
- "**/.pytest_cache/**"
|
|
153
|
+
|
|
154
|
+
max_file_size: 1048576 # 1MB
|
|
155
|
+
update_interval: 86400 # 24 hours
|
|
156
|
+
|
|
157
|
+
resources:
|
|
158
|
+
search_paths: [] # Additional search paths for user resources
|
|
159
|
+
# Default search paths are automatically included:
|
|
160
|
+
# - Package default resources (src/holoviz_mcp/config/resources/)
|
|
161
|
+
# - User config resources (~/.holoviz_mcp/config/resources/)
|
|
162
|
+
|
|
163
|
+
prompts:
|
|
164
|
+
search_paths: [] # Additional search paths for user prompts
|
|
165
|
+
# Default search paths are automatically included:
|
|
166
|
+
# - Package default prompts (src/holoviz_mcp/config/prompts/)
|
|
167
|
+
# - User config prompts (~/.holoviz_mcp/config/prompts/)
|