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,361 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-08
3
+ # File: src/scitex/plt/_mcp_handlers.py
4
+ # ----------------------------------------
5
+
6
+ """
7
+ MCP Handler implementations for SciTeX plt module.
8
+
9
+ Provides async handlers for publication-quality plotting operations.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ from typing import Optional
16
+
17
+
18
+ async def get_style_handler() -> dict:
19
+ """
20
+ Get current SciTeX publication style configuration.
21
+
22
+ Returns
23
+ -------
24
+ dict
25
+ Success status and current style parameters
26
+ """
27
+ try:
28
+ from scitex.plt.styles.presets import get_style
29
+
30
+ style = get_style()
31
+
32
+ return {
33
+ "success": True,
34
+ "style": style,
35
+ "description": "Current SciTeX publication style configuration",
36
+ }
37
+ except Exception as e:
38
+ return {
39
+ "success": False,
40
+ "error": str(e),
41
+ }
42
+
43
+
44
+ async def set_style_handler(
45
+ axes_width_mm: Optional[float] = None,
46
+ axes_height_mm: Optional[float] = None,
47
+ margin_left_mm: Optional[float] = None,
48
+ margin_right_mm: Optional[float] = None,
49
+ margin_top_mm: Optional[float] = None,
50
+ margin_bottom_mm: Optional[float] = None,
51
+ dpi: Optional[int] = None,
52
+ axis_font_size_pt: Optional[float] = None,
53
+ tick_font_size_pt: Optional[float] = None,
54
+ title_font_size_pt: Optional[float] = None,
55
+ legend_font_size_pt: Optional[float] = None,
56
+ trace_thickness_mm: Optional[float] = None,
57
+ reset: bool = False,
58
+ ) -> dict:
59
+ """
60
+ Set global style overrides for publication figures.
61
+
62
+ Parameters
63
+ ----------
64
+ axes_width_mm : float, optional
65
+ Axes width in millimeters
66
+ axes_height_mm : float, optional
67
+ Axes height in millimeters
68
+ margin_*_mm : float, optional
69
+ Margins in millimeters
70
+ dpi : int, optional
71
+ Output resolution
72
+ *_font_size_pt : float, optional
73
+ Font sizes in points
74
+ trace_thickness_mm : float, optional
75
+ Line thickness in mm
76
+ reset : bool, optional
77
+ Reset to defaults before applying
78
+
79
+ Returns
80
+ -------
81
+ dict
82
+ Success status and updated style
83
+ """
84
+ try:
85
+ from scitex.plt.styles.presets import get_style, set_style
86
+
87
+ # Reset if requested
88
+ if reset:
89
+ set_style(None)
90
+
91
+ # Build style dict from provided parameters
92
+ style_updates = {}
93
+
94
+ if axes_width_mm is not None:
95
+ style_updates["axes_width_mm"] = axes_width_mm
96
+ if axes_height_mm is not None:
97
+ style_updates["axes_height_mm"] = axes_height_mm
98
+ if margin_left_mm is not None:
99
+ style_updates["margin_left_mm"] = margin_left_mm
100
+ if margin_right_mm is not None:
101
+ style_updates["margin_right_mm"] = margin_right_mm
102
+ if margin_top_mm is not None:
103
+ style_updates["margin_top_mm"] = margin_top_mm
104
+ if margin_bottom_mm is not None:
105
+ style_updates["margin_bottom_mm"] = margin_bottom_mm
106
+ if dpi is not None:
107
+ style_updates["dpi"] = dpi
108
+ if axis_font_size_pt is not None:
109
+ style_updates["axis_font_size_pt"] = axis_font_size_pt
110
+ if tick_font_size_pt is not None:
111
+ style_updates["tick_font_size_pt"] = tick_font_size_pt
112
+ if title_font_size_pt is not None:
113
+ style_updates["title_font_size_pt"] = title_font_size_pt
114
+ if legend_font_size_pt is not None:
115
+ style_updates["legend_font_size_pt"] = legend_font_size_pt
116
+ if trace_thickness_mm is not None:
117
+ style_updates["trace_thickness_mm"] = trace_thickness_mm
118
+
119
+ # Apply style updates
120
+ if style_updates:
121
+ set_style(style_updates)
122
+
123
+ # Get final style
124
+ final_style = get_style()
125
+
126
+ return {
127
+ "success": True,
128
+ "updated_parameters": list(style_updates.keys()),
129
+ "style": final_style,
130
+ "message": f"Updated {len(style_updates)} style parameters",
131
+ }
132
+ except Exception as e:
133
+ return {
134
+ "success": False,
135
+ "error": str(e),
136
+ }
137
+
138
+
139
+ async def list_presets_handler() -> dict:
140
+ """
141
+ List available publication style presets.
142
+
143
+ Returns
144
+ -------
145
+ dict
146
+ Success status and list of presets
147
+ """
148
+ try:
149
+ # Define available presets with descriptions
150
+ presets = [
151
+ {
152
+ "name": "SCITEX_STYLE",
153
+ "description": "Default SciTeX publication style",
154
+ "axes_size_mm": "40x28",
155
+ "dpi": 300,
156
+ "font_sizes_pt": {"axis": 7, "tick": 7, "title": 8, "legend": 6},
157
+ },
158
+ {
159
+ "name": "nature",
160
+ "description": "Nature journal style (single column)",
161
+ "axes_size_mm": "89x60",
162
+ "dpi": 300,
163
+ "notes": "Single column width: 89mm",
164
+ },
165
+ {
166
+ "name": "science",
167
+ "description": "Science journal style",
168
+ "axes_size_mm": "85x60",
169
+ "dpi": 300,
170
+ "notes": "Single column width: 85mm",
171
+ },
172
+ {
173
+ "name": "pnas",
174
+ "description": "PNAS journal style",
175
+ "axes_size_mm": "87x60",
176
+ "dpi": 300,
177
+ "notes": "Single column width: 8.7cm",
178
+ },
179
+ {
180
+ "name": "ieee",
181
+ "description": "IEEE journal style",
182
+ "axes_size_mm": "88x60",
183
+ "dpi": 300,
184
+ "notes": "Single column width: 3.5 inches",
185
+ },
186
+ ]
187
+
188
+ return {
189
+ "success": True,
190
+ "count": len(presets),
191
+ "presets": presets,
192
+ "usage": "Use set_style() to apply custom dimensions",
193
+ }
194
+ except Exception as e:
195
+ return {
196
+ "success": False,
197
+ "error": str(e),
198
+ }
199
+
200
+
201
+ async def crop_figure_handler(
202
+ input_path: str,
203
+ output_path: Optional[str] = None,
204
+ margin: int = 12,
205
+ overwrite: bool = False,
206
+ ) -> dict:
207
+ """
208
+ Auto-crop whitespace from a saved figure image.
209
+
210
+ Parameters
211
+ ----------
212
+ input_path : str
213
+ Path to input figure
214
+ output_path : str, optional
215
+ Output path (adds '_cropped' suffix if not provided)
216
+ margin : int, optional
217
+ Margin in pixels (default: 12)
218
+ overwrite : bool, optional
219
+ Overwrite input file
220
+
221
+ Returns
222
+ -------
223
+ dict
224
+ Success status and output path
225
+ """
226
+ try:
227
+ from scitex.plt import crop
228
+
229
+ loop = asyncio.get_event_loop()
230
+ result_path = await loop.run_in_executor(
231
+ None,
232
+ lambda: crop(
233
+ input_path=input_path,
234
+ output_path=output_path,
235
+ margin=margin,
236
+ overwrite=overwrite,
237
+ ),
238
+ )
239
+
240
+ return {
241
+ "success": True,
242
+ "input_path": input_path,
243
+ "output_path": str(result_path),
244
+ "margin_pixels": margin,
245
+ "message": f"Cropped figure saved to {result_path}",
246
+ }
247
+ except Exception as e:
248
+ return {
249
+ "success": False,
250
+ "error": str(e),
251
+ }
252
+
253
+
254
+ async def get_dpi_settings_handler() -> dict:
255
+ """
256
+ Get DPI settings for different output contexts.
257
+
258
+ Returns
259
+ -------
260
+ dict
261
+ Success status and DPI settings
262
+ """
263
+ try:
264
+ from scitex.plt.styles.presets import (
265
+ get_default_dpi,
266
+ get_display_dpi,
267
+ get_preview_dpi,
268
+ )
269
+
270
+ return {
271
+ "success": True,
272
+ "dpi_settings": {
273
+ "save": {
274
+ "value": get_default_dpi(),
275
+ "description": "Publication-quality output (high resolution)",
276
+ },
277
+ "display": {
278
+ "value": get_display_dpi(),
279
+ "description": "Screen display (lower resolution for speed)",
280
+ },
281
+ "preview": {
282
+ "value": get_preview_dpi(),
283
+ "description": "Editor previews and thumbnails",
284
+ },
285
+ },
286
+ "recommendation": "Use 'save' DPI for final figures, 'display' for iterating",
287
+ }
288
+ except Exception as e:
289
+ return {
290
+ "success": False,
291
+ "error": str(e),
292
+ }
293
+
294
+
295
+ async def get_color_palette_handler(format: str = "hex") -> dict:
296
+ """
297
+ Get the SciTeX color palette.
298
+
299
+ Parameters
300
+ ----------
301
+ format : str
302
+ Color format: 'hex', 'rgb', or 'rgba'
303
+
304
+ Returns
305
+ -------
306
+ dict
307
+ Success status and color palette
308
+ """
309
+ try:
310
+ from scitex.plt import color as color_module
311
+
312
+ # Get color parameters
313
+ params = getattr(color_module, "PARAMS", {})
314
+
315
+ # Get cycle colors
316
+ rgba_cycle = params.get("RGBA_NORM_FOR_CYCLE", {})
317
+
318
+ colors = {}
319
+ for name, rgba in rgba_cycle.items():
320
+ if format == "hex":
321
+ # Convert RGBA to hex
322
+ r, g, b = int(rgba[0] * 255), int(rgba[1] * 255), int(rgba[2] * 255)
323
+ colors[name] = f"#{r:02x}{g:02x}{b:02x}"
324
+ elif format == "rgb":
325
+ colors[name] = {
326
+ "r": int(rgba[0] * 255),
327
+ "g": int(rgba[1] * 255),
328
+ "b": int(rgba[2] * 255),
329
+ }
330
+ else: # rgba
331
+ colors[name] = {
332
+ "r": rgba[0],
333
+ "g": rgba[1],
334
+ "b": rgba[2],
335
+ "a": rgba[3] if len(rgba) > 3 else 1.0,
336
+ }
337
+
338
+ return {
339
+ "success": True,
340
+ "format": format,
341
+ "count": len(colors),
342
+ "colors": colors,
343
+ "usage": "Colors are used in matplotlib's default color cycle",
344
+ }
345
+ except Exception as e:
346
+ return {
347
+ "success": False,
348
+ "error": str(e),
349
+ }
350
+
351
+
352
+ __all__ = [
353
+ "get_style_handler",
354
+ "set_style_handler",
355
+ "list_presets_handler",
356
+ "crop_figure_handler",
357
+ "get_dpi_settings_handler",
358
+ "get_color_palette_handler",
359
+ ]
360
+
361
+ # EOF
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-08
3
+ # File: src/scitex/plt/_mcp_tool_schemas.py
4
+ # ----------------------------------------
5
+
6
+ """
7
+ MCP Tool schemas for SciTeX plt module.
8
+
9
+ Defines tools for publication-quality plotting:
10
+ - get_style: Get current style configuration
11
+ - set_style: Set global style overrides
12
+ - list_presets: List available style presets
13
+ - create_figure: Create figure with publication style
14
+ - crop_figure: Auto-crop figure whitespace
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 plt operations."""
24
+ return [
25
+ # Get current style
26
+ types.Tool(
27
+ name="get_style",
28
+ description="Get current SciTeX publication style configuration with all parameters (axes dimensions, fonts, margins, etc.)",
29
+ inputSchema={
30
+ "type": "object",
31
+ "properties": {},
32
+ "required": [],
33
+ },
34
+ ),
35
+ # Set style
36
+ types.Tool(
37
+ name="set_style",
38
+ description="Set global style overrides for publication figures. Parameters like axes_width_mm, margin_left_mm, font sizes, etc.",
39
+ inputSchema={
40
+ "type": "object",
41
+ "properties": {
42
+ "axes_width_mm": {
43
+ "type": "number",
44
+ "description": "Axes width in millimeters (default: 40)",
45
+ },
46
+ "axes_height_mm": {
47
+ "type": "number",
48
+ "description": "Axes height in millimeters (default: 28)",
49
+ },
50
+ "margin_left_mm": {
51
+ "type": "number",
52
+ "description": "Left margin in millimeters (default: 20)",
53
+ },
54
+ "margin_right_mm": {
55
+ "type": "number",
56
+ "description": "Right margin in millimeters (default: 20)",
57
+ },
58
+ "margin_top_mm": {
59
+ "type": "number",
60
+ "description": "Top margin in millimeters (default: 20)",
61
+ },
62
+ "margin_bottom_mm": {
63
+ "type": "number",
64
+ "description": "Bottom margin in millimeters (default: 20)",
65
+ },
66
+ "dpi": {
67
+ "type": "integer",
68
+ "description": "Output resolution in DPI (default: 300)",
69
+ },
70
+ "axis_font_size_pt": {
71
+ "type": "number",
72
+ "description": "Axis label font size in points (default: 7)",
73
+ },
74
+ "tick_font_size_pt": {
75
+ "type": "number",
76
+ "description": "Tick label font size in points (default: 7)",
77
+ },
78
+ "title_font_size_pt": {
79
+ "type": "number",
80
+ "description": "Title font size in points (default: 8)",
81
+ },
82
+ "legend_font_size_pt": {
83
+ "type": "number",
84
+ "description": "Legend font size in points (default: 6)",
85
+ },
86
+ "trace_thickness_mm": {
87
+ "type": "number",
88
+ "description": "Line trace thickness in mm (default: 0.2)",
89
+ },
90
+ "reset": {
91
+ "type": "boolean",
92
+ "description": "If true, reset style to defaults before applying",
93
+ },
94
+ },
95
+ "required": [],
96
+ },
97
+ ),
98
+ # List presets
99
+ types.Tool(
100
+ name="list_presets",
101
+ description="List available publication style presets (e.g., Nature, Science journal styles)",
102
+ inputSchema={
103
+ "type": "object",
104
+ "properties": {},
105
+ "required": [],
106
+ },
107
+ ),
108
+ # Crop figure
109
+ types.Tool(
110
+ name="crop_figure",
111
+ description="Auto-crop whitespace from a saved figure image",
112
+ inputSchema={
113
+ "type": "object",
114
+ "properties": {
115
+ "input_path": {
116
+ "type": "string",
117
+ "description": "Path to the input figure image",
118
+ },
119
+ "output_path": {
120
+ "type": "string",
121
+ "description": "Output path (optional, adds '_cropped' suffix if not provided)",
122
+ },
123
+ "margin": {
124
+ "type": "integer",
125
+ "description": "Margin in pixels around content (default: 12, ~1mm at 300 DPI)",
126
+ "default": 12,
127
+ },
128
+ "overwrite": {
129
+ "type": "boolean",
130
+ "description": "Overwrite input file (default: false)",
131
+ "default": False,
132
+ },
133
+ },
134
+ "required": ["input_path"],
135
+ },
136
+ ),
137
+ # Get DPI settings
138
+ types.Tool(
139
+ name="get_dpi_settings",
140
+ description="Get DPI settings for different output contexts (save, display, preview)",
141
+ inputSchema={
142
+ "type": "object",
143
+ "properties": {},
144
+ "required": [],
145
+ },
146
+ ),
147
+ # Get color palette
148
+ types.Tool(
149
+ name="get_color_palette",
150
+ description="Get the SciTeX color palette for consistent figure colors",
151
+ inputSchema={
152
+ "type": "object",
153
+ "properties": {
154
+ "format": {
155
+ "type": "string",
156
+ "description": "Color format to return",
157
+ "enum": ["hex", "rgb", "rgba"],
158
+ "default": "hex",
159
+ },
160
+ },
161
+ "required": [],
162
+ },
163
+ ),
164
+ ]
165
+
166
+
167
+ __all__ = ["get_tool_schemas"]
168
+
169
+ # EOF