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.

Files changed (37) hide show
  1. holoviz_mcp/__init__.py +18 -0
  2. holoviz_mcp/apps/__init__.py +1 -0
  3. holoviz_mcp/apps/configuration_viewer.py +116 -0
  4. holoviz_mcp/apps/search.py +314 -0
  5. holoviz_mcp/config/__init__.py +31 -0
  6. holoviz_mcp/config/config.yaml +167 -0
  7. holoviz_mcp/config/loader.py +308 -0
  8. holoviz_mcp/config/models.py +216 -0
  9. holoviz_mcp/config/resources/best-practices/hvplot.md +62 -0
  10. holoviz_mcp/config/resources/best-practices/panel-material-ui.md +318 -0
  11. holoviz_mcp/config/resources/best-practices/panel.md +294 -0
  12. holoviz_mcp/config/schema.json +203 -0
  13. holoviz_mcp/docs_mcp/__init__.py +1 -0
  14. holoviz_mcp/docs_mcp/data.py +963 -0
  15. holoviz_mcp/docs_mcp/models.py +21 -0
  16. holoviz_mcp/docs_mcp/pages_design.md +407 -0
  17. holoviz_mcp/docs_mcp/server.py +220 -0
  18. holoviz_mcp/hvplot_mcp/__init__.py +1 -0
  19. holoviz_mcp/hvplot_mcp/server.py +152 -0
  20. holoviz_mcp/panel_mcp/__init__.py +17 -0
  21. holoviz_mcp/panel_mcp/data.py +316 -0
  22. holoviz_mcp/panel_mcp/models.py +124 -0
  23. holoviz_mcp/panel_mcp/server.py +650 -0
  24. holoviz_mcp/py.typed +0 -0
  25. holoviz_mcp/serve.py +34 -0
  26. holoviz_mcp/server.py +77 -0
  27. holoviz_mcp/shared/__init__.py +1 -0
  28. holoviz_mcp/shared/extract_tools.py +74 -0
  29. holoviz_mcp-0.0.1a2.dist-info/METADATA +641 -0
  30. holoviz_mcp-0.0.1a2.dist-info/RECORD +33 -0
  31. {holoviz_mcp-0.0.1a0.dist-info → holoviz_mcp-0.0.1a2.dist-info}/WHEEL +1 -2
  32. holoviz_mcp-0.0.1a2.dist-info/entry_points.txt +4 -0
  33. holoviz_mcp-0.0.1a2.dist-info/licenses/LICENSE.txt +30 -0
  34. holoviz_mcp-0.0.1a0.dist-info/METADATA +0 -6
  35. holoviz_mcp-0.0.1a0.dist-info/RECORD +0 -5
  36. holoviz_mcp-0.0.1a0.dist-info/top_level.txt +0 -1
  37. main.py +0 -6
