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
scitex/cli/introspect.py
CHANGED
|
@@ -11,6 +11,13 @@ import sys
|
|
|
11
11
|
import click
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
def _normalize_path(ctx, param, value):
|
|
15
|
+
"""Normalize dotted path: convert hyphens to underscores for Python module names."""
|
|
16
|
+
if value:
|
|
17
|
+
return value.replace("-", "_")
|
|
18
|
+
return value
|
|
19
|
+
|
|
20
|
+
|
|
14
21
|
@click.group(
|
|
15
22
|
context_settings={"help_option_names": ["-h", "--help"]},
|
|
16
23
|
invoke_without_command=True,
|
|
@@ -48,7 +55,7 @@ def introspect(ctx, help_recursive):
|
|
|
48
55
|
|
|
49
56
|
|
|
50
57
|
@introspect.command()
|
|
51
|
-
@click.argument("dotted_path")
|
|
58
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
52
59
|
@click.option("--no-defaults", is_flag=True, help="Exclude default values")
|
|
53
60
|
@click.option("--no-annotations", is_flag=True, help="Exclude type annotations")
|
|
54
61
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -90,7 +97,7 @@ def q(dotted_path, no_defaults, no_annotations, as_json):
|
|
|
90
97
|
|
|
91
98
|
|
|
92
99
|
@introspect.command()
|
|
93
|
-
@click.argument("dotted_path")
|
|
100
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
94
101
|
@click.option("--max-lines", "-n", type=int, help="Limit output to N lines")
|
|
95
102
|
@click.option("--no-decorators", is_flag=True, help="Exclude decorator lines")
|
|
96
103
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -125,7 +132,7 @@ def qq(dotted_path, max_lines, no_decorators, as_json):
|
|
|
125
132
|
|
|
126
133
|
|
|
127
134
|
@introspect.command("dir")
|
|
128
|
-
@click.argument("dotted_path")
|
|
135
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
129
136
|
@click.option(
|
|
130
137
|
"--filter",
|
|
131
138
|
"-f",
|
|
@@ -176,7 +183,7 @@ def dir_cmd(dotted_path, filter, kind, inherited, as_json):
|
|
|
176
183
|
|
|
177
184
|
|
|
178
185
|
@introspect.command()
|
|
179
|
-
@click.argument("dotted_path")
|
|
186
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
180
187
|
@click.option("--max-depth", "-d", type=int, default=5, help="Max recursion depth")
|
|
181
188
|
@click.option("--docstring", is_flag=True, help="Include docstrings")
|
|
182
189
|
@click.option("--root-only", is_flag=True, help="Show only root-level items")
|
|
@@ -214,7 +221,7 @@ def api(dotted_path, max_depth, docstring, root_only, as_json):
|
|
|
214
221
|
|
|
215
222
|
|
|
216
223
|
@introspect.command()
|
|
217
|
-
@click.argument("dotted_path")
|
|
224
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
218
225
|
@click.option(
|
|
219
226
|
"--format",
|
|
220
227
|
"-f",
|
|
@@ -259,7 +266,7 @@ def docstring(dotted_path, format, as_json):
|
|
|
259
266
|
|
|
260
267
|
|
|
261
268
|
@introspect.command()
|
|
262
|
-
@click.argument("dotted_path")
|
|
269
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
263
270
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
264
271
|
def exports(dotted_path, as_json):
|
|
265
272
|
"""
|
|
@@ -289,7 +296,7 @@ def exports(dotted_path, as_json):
|
|
|
289
296
|
|
|
290
297
|
|
|
291
298
|
@introspect.command()
|
|
292
|
-
@click.argument("dotted_path")
|
|
299
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
293
300
|
@click.option("--search-paths", "-p", help="Comma-separated search paths")
|
|
294
301
|
@click.option("--max-results", "-n", type=int, default=10, help="Max examples")
|
|
295
302
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -332,7 +339,7 @@ def examples(dotted_path, search_paths, max_results, as_json):
|
|
|
332
339
|
|
|
333
340
|
|
|
334
341
|
@introspect.command("hierarchy")
|
|
335
|
-
@click.argument("dotted_path")
|
|
342
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
336
343
|
@click.option("--builtins", is_flag=True, help="Include builtin classes")
|
|
337
344
|
@click.option("--max-depth", "-d", type=int, default=10, help="Max subclass depth")
|
|
338
345
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -368,7 +375,7 @@ def _print_subclasses(subclasses, indent=0):
|
|
|
368
375
|
|
|
369
376
|
|
|
370
377
|
@introspect.command("hints")
|
|
371
|
-
@click.argument("dotted_path")
|
|
378
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
372
379
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
373
380
|
def type_hints(dotted_path, as_json):
|
|
374
381
|
"""Get detailed type hint analysis"""
|
|
@@ -392,7 +399,7 @@ def type_hints(dotted_path, as_json):
|
|
|
392
399
|
|
|
393
400
|
|
|
394
401
|
@introspect.command("imports")
|
|
395
|
-
@click.argument("dotted_path")
|
|
402
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
396
403
|
@click.option("--no-categorize", is_flag=True, help="Don't group by category")
|
|
397
404
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
398
405
|
def imports(dotted_path, no_categorize, as_json):
|
|
@@ -421,7 +428,7 @@ def imports(dotted_path, no_categorize, as_json):
|
|
|
421
428
|
|
|
422
429
|
|
|
423
430
|
@introspect.command("deps")
|
|
424
|
-
@click.argument("dotted_path")
|
|
431
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
425
432
|
@click.option("--recursive", "-r", is_flag=True, help="Recursive analysis")
|
|
426
433
|
@click.option("--max-depth", "-d", type=int, default=3, help="Max recursion depth")
|
|
427
434
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
@@ -444,7 +451,7 @@ def dependencies(dotted_path, recursive, max_depth, as_json):
|
|
|
444
451
|
|
|
445
452
|
|
|
446
453
|
@introspect.command("calls")
|
|
447
|
-
@click.argument("dotted_path")
|
|
454
|
+
@click.argument("dotted_path", callback=_normalize_path)
|
|
448
455
|
@click.option("--timeout", "-t", type=int, default=10, help="Timeout in seconds")
|
|
449
456
|
@click.option("--all", "all_calls", is_flag=True, help="Include external calls")
|
|
450
457
|
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
scitex/cli/plt.py
CHANGED
|
@@ -322,33 +322,90 @@ def convert(input_file, output, fmt):
|
|
|
322
322
|
sys.exit(_run_figrecipe(*args))
|
|
323
323
|
|
|
324
324
|
|
|
325
|
-
@plt.
|
|
326
|
-
@click.
|
|
327
|
-
|
|
328
|
-
"--transport",
|
|
329
|
-
type=click.Choice(["stdio", "sse", "http"]),
|
|
330
|
-
default="stdio",
|
|
331
|
-
help="Transport protocol",
|
|
332
|
-
)
|
|
333
|
-
@click.option("--host", default="0.0.0.0", help="Host for HTTP/SSE transport")
|
|
334
|
-
@click.option("--port", default=8087, type=int, help="Port for HTTP/SSE transport")
|
|
335
|
-
def serve(transport, host, port):
|
|
325
|
+
@plt.group(invoke_without_command=True)
|
|
326
|
+
@click.pass_context
|
|
327
|
+
def mcp(ctx):
|
|
336
328
|
"""
|
|
337
|
-
|
|
329
|
+
MCP (Model Context Protocol) server operations
|
|
330
|
+
|
|
331
|
+
\b
|
|
332
|
+
Commands:
|
|
333
|
+
start - Start the MCP server
|
|
334
|
+
doctor - Check MCP server health
|
|
335
|
+
list-tools - List available MCP tools
|
|
336
|
+
info - Show MCP server information
|
|
337
|
+
install - Show installation instructions
|
|
338
338
|
|
|
339
339
|
\b
|
|
340
340
|
Examples:
|
|
341
|
-
scitex plt
|
|
342
|
-
scitex plt
|
|
341
|
+
scitex plt mcp start
|
|
342
|
+
scitex plt mcp doctor
|
|
343
343
|
"""
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
args.extend(["--host", host, "--port", str(port)])
|
|
347
|
-
click.secho(f"Starting figrecipe MCP server ({transport})", fg="cyan")
|
|
348
|
-
click.echo(f" Host: {host}")
|
|
349
|
-
click.echo(f" Port: {port}")
|
|
344
|
+
if ctx.invoked_subcommand is None:
|
|
345
|
+
click.echo(ctx.get_help())
|
|
350
346
|
|
|
351
|
-
|
|
347
|
+
|
|
348
|
+
@mcp.command()
|
|
349
|
+
@click.option("--host", default="0.0.0.0", help="Host for HTTP transport")
|
|
350
|
+
@click.option("--port", default=8087, type=int, help="Port for HTTP transport")
|
|
351
|
+
def start(host, port):
|
|
352
|
+
"""
|
|
353
|
+
Start the MCP server
|
|
354
|
+
|
|
355
|
+
\b
|
|
356
|
+
Example:
|
|
357
|
+
scitex plt mcp start
|
|
358
|
+
scitex plt mcp start --port 8087
|
|
359
|
+
"""
|
|
360
|
+
sys.exit(_run_figrecipe("mcp", "run", "--host", host, "--port", str(port)))
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@mcp.command()
|
|
364
|
+
def doctor():
|
|
365
|
+
"""
|
|
366
|
+
Check MCP server health
|
|
367
|
+
|
|
368
|
+
\b
|
|
369
|
+
Example:
|
|
370
|
+
scitex plt mcp doctor
|
|
371
|
+
"""
|
|
372
|
+
sys.exit(_run_figrecipe("mcp", "doctor"))
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@mcp.command("list-tools")
|
|
376
|
+
def list_tools_mcp():
|
|
377
|
+
"""
|
|
378
|
+
List available MCP tools
|
|
379
|
+
|
|
380
|
+
\b
|
|
381
|
+
Example:
|
|
382
|
+
scitex plt mcp list-tools
|
|
383
|
+
"""
|
|
384
|
+
sys.exit(_run_figrecipe("mcp", "list-tools"))
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@mcp.command()
|
|
388
|
+
def info():
|
|
389
|
+
"""
|
|
390
|
+
Show MCP server information
|
|
391
|
+
|
|
392
|
+
\b
|
|
393
|
+
Example:
|
|
394
|
+
scitex plt mcp info
|
|
395
|
+
"""
|
|
396
|
+
sys.exit(_run_figrecipe("mcp", "info"))
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@mcp.command()
|
|
400
|
+
def install():
|
|
401
|
+
"""
|
|
402
|
+
Show installation instructions
|
|
403
|
+
|
|
404
|
+
\b
|
|
405
|
+
Example:
|
|
406
|
+
scitex plt mcp install
|
|
407
|
+
"""
|
|
408
|
+
sys.exit(_run_figrecipe("mcp", "install"))
|
|
352
409
|
|
|
353
410
|
|
|
354
411
|
if __name__ == "__main__":
|
scitex/cli/scholar/__init__.py
CHANGED
|
@@ -21,6 +21,11 @@ CrossRef database (167M+ papers via crossref-local):
|
|
|
21
21
|
scitex scholar crossref-scitex get 10.1038/nature12373
|
|
22
22
|
scitex scholar crossref-scitex count "epilepsy seizure"
|
|
23
23
|
scitex scholar crossref-scitex info
|
|
24
|
+
|
|
25
|
+
OpenAlex database (284M+ works via openalex-local):
|
|
26
|
+
scitex scholar openalex-scitex search "neural networks"
|
|
27
|
+
scitex scholar openalex-scitex search-by-doi 10.1038/nature12373
|
|
28
|
+
scitex scholar openalex-scitex status
|
|
24
29
|
"""
|
|
25
30
|
|
|
26
31
|
from __future__ import annotations
|
|
@@ -31,6 +36,7 @@ from ._crossref_scitex import crossref_scitex
|
|
|
31
36
|
from ._fetch import fetch
|
|
32
37
|
from ._jobs import jobs
|
|
33
38
|
from ._library import config, library
|
|
39
|
+
from ._openalex_scitex import openalex_scitex
|
|
34
40
|
|
|
35
41
|
|
|
36
42
|
@click.group(
|
|
@@ -40,8 +46,7 @@ from ._library import config, library
|
|
|
40
46
|
@click.option("--help-recursive", is_flag=True, help="Show help for all subcommands")
|
|
41
47
|
@click.pass_context
|
|
42
48
|
def scholar(ctx, help_recursive):
|
|
43
|
-
"""
|
|
44
|
-
Scientific paper management
|
|
49
|
+
r"""Scientific paper management.
|
|
45
50
|
|
|
46
51
|
\b
|
|
47
52
|
Fetch papers, manage your library, and track background jobs.
|
|
@@ -93,7 +98,160 @@ def _print_help_recursive(ctx):
|
|
|
93
98
|
click.echo(sub_cmd.get_help(sub_sub_ctx))
|
|
94
99
|
|
|
95
100
|
|
|
101
|
+
@scholar.group(invoke_without_command=True)
|
|
102
|
+
@click.pass_context
|
|
103
|
+
def mcp(ctx):
|
|
104
|
+
r"""MCP (Model Context Protocol) server operations.
|
|
105
|
+
|
|
106
|
+
\b
|
|
107
|
+
Commands:
|
|
108
|
+
start - Start the MCP server
|
|
109
|
+
doctor - Check MCP server health
|
|
110
|
+
list-tools - List available MCP tools
|
|
111
|
+
|
|
112
|
+
\b
|
|
113
|
+
Examples:
|
|
114
|
+
scitex scholar mcp start
|
|
115
|
+
scitex scholar mcp list-tools
|
|
116
|
+
"""
|
|
117
|
+
if ctx.invoked_subcommand is None:
|
|
118
|
+
click.echo(ctx.get_help())
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@mcp.command()
|
|
122
|
+
@click.option(
|
|
123
|
+
"-t",
|
|
124
|
+
"--transport",
|
|
125
|
+
type=click.Choice(["stdio", "sse", "http"]),
|
|
126
|
+
default="stdio",
|
|
127
|
+
help="Transport protocol (default: stdio)",
|
|
128
|
+
)
|
|
129
|
+
@click.option("--host", default="0.0.0.0", help="Host for HTTP/SSE (default: 0.0.0.0)")
|
|
130
|
+
@click.option(
|
|
131
|
+
"--port", default=8085, type=int, help="Port for HTTP/SSE (default: 8085)"
|
|
132
|
+
)
|
|
133
|
+
def start(transport, host, port):
|
|
134
|
+
r"""Start the MCP server with scholar tools.
|
|
135
|
+
|
|
136
|
+
\b
|
|
137
|
+
NOTE: This now uses the unified scitex MCP server which includes
|
|
138
|
+
all scholar tools plus other scitex tools (plt, stats, etc.)
|
|
139
|
+
|
|
140
|
+
\b
|
|
141
|
+
Examples:
|
|
142
|
+
scitex scholar mcp start
|
|
143
|
+
scitex scholar mcp start -t http --port 8085
|
|
144
|
+
|
|
145
|
+
\b
|
|
146
|
+
Equivalent to: scitex serve -t <transport>
|
|
147
|
+
"""
|
|
148
|
+
import sys
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
from scitex.mcp_server import run_server
|
|
152
|
+
|
|
153
|
+
if transport != "stdio":
|
|
154
|
+
click.secho(f"Starting unified scitex MCP server ({transport})", fg="cyan")
|
|
155
|
+
click.echo(f" Host: {host}")
|
|
156
|
+
click.echo(f" Port: {port}")
|
|
157
|
+
click.echo(" Includes: scholar, plt, stats, audio, and more")
|
|
158
|
+
|
|
159
|
+
run_server(transport=transport, host=host, port=port)
|
|
160
|
+
|
|
161
|
+
except ImportError as e:
|
|
162
|
+
click.secho(f"Error: {e}", fg="red", err=True)
|
|
163
|
+
click.echo("\nInstall dependencies: pip install fastmcp")
|
|
164
|
+
sys.exit(1)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
click.secho(f"Error: {e}", fg="red", err=True)
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@mcp.command()
|
|
171
|
+
def doctor():
|
|
172
|
+
r"""Check MCP server health and dependencies.
|
|
173
|
+
|
|
174
|
+
\b
|
|
175
|
+
Example:
|
|
176
|
+
scitex scholar mcp doctor
|
|
177
|
+
"""
|
|
178
|
+
click.secho("Scholar MCP Server Health Check", fg="cyan", bold=True)
|
|
179
|
+
click.echo()
|
|
180
|
+
|
|
181
|
+
click.echo("Checking FastMCP... ", nl=False)
|
|
182
|
+
try:
|
|
183
|
+
import fastmcp # noqa: F401
|
|
184
|
+
|
|
185
|
+
click.secho("OK", fg="green")
|
|
186
|
+
except ImportError:
|
|
187
|
+
click.secho("NOT INSTALLED", fg="red")
|
|
188
|
+
click.echo(" Install with: pip install fastmcp")
|
|
189
|
+
|
|
190
|
+
click.echo("Checking scholar module... ", nl=False)
|
|
191
|
+
try:
|
|
192
|
+
from scitex import scholar as _ # noqa: F401
|
|
193
|
+
|
|
194
|
+
click.secho("OK", fg="green")
|
|
195
|
+
except ImportError as e:
|
|
196
|
+
click.secho(f"FAIL ({e})", fg="red")
|
|
197
|
+
|
|
198
|
+
click.echo("Checking crossref-local... ", nl=False)
|
|
199
|
+
try:
|
|
200
|
+
import crossref_local # noqa: F401
|
|
201
|
+
|
|
202
|
+
click.secho("OK", fg="green")
|
|
203
|
+
except ImportError:
|
|
204
|
+
click.secho("NOT INSTALLED (optional)", fg="yellow")
|
|
205
|
+
|
|
206
|
+
click.echo("Checking openalex-local... ", nl=False)
|
|
207
|
+
try:
|
|
208
|
+
import openalex_local # noqa: F401
|
|
209
|
+
|
|
210
|
+
click.secho("OK", fg="green")
|
|
211
|
+
except ImportError:
|
|
212
|
+
click.secho("NOT INSTALLED (optional)", fg="yellow")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@mcp.command("list-tools")
|
|
216
|
+
def list_tools():
|
|
217
|
+
r"""List available MCP tools.
|
|
218
|
+
|
|
219
|
+
\b
|
|
220
|
+
Example:
|
|
221
|
+
scitex scholar mcp list-tools
|
|
222
|
+
"""
|
|
223
|
+
click.secho("Scholar MCP Tools", fg="cyan", bold=True)
|
|
224
|
+
click.echo()
|
|
225
|
+
tools = [
|
|
226
|
+
("search_papers", "Search for papers by query"),
|
|
227
|
+
("resolve_dois", "Resolve DOIs to metadata"),
|
|
228
|
+
("enrich_bibtex", "Enrich BibTeX with abstracts/DOIs"),
|
|
229
|
+
("download_pdf", "Download PDF for a paper"),
|
|
230
|
+
("download_pdfs_batch", "Batch download PDFs"),
|
|
231
|
+
("get_library_status", "Get library status"),
|
|
232
|
+
("parse_bibtex", "Parse BibTeX file"),
|
|
233
|
+
("validate_pdfs", "Validate downloaded PDFs"),
|
|
234
|
+
("authenticate", "Authenticate with institution"),
|
|
235
|
+
("check_auth_status", "Check authentication status"),
|
|
236
|
+
("fetch_papers", "Fetch papers by DOIs (async)"),
|
|
237
|
+
# CrossRef-Local (167M+ papers)
|
|
238
|
+
("crossref_search", "Search CrossRef database (167M+ papers)"),
|
|
239
|
+
("crossref_get", "Get paper by DOI from CrossRef"),
|
|
240
|
+
("crossref_count", "Count papers matching query"),
|
|
241
|
+
("crossref_citations", "Get citation relationships"),
|
|
242
|
+
("crossref_info", "Get CrossRef database status"),
|
|
243
|
+
# OpenAlex-Local (284M+ works)
|
|
244
|
+
("openalex_search", "Search OpenAlex database (284M+ works)"),
|
|
245
|
+
("openalex_get", "Get paper by DOI/ID from OpenAlex"),
|
|
246
|
+
("openalex_count", "Count papers matching query"),
|
|
247
|
+
("openalex_info", "Get OpenAlex database status"),
|
|
248
|
+
]
|
|
249
|
+
for name, desc in tools:
|
|
250
|
+
click.echo(f" {name}: {desc}")
|
|
251
|
+
|
|
252
|
+
|
|
96
253
|
scholar.add_command(crossref_scitex)
|
|
254
|
+
scholar.add_command(openalex_scitex)
|
|
97
255
|
scholar.add_command(fetch)
|
|
98
256
|
scholar.add_command(library)
|
|
99
257
|
scholar.add_command(config)
|