scitex 2.15.2__py3-none-any.whl → 2.15.4__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/_mcp_resources/__init__.py +2 -0
- scitex/_mcp_resources/_scholar.py +148 -0
- scitex/_mcp_tools/scholar.py +50 -99
- scitex/_mcp_tools/social.py +15 -232
- scitex/_mcp_tools/writer.py +7 -17
- scitex/canvas/mcp_server.py +16 -3
- scitex/capture/mcp_server.py +16 -2
- scitex/cli/audio.py +90 -20
- scitex/cli/capture.py +120 -0
- scitex/cli/introspect.py +19 -12
- scitex/cli/plt.py +78 -21
- scitex/cli/scholar/__init__.py +160 -2
- scitex/cli/scholar/_crossref_scitex.py +25 -266
- scitex/cli/scholar/_openalex_scitex.py +55 -0
- scitex/cli/social.py +63 -22
- scitex/cli/stats.py +121 -3
- scitex/cli/writer.py +49 -423
- scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +90 -0
- scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +1571 -0
- scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +6262 -0
- scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +1274 -0
- scitex/dev/plt/data/mpl/dir_ax.txt +459 -0
- scitex/introspect/_list_api.py +5 -2
- scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +2 -2
- scitex/scholar/__init__.py +14 -9
- scitex/scholar/_mcp/crossref_tool_schemas.py +133 -0
- scitex/scholar/_mcp/openalex_handlers.py +212 -0
- scitex/scholar/_mcp/openalex_tool_schemas.py +96 -0
- scitex/scholar/_mcp/tool_schemas.py +16 -1
- scitex/scholar/data/.gitkeep +0 -0
- scitex/scholar/data/README.md +44 -0
- scitex/scholar/data/bib_files/bibliography.bib +1952 -0
- scitex/scholar/data/bib_files/neurovista.bib +277 -0
- scitex/scholar/data/bib_files/neurovista_enriched.bib +441 -0
- scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +441 -0
- scitex/scholar/data/bib_files/neurovista_processed.bib +338 -0
- scitex/scholar/data/bib_files/openaccess.bib +89 -0
- scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +2178 -0
- scitex/scholar/data/bib_files/pac.bib +698 -0
- scitex/scholar/data/bib_files/pac_enriched.bib +1061 -0
- scitex/scholar/data/bib_files/pac_processed.bib +0 -0
- scitex/scholar/data/bib_files/pac_titles.txt +75 -0
- scitex/scholar/data/bib_files/paywalled.bib +98 -0
- scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +58 -0
- scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +87 -0
- scitex/scholar/data/bib_files/seizure_prediction.bib +694 -0
- scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
- scitex/scholar/data/bib_files/test_complete_enriched.bib +437 -0
- scitex/scholar/data/bib_files/test_final_enriched.bib +437 -0
- scitex/scholar/data/bib_files/test_seizure.bib +46 -0
- scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
- scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
- scitex/scholar/data/impact_factor.db +0 -0
- scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +2 -2
- scitex/scholar/local_dbs/__init__.py +31 -0
- scitex/scholar/local_dbs/crossref_scitex.py +30 -0
- scitex/scholar/local_dbs/openalex_scitex.py +30 -0
- scitex/scholar/mcp_server.py +59 -4
- scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +2 -2
- scitex/stats/mcp_server.py +16 -3
- scitex/template/mcp_server.py +16 -3
- scitex/ui/mcp_server.py +16 -3
- scitex/writer/__init__.py +43 -34
- {scitex-2.15.2.dist-info → scitex-2.15.4.dist-info}/METADATA +22 -3
- {scitex-2.15.2.dist-info → scitex-2.15.4.dist-info}/RECORD +70 -38
- scitex/scholar/crossref_scitex.py +0 -367
- scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +0 -462
- scitex/scholar/url_finder/.tmp/open_url/README.md +0 -223
- scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +0 -694
- scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +0 -1160
- scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +0 -344
- scitex/scholar/url_finder/.tmp/open_url/__init__.py +0 -24
- {scitex-2.15.2.dist-info → scitex-2.15.4.dist-info}/WHEEL +0 -0
- {scitex-2.15.2.dist-info → scitex-2.15.4.dist-info}/entry_points.txt +0 -0
- {scitex-2.15.2.dist-info → scitex-2.15.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,142 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# Timestamp: 2026-01-
|
|
2
|
+
# Timestamp: 2026-01-29
|
|
3
3
|
# File: src/scitex/cli/scholar/_crossref_scitex.py
|
|
4
|
-
"""CrossRef-SciTeX CLI
|
|
4
|
+
"""CrossRef-SciTeX CLI - Thin wrapper delegating to crossref-local.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
This module provides access to the local CrossRef database (167M+ papers)
|
|
7
|
+
by delegating directly to crossref-local CLI without any modifications.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
-
import json
|
|
13
12
|
import sys
|
|
14
13
|
|
|
15
14
|
import click
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
@click.
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
\b
|
|
28
|
-
Examples:
|
|
29
|
-
scitex scholar crossref-scitex search "deep learning"
|
|
30
|
-
scitex scholar crossref-scitex get 10.1038/nature12373
|
|
31
|
-
scitex scholar crossref-scitex count "epilepsy seizure"
|
|
32
|
-
scitex scholar crossref-scitex info
|
|
33
|
-
"""
|
|
34
|
-
pass
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@crossref_scitex.command("search")
|
|
38
|
-
@click.argument("query")
|
|
39
|
-
@click.option("-n", "--limit", default=20, help="Maximum results (default: 20)")
|
|
40
|
-
@click.option("--offset", default=0, help="Skip N results for pagination")
|
|
41
|
-
@click.option("--year-min", type=int, help="Minimum publication year")
|
|
42
|
-
@click.option("--year-max", type=int, help="Maximum publication year")
|
|
43
|
-
@click.option("--enrich", is_flag=True, help="Add citation counts and references")
|
|
44
|
-
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
45
|
-
def search_cmd(query, limit, offset, year_min, year_max, enrich, as_json):
|
|
46
|
-
"""
|
|
47
|
-
Search for papers in CrossRef database.
|
|
17
|
+
@click.command(
|
|
18
|
+
"crossref-scitex",
|
|
19
|
+
context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
|
|
20
|
+
)
|
|
21
|
+
@click.option("--help-recursive", is_flag=True, help="Show help for all commands")
|
|
22
|
+
@click.pass_context
|
|
23
|
+
def crossref_scitex(ctx, help_recursive):
|
|
24
|
+
r"""CrossRef-SciTeX database search (167M+ papers).
|
|
48
25
|
|
|
49
26
|
\b
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
scitex scholar crossref search "deep learning" --limit 50
|
|
53
|
-
scitex scholar crossref search "CRISPR" --year-min 2020 --enrich
|
|
54
|
-
"""
|
|
55
|
-
try:
|
|
56
|
-
from scitex.scholar import crossref_scitex as crossref
|
|
57
|
-
except ImportError:
|
|
58
|
-
click.secho(
|
|
59
|
-
"crossref-local not installed. Install with: pip install crossref-local",
|
|
60
|
-
fg="red",
|
|
61
|
-
)
|
|
62
|
-
sys.exit(1)
|
|
63
|
-
|
|
64
|
-
try:
|
|
65
|
-
results = crossref.search(query, limit=limit, offset=offset)
|
|
66
|
-
|
|
67
|
-
if enrich:
|
|
68
|
-
results = crossref.enrich(results)
|
|
69
|
-
|
|
70
|
-
papers = []
|
|
71
|
-
for work in results:
|
|
72
|
-
if year_min and work.year and work.year < year_min:
|
|
73
|
-
continue
|
|
74
|
-
if year_max and work.year and work.year > year_max:
|
|
75
|
-
continue
|
|
76
|
-
papers.append(work)
|
|
77
|
-
if len(papers) >= limit:
|
|
78
|
-
break
|
|
79
|
-
|
|
80
|
-
if as_json:
|
|
81
|
-
output = {
|
|
82
|
-
"query": query,
|
|
83
|
-
"total": results.total,
|
|
84
|
-
"count": len(papers),
|
|
85
|
-
"papers": [
|
|
86
|
-
{
|
|
87
|
-
"doi": p.doi,
|
|
88
|
-
"title": p.title,
|
|
89
|
-
"authors": p.authors,
|
|
90
|
-
"year": p.year,
|
|
91
|
-
"journal": p.journal,
|
|
92
|
-
"citation_count": p.citation_count,
|
|
93
|
-
}
|
|
94
|
-
for p in papers
|
|
95
|
-
],
|
|
96
|
-
}
|
|
97
|
-
click.echo(json.dumps(output, indent=2))
|
|
98
|
-
else:
|
|
99
|
-
click.secho(
|
|
100
|
-
f"Found {results.total} papers for: {query}", fg="green", bold=True
|
|
101
|
-
)
|
|
102
|
-
click.echo()
|
|
103
|
-
|
|
104
|
-
for i, paper in enumerate(papers, 1):
|
|
105
|
-
authors = ", ".join(paper.authors[:3]) if paper.authors else "Unknown"
|
|
106
|
-
if paper.authors and len(paper.authors) > 3:
|
|
107
|
-
authors += " et al."
|
|
108
|
-
|
|
109
|
-
click.secho(f"{i}. {paper.title}", fg="cyan", bold=True)
|
|
110
|
-
click.echo(f" Authors: {authors}")
|
|
111
|
-
click.echo(
|
|
112
|
-
f" Year: {paper.year or 'N/A'} | Journal: {paper.journal or 'N/A'}"
|
|
113
|
-
)
|
|
114
|
-
click.echo(f" DOI: {paper.doi}")
|
|
115
|
-
if paper.citation_count:
|
|
116
|
-
click.echo(f" Citations: {paper.citation_count}")
|
|
117
|
-
click.echo()
|
|
118
|
-
|
|
119
|
-
except Exception as e:
|
|
120
|
-
click.secho(f"Error: {e}", fg="red")
|
|
121
|
-
sys.exit(1)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@crossref_scitex.command("get")
|
|
125
|
-
@click.argument("doi")
|
|
126
|
-
@click.option("--citations", is_flag=True, help="Include citing papers")
|
|
127
|
-
@click.option("--references", is_flag=True, help="Include referenced papers")
|
|
128
|
-
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
129
|
-
def get_cmd(doi, citations, references, as_json):
|
|
130
|
-
"""
|
|
131
|
-
Get paper details by DOI.
|
|
27
|
+
Thin wrapper for crossref-local. All arguments passed directly.
|
|
28
|
+
Run 'crossref-local --help' for full options.
|
|
132
29
|
|
|
133
30
|
\b
|
|
134
31
|
Examples:
|
|
135
|
-
scitex scholar crossref
|
|
136
|
-
scitex scholar crossref
|
|
32
|
+
scitex scholar crossref-scitex search "deep learning" --abstracts
|
|
33
|
+
scitex scholar crossref-scitex search-by-doi 10.1038/nature12373
|
|
34
|
+
scitex scholar crossref-scitex status
|
|
35
|
+
scitex scholar crossref-scitex cache query "neural networks"
|
|
137
36
|
"""
|
|
138
37
|
try:
|
|
139
|
-
from
|
|
38
|
+
from crossref_local.cli import cli as crossref_cli
|
|
140
39
|
except ImportError:
|
|
141
40
|
click.secho(
|
|
142
41
|
"crossref-local not installed. Install with: pip install crossref-local",
|
|
@@ -144,153 +43,13 @@ def get_cmd(doi, citations, references, as_json):
|
|
|
144
43
|
)
|
|
145
44
|
sys.exit(1)
|
|
146
45
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
click.secho(f"DOI not found: {doi}", fg="red")
|
|
152
|
-
sys.exit(1)
|
|
153
|
-
|
|
154
|
-
if as_json:
|
|
155
|
-
output = {
|
|
156
|
-
"doi": work.doi,
|
|
157
|
-
"title": work.title,
|
|
158
|
-
"authors": work.authors,
|
|
159
|
-
"year": work.year,
|
|
160
|
-
"journal": work.journal,
|
|
161
|
-
"abstract": work.abstract,
|
|
162
|
-
"citation_count": work.citation_count,
|
|
163
|
-
"reference_count": work.reference_count,
|
|
164
|
-
"type": work.type,
|
|
165
|
-
"publisher": work.publisher,
|
|
166
|
-
}
|
|
167
|
-
if citations:
|
|
168
|
-
output["citing_dois"] = crossref.get_citing(doi)
|
|
169
|
-
if references:
|
|
170
|
-
output["referenced_dois"] = crossref.get_cited(doi)
|
|
171
|
-
click.echo(json.dumps(output, indent=2))
|
|
172
|
-
else:
|
|
173
|
-
click.secho(work.title, fg="cyan", bold=True)
|
|
174
|
-
click.echo()
|
|
175
|
-
|
|
176
|
-
if work.authors:
|
|
177
|
-
click.echo(f"Authors: {', '.join(work.authors)}")
|
|
178
|
-
click.echo(f"Year: {work.year or 'N/A'}")
|
|
179
|
-
click.echo(f"Journal: {work.journal or 'N/A'}")
|
|
180
|
-
click.echo(f"DOI: {work.doi}")
|
|
181
|
-
click.echo(f"Type: {work.type or 'N/A'}")
|
|
182
|
-
click.echo(f"Publisher: {work.publisher or 'N/A'}")
|
|
183
|
-
click.echo(f"Citations: {work.citation_count or 0}")
|
|
184
|
-
click.echo(f"References: {work.reference_count or 0}")
|
|
185
|
-
|
|
186
|
-
if work.abstract:
|
|
187
|
-
click.echo()
|
|
188
|
-
click.secho("Abstract:", bold=True)
|
|
189
|
-
click.echo(
|
|
190
|
-
work.abstract[:500] + "..."
|
|
191
|
-
if len(work.abstract) > 500
|
|
192
|
-
else work.abstract
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
if citations:
|
|
196
|
-
citing = crossref.get_citing(doi)
|
|
197
|
-
click.echo()
|
|
198
|
-
click.secho(f"Citing papers ({len(citing)}):", bold=True)
|
|
199
|
-
for c_doi in citing[:10]:
|
|
200
|
-
click.echo(f" - {c_doi}")
|
|
201
|
-
if len(citing) > 10:
|
|
202
|
-
click.echo(f" ... and {len(citing) - 10} more")
|
|
203
|
-
|
|
204
|
-
if references:
|
|
205
|
-
cited = crossref.get_cited(doi)
|
|
206
|
-
click.echo()
|
|
207
|
-
click.secho(f"References ({len(cited)}):", bold=True)
|
|
208
|
-
for r_doi in cited[:10]:
|
|
209
|
-
click.echo(f" - {r_doi}")
|
|
210
|
-
if len(cited) > 10:
|
|
211
|
-
click.echo(f" ... and {len(cited) - 10} more")
|
|
212
|
-
|
|
213
|
-
except Exception as e:
|
|
214
|
-
click.secho(f"Error: {e}", fg="red")
|
|
215
|
-
sys.exit(1)
|
|
46
|
+
# Handle --help-recursive by delegating to crossref-local
|
|
47
|
+
args = ctx.args
|
|
48
|
+
if help_recursive:
|
|
49
|
+
args = ["--help-recursive"]
|
|
216
50
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
@click.argument("query")
|
|
220
|
-
def count_cmd(query):
|
|
221
|
-
"""
|
|
222
|
-
Count papers matching a query.
|
|
223
|
-
|
|
224
|
-
\b
|
|
225
|
-
Examples:
|
|
226
|
-
scitex scholar crossref count "machine learning"
|
|
227
|
-
scitex scholar crossref count "CRISPR gene editing"
|
|
228
|
-
"""
|
|
229
|
-
try:
|
|
230
|
-
from scitex.scholar import crossref_scitex as crossref
|
|
231
|
-
except ImportError:
|
|
232
|
-
click.secho(
|
|
233
|
-
"crossref-local not installed. Install with: pip install crossref-local",
|
|
234
|
-
fg="red",
|
|
235
|
-
)
|
|
236
|
-
sys.exit(1)
|
|
237
|
-
|
|
238
|
-
try:
|
|
239
|
-
count = crossref.count(query)
|
|
240
|
-
click.echo(f"{count:,} papers match: {query}")
|
|
241
|
-
except Exception as e:
|
|
242
|
-
click.secho(f"Error: {e}", fg="red")
|
|
243
|
-
sys.exit(1)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
@crossref_scitex.command("info")
|
|
247
|
-
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
248
|
-
def info_cmd(as_json):
|
|
249
|
-
"""
|
|
250
|
-
Show CrossRef database configuration and status.
|
|
251
|
-
|
|
252
|
-
\b
|
|
253
|
-
Examples:
|
|
254
|
-
scitex scholar crossref info
|
|
255
|
-
scitex scholar crossref info --json
|
|
256
|
-
"""
|
|
257
|
-
try:
|
|
258
|
-
from scitex.scholar import crossref_scitex as crossref
|
|
259
|
-
except ImportError:
|
|
260
|
-
click.secho(
|
|
261
|
-
"crossref-local not installed. Install with: pip install crossref-local",
|
|
262
|
-
fg="red",
|
|
263
|
-
)
|
|
264
|
-
sys.exit(1)
|
|
265
|
-
|
|
266
|
-
try:
|
|
267
|
-
info = crossref.info()
|
|
268
|
-
mode = crossref.get_mode()
|
|
269
|
-
|
|
270
|
-
if as_json:
|
|
271
|
-
info["mode"] = mode
|
|
272
|
-
click.echo(json.dumps(info, indent=2))
|
|
273
|
-
else:
|
|
274
|
-
click.secho("CrossRef Database Status", fg="cyan", bold=True)
|
|
275
|
-
click.echo()
|
|
276
|
-
click.echo(f"Mode: {mode}")
|
|
277
|
-
click.echo(f"Status: {info.get('status', 'unknown')}")
|
|
278
|
-
|
|
279
|
-
if "version" in info:
|
|
280
|
-
click.echo(f"Version: {info['version']}")
|
|
281
|
-
|
|
282
|
-
if "work_count" in info:
|
|
283
|
-
click.echo(f"Papers: {info['work_count']:,}")
|
|
284
|
-
|
|
285
|
-
if "db_path" in info:
|
|
286
|
-
click.echo(f"Database: {info['db_path']}")
|
|
287
|
-
|
|
288
|
-
if "api_url" in info:
|
|
289
|
-
click.echo(f"API URL: {info['api_url']}")
|
|
290
|
-
|
|
291
|
-
except Exception as e:
|
|
292
|
-
click.secho(f"Error: {e}", fg="red")
|
|
293
|
-
sys.exit(1)
|
|
51
|
+
# Delegate all arguments to crossref-local CLI
|
|
52
|
+
sys.exit(crossref_cli.main(args, standalone_mode=False))
|
|
294
53
|
|
|
295
54
|
|
|
296
55
|
# EOF
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2026-01-29
|
|
3
|
+
# File: src/scitex/cli/scholar/_openalex_scitex.py
|
|
4
|
+
"""OpenAlex-SciTeX CLI - Thin wrapper delegating to openalex-local.
|
|
5
|
+
|
|
6
|
+
This module provides access to the local OpenAlex database (284M+ works)
|
|
7
|
+
by delegating directly to openalex-local CLI without any modifications.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command(
|
|
18
|
+
"openalex-scitex",
|
|
19
|
+
context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
|
|
20
|
+
)
|
|
21
|
+
@click.option("--help-recursive", is_flag=True, help="Show help for all commands")
|
|
22
|
+
@click.pass_context
|
|
23
|
+
def openalex_scitex(ctx, help_recursive):
|
|
24
|
+
"""
|
|
25
|
+
OpenAlex-SciTeX database search (284M+ works)
|
|
26
|
+
|
|
27
|
+
\b
|
|
28
|
+
Thin wrapper for openalex-local. All arguments passed directly.
|
|
29
|
+
Run 'openalex-local --help' for full options.
|
|
30
|
+
|
|
31
|
+
\b
|
|
32
|
+
Examples:
|
|
33
|
+
scitex scholar openalex-scitex search "machine learning"
|
|
34
|
+
scitex scholar openalex-scitex search-by-doi 10.1038/nature12373
|
|
35
|
+
scitex scholar openalex-scitex status
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
from openalex_local.cli import cli as openalex_cli
|
|
39
|
+
except ImportError:
|
|
40
|
+
click.secho(
|
|
41
|
+
"openalex-local not installed. Install with: pip install openalex-local",
|
|
42
|
+
fg="red",
|
|
43
|
+
)
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
|
|
46
|
+
# Handle --help-recursive by delegating to openalex-local
|
|
47
|
+
args = ctx.args
|
|
48
|
+
if help_recursive:
|
|
49
|
+
args = ["--help-recursive"]
|
|
50
|
+
|
|
51
|
+
# Delegate all arguments to openalex-local CLI
|
|
52
|
+
sys.exit(openalex_cli.main(args, standalone_mode=False))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# EOF
|
scitex/cli/social.py
CHANGED
|
@@ -279,33 +279,74 @@ def thread(platform, file, delay, dry_run, as_json):
|
|
|
279
279
|
sys.exit(_run_socialia(*args, json_output=as_json))
|
|
280
280
|
|
|
281
281
|
|
|
282
|
-
@social.
|
|
283
|
-
@click.
|
|
284
|
-
|
|
285
|
-
"--transport",
|
|
286
|
-
type=click.Choice(["stdio", "sse", "http"]),
|
|
287
|
-
default="stdio",
|
|
288
|
-
help="Transport protocol",
|
|
289
|
-
)
|
|
290
|
-
@click.option("--host", default="0.0.0.0", help="Host for HTTP/SSE transport")
|
|
291
|
-
@click.option("--port", default=8086, type=int, help="Port for HTTP/SSE transport")
|
|
292
|
-
def serve(transport, host, port):
|
|
282
|
+
@social.group(invoke_without_command=True)
|
|
283
|
+
@click.pass_context
|
|
284
|
+
def mcp(ctx):
|
|
293
285
|
"""
|
|
294
|
-
|
|
286
|
+
MCP (Model Context Protocol) server operations
|
|
287
|
+
|
|
288
|
+
\b
|
|
289
|
+
Commands:
|
|
290
|
+
start - Start the MCP server
|
|
291
|
+
doctor - Check MCP server health
|
|
292
|
+
list-tools - List available MCP tools
|
|
293
|
+
installation - Show Claude Desktop configuration
|
|
295
294
|
|
|
296
295
|
\b
|
|
297
296
|
Examples:
|
|
298
|
-
scitex social
|
|
299
|
-
scitex social
|
|
297
|
+
scitex social mcp start
|
|
298
|
+
scitex social mcp doctor
|
|
299
|
+
"""
|
|
300
|
+
if ctx.invoked_subcommand is None:
|
|
301
|
+
click.echo(ctx.get_help())
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@mcp.command()
|
|
305
|
+
def start():
|
|
306
|
+
"""
|
|
307
|
+
Start the MCP server
|
|
308
|
+
|
|
309
|
+
\b
|
|
310
|
+
Example:
|
|
311
|
+
scitex social mcp start
|
|
312
|
+
"""
|
|
313
|
+
sys.exit(_run_socialia("mcp", "start"))
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@mcp.command()
|
|
317
|
+
def doctor():
|
|
318
|
+
"""
|
|
319
|
+
Check MCP server health
|
|
320
|
+
|
|
321
|
+
\b
|
|
322
|
+
Example:
|
|
323
|
+
scitex social mcp doctor
|
|
324
|
+
"""
|
|
325
|
+
sys.exit(_run_socialia("mcp", "doctor"))
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
@mcp.command("list-tools")
|
|
329
|
+
def list_tools():
|
|
330
|
+
"""
|
|
331
|
+
List available MCP tools
|
|
332
|
+
|
|
333
|
+
\b
|
|
334
|
+
Example:
|
|
335
|
+
scitex social mcp list-tools
|
|
336
|
+
"""
|
|
337
|
+
sys.exit(_run_socialia("mcp", "list-tools"))
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
@mcp.command()
|
|
341
|
+
def installation():
|
|
342
|
+
"""
|
|
343
|
+
Show Claude Desktop configuration
|
|
344
|
+
|
|
345
|
+
\b
|
|
346
|
+
Example:
|
|
347
|
+
scitex social mcp installation
|
|
300
348
|
"""
|
|
301
|
-
|
|
302
|
-
if transport != "stdio":
|
|
303
|
-
args.extend(["--host", host, "--port", str(port)])
|
|
304
|
-
click.secho(f"Starting socialia MCP server ({transport})", fg="cyan")
|
|
305
|
-
click.echo(f" Host: {host}")
|
|
306
|
-
click.echo(f" Port: {port}")
|
|
307
|
-
|
|
308
|
-
sys.exit(_run_socialia(*args))
|
|
349
|
+
sys.exit(_run_socialia("mcp", "installation"))
|
|
309
350
|
|
|
310
351
|
|
|
311
352
|
if __name__ == "__main__":
|
scitex/cli/stats.py
CHANGED
|
@@ -139,9 +139,9 @@ def recommend(
|
|
|
139
139
|
output = {
|
|
140
140
|
"context": {
|
|
141
141
|
"n_groups": n_groups,
|
|
142
|
-
"sample_sizes":
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
"sample_sizes": (
|
|
143
|
+
list(sample_sizes) if sample_sizes else [30] * n_groups
|
|
144
|
+
),
|
|
145
145
|
"outcome_type": outcome_type,
|
|
146
146
|
"design": design,
|
|
147
147
|
"paired": paired,
|
|
@@ -346,5 +346,123 @@ def tests():
|
|
|
346
346
|
sys.exit(1)
|
|
347
347
|
|
|
348
348
|
|
|
349
|
+
@stats.group(invoke_without_command=True)
|
|
350
|
+
@click.pass_context
|
|
351
|
+
def mcp(ctx):
|
|
352
|
+
"""
|
|
353
|
+
MCP (Model Context Protocol) server operations
|
|
354
|
+
|
|
355
|
+
\b
|
|
356
|
+
Commands:
|
|
357
|
+
start - Start the MCP server
|
|
358
|
+
doctor - Check MCP server health
|
|
359
|
+
list-tools - List available MCP tools
|
|
360
|
+
|
|
361
|
+
\b
|
|
362
|
+
Examples:
|
|
363
|
+
scitex stats mcp start
|
|
364
|
+
scitex stats mcp list-tools
|
|
365
|
+
"""
|
|
366
|
+
if ctx.invoked_subcommand is None:
|
|
367
|
+
click.echo(ctx.get_help())
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@mcp.command()
|
|
371
|
+
@click.option(
|
|
372
|
+
"-t",
|
|
373
|
+
"--transport",
|
|
374
|
+
type=click.Choice(["stdio", "sse", "http"]),
|
|
375
|
+
default="stdio",
|
|
376
|
+
help="Transport protocol (default: stdio)",
|
|
377
|
+
)
|
|
378
|
+
@click.option("--host", default="0.0.0.0", help="Host for HTTP/SSE (default: 0.0.0.0)")
|
|
379
|
+
@click.option(
|
|
380
|
+
"--port", default=8095, type=int, help="Port for HTTP/SSE (default: 8095)"
|
|
381
|
+
)
|
|
382
|
+
def start(transport, host, port):
|
|
383
|
+
"""
|
|
384
|
+
Start the stats MCP server
|
|
385
|
+
|
|
386
|
+
\b
|
|
387
|
+
Examples:
|
|
388
|
+
scitex stats mcp start
|
|
389
|
+
scitex stats mcp start -t http --port 8095
|
|
390
|
+
"""
|
|
391
|
+
try:
|
|
392
|
+
from scitex.stats.mcp_server import main as run_server
|
|
393
|
+
|
|
394
|
+
if transport != "stdio":
|
|
395
|
+
click.secho(f"Starting stats MCP server ({transport})", fg="cyan")
|
|
396
|
+
click.echo(f" Host: {host}")
|
|
397
|
+
click.echo(f" Port: {port}")
|
|
398
|
+
|
|
399
|
+
run_server()
|
|
400
|
+
|
|
401
|
+
except ImportError as e:
|
|
402
|
+
click.secho(f"Error: {e}", fg="red", err=True)
|
|
403
|
+
click.echo("\nInstall dependencies: pip install fastmcp")
|
|
404
|
+
sys.exit(1)
|
|
405
|
+
except Exception as e:
|
|
406
|
+
click.secho(f"Error: {e}", fg="red", err=True)
|
|
407
|
+
sys.exit(1)
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@mcp.command()
|
|
411
|
+
def doctor():
|
|
412
|
+
"""
|
|
413
|
+
Check MCP server health and dependencies
|
|
414
|
+
|
|
415
|
+
\b
|
|
416
|
+
Example:
|
|
417
|
+
scitex stats mcp doctor
|
|
418
|
+
"""
|
|
419
|
+
click.secho("Stats MCP Server Health Check", fg="cyan", bold=True)
|
|
420
|
+
click.echo()
|
|
421
|
+
|
|
422
|
+
click.echo("Checking FastMCP... ", nl=False)
|
|
423
|
+
try:
|
|
424
|
+
import fastmcp # noqa: F401
|
|
425
|
+
|
|
426
|
+
click.secho("OK", fg="green")
|
|
427
|
+
except ImportError:
|
|
428
|
+
click.secho("NOT INSTALLED", fg="red")
|
|
429
|
+
click.echo(" Install with: pip install fastmcp")
|
|
430
|
+
|
|
431
|
+
click.echo("Checking stats module... ", nl=False)
|
|
432
|
+
try:
|
|
433
|
+
from scitex import stats as _ # noqa: F401
|
|
434
|
+
|
|
435
|
+
click.secho("OK", fg="green")
|
|
436
|
+
except ImportError as e:
|
|
437
|
+
click.secho(f"FAIL ({e})", fg="red")
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
@mcp.command("list-tools")
|
|
441
|
+
def list_tools():
|
|
442
|
+
"""
|
|
443
|
+
List available MCP tools
|
|
444
|
+
|
|
445
|
+
\b
|
|
446
|
+
Example:
|
|
447
|
+
scitex stats mcp list-tools
|
|
448
|
+
"""
|
|
449
|
+
click.secho("Stats MCP Tools", fg="cyan", bold=True)
|
|
450
|
+
click.echo()
|
|
451
|
+
tools = [
|
|
452
|
+
("stats_recommend_tests", "Recommend appropriate statistical tests"),
|
|
453
|
+
("stats_run_test", "Execute a statistical test on data"),
|
|
454
|
+
("stats_format_results", "Format results in journal style"),
|
|
455
|
+
("stats_power_analysis", "Calculate power or sample size"),
|
|
456
|
+
("stats_correct_pvalues", "Apply multiple comparison correction"),
|
|
457
|
+
("stats_describe", "Calculate descriptive statistics"),
|
|
458
|
+
("stats_effect_size", "Calculate effect size"),
|
|
459
|
+
("stats_normality_test", "Test for normal distribution"),
|
|
460
|
+
("stats_posthoc_test", "Run post-hoc pairwise comparisons"),
|
|
461
|
+
("stats_p_to_stars", "Convert p-value to significance stars"),
|
|
462
|
+
]
|
|
463
|
+
for name, desc in tools:
|
|
464
|
+
click.echo(f" {name}: {desc}")
|
|
465
|
+
|
|
466
|
+
|
|
349
467
|
if __name__ == "__main__":
|
|
350
468
|
stats()
|