scitex 2.11.0__py3-none-any.whl → 2.13.0__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.
Files changed (148) hide show
  1. scitex/__main__.py +24 -5
  2. scitex/__version__.py +1 -1
  3. scitex/_optional_deps.py +33 -0
  4. scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
  5. scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
  6. scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
  7. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
  8. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
  9. scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
  10. scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
  11. scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
  12. scitex/ai/plt/_plot_feature_importance.py +1 -1
  13. scitex/ai/plt/_plot_learning_curve.py +1 -1
  14. scitex/ai/plt/_plot_optuna_study.py +1 -1
  15. scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
  16. scitex/ai/plt/_plot_roc_curve.py +1 -1
  17. scitex/ai/plt/_stx_conf_mat.py +1 -1
  18. scitex/ai/training/_LearningCurveLogger.py +1 -1
  19. scitex/audio/mcp_server.py +38 -8
  20. scitex/browser/automation/CookieHandler.py +1 -1
  21. scitex/browser/core/BrowserMixin.py +1 -1
  22. scitex/browser/core/ChromeProfileManager.py +1 -1
  23. scitex/browser/debugging/_browser_logger.py +1 -1
  24. scitex/browser/debugging/_highlight_element.py +1 -1
  25. scitex/browser/debugging/_show_grid.py +1 -1
  26. scitex/browser/interaction/click_center.py +1 -1
  27. scitex/browser/interaction/click_with_fallbacks.py +1 -1
  28. scitex/browser/interaction/close_popups.py +1 -1
  29. scitex/browser/interaction/fill_with_fallbacks.py +1 -1
  30. scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
  31. scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
  32. scitex/browser/stealth/HumanBehavior.py +1 -1
  33. scitex/browser/stealth/StealthManager.py +1 -1
  34. scitex/canvas/_mcp_handlers.py +372 -0
  35. scitex/canvas/_mcp_tool_schemas.py +219 -0
  36. scitex/canvas/mcp_server.py +151 -0
  37. scitex/capture/mcp_server.py +41 -12
  38. scitex/cli/audio.py +233 -0
  39. scitex/cli/capture.py +307 -0
  40. scitex/cli/main.py +27 -4
  41. scitex/cli/repro.py +233 -0
  42. scitex/cli/resource.py +240 -0
  43. scitex/cli/stats.py +325 -0
  44. scitex/cli/template.py +236 -0
  45. scitex/cli/tex.py +286 -0
  46. scitex/cli/web.py +11 -12
  47. scitex/dev/__init__.py +3 -0
  48. scitex/dev/_pyproject.py +405 -0
  49. scitex/dev/plt/__init__.py +2 -2
  50. scitex/dev/plt/mpl/get_dir_ax.py +1 -1
  51. scitex/dev/plt/mpl/get_signatures.py +1 -1
  52. scitex/dev/plt/mpl/get_signatures_details.py +1 -1
  53. scitex/diagram/_mcp_handlers.py +400 -0
  54. scitex/diagram/_mcp_tool_schemas.py +157 -0
  55. scitex/diagram/mcp_server.py +151 -0
  56. scitex/dsp/_demo_sig.py +51 -5
  57. scitex/dsp/_mne.py +13 -2
  58. scitex/dsp/_modulation_index.py +15 -3
  59. scitex/dsp/_pac.py +23 -5
  60. scitex/dsp/_psd.py +16 -4
  61. scitex/dsp/_resample.py +24 -4
  62. scitex/dsp/_transform.py +16 -3
  63. scitex/dsp/add_noise.py +15 -1
  64. scitex/dsp/norm.py +17 -2
  65. scitex/dsp/reference.py +17 -1
  66. scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
  67. scitex/dsp/utils/_zero_pad.py +18 -4
  68. scitex/dt/_normalize_timestamp.py +1 -1
  69. scitex/git/_session.py +1 -1
  70. scitex/io/_load_modules/_con.py +12 -1
  71. scitex/io/_load_modules/_eeg.py +12 -1
  72. scitex/io/_load_modules/_optuna.py +21 -63
  73. scitex/io/_load_modules/_torch.py +11 -3
  74. scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
  75. scitex/io/_save_modules/_torch.py +11 -3
  76. scitex/mcp_server.py +159 -0
  77. scitex/plt/_mcp_handlers.py +361 -0
  78. scitex/plt/_mcp_tool_schemas.py +169 -0
  79. scitex/plt/mcp_server.py +205 -0
  80. scitex/repro/README_RandomStateManager.md +3 -3
  81. scitex/repro/_RandomStateManager.py +14 -14
  82. scitex/repro/_gen_ID.py +1 -1
  83. scitex/repro/_gen_timestamp.py +1 -1
  84. scitex/repro/_hash_array.py +4 -4
  85. scitex/scholar/__main__.py +24 -2
  86. scitex/scholar/_mcp_handlers.py +685 -0
  87. scitex/scholar/_mcp_tool_schemas.py +339 -0
  88. scitex/scholar/docs/template.py +1 -1
  89. scitex/scholar/examples/07_storage_integration.py +1 -1
  90. scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
  91. scitex/scholar/impact_factor/jcr/build_database.py +1 -1
  92. scitex/scholar/mcp_server.py +315 -0
  93. scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
  94. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
  95. scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
  96. scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
  97. scitex/scholar/storage/PaperIO.py +1 -1
  98. scitex/session/README.md +4 -4
  99. scitex/session/__init__.py +1 -1
  100. scitex/session/_decorator.py +9 -9
  101. scitex/session/_lifecycle.py +5 -5
  102. scitex/session/template.py +1 -1
  103. scitex/stats/__main__.py +281 -0
  104. scitex/stats/_mcp_handlers.py +1191 -0
  105. scitex/stats/_mcp_tool_schemas.py +384 -0
  106. scitex/stats/correct/_correct_bonferroni.py +1 -1
  107. scitex/stats/correct/_correct_fdr.py +1 -1
  108. scitex/stats/correct/_correct_fdr_.py +1 -1
  109. scitex/stats/correct/_correct_holm.py +1 -1
  110. scitex/stats/correct/_correct_sidak.py +1 -1
  111. scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
  112. scitex/stats/effect_sizes/_cohens_d.py +1 -1
  113. scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
  114. scitex/stats/effect_sizes/_eta_squared.py +1 -1
  115. scitex/stats/effect_sizes/_prob_superiority.py +1 -1
  116. scitex/stats/mcp_server.py +405 -0
  117. scitex/stats/posthoc/_dunnett.py +1 -1
  118. scitex/stats/posthoc/_games_howell.py +1 -1
  119. scitex/stats/posthoc/_tukey_hsd.py +1 -1
  120. scitex/stats/power/_power.py +1 -1
  121. scitex/stats/utils/_effect_size.py +1 -1
  122. scitex/stats/utils/_formatters.py +1 -1
  123. scitex/stats/utils/_power.py +1 -1
  124. scitex/template/_mcp_handlers.py +259 -0
  125. scitex/template/_mcp_tool_schemas.py +112 -0
  126. scitex/template/mcp_server.py +186 -0
  127. scitex/utils/_verify_scitex_format.py +2 -2
  128. scitex/utils/template.py +1 -1
  129. scitex/web/__init__.py +12 -11
  130. scitex/web/_scraping.py +26 -265
  131. scitex/web/download_images.py +316 -0
  132. scitex/writer/Writer.py +1 -1
  133. scitex/writer/_clone_writer_project.py +1 -1
  134. scitex/writer/_validate_tree_structures.py +1 -1
  135. scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
  136. scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
  137. scitex/writer/dataclasses/core/_Document.py +1 -1
  138. scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
  139. scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
  140. scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
  141. scitex/writer/utils/.legacy_git_retry.py +7 -5
  142. scitex/writer/utils/_parse_latex_logs.py +1 -1
  143. {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/METADATA +431 -269
  144. {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/RECORD +147 -118
  145. scitex-2.13.0.dist-info/entry_points.txt +11 -0
  146. scitex-2.11.0.dist-info/entry_points.txt +0 -2
  147. {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
  148. {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-08
3
+ # File: src/scitex/canvas/_mcp_handlers.py
4
+ # ----------------------------------------
5
+
6
+ """
7
+ MCP Handler implementations for SciTeX canvas module.
8
+
9
+ Provides async handlers for multi-panel figure composition.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ from typing import Optional
16
+
17
+
18
+ async def create_canvas_handler(
19
+ parent_dir: str,
20
+ canvas_name: str,
21
+ width_mm: float = 180,
22
+ height_mm: float = 120,
23
+ ) -> dict:
24
+ """
25
+ Create a new canvas workspace.
26
+
27
+ Parameters
28
+ ----------
29
+ parent_dir : str
30
+ Parent directory for canvas
31
+ canvas_name : str
32
+ Name for the canvas
33
+ width_mm : float
34
+ Canvas width in mm
35
+ height_mm : float
36
+ Canvas height in mm
37
+
38
+ Returns
39
+ -------
40
+ dict
41
+ Success status and canvas info
42
+ """
43
+ try:
44
+ import scitex.canvas as canvas_module
45
+
46
+ loop = asyncio.get_event_loop()
47
+ await loop.run_in_executor(
48
+ None,
49
+ lambda: canvas_module.create_canvas(
50
+ parent_dir,
51
+ canvas_name,
52
+ ),
53
+ )
54
+
55
+ canvas_path = canvas_module.get_canvas_path(parent_dir, canvas_name)
56
+
57
+ return {
58
+ "success": True,
59
+ "canvas_name": canvas_name,
60
+ "canvas_path": str(canvas_path),
61
+ "size_mm": {"width": width_mm, "height": height_mm},
62
+ "message": f"Created canvas '{canvas_name}' at {canvas_path}",
63
+ }
64
+ except Exception as e:
65
+ return {
66
+ "success": False,
67
+ "error": str(e),
68
+ }
69
+
70
+
71
+ async def add_panel_handler(
72
+ parent_dir: str,
73
+ canvas_name: str,
74
+ panel_name: str,
75
+ source: str,
76
+ x_mm: float = 0,
77
+ y_mm: float = 0,
78
+ width_mm: float = 50,
79
+ height_mm: float = 50,
80
+ label: Optional[str] = None,
81
+ ) -> dict:
82
+ """
83
+ Add a panel to a canvas.
84
+
85
+ Parameters
86
+ ----------
87
+ parent_dir : str
88
+ Parent directory containing canvas
89
+ canvas_name : str
90
+ Canvas name
91
+ panel_name : str
92
+ Name for this panel
93
+ source : str
94
+ Path to source file
95
+ x_mm, y_mm : float
96
+ Position in mm
97
+ width_mm, height_mm : float
98
+ Size in mm
99
+ label : str, optional
100
+ Panel label (A, B, C...)
101
+
102
+ Returns
103
+ -------
104
+ dict
105
+ Success status and panel info
106
+ """
107
+ try:
108
+ import scitex.canvas as canvas_module
109
+
110
+ loop = asyncio.get_event_loop()
111
+ await loop.run_in_executor(
112
+ None,
113
+ lambda: canvas_module.add_panel(
114
+ parent_dir=parent_dir,
115
+ canvas_name=canvas_name,
116
+ panel_name=panel_name,
117
+ source=source,
118
+ xy_mm=(x_mm, y_mm),
119
+ size_mm=(width_mm, height_mm),
120
+ label=label or "",
121
+ ),
122
+ )
123
+
124
+ return {
125
+ "success": True,
126
+ "canvas_name": canvas_name,
127
+ "panel_name": panel_name,
128
+ "source": source,
129
+ "position_mm": {"x": x_mm, "y": y_mm},
130
+ "size_mm": {"width": width_mm, "height": height_mm},
131
+ "label": label,
132
+ "message": f"Added panel '{panel_name}' to canvas '{canvas_name}'",
133
+ }
134
+ except Exception as e:
135
+ return {
136
+ "success": False,
137
+ "error": str(e),
138
+ }
139
+
140
+
141
+ async def list_panels_handler(
142
+ parent_dir: str,
143
+ canvas_name: str,
144
+ ) -> dict:
145
+ """
146
+ List all panels in a canvas.
147
+
148
+ Parameters
149
+ ----------
150
+ parent_dir : str
151
+ Parent directory
152
+ canvas_name : str
153
+ Canvas name
154
+
155
+ Returns
156
+ -------
157
+ dict
158
+ Success status and panel list
159
+ """
160
+ try:
161
+ import scitex.canvas as canvas_module
162
+
163
+ loop = asyncio.get_event_loop()
164
+ panels = await loop.run_in_executor(
165
+ None,
166
+ lambda: canvas_module.list_panels(parent_dir, canvas_name),
167
+ )
168
+
169
+ return {
170
+ "success": True,
171
+ "canvas_name": canvas_name,
172
+ "count": len(panels) if panels else 0,
173
+ "panels": panels or [],
174
+ }
175
+ except Exception as e:
176
+ return {
177
+ "success": False,
178
+ "error": str(e),
179
+ }
180
+
181
+
182
+ async def remove_panel_handler(
183
+ parent_dir: str,
184
+ canvas_name: str,
185
+ panel_name: str,
186
+ ) -> dict:
187
+ """
188
+ Remove a panel from a canvas.
189
+
190
+ Parameters
191
+ ----------
192
+ parent_dir : str
193
+ Parent directory
194
+ canvas_name : str
195
+ Canvas name
196
+ panel_name : str
197
+ Panel to remove
198
+
199
+ Returns
200
+ -------
201
+ dict
202
+ Success status
203
+ """
204
+ try:
205
+ import scitex.canvas as canvas_module
206
+
207
+ loop = asyncio.get_event_loop()
208
+ await loop.run_in_executor(
209
+ None,
210
+ lambda: canvas_module.remove_panel(parent_dir, canvas_name, panel_name),
211
+ )
212
+
213
+ return {
214
+ "success": True,
215
+ "canvas_name": canvas_name,
216
+ "panel_name": panel_name,
217
+ "message": f"Removed panel '{panel_name}' from canvas '{canvas_name}'",
218
+ }
219
+ except Exception as e:
220
+ return {
221
+ "success": False,
222
+ "error": str(e),
223
+ }
224
+
225
+
226
+ async def export_canvas_handler(
227
+ parent_dir: str,
228
+ canvas_name: str,
229
+ output_path: Optional[str] = None,
230
+ format: Optional[str] = None,
231
+ dpi: int = 300,
232
+ ) -> dict:
233
+ """
234
+ Export canvas to file.
235
+
236
+ Parameters
237
+ ----------
238
+ parent_dir : str
239
+ Parent directory
240
+ canvas_name : str
241
+ Canvas name
242
+ output_path : str, optional
243
+ Output file path
244
+ format : str, optional
245
+ Output format (png, pdf, svg)
246
+ dpi : int
247
+ Output DPI
248
+
249
+ Returns
250
+ -------
251
+ dict
252
+ Success status and output path
253
+ """
254
+ try:
255
+ from pathlib import Path
256
+
257
+ import scitex.canvas as canvas_module
258
+
259
+ # Build output path if not provided
260
+ if output_path is None:
261
+ canvas_path = canvas_module.get_canvas_path(parent_dir, canvas_name)
262
+ fmt = format or "png"
263
+ output_path = str(Path(canvas_path) / "exports" / f"{canvas_name}.{fmt}")
264
+
265
+ loop = asyncio.get_event_loop()
266
+ result_path = await loop.run_in_executor(
267
+ None,
268
+ lambda: canvas_module.export_canvas(
269
+ parent_dir,
270
+ canvas_name,
271
+ output_path,
272
+ ),
273
+ )
274
+
275
+ return {
276
+ "success": True,
277
+ "canvas_name": canvas_name,
278
+ "output_path": str(result_path) if result_path else output_path,
279
+ "format": format or Path(output_path).suffix.lstrip("."),
280
+ "dpi": dpi,
281
+ "message": f"Exported canvas to {output_path}",
282
+ }
283
+ except Exception as e:
284
+ return {
285
+ "success": False,
286
+ "error": str(e),
287
+ }
288
+
289
+
290
+ async def list_canvases_handler(parent_dir: str) -> dict:
291
+ """
292
+ List all canvases in a directory.
293
+
294
+ Parameters
295
+ ----------
296
+ parent_dir : str
297
+ Directory to search
298
+
299
+ Returns
300
+ -------
301
+ dict
302
+ Success status and canvas list
303
+ """
304
+ try:
305
+ import scitex.canvas as canvas_module
306
+
307
+ loop = asyncio.get_event_loop()
308
+ canvases = await loop.run_in_executor(
309
+ None,
310
+ lambda: canvas_module.list_canvases(parent_dir),
311
+ )
312
+
313
+ return {
314
+ "success": True,
315
+ "parent_dir": parent_dir,
316
+ "count": len(canvases) if canvases else 0,
317
+ "canvases": canvases or [],
318
+ }
319
+ except Exception as e:
320
+ return {
321
+ "success": False,
322
+ "error": str(e),
323
+ }
324
+
325
+
326
+ async def canvas_exists_handler(
327
+ parent_dir: str,
328
+ canvas_name: str,
329
+ ) -> dict:
330
+ """
331
+ Check if a canvas exists.
332
+
333
+ Parameters
334
+ ----------
335
+ parent_dir : str
336
+ Parent directory
337
+ canvas_name : str
338
+ Canvas name
339
+
340
+ Returns
341
+ -------
342
+ dict
343
+ Success status and existence flag
344
+ """
345
+ try:
346
+ import scitex.canvas as canvas_module
347
+
348
+ exists = canvas_module.canvas_exists(parent_dir, canvas_name)
349
+
350
+ return {
351
+ "success": True,
352
+ "canvas_name": canvas_name,
353
+ "exists": exists,
354
+ }
355
+ except Exception as e:
356
+ return {
357
+ "success": False,
358
+ "error": str(e),
359
+ }
360
+
361
+
362
+ __all__ = [
363
+ "create_canvas_handler",
364
+ "add_panel_handler",
365
+ "list_panels_handler",
366
+ "remove_panel_handler",
367
+ "export_canvas_handler",
368
+ "list_canvases_handler",
369
+ "canvas_exists_handler",
370
+ ]
371
+
372
+ # EOF
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-08
3
+ # File: src/scitex/canvas/_mcp_tool_schemas.py
4
+ # ----------------------------------------
5
+
6
+ """
7
+ MCP Tool schemas for SciTeX canvas module.
8
+
9
+ Defines tools for multi-panel figure composition:
10
+ - create_canvas: Create paper figure workspace
11
+ - add_panel: Add subplot to canvas
12
+ - list_panels: List panels in canvas
13
+ - export_canvas: Render final figure
14
+ - list_canvases: List available canvases
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import mcp.types as types
20
+
21
+
22
+ def get_tool_schemas() -> list[types.Tool]:
23
+ """Return list of available MCP tools for canvas operations."""
24
+ return [
25
+ # Create canvas
26
+ types.Tool(
27
+ name="create_canvas",
28
+ description="Create a new paper figure canvas workspace for multi-panel composition",
29
+ inputSchema={
30
+ "type": "object",
31
+ "properties": {
32
+ "parent_dir": {
33
+ "type": "string",
34
+ "description": "Parent directory for the canvas",
35
+ },
36
+ "canvas_name": {
37
+ "type": "string",
38
+ "description": "Name for the canvas (e.g., 'fig1', 'Figure_2')",
39
+ },
40
+ "width_mm": {
41
+ "type": "number",
42
+ "description": "Canvas width in millimeters (default: 180 for double column)",
43
+ "default": 180,
44
+ },
45
+ "height_mm": {
46
+ "type": "number",
47
+ "description": "Canvas height in millimeters (default: 120)",
48
+ "default": 120,
49
+ },
50
+ },
51
+ "required": ["parent_dir", "canvas_name"],
52
+ },
53
+ ),
54
+ # Add panel
55
+ types.Tool(
56
+ name="add_panel",
57
+ description="Add a panel (subplot) to an existing canvas from an image or plot file",
58
+ inputSchema={
59
+ "type": "object",
60
+ "properties": {
61
+ "parent_dir": {
62
+ "type": "string",
63
+ "description": "Parent directory containing the canvas",
64
+ },
65
+ "canvas_name": {
66
+ "type": "string",
67
+ "description": "Canvas name",
68
+ },
69
+ "panel_name": {
70
+ "type": "string",
71
+ "description": "Name for this panel (e.g., 'panel_a', 'timecourse')",
72
+ },
73
+ "source": {
74
+ "type": "string",
75
+ "description": "Path to source file (PNG, JPG, SVG, or SciTeX plot)",
76
+ },
77
+ "x_mm": {
78
+ "type": "number",
79
+ "description": "X position in millimeters from left edge",
80
+ "default": 0,
81
+ },
82
+ "y_mm": {
83
+ "type": "number",
84
+ "description": "Y position in millimeters from top edge",
85
+ "default": 0,
86
+ },
87
+ "width_mm": {
88
+ "type": "number",
89
+ "description": "Panel width in millimeters",
90
+ "default": 50,
91
+ },
92
+ "height_mm": {
93
+ "type": "number",
94
+ "description": "Panel height in millimeters",
95
+ "default": 50,
96
+ },
97
+ "label": {
98
+ "type": "string",
99
+ "description": "Panel label (e.g., 'A', 'B', 'C')",
100
+ },
101
+ },
102
+ "required": ["parent_dir", "canvas_name", "panel_name", "source"],
103
+ },
104
+ ),
105
+ # List panels
106
+ types.Tool(
107
+ name="list_panels",
108
+ description="List all panels in a canvas with their properties",
109
+ inputSchema={
110
+ "type": "object",
111
+ "properties": {
112
+ "parent_dir": {
113
+ "type": "string",
114
+ "description": "Parent directory containing the canvas",
115
+ },
116
+ "canvas_name": {
117
+ "type": "string",
118
+ "description": "Canvas name",
119
+ },
120
+ },
121
+ "required": ["parent_dir", "canvas_name"],
122
+ },
123
+ ),
124
+ # Remove panel
125
+ types.Tool(
126
+ name="remove_panel",
127
+ description="Remove a panel from a canvas",
128
+ inputSchema={
129
+ "type": "object",
130
+ "properties": {
131
+ "parent_dir": {
132
+ "type": "string",
133
+ "description": "Parent directory containing the canvas",
134
+ },
135
+ "canvas_name": {
136
+ "type": "string",
137
+ "description": "Canvas name",
138
+ },
139
+ "panel_name": {
140
+ "type": "string",
141
+ "description": "Name of the panel to remove",
142
+ },
143
+ },
144
+ "required": ["parent_dir", "canvas_name", "panel_name"],
145
+ },
146
+ ),
147
+ # Export canvas
148
+ types.Tool(
149
+ name="export_canvas",
150
+ description="Export/render canvas to PNG, PDF, or SVG format",
151
+ inputSchema={
152
+ "type": "object",
153
+ "properties": {
154
+ "parent_dir": {
155
+ "type": "string",
156
+ "description": "Parent directory containing the canvas",
157
+ },
158
+ "canvas_name": {
159
+ "type": "string",
160
+ "description": "Canvas name",
161
+ },
162
+ "output_path": {
163
+ "type": "string",
164
+ "description": "Output file path (format determined by extension)",
165
+ },
166
+ "format": {
167
+ "type": "string",
168
+ "description": "Output format (auto-detected from path if not specified)",
169
+ "enum": ["png", "pdf", "svg"],
170
+ },
171
+ "dpi": {
172
+ "type": "integer",
173
+ "description": "Output DPI for raster formats (default: 300)",
174
+ "default": 300,
175
+ },
176
+ },
177
+ "required": ["parent_dir", "canvas_name"],
178
+ },
179
+ ),
180
+ # List canvases
181
+ types.Tool(
182
+ name="list_canvases",
183
+ description="List all canvases in a directory",
184
+ inputSchema={
185
+ "type": "object",
186
+ "properties": {
187
+ "parent_dir": {
188
+ "type": "string",
189
+ "description": "Directory to search for canvases",
190
+ },
191
+ },
192
+ "required": ["parent_dir"],
193
+ },
194
+ ),
195
+ # Canvas exists
196
+ types.Tool(
197
+ name="canvas_exists",
198
+ description="Check if a canvas exists",
199
+ inputSchema={
200
+ "type": "object",
201
+ "properties": {
202
+ "parent_dir": {
203
+ "type": "string",
204
+ "description": "Parent directory",
205
+ },
206
+ "canvas_name": {
207
+ "type": "string",
208
+ "description": "Canvas name to check",
209
+ },
210
+ },
211
+ "required": ["parent_dir", "canvas_name"],
212
+ },
213
+ ),
214
+ ]
215
+
216
+
217
+ __all__ = ["get_tool_schemas"]
218
+
219
+ # EOF