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.
- scitex/__main__.py +24 -5
- scitex/__version__.py +1 -1
- scitex/_optional_deps.py +33 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
- scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
- scitex/ai/plt/_plot_feature_importance.py +1 -1
- scitex/ai/plt/_plot_learning_curve.py +1 -1
- scitex/ai/plt/_plot_optuna_study.py +1 -1
- scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
- scitex/ai/plt/_plot_roc_curve.py +1 -1
- scitex/ai/plt/_stx_conf_mat.py +1 -1
- scitex/ai/training/_LearningCurveLogger.py +1 -1
- scitex/audio/mcp_server.py +38 -8
- scitex/browser/automation/CookieHandler.py +1 -1
- scitex/browser/core/BrowserMixin.py +1 -1
- scitex/browser/core/ChromeProfileManager.py +1 -1
- scitex/browser/debugging/_browser_logger.py +1 -1
- scitex/browser/debugging/_highlight_element.py +1 -1
- scitex/browser/debugging/_show_grid.py +1 -1
- scitex/browser/interaction/click_center.py +1 -1
- scitex/browser/interaction/click_with_fallbacks.py +1 -1
- scitex/browser/interaction/close_popups.py +1 -1
- scitex/browser/interaction/fill_with_fallbacks.py +1 -1
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
- scitex/browser/stealth/HumanBehavior.py +1 -1
- scitex/browser/stealth/StealthManager.py +1 -1
- scitex/canvas/_mcp_handlers.py +372 -0
- scitex/canvas/_mcp_tool_schemas.py +219 -0
- scitex/canvas/mcp_server.py +151 -0
- scitex/capture/mcp_server.py +41 -12
- scitex/cli/audio.py +233 -0
- scitex/cli/capture.py +307 -0
- scitex/cli/main.py +27 -4
- scitex/cli/repro.py +233 -0
- scitex/cli/resource.py +240 -0
- scitex/cli/stats.py +325 -0
- scitex/cli/template.py +236 -0
- scitex/cli/tex.py +286 -0
- scitex/cli/web.py +11 -12
- scitex/dev/__init__.py +3 -0
- scitex/dev/_pyproject.py +405 -0
- scitex/dev/plt/__init__.py +2 -2
- scitex/dev/plt/mpl/get_dir_ax.py +1 -1
- scitex/dev/plt/mpl/get_signatures.py +1 -1
- scitex/dev/plt/mpl/get_signatures_details.py +1 -1
- scitex/diagram/_mcp_handlers.py +400 -0
- scitex/diagram/_mcp_tool_schemas.py +157 -0
- scitex/diagram/mcp_server.py +151 -0
- scitex/dsp/_demo_sig.py +51 -5
- scitex/dsp/_mne.py +13 -2
- scitex/dsp/_modulation_index.py +15 -3
- scitex/dsp/_pac.py +23 -5
- scitex/dsp/_psd.py +16 -4
- scitex/dsp/_resample.py +24 -4
- scitex/dsp/_transform.py +16 -3
- scitex/dsp/add_noise.py +15 -1
- scitex/dsp/norm.py +17 -2
- scitex/dsp/reference.py +17 -1
- scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
- scitex/dsp/utils/_zero_pad.py +18 -4
- scitex/dt/_normalize_timestamp.py +1 -1
- scitex/git/_session.py +1 -1
- scitex/io/_load_modules/_con.py +12 -1
- scitex/io/_load_modules/_eeg.py +12 -1
- scitex/io/_load_modules/_optuna.py +21 -63
- scitex/io/_load_modules/_torch.py +11 -3
- scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
- scitex/io/_save_modules/_torch.py +11 -3
- scitex/mcp_server.py +159 -0
- scitex/plt/_mcp_handlers.py +361 -0
- scitex/plt/_mcp_tool_schemas.py +169 -0
- scitex/plt/mcp_server.py +205 -0
- scitex/repro/README_RandomStateManager.md +3 -3
- scitex/repro/_RandomStateManager.py +14 -14
- scitex/repro/_gen_ID.py +1 -1
- scitex/repro/_gen_timestamp.py +1 -1
- scitex/repro/_hash_array.py +4 -4
- scitex/scholar/__main__.py +24 -2
- scitex/scholar/_mcp_handlers.py +685 -0
- scitex/scholar/_mcp_tool_schemas.py +339 -0
- scitex/scholar/docs/template.py +1 -1
- scitex/scholar/examples/07_storage_integration.py +1 -1
- scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
- scitex/scholar/impact_factor/jcr/build_database.py +1 -1
- scitex/scholar/mcp_server.py +315 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
- scitex/scholar/storage/PaperIO.py +1 -1
- scitex/session/README.md +4 -4
- scitex/session/__init__.py +1 -1
- scitex/session/_decorator.py +9 -9
- scitex/session/_lifecycle.py +5 -5
- scitex/session/template.py +1 -1
- scitex/stats/__main__.py +281 -0
- scitex/stats/_mcp_handlers.py +1191 -0
- scitex/stats/_mcp_tool_schemas.py +384 -0
- scitex/stats/correct/_correct_bonferroni.py +1 -1
- scitex/stats/correct/_correct_fdr.py +1 -1
- scitex/stats/correct/_correct_fdr_.py +1 -1
- scitex/stats/correct/_correct_holm.py +1 -1
- scitex/stats/correct/_correct_sidak.py +1 -1
- scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
- scitex/stats/effect_sizes/_cohens_d.py +1 -1
- scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
- scitex/stats/effect_sizes/_eta_squared.py +1 -1
- scitex/stats/effect_sizes/_prob_superiority.py +1 -1
- scitex/stats/mcp_server.py +405 -0
- scitex/stats/posthoc/_dunnett.py +1 -1
- scitex/stats/posthoc/_games_howell.py +1 -1
- scitex/stats/posthoc/_tukey_hsd.py +1 -1
- scitex/stats/power/_power.py +1 -1
- scitex/stats/utils/_effect_size.py +1 -1
- scitex/stats/utils/_formatters.py +1 -1
- scitex/stats/utils/_power.py +1 -1
- scitex/template/_mcp_handlers.py +259 -0
- scitex/template/_mcp_tool_schemas.py +112 -0
- scitex/template/mcp_server.py +186 -0
- scitex/utils/_verify_scitex_format.py +2 -2
- scitex/utils/template.py +1 -1
- scitex/web/__init__.py +12 -11
- scitex/web/_scraping.py +26 -265
- scitex/web/download_images.py +316 -0
- scitex/writer/Writer.py +1 -1
- scitex/writer/_clone_writer_project.py +1 -1
- scitex/writer/_validate_tree_structures.py +1 -1
- scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
- scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
- scitex/writer/dataclasses/core/_Document.py +1 -1
- scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
- scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
- scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
- scitex/writer/utils/.legacy_git_retry.py +7 -5
- scitex/writer/utils/_parse_latex_logs.py +1 -1
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/METADATA +431 -269
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/RECORD +147 -118
- scitex-2.13.0.dist-info/entry_points.txt +11 -0
- scitex-2.11.0.dist-info/entry_points.txt +0 -2
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
scitex/plt/mcp_server.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2026-01-08
|
|
3
|
+
# File: src/scitex/plt/mcp_server.py
|
|
4
|
+
# ----------------------------------------
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
MCP Server for SciTeX plt - Publication-quality plotting.
|
|
8
|
+
|
|
9
|
+
Provides tools for:
|
|
10
|
+
- Style configuration (get/set publication styles)
|
|
11
|
+
- Style presets (journal-specific configurations)
|
|
12
|
+
- Figure cropping (auto-crop whitespace)
|
|
13
|
+
- DPI management
|
|
14
|
+
- Color palette access
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import asyncio
|
|
20
|
+
|
|
21
|
+
# Graceful MCP dependency handling
|
|
22
|
+
try:
|
|
23
|
+
import mcp.types as types
|
|
24
|
+
from mcp.server import NotificationOptions, Server
|
|
25
|
+
from mcp.server.models import InitializationOptions
|
|
26
|
+
from mcp.server.stdio import stdio_server
|
|
27
|
+
|
|
28
|
+
MCP_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
MCP_AVAILABLE = False
|
|
31
|
+
types = None # type: ignore
|
|
32
|
+
Server = None # type: ignore
|
|
33
|
+
NotificationOptions = None # type: ignore
|
|
34
|
+
InitializationOptions = None # type: ignore
|
|
35
|
+
stdio_server = None # type: ignore
|
|
36
|
+
|
|
37
|
+
__all__ = ["PltServer", "main", "MCP_AVAILABLE"]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class PltServer:
|
|
41
|
+
"""MCP Server for Publication-quality Plotting."""
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
self.server = Server("scitex-plt")
|
|
45
|
+
self.setup_handlers()
|
|
46
|
+
|
|
47
|
+
def setup_handlers(self):
|
|
48
|
+
"""Set up MCP server handlers."""
|
|
49
|
+
from ._mcp_handlers import (
|
|
50
|
+
crop_figure_handler,
|
|
51
|
+
get_color_palette_handler,
|
|
52
|
+
get_dpi_settings_handler,
|
|
53
|
+
get_style_handler,
|
|
54
|
+
list_presets_handler,
|
|
55
|
+
set_style_handler,
|
|
56
|
+
)
|
|
57
|
+
from ._mcp_tool_schemas import get_tool_schemas
|
|
58
|
+
|
|
59
|
+
@self.server.list_tools()
|
|
60
|
+
async def handle_list_tools():
|
|
61
|
+
return get_tool_schemas()
|
|
62
|
+
|
|
63
|
+
@self.server.call_tool()
|
|
64
|
+
async def handle_call_tool(name: str, arguments: dict):
|
|
65
|
+
if name == "get_style":
|
|
66
|
+
return await self._wrap_result(get_style_handler())
|
|
67
|
+
|
|
68
|
+
elif name == "set_style":
|
|
69
|
+
return await self._wrap_result(set_style_handler(**arguments))
|
|
70
|
+
|
|
71
|
+
elif name == "list_presets":
|
|
72
|
+
return await self._wrap_result(list_presets_handler())
|
|
73
|
+
|
|
74
|
+
elif name == "crop_figure":
|
|
75
|
+
return await self._wrap_result(crop_figure_handler(**arguments))
|
|
76
|
+
|
|
77
|
+
elif name == "get_dpi_settings":
|
|
78
|
+
return await self._wrap_result(get_dpi_settings_handler())
|
|
79
|
+
|
|
80
|
+
elif name == "get_color_palette":
|
|
81
|
+
return await self._wrap_result(get_color_palette_handler(**arguments))
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
raise ValueError(f"Unknown tool: {name}")
|
|
85
|
+
|
|
86
|
+
@self.server.list_resources()
|
|
87
|
+
async def handle_list_resources():
|
|
88
|
+
"""List available plt resources."""
|
|
89
|
+
resources = [
|
|
90
|
+
types.Resource(
|
|
91
|
+
uri="plt://style/current",
|
|
92
|
+
name="Current Style",
|
|
93
|
+
description="Current publication style configuration",
|
|
94
|
+
mimeType="application/json",
|
|
95
|
+
),
|
|
96
|
+
types.Resource(
|
|
97
|
+
uri="plt://presets",
|
|
98
|
+
name="Style Presets",
|
|
99
|
+
description="Available journal style presets",
|
|
100
|
+
mimeType="application/json",
|
|
101
|
+
),
|
|
102
|
+
types.Resource(
|
|
103
|
+
uri="plt://colors",
|
|
104
|
+
name="Color Palette",
|
|
105
|
+
description="SciTeX color palette",
|
|
106
|
+
mimeType="application/json",
|
|
107
|
+
),
|
|
108
|
+
]
|
|
109
|
+
return resources
|
|
110
|
+
|
|
111
|
+
@self.server.read_resource()
|
|
112
|
+
async def handle_read_resource(uri: str):
|
|
113
|
+
"""Read a plt resource."""
|
|
114
|
+
import json
|
|
115
|
+
|
|
116
|
+
if uri == "plt://style/current":
|
|
117
|
+
result = await get_style_handler()
|
|
118
|
+
return types.TextResourceContents(
|
|
119
|
+
uri=uri,
|
|
120
|
+
mimeType="application/json",
|
|
121
|
+
text=json.dumps(result, indent=2),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
elif uri == "plt://presets":
|
|
125
|
+
result = await list_presets_handler()
|
|
126
|
+
return types.TextResourceContents(
|
|
127
|
+
uri=uri,
|
|
128
|
+
mimeType="application/json",
|
|
129
|
+
text=json.dumps(result, indent=2),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
elif uri == "plt://colors":
|
|
133
|
+
result = await get_color_palette_handler()
|
|
134
|
+
return types.TextResourceContents(
|
|
135
|
+
uri=uri,
|
|
136
|
+
mimeType="application/json",
|
|
137
|
+
text=json.dumps(result, indent=2),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
else:
|
|
141
|
+
raise ValueError(f"Unknown resource URI: {uri}")
|
|
142
|
+
|
|
143
|
+
async def _wrap_result(self, coro):
|
|
144
|
+
"""Wrap handler result as MCP TextContent."""
|
|
145
|
+
import json
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
result = await coro
|
|
149
|
+
return [
|
|
150
|
+
types.TextContent(
|
|
151
|
+
type="text",
|
|
152
|
+
text=json.dumps(result, indent=2, default=str),
|
|
153
|
+
)
|
|
154
|
+
]
|
|
155
|
+
except Exception as e:
|
|
156
|
+
return [
|
|
157
|
+
types.TextContent(
|
|
158
|
+
type="text",
|
|
159
|
+
text=json.dumps({"success": False, "error": str(e)}, indent=2),
|
|
160
|
+
)
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
async def _run_server():
|
|
165
|
+
"""Run the MCP server (internal)."""
|
|
166
|
+
server = PltServer()
|
|
167
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
168
|
+
await server.server.run(
|
|
169
|
+
read_stream,
|
|
170
|
+
write_stream,
|
|
171
|
+
InitializationOptions(
|
|
172
|
+
server_name="scitex-plt",
|
|
173
|
+
server_version="0.1.0",
|
|
174
|
+
capabilities=server.server.get_capabilities(
|
|
175
|
+
notification_options=NotificationOptions(),
|
|
176
|
+
experimental_capabilities={},
|
|
177
|
+
),
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def main():
|
|
183
|
+
"""Main entry point for the MCP server."""
|
|
184
|
+
if not MCP_AVAILABLE:
|
|
185
|
+
import sys
|
|
186
|
+
|
|
187
|
+
print("=" * 60)
|
|
188
|
+
print("MCP Server 'scitex-plt' requires the 'mcp' package.")
|
|
189
|
+
print()
|
|
190
|
+
print("Install with:")
|
|
191
|
+
print(" pip install mcp")
|
|
192
|
+
print()
|
|
193
|
+
print("Or install scitex with MCP support:")
|
|
194
|
+
print(" pip install scitex[mcp]")
|
|
195
|
+
print("=" * 60)
|
|
196
|
+
sys.exit(1)
|
|
197
|
+
|
|
198
|
+
asyncio.run(_run_server())
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
if __name__ == "__main__":
|
|
202
|
+
main()
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
# EOF
|
|
@@ -28,7 +28,7 @@ import torch
|
|
|
28
28
|
import tensorflow as tf
|
|
29
29
|
|
|
30
30
|
# Initialize once - fixes everything!
|
|
31
|
-
|
|
31
|
+
rng = stx.rng.RandomStateManager(seed=42)
|
|
32
32
|
|
|
33
33
|
# Python random - automatically fixed
|
|
34
34
|
python_val = random.random() # Reproducible!
|
|
@@ -87,7 +87,7 @@ import sys
|
|
|
87
87
|
import scitex as stx
|
|
88
88
|
|
|
89
89
|
# Session.start returns RNG, fixing random seeds of the supported libraries automatically
|
|
90
|
-
CONFIG, stdout, stderr, plt, CC,
|
|
90
|
+
CONFIG, stdout, stderr, plt, CC, rng = stx.session.start(
|
|
91
91
|
sys=sys,
|
|
92
92
|
seed=42
|
|
93
93
|
)
|
|
@@ -208,4 +208,4 @@ When you create a RandomStateManager, it automatically:
|
|
|
208
208
|
|
|
209
209
|
yusuke.watanabe@scitex.ai
|
|
210
210
|
|
|
211
|
-
<!-- EOF -->
|
|
211
|
+
<!-- EOF -->
|
|
@@ -14,7 +14,7 @@ __DIR__ = os.path.dirname(__FILE__)
|
|
|
14
14
|
Clean, simple RandomStateManager for scientific reproducibility.
|
|
15
15
|
|
|
16
16
|
Main API:
|
|
17
|
-
|
|
17
|
+
rng = RandomStateManager(seed=42) # Create instance
|
|
18
18
|
gen = rng("name") # Get named generator
|
|
19
19
|
rng.verify(obj, "name") # Verify reproducibility
|
|
20
20
|
"""
|
|
@@ -44,11 +44,11 @@ class RandomStateManager:
|
|
|
44
44
|
>>> import scitex as stx
|
|
45
45
|
>>>
|
|
46
46
|
>>> # Method 1: Direct usage
|
|
47
|
-
>>>
|
|
47
|
+
>>> rng = stx.rng.RandomStateManager(seed=42)
|
|
48
48
|
>>> data = rng("data").random(100)
|
|
49
49
|
>>>
|
|
50
50
|
>>> # Method 2: From session.start
|
|
51
|
-
>>> CONFIG, stdout, stderr, plt, CC,
|
|
51
|
+
>>> CONFIG, stdout, stderr, plt, CC, rng = stx.session.start(seed=42)
|
|
52
52
|
>>> model = rng("model").normal(size=(10, 10))
|
|
53
53
|
>>>
|
|
54
54
|
>>> # Verify reproducibility
|
|
@@ -98,7 +98,7 @@ class RandomStateManager:
|
|
|
98
98
|
np.random.seed(self.seed)
|
|
99
99
|
# Also set default_rng for new API
|
|
100
100
|
self._np = np
|
|
101
|
-
self.
|
|
101
|
+
self._np_default_rng = np.random.default_rng(self.seed)
|
|
102
102
|
fixed_modules.append("numpy")
|
|
103
103
|
except ImportError:
|
|
104
104
|
self._np = None
|
|
@@ -159,7 +159,7 @@ class RandomStateManager:
|
|
|
159
159
|
|
|
160
160
|
Examples
|
|
161
161
|
--------
|
|
162
|
-
>>>
|
|
162
|
+
>>> rng = RandomStateManager(42)
|
|
163
163
|
>>> gen = rng.get_np_generator("data")
|
|
164
164
|
>>> values = gen.random(100)
|
|
165
165
|
>>> perm = gen.permutation(100)
|
|
@@ -427,7 +427,7 @@ class RandomStateManager:
|
|
|
427
427
|
|
|
428
428
|
Examples
|
|
429
429
|
--------
|
|
430
|
-
>>>
|
|
430
|
+
>>> rng = RandomStateManager(42)
|
|
431
431
|
>>> from sklearn.model_selection import train_test_split
|
|
432
432
|
>>> X_train, X_test = train_test_split(
|
|
433
433
|
... X, test_size=0.2,
|
|
@@ -455,7 +455,7 @@ class RandomStateManager:
|
|
|
455
455
|
|
|
456
456
|
Examples
|
|
457
457
|
--------
|
|
458
|
-
>>>
|
|
458
|
+
>>> rng = RandomStateManager(42)
|
|
459
459
|
>>> gen = rng.get_torch_generator("model")
|
|
460
460
|
>>> torch.randn(5, 5, generator=gen)
|
|
461
461
|
"""
|
|
@@ -503,7 +503,7 @@ class RandomStateManager:
|
|
|
503
503
|
|
|
504
504
|
Examples
|
|
505
505
|
--------
|
|
506
|
-
>>>
|
|
506
|
+
>>> rng = RandomStateManager(42)
|
|
507
507
|
>>> rng.clear_cache() # Clear all
|
|
508
508
|
>>> rng.clear_cache("old_data") # Clear specific
|
|
509
509
|
>>> rng.clear_cache(["test1", "test2"]) # Clear multiple
|
|
@@ -559,7 +559,7 @@ def get(verbose: bool = False) -> RandomStateManager:
|
|
|
559
559
|
Examples
|
|
560
560
|
--------
|
|
561
561
|
>>> import scitex as stx
|
|
562
|
-
>>>
|
|
562
|
+
>>> rng = stx.rng.get()
|
|
563
563
|
>>> data = rng("data").random(100)
|
|
564
564
|
"""
|
|
565
565
|
global _GLOBAL_INSTANCE
|
|
@@ -589,7 +589,7 @@ def reset(seed: int = 42, verbose: bool = False) -> RandomStateManager:
|
|
|
589
589
|
Examples
|
|
590
590
|
--------
|
|
591
591
|
>>> import scitex as stx
|
|
592
|
-
>>>
|
|
592
|
+
>>> rng = stx.repro.reset(seed=123)
|
|
593
593
|
"""
|
|
594
594
|
global _GLOBAL_INSTANCE
|
|
595
595
|
_GLOBAL_INSTANCE = RandomStateManager(seed, verbose=verbose)
|
|
@@ -626,8 +626,8 @@ def main(args):
|
|
|
626
626
|
print(f"Seed: {args.seed}")
|
|
627
627
|
|
|
628
628
|
# Get named generators
|
|
629
|
-
data_gen =
|
|
630
|
-
model_gen =
|
|
629
|
+
data_gen = rng("data")
|
|
630
|
+
model_gen = rng("model")
|
|
631
631
|
|
|
632
632
|
# Generate data
|
|
633
633
|
print(f"\n{'Data Generation':-^60}")
|
|
@@ -641,7 +641,7 @@ def main(args):
|
|
|
641
641
|
|
|
642
642
|
# Verify reproducibility
|
|
643
643
|
print(f"\n{'Verification':-^60}")
|
|
644
|
-
|
|
644
|
+
rng.verify(data, "demo_data")
|
|
645
645
|
print("✓ Data reproducibility verified")
|
|
646
646
|
|
|
647
647
|
print(f"\n{'=' * 60}")
|
|
@@ -660,7 +660,7 @@ if __name__ == "__main__":
|
|
|
660
660
|
|
|
661
661
|
args = parse_args()
|
|
662
662
|
|
|
663
|
-
CONFIG, sys.stdout, sys.stderr, plt, CC,
|
|
663
|
+
CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
|
|
664
664
|
sys,
|
|
665
665
|
plt,
|
|
666
666
|
args=args,
|
scitex/repro/_gen_ID.py
CHANGED
scitex/repro/_gen_timestamp.py
CHANGED
scitex/repro/_hash_array.py
CHANGED
|
@@ -72,8 +72,8 @@ def main(args):
|
|
|
72
72
|
print(f"Array size: {args.size}")
|
|
73
73
|
print(f"Seed: {args.seed}")
|
|
74
74
|
|
|
75
|
-
# Generate arrays using
|
|
76
|
-
gen =
|
|
75
|
+
# Generate arrays using rng
|
|
76
|
+
gen = rng("demo")
|
|
77
77
|
|
|
78
78
|
# Create array and hash it
|
|
79
79
|
print(f"\n{'Hash Generation':-^60}")
|
|
@@ -95,7 +95,7 @@ def main(args):
|
|
|
95
95
|
|
|
96
96
|
# Reset generator and create same data
|
|
97
97
|
print(f"\n{'Reproducibility Check':-^60}")
|
|
98
|
-
gen_repro =
|
|
98
|
+
gen_repro = rng("demo") # Same name = same seed
|
|
99
99
|
data3 = gen_repro.random(args.size)
|
|
100
100
|
hash3 = hash_array(data3)
|
|
101
101
|
print(f"Array 3 hash (reproduced): {hash3}")
|
|
@@ -115,7 +115,7 @@ if __name__ == "__main__":
|
|
|
115
115
|
|
|
116
116
|
args = parse_args()
|
|
117
117
|
|
|
118
|
-
CONFIG, sys.stdout, sys.stderr, plt, CC,
|
|
118
|
+
CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
|
|
119
119
|
sys,
|
|
120
120
|
plt,
|
|
121
121
|
args=args,
|
scitex/scholar/__main__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/scholar/__main__.py
|
|
4
3
|
|
|
5
4
|
"""Scholar CLI entry point - Subcommand-based interface.
|
|
@@ -8,6 +7,7 @@ Clean interface routing to battle-tested pipeline implementations:
|
|
|
8
7
|
- single: Process single paper (DOI or title)
|
|
9
8
|
- parallel: Process multiple papers in parallel
|
|
10
9
|
- bibtex: Process papers from BibTeX file
|
|
10
|
+
- mcp: Start MCP server for LLM integration
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
@@ -33,6 +33,7 @@ Clean subcommand interface to battle-tested pipelines:
|
|
|
33
33
|
single - Process a single paper (DOI or title)
|
|
34
34
|
parallel - Process multiple papers in parallel
|
|
35
35
|
bibtex - Process papers from BibTeX file
|
|
36
|
+
mcp - Start MCP server for LLM integration
|
|
36
37
|
|
|
37
38
|
STORAGE: ~/.scitex/scholar/library/
|
|
38
39
|
MASTER/{8DIGITID}/ - Centralized storage (no duplicates)
|
|
@@ -193,6 +194,16 @@ STORAGE: ~/.scitex/scholar/library/
|
|
|
193
194
|
help="Base Chrome profile to sync from (default: system)",
|
|
194
195
|
)
|
|
195
196
|
|
|
197
|
+
# ========================================
|
|
198
|
+
# Subcommand: mcp
|
|
199
|
+
# ========================================
|
|
200
|
+
subparsers.add_parser(
|
|
201
|
+
"mcp",
|
|
202
|
+
help="Start MCP server for LLM integration",
|
|
203
|
+
description="Start the MCP (Model Context Protocol) server for Claude/LLM integration",
|
|
204
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
205
|
+
)
|
|
206
|
+
|
|
196
207
|
return parser
|
|
197
208
|
|
|
198
209
|
|
|
@@ -220,7 +231,7 @@ async def run_single_pipeline(args):
|
|
|
220
231
|
force=args.force,
|
|
221
232
|
)
|
|
222
233
|
|
|
223
|
-
logger.success(
|
|
234
|
+
logger.success("Single paper pipeline completed")
|
|
224
235
|
return 0
|
|
225
236
|
|
|
226
237
|
|
|
@@ -288,6 +299,15 @@ async def run_bibtex_pipeline(args):
|
|
|
288
299
|
return 0
|
|
289
300
|
|
|
290
301
|
|
|
302
|
+
async def run_mcp_server():
|
|
303
|
+
"""Run MCP server."""
|
|
304
|
+
from .mcp_server import main as mcp_main
|
|
305
|
+
|
|
306
|
+
logger.info("Starting Scholar MCP server...")
|
|
307
|
+
await mcp_main()
|
|
308
|
+
return 0
|
|
309
|
+
|
|
310
|
+
|
|
291
311
|
async def main_async():
|
|
292
312
|
"""Main async entry point."""
|
|
293
313
|
parser = create_parser()
|
|
@@ -300,6 +320,8 @@ async def main_async():
|
|
|
300
320
|
return await run_parallel_pipeline(args)
|
|
301
321
|
elif args.command == "bibtex":
|
|
302
322
|
return await run_bibtex_pipeline(args)
|
|
323
|
+
elif args.command == "mcp":
|
|
324
|
+
return await run_mcp_server()
|
|
303
325
|
else:
|
|
304
326
|
logger.error(f"Unknown command: {args.command}")
|
|
305
327
|
return 1
|