@@ -0,0 +1,152 @@
1
+ """[hvPlot](https://hvplot.holoviz.org/) MCP Server.
2
+
3
+ This MCP server provides tools, resources, and prompts for using hvPlot to develop quick, interactive
4
+ plots in Python using best practices.
5
+
6
+ Use this server to:
7
+ - List available hvPlot plot types (e.g., 'line', 'scatter', 'bar', ...)
8
+ - Get docstrings and function signatures for hvPlot plot types
9
+ - Access hvPlot documentation and best practices
10
+ """
11
+
12
+ from typing import Literal
13
+ from typing import Optional
14
+ from typing import Union
15
+
16
+ from fastmcp import Context
17
+ from fastmcp import FastMCP
18
+
19
+ # Create the FastMCP server
20
+ mcp = FastMCP(
21
+ name="hvplot",
22
+ instructions="""
23
+ [hvPlot](https://hvplot.holoviz.org/) MCP Server.
24
+
25
+ This MCP server provides tools, resources, and prompts for using hvPlot to develop quick, interactive plots
26
+ in Python using best practices. Use this server to:
27
+
28
+ - List available hvPlot plot types
29
+ - Get docstrings and function signatures for hvPlot plot types
30
+ - Access hvPlot documentation and best practices""",
31
+ )
32
+
33
+
34
+ def _help(
35
+ plot_type: Optional[str] = None, docstring: bool = True, generic: bool = True, style: Union[Literal["matplotlib", "bokeh", "plotly"], bool] = True
36
+ ) -> tuple[str, str]:
37
+ """Retrieve hvPlot docstring and function signature for a plot type."""
38
+ import holoviews as hv
39
+ from hvplot.plotting.core import hvPlot
40
+ from hvplot.util import _get_doc_and_signature
41
+
42
+ if isinstance(style, str):
43
+ hv.extension(style)
44
+ else:
45
+ hv.extension("bokeh")
46
+
47
+ doc, sig = _get_doc_and_signature(cls=hvPlot, kind=plot_type, docstring=docstring, generic=generic, style=style)
48
+ return doc, sig
49
+
50
+
51
+ @mcp.tool
52
+ async def list_plot_types(ctx: Context) -> list[str]:
53
+ """
54
+ List all available hvPlot plot types supported in the current environment.
55
+
56
+ Use this tool to discover what plot types you can generate with hvPlot.
57
+
58
+ Note: The plot types are also called "kinds".
59
+
60
+ Parameters
61
+ ----------
62
+ ctx : Context
63
+ FastMCP context (automatically provided by the MCP framework).
64
+
65
+ Returns
66
+ -------
67
+ list[str]
68
+ Sorted list of all plot type names (e.g., 'line', 'scatter', 'bar', ...).
69
+
70
+ Examples
71
+ --------
72
+ >>> list_plot_types()
73
+ ['area', 'bar', 'box', 'contour', ...]
74
+ """
75
+ from hvplot.converter import HoloViewsConverter
76
+
77
+ return sorted(HoloViewsConverter._kind_mapping)
78
+
79
+
80
+ @mcp.tool
81
+ async def get_docstring(
82
+ ctx: Context, plot_type: str, docstring: bool = True, generic: bool = True, style: Union[Literal["matplotlib", "bokeh", "plotly"], bool] = True
83
+ ) -> str:
84
+ """
85
+ Get the hvPlot docstring for a specific plot type, including available options and usage details.
86
+
87
+ Use this tool to retrieve the full docstring for a plot type, including generic and style options.
88
+ Equivalent to `hvplot.help(plot_type)` in the hvPlot API.
89
+
90
+ Parameters
91
+ ----------
92
+ ctx : Context
93
+ FastMCP context (automatically provided by the MCP framework).
94
+ plot_type : str
95
+ The type of plot to provide help for (e.g., 'line', 'scatter').
96
+ docstring : bool, default=True
97
+ Whether to include the docstring in the output.
98
+ generic : bool, default=True
99
+ Whether to include generic plotting options shared by all plot types.
100
+ style : str or bool, default=True
101
+ Plotting backend to use for style options. If True, automatically infers the backend.
102
+
103
+ Returns
104
+ -------
105
+ str
106
+ The docstring for the specified plot type, including all relevant options and usage information.
107
+
108
+ Examples
109
+ --------
110
+ >>> get_docstring(plot_type='line')
111
+ """
112
+ doc, _ = _help(plot_type=plot_type, docstring=docstring, generic=generic, style=style)
113
+ return doc
114
+
115
+
116
+ @mcp.tool
117
+ async def get_signature(
118
+ ctx: Context, plot_type: str, docstring: bool = True, generic: bool = True, style: Union[Literal["matplotlib", "bokeh", "plotly"], bool] = True
119
+ ) -> str:
120
+ """
121
+ Get the function signature for a specific hvPlot plot type.
122
+
123
+ Use this tool to retrieve the Python function signature for a plot type, showing all accepted arguments and their defaults.
124
+
125
+ Parameters
126
+ ----------
127
+ ctx : Context
128
+ FastMCP context (automatically provided by the MCP framework).
129
+ plot_type : str
130
+ The type of plot to provide help for (e.g., 'line', 'scatter').
131
+ docstring : bool, default=True
132
+ Whether to include the docstring in the output (ignored here, included for API compatibility).
133
+ generic : bool, default=True
134
+ Whether to include generic plotting options shared by all plot types (ignored here, included for API compatibility).
135
+ style : str or bool, default=True
136
+ Plotting backend to use for style options. If True, automatically infers the backend (ignored here).
137
+
138
+ Returns
139
+ -------
140
+ str
141
+ The function signature for the specified plot type.
142
+
143
+ Examples
144
+ --------
145
+ >>> get_signature(plot_type='line')
146
+ """
147
+ _, sig = _help(plot_type=plot_type, docstring=docstring, generic=generic, style=style)
148
+ return str(sig)
149
+
150
+
151
+ if __name__ == "__main__":
152
+ mcp.run()
@@ -0,0 +1,17 @@
1
+ """
2
+ Panel MCP Server Package.
3
+
4
+ This package provides Model Context Protocol (MCP) tools for working with Panel,
5
+ the Python library for creating interactive web applications and dashboards.
6
+
7
+ The package includes:
8
+ - Component discovery and introspection tools
9
+ - Parameter information extraction
10
+ - URL proxying utilities for remote environments
11
+ - Data models for component metadata
12
+
13
+ Main modules:
14
+ - server: MCP server implementation with Panel-specific tools
15
+ - data: Component metadata collection and utilities
16
+ - models: Pydantic models for component information
17
+ """
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Data collection module for Panel component metadata.
4
+
5
+ This module provides functionality to collect metadata about Panel UI components,
6
+ including their documentation, parameter schema, and module information. It supports
7
+ collecting information from panel.viewable.Viewable subclasses across different
8
+ Panel-related packages.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ from pathlib import Path
15
+
16
+ from panel.viewable import Viewable
17
+
18
+ from .models import ComponentDetails
19
+ from .models import ParameterInfo
20
+
21
+
22
+ def find_all_subclasses(cls: type) -> set[type]:
23
+ """
24
+ Recursively find all subclasses of a given class.
25
+
26
+ This function performs a depth-first search through the class hierarchy
27
+ to find all classes that inherit from the given base class, either directly
28
+ or through inheritance chains.
29
+
30
+ Parameters
31
+ ----------
32
+ cls : type
33
+ The base class to find subclasses for.
34
+
35
+ Returns
36
+ -------
37
+ set[type]
38
+ Set of all subclasses found recursively, not including the base class itself.
39
+ """
40
+ subclasses = set()
41
+ for subclass in cls.__subclasses__():
42
+ subclasses.add(subclass)
43
+ subclasses.update(find_all_subclasses(subclass))
44
+ return subclasses
45
+
46
+
47
+ def collect_component_info(cls: type) -> ComponentDetails:
48
+ """
49
+ Collect comprehensive information about a Panel component class.
50
+
51
+ Extracts metadata including docstring, parameter information, method signatures,
52
+ and other relevant details from a Panel component class. Handles parameter
53
+ introspection safely, converting non-serializable values appropriately.
54
+
55
+ Parameters
56
+ ----------
57
+ cls : type
58
+ The Panel component class to analyze.
59
+
60
+ Returns
61
+ -------
62
+ ComponentDetails
63
+ A complete model containing all collected component information.
64
+ """
65
+ # Extract docstring
66
+ docstring = cls.__doc__ if cls.__doc__ else ""
67
+
68
+ # Extract description (first sentence from docstring)
69
+ description = ""
70
+ if docstring:
71
+ # Clean the docstring and get first sentence
72
+ cleaned_docstring = docstring.strip()
73
+ if cleaned_docstring:
74
+ # Find first sentence ending with period, exclamation, or question mark
75
+ import re
76
+
77
+ sentences = re.split(r"[.!?]", cleaned_docstring)
78
+ if sentences:
79
+ description = sentences[0].strip()
80
+ # Remove leading/trailing whitespace and normalize spaces
81
+ description = " ".join(description.split())
82
+
83
+ # Extract parameters information
84
+ parameters = {}
85
+ if hasattr(cls, "param"):
86
+ for param_name in cls.param:
87
+ # Skip private parameters
88
+ if param_name.startswith("_"):
89
+ continue
90
+
91
+ param_obj = cls.param[param_name]
92
+ param_data = {}
93
+
94
+ # Get common parameter attributes (skip private ones)
95
+ for attr in ["default", "doc", "allow_None", "constant", "readonly", "per_instance"]:
96
+ if hasattr(param_obj, attr):
97
+ value = getattr(param_obj, attr)
98
+ # Handle non-JSON serializable values
99
+ try:
100
+ json.dumps(value)
101
+ param_data[attr] = value
102
+ except (TypeError, ValueError):
103
+ param_data[attr] = "NON_JSON_SERIALIZABLE_VALUE"
104
+
105
+ # Get type-specific attributes
106
+ param_type = type(param_obj).__name__
107
+ param_data["type"] = param_type
108
+
109
+ # For Selector parameters, get options
110
+ if hasattr(param_obj, "objects"):
111
+ try:
112
+ json.dumps(param_obj.objects)
113
+ param_data["objects"] = param_obj.objects
114
+ except (TypeError, ValueError):
115
+ param_data["objects"] = "NON_JSON_SERIALIZABLE_VALUE"
116
+
117
+ # For Number parameters, get bounds
118
+ if hasattr(param_obj, "bounds"):
119
+ try:
120
+ json.dumps(param_obj.bounds)
121
+ param_data["bounds"] = param_obj.bounds
122
+ except (TypeError, ValueError):
123
+ param_data["bounds"] = "NON_JSON_SERIALIZABLE_VALUE"
124
+
125
+ # For String parameters, get regex
126
+ if hasattr(param_obj, "regex"):
127
+ try:
128
+ json.dumps(param_obj.regex)
129
+ param_data["regex"] = param_obj.regex
130
+ except (TypeError, ValueError):
131
+ param_data["regex"] = "NON_JSON_SERIALIZABLE_VALUE"
132
+
133
+ # Create ParameterInfo model
134
+ parameters[param_name] = ParameterInfo(**param_data)
135
+
136
+ # Get __init__ method signature
137
+ init_signature = ""
138
+ if hasattr(cls, "__init__"):
139
+ try:
140
+ import inspect
141
+
142
+ sig = inspect.signature(cls.__init__) # type: ignore[misc]
143
+ init_signature = str(sig)
144
+ except Exception as e:
145
+ init_signature = f"Error getting signature: {e}"
146
+
147
+ # Read reference guide content
148
+ # Create and return ComponentInfo model
149
+ return ComponentDetails(
150
+ name=cls.__name__,
151
+ description=description,
152
+ project=cls.__module__.split(".")[0],
153
+ module_path=f"{cls.__module__}.{cls.__name__}",
154
+ init_signature=init_signature,
155
+ docstring=docstring,
156
+ parameters=parameters,
157
+ )
158
+
159
+
160
+ def get_components(parent=Viewable) -> list[ComponentDetails]:
161
+ """
162
+ Get detailed information about all Panel component subclasses.
163
+
164
+ Discovers all subclasses of the specified parent class (typically Viewable),
165
+ filters out private classes, and collects comprehensive metadata for each.
166
+ Results are sorted alphabetically by module path for consistency.
167
+
168
+ Parameters
169
+ ----------
170
+ parent : type, optional
171
+ The parent class to search for subclasses. Defaults to panel.viewable.Viewable.
172
+
173
+ Returns
174
+ -------
175
+ list[ComponentDetails]
176
+ List of detailed component information models, sorted by module path.
177
+ """
178
+ all_subclasses = find_all_subclasses(parent)
179
+
180
+ # Filter to only those in panel_material_ui package and exclude private classes
181
+ subclasses = [cls for cls in all_subclasses if not cls.__name__.startswith("_")]
182
+
183
+ # Collect component information
184
+ component_data = [collect_component_info(cls) for cls in subclasses]
185
+
186
+ # Sort by module_path for consistent ordering
187
+ component_data.sort(key=lambda x: x.module_path)
188
+ return component_data
189
+
190
+
191
+ def save_components(data: list[ComponentDetails], filename: str) -> str:
192
+ """
193
+ Save component data to a JSON file.
194
+
195
+ Serializes a list of ComponentDetails objects to JSON format for persistence.
196
+ The JSON is formatted with indentation for human readability.
197
+
198
+ Parameters
199
+ ----------
200
+ data : list[ComponentDetails]
201
+ Component data to save, typically from get_components().
202
+ filename : str
203
+ Path where the JSON file should be created.
204
+
205
+ Returns
206
+ -------
207
+ str
208
+ Absolute path to the created file.
209
+ """
210
+ filepath = Path(filename)
211
+
212
+ # Convert Pydantic models to dict for JSON serialization
213
+ json_data = [component.model_dump() for component in data]
214
+
215
+ with open(filepath, "w", encoding="utf-8") as f:
216
+ json.dump(json_data, f, indent=2, ensure_ascii=False)
217
+
218
+ return str(filepath)
219
+
220
+
221
+ def load_components(filepath: str) -> list[ComponentDetails]:
222
+ """
223
+ Load component data from a JSON file.
224
+
225
+ Reads and deserializes component data that was previously saved using
226
+ save_components(). Validates the file exists before attempting to load.
227
+
228
+ Parameters
229
+ ----------
230
+ filepath : str
231
+ Path to the saved component data JSON file.
232
+
233
+ Returns
234
+ -------
235
+ list[ComponentDetails]
236
+ Loaded component data as Pydantic model instances.
237
+
238
+ Raises
239
+ ------
240
+ FileNotFoundError
241
+ If the specified file does not exist.
242
+ """
243
+ file_path = Path(filepath)
244
+
245
+ if not file_path.exists():
246
+ raise FileNotFoundError(f"File not found: {filepath}")
247
+
248
+ with open(file_path, "r", encoding="utf-8") as f:
249
+ json_data = json.load(f)
250
+
251
+ # Convert JSON data back to Pydantic models
252
+ return [ComponentDetails(**item) for item in json_data]
253
+
254
+
255
+ def to_proxy_url(url: str, jupyter_server_proxy_url: str = "") -> str:
256
+ """
257
+ Convert localhost URLs to Jupyter server proxy URLs when applicable.
258
+
259
+ This function handles URL conversion for environments where localhost access
260
+ needs to be proxied (like JupyterHub, Binder, etc.). It supports both
261
+ 'localhost' and '127.0.0.1' addresses and preserves paths and query parameters.
262
+
263
+ Parameters
264
+ ----------
265
+ url : str
266
+ The original URL to potentially convert. Can be any URL, but only
267
+ localhost and 127.0.0.1 URLs will be converted.
268
+ jupyter_server_proxy_url : str, optional
269
+ Base URL for the Jupyter server proxy. If None or empty, no conversion
270
+ is performed. Defaults to the configured proxy URL.
271
+
272
+ Returns
273
+ -------
274
+ str
275
+ The converted proxy URL if applicable, otherwise the original URL.
276
+ Proxy URLs maintain the original port, path, and query parameters.
277
+
278
+ Examples
279
+ --------
280
+ >>> to_proxy_url("http://localhost:5007/app")
281
+ "https://hub.example.com/user/alice/proxy/5007/app"
282
+
283
+ >>> to_proxy_url("https://external.com/page")
284
+ "https://external.com/page" # No conversion for external URLs
285
+ """
286
+ if jupyter_server_proxy_url and jupyter_server_proxy_url.strip():
287
+ # Check if this is a localhost or 127.0.0.1 URL
288
+ if url.startswith("http://localhost:"):
289
+ # Parse the URL to extract port, path, and query
290
+ url_parts = url.replace("http://localhost:", "")
291
+ elif url.startswith("http://127.0.0.1:"):
292
+ # Parse the URL to extract port, path, and query
293
+ url_parts = url.replace("http://127.0.0.1:", "")
294
+ else:
295
+ # Not a local URL, return original
296
+ proxy_url = url
297
+ return proxy_url
298
+
299
+ # Find the port (everything before the first slash or end of string)
300
+ if "/" in url_parts:
301
+ port = url_parts.split("/", 1)[0]
302
+ path_and_query = "/" + url_parts.split("/", 1)[1]
303
+ else:
304
+ port = url_parts
305
+ path_and_query = "/"
306
+
307
+ # Validate that port is a valid number
308
+ if port and port.isdigit() and 1 <= int(port) <= 65535:
309
+ # Build the proxy URL
310
+ proxy_url = f"{jupyter_server_proxy_url}{port}{path_and_query}"
311
+ else:
312
+ # Invalid port, return original URL
313
+ proxy_url = url
314
+ else:
315
+ proxy_url = url
316
+ return proxy_url
@@ -0,0 +1,124 @@
1
+ """Pydantic models for Panel component metadata collection.
2
+
3
+ This module defines the data models used to represent Panel UI component information,
4
+ including parameter details, component summaries, and search results.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+ from typing import Optional
11
+
12
+ from pydantic import BaseModel
13
+ from pydantic import ConfigDict
14
+ from pydantic import Field
15
+
16
+
17
+ class ParameterInfo(BaseModel):
18
+ """
19
+ Information about a Panel component parameter.
20
+
21
+ This model captures parameter metadata including type, default value,
22
+ documentation, and type-specific attributes like bounds or options.
23
+ """
24
+
25
+ model_config = ConfigDict(extra="allow") # Allow additional fields we don't know about
26
+
27
+ # Common attributes that most parameters have
28
+ type: str = Field(description="The type of the parameter, e.g., 'Parameter', 'Number', 'Selector'.")
29
+ default: Optional[Any] = Field(default=None, description="The default value for the parameter.")
30
+ doc: Optional[str] = Field(default=None, description="Documentation string for the parameter.")
31
+ # Optional attributes that may not be present
32
+ allow_None: Optional[bool] = Field(default=None, description="Whether the parameter accepts None values.")
33
+ constant: Optional[bool] = Field(default=None, description="Whether the parameter is constant (cannot be changed after initialization).")
34
+ readonly: Optional[bool] = Field(default=None, description="Whether the parameter is read-only.")
35
+ per_instance: Optional[bool] = Field(default=None, description="Whether the parameter is per-instance or shared across instances.")
36
+
37
+ # Type-specific attributes (will be present only for relevant parameter types)
38
+ objects: Optional[Any] = Field(default=None, description="Available options for Selector-type parameters.")
39
+ bounds: Optional[Any] = Field(default=None, description="Value bounds for Number-type parameters.")
40
+ regex: Optional[str] = Field(default=None, description="Regular expression pattern for String-type parameters.")
41
+
42
+
43
+ class ComponentSummary(BaseModel):
44
+ """
45
+ High-level information about a Panel UI component.
46
+
47
+ This model provides a compact representation of a component without
48
+ detailed parameter information or docstrings. Used for listings and
49
+ quick overviews.
50
+ """
51
+
52
+ module_path: str = Field(description="Full module path of the component, e.g., 'panel.widgets.Button' or 'panel_material_ui.Button'.")
53
+ name: str = Field(description="Name of the component, e.g., 'Button' or 'TextInput'.")
54
+ project: str = Field(description="Project name of the component, e.g., 'panel' or 'panel_material_ui'.")
55
+ description: str = Field(description="Short description of the component's purpose and functionality.")
56
+
57
+
58
+ class ComponentSummarySearchResult(ComponentSummary):
59
+ """
60
+ Component summary with search relevance scoring.
61
+
62
+ Extends ComponentSummary with a relevance score for search results,
63
+ allowing proper ranking and filtering of search matches.
64
+
65
+ """
66
+
67
+ relevance_score: int = Field(default=0, description="Relevance score for search results")
68
+
69
+ @classmethod
70
+ def from_component(cls, component: ComponentDetails, relevance_score: int) -> ComponentSummarySearchResult:
71
+ """
72
+ Create a search result from a component and relevance score.
73
+
74
+ Parameters
75
+ ----------
76
+ component : ComponentDetails
77
+ The component to create a search result from.
78
+ relevance_score : int
79
+ The relevance score (0-100) for this search result.
80
+
81
+ Returns
82
+ -------
83
+ ComponentSummarySearchResult
84
+ A search result summary of the component.
85
+ """
86
+ return cls(
87
+ module_path=component.module_path, name=component.name, project=component.project, description=component.description, relevance_score=relevance_score
88
+ )
89
+
90
+
91
+ class ComponentDetails(ComponentSummary):
92
+ """
93
+ Complete information about a Panel UI component.
94
+
95
+ This model includes all available information about a component:
96
+ summary information, initialization signature, full docstring,
97
+ and detailed parameter specifications.
98
+
99
+ """
100
+
101
+ init_signature: str = Field(description="Signature of the component's __init__ method.")
102
+ docstring: str = Field(description="Docstring of the component, providing detailed information about its usage.")
103
+ parameters: dict[str, ParameterInfo] = Field(
104
+ description="Dictionary of parameters for the component, where keys are parameter names and values are ParameterInfo objects."
105
+ )
106
+
107
+ def to_base(self) -> ComponentSummary:
108
+ """
109
+ Convert to a basic component summary.
110
+
111
+ Strips away detailed information to create a lightweight
112
+ summary suitable for listings and overviews.
113
+
114
+ Returns
115
+ -------
116
+ ComponentSummary
117
+ A summary version of this component.
118
+ """
119
+ return ComponentSummary(
120
+ module_path=self.module_path,
121
+ name=self.name,
122
+ project=self.project,
123
+ description=self.description,
124
+ )