scitex 2.14.0__py3-none-any.whl → 2.15.2__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 (300) hide show
  1. scitex/__init__.py +71 -17
  2. scitex/_env_loader.py +156 -0
  3. scitex/_mcp_resources/__init__.py +37 -0
  4. scitex/_mcp_resources/_cheatsheet.py +135 -0
  5. scitex/_mcp_resources/_figrecipe.py +138 -0
  6. scitex/_mcp_resources/_formats.py +102 -0
  7. scitex/_mcp_resources/_modules.py +337 -0
  8. scitex/_mcp_resources/_session.py +149 -0
  9. scitex/_mcp_tools/__init__.py +4 -0
  10. scitex/_mcp_tools/audio.py +66 -0
  11. scitex/_mcp_tools/diagram.py +11 -95
  12. scitex/_mcp_tools/introspect.py +210 -0
  13. scitex/_mcp_tools/plt.py +260 -305
  14. scitex/_mcp_tools/scholar.py +74 -0
  15. scitex/_mcp_tools/social.py +244 -0
  16. scitex/_mcp_tools/template.py +24 -0
  17. scitex/_mcp_tools/writer.py +21 -204
  18. scitex/ai/_gen_ai/_PARAMS.py +10 -7
  19. scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
  20. scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
  21. scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
  22. scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
  23. scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
  24. scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
  25. scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
  26. scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
  27. scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
  28. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +30 -1550
  29. scitex/ai/classification/timeseries/_sliding_window_core.py +467 -0
  30. scitex/ai/classification/timeseries/_sliding_window_plotting.py +369 -0
  31. scitex/audio/README.md +40 -36
  32. scitex/audio/__init__.py +129 -61
  33. scitex/audio/_branding.py +185 -0
  34. scitex/audio/_mcp/__init__.py +32 -0
  35. scitex/audio/_mcp/handlers.py +59 -6
  36. scitex/audio/_mcp/speak_handlers.py +238 -0
  37. scitex/audio/_relay.py +225 -0
  38. scitex/audio/_tts.py +18 -10
  39. scitex/audio/engines/base.py +17 -10
  40. scitex/audio/engines/elevenlabs_engine.py +7 -2
  41. scitex/audio/mcp_server.py +228 -75
  42. scitex/canvas/README.md +1 -1
  43. scitex/canvas/editor/_dearpygui/__init__.py +25 -0
  44. scitex/canvas/editor/_dearpygui/_editor.py +147 -0
  45. scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
  46. scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
  47. scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
  48. scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
  49. scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
  50. scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
  51. scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
  52. scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
  53. scitex/canvas/editor/_dearpygui/_selection.py +295 -0
  54. scitex/canvas/editor/_dearpygui/_state.py +93 -0
  55. scitex/canvas/editor/_dearpygui/_utils.py +61 -0
  56. scitex/canvas/editor/flask_editor/_core/__init__.py +27 -0
  57. scitex/canvas/editor/flask_editor/_core/_bbox_extraction.py +200 -0
  58. scitex/canvas/editor/flask_editor/_core/_editor.py +173 -0
  59. scitex/canvas/editor/flask_editor/_core/_export_helpers.py +353 -0
  60. scitex/canvas/editor/flask_editor/_core/_routes_basic.py +190 -0
  61. scitex/canvas/editor/flask_editor/_core/_routes_export.py +332 -0
  62. scitex/canvas/editor/flask_editor/_core/_routes_panels.py +252 -0
  63. scitex/canvas/editor/flask_editor/_core/_routes_save.py +218 -0
  64. scitex/canvas/editor/flask_editor/_core.py +25 -1684
  65. scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
  66. scitex/cli/__init__.py +38 -43
  67. scitex/cli/audio.py +76 -27
  68. scitex/cli/capture.py +13 -20
  69. scitex/cli/introspect.py +481 -0
  70. scitex/cli/main.py +200 -109
  71. scitex/cli/mcp.py +60 -34
  72. scitex/cli/plt.py +357 -0
  73. scitex/cli/repro.py +15 -8
  74. scitex/cli/resource.py +15 -8
  75. scitex/cli/scholar/__init__.py +23 -8
  76. scitex/cli/scholar/_crossref_scitex.py +296 -0
  77. scitex/cli/scholar/_fetch.py +25 -3
  78. scitex/cli/social.py +314 -0
  79. scitex/cli/stats.py +15 -8
  80. scitex/cli/template.py +129 -12
  81. scitex/cli/tex.py +15 -8
  82. scitex/cli/writer.py +132 -8
  83. scitex/cloud/__init__.py +41 -2
  84. scitex/config/README.md +1 -1
  85. scitex/config/__init__.py +16 -2
  86. scitex/config/_env_registry.py +256 -0
  87. scitex/context/__init__.py +22 -0
  88. scitex/dev/__init__.py +20 -1
  89. scitex/diagram/__init__.py +42 -19
  90. scitex/diagram/mcp_server.py +13 -125
  91. scitex/gen/__init__.py +50 -14
  92. scitex/gen/_list_packages.py +4 -4
  93. scitex/introspect/__init__.py +82 -0
  94. scitex/introspect/_call_graph.py +303 -0
  95. scitex/introspect/_class_hierarchy.py +163 -0
  96. scitex/introspect/_core.py +41 -0
  97. scitex/introspect/_docstring.py +131 -0
  98. scitex/introspect/_examples.py +113 -0
  99. scitex/introspect/_imports.py +271 -0
  100. scitex/{gen/_inspect_module.py → introspect/_list_api.py} +43 -54
  101. scitex/introspect/_mcp/__init__.py +41 -0
  102. scitex/introspect/_mcp/handlers.py +233 -0
  103. scitex/introspect/_members.py +155 -0
  104. scitex/introspect/_resolve.py +89 -0
  105. scitex/introspect/_signature.py +131 -0
  106. scitex/introspect/_source.py +80 -0
  107. scitex/introspect/_type_hints.py +172 -0
  108. scitex/io/_save.py +1 -2
  109. scitex/io/bundle/README.md +1 -1
  110. scitex/logging/_formatters.py +19 -9
  111. scitex/mcp_server.py +98 -5
  112. scitex/os/__init__.py +4 -0
  113. scitex/{gen → os}/_check_host.py +4 -5
  114. scitex/plt/__init__.py +245 -550
  115. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
  116. scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  117. scitex/plt/gallery/README.md +1 -1
  118. scitex/plt/utils/_hitmap/__init__.py +82 -0
  119. scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
  120. scitex/plt/utils/_hitmap/_color_application.py +346 -0
  121. scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
  122. scitex/plt/utils/_hitmap/_constants.py +40 -0
  123. scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
  124. scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
  125. scitex/plt/utils/_hitmap/_query.py +113 -0
  126. scitex/plt/utils/_hitmap.py +46 -1616
  127. scitex/plt/utils/_metadata/__init__.py +80 -0
  128. scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
  129. scitex/plt/utils/_metadata/_artists/_base.py +195 -0
  130. scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
  131. scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
  132. scitex/plt/utils/_metadata/_artists/_images.py +80 -0
  133. scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
  134. scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
  135. scitex/plt/utils/_metadata/_artists/_text.py +106 -0
  136. scitex/plt/utils/_metadata/_csv.py +416 -0
  137. scitex/plt/utils/_metadata/_detect.py +225 -0
  138. scitex/plt/utils/_metadata/_legend.py +127 -0
  139. scitex/plt/utils/_metadata/_rounding.py +117 -0
  140. scitex/plt/utils/_metadata/_verification.py +202 -0
  141. scitex/schema/README.md +1 -1
  142. scitex/scholar/__init__.py +8 -0
  143. scitex/scholar/_mcp/crossref_handlers.py +265 -0
  144. scitex/scholar/core/Scholar.py +63 -1700
  145. scitex/scholar/core/_mixins/__init__.py +36 -0
  146. scitex/scholar/core/_mixins/_enrichers.py +270 -0
  147. scitex/scholar/core/_mixins/_library_handlers.py +100 -0
  148. scitex/scholar/core/_mixins/_loaders.py +103 -0
  149. scitex/scholar/core/_mixins/_pdf_download.py +375 -0
  150. scitex/scholar/core/_mixins/_pipeline.py +312 -0
  151. scitex/scholar/core/_mixins/_project_handlers.py +125 -0
  152. scitex/scholar/core/_mixins/_savers.py +69 -0
  153. scitex/scholar/core/_mixins/_search.py +103 -0
  154. scitex/scholar/core/_mixins/_services.py +88 -0
  155. scitex/scholar/core/_mixins/_url_finding.py +105 -0
  156. scitex/scholar/crossref_scitex.py +367 -0
  157. scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  158. scitex/scholar/examples/00_run_all.sh +120 -0
  159. scitex/scholar/jobs/_executors.py +27 -3
  160. scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
  161. scitex/scholar/pdf_download/_cli.py +154 -0
  162. scitex/scholar/pdf_download/strategies/__init__.py +11 -8
  163. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
  164. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
  165. scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
  166. scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
  167. scitex/scholar/pipelines/_single_steps.py +71 -36
  168. scitex/scholar/storage/_LibraryManager.py +97 -1695
  169. scitex/scholar/storage/_mixins/__init__.py +30 -0
  170. scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
  171. scitex/scholar/storage/_mixins/_library_operations.py +218 -0
  172. scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
  173. scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
  174. scitex/scholar/storage/_mixins/_resolution.py +376 -0
  175. scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
  176. scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
  177. scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +462 -0
  178. scitex/scholar/url_finder/.tmp/open_url/README.md +223 -0
  179. scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +694 -0
  180. scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +1160 -0
  181. scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +344 -0
  182. scitex/scholar/url_finder/.tmp/open_url/__init__.py +24 -0
  183. scitex/security/README.md +3 -3
  184. scitex/session/README.md +1 -1
  185. scitex/session/__init__.py +26 -7
  186. scitex/session/_decorator.py +1 -1
  187. scitex/sh/README.md +1 -1
  188. scitex/sh/__init__.py +7 -4
  189. scitex/social/__init__.py +155 -0
  190. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  191. scitex/stats/_mcp/_handlers/__init__.py +31 -0
  192. scitex/stats/_mcp/_handlers/_corrections.py +113 -0
  193. scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
  194. scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
  195. scitex/stats/_mcp/_handlers/_format.py +94 -0
  196. scitex/stats/_mcp/_handlers/_normality.py +110 -0
  197. scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
  198. scitex/stats/_mcp/_handlers/_power.py +247 -0
  199. scitex/stats/_mcp/_handlers/_recommend.py +102 -0
  200. scitex/stats/_mcp/_handlers/_run_test.py +279 -0
  201. scitex/stats/_mcp/_handlers/_stars.py +48 -0
  202. scitex/stats/_mcp/handlers.py +19 -1171
  203. scitex/stats/auto/_stat_style.py +175 -0
  204. scitex/stats/auto/_style_definitions.py +411 -0
  205. scitex/stats/auto/_styles.py +22 -620
  206. scitex/stats/descriptive/__init__.py +11 -8
  207. scitex/stats/descriptive/_ci.py +39 -0
  208. scitex/stats/power/_power.py +15 -4
  209. scitex/str/__init__.py +2 -1
  210. scitex/str/_title_case.py +63 -0
  211. scitex/template/README.md +1 -1
  212. scitex/template/__init__.py +25 -10
  213. scitex/template/_code_templates.py +147 -0
  214. scitex/template/_mcp/handlers.py +81 -0
  215. scitex/template/_mcp/tool_schemas.py +55 -0
  216. scitex/template/_templates/__init__.py +51 -0
  217. scitex/template/_templates/audio.py +233 -0
  218. scitex/template/_templates/canvas.py +312 -0
  219. scitex/template/_templates/capture.py +268 -0
  220. scitex/template/_templates/config.py +43 -0
  221. scitex/template/_templates/diagram.py +294 -0
  222. scitex/template/_templates/io.py +107 -0
  223. scitex/template/_templates/module.py +53 -0
  224. scitex/template/_templates/plt.py +202 -0
  225. scitex/template/_templates/scholar.py +267 -0
  226. scitex/template/_templates/session.py +130 -0
  227. scitex/template/_templates/session_minimal.py +43 -0
  228. scitex/template/_templates/session_plot.py +67 -0
  229. scitex/template/_templates/session_stats.py +77 -0
  230. scitex/template/_templates/stats.py +323 -0
  231. scitex/template/_templates/writer.py +296 -0
  232. scitex/template/clone_writer_directory.py +5 -5
  233. scitex/ui/_backends/_email.py +10 -2
  234. scitex/ui/_backends/_webhook.py +5 -1
  235. scitex/web/_search_pubmed.py +10 -6
  236. scitex/writer/README.md +1 -1
  237. scitex/writer/_mcp/handlers.py +11 -744
  238. scitex/writer/_mcp/tool_schemas.py +5 -335
  239. scitex-2.15.2.dist-info/METADATA +648 -0
  240. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/RECORD +246 -150
  241. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  242. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  243. scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +0 -90
  244. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +0 -1571
  245. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +0 -6262
  246. scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +0 -1274
  247. scitex/dev/plt/data/mpl/dir_ax.txt +0 -459
  248. scitex/diagram/_compile.py +0 -312
  249. scitex/diagram/_diagram.py +0 -355
  250. scitex/diagram/_mcp/__init__.py +0 -4
  251. scitex/diagram/_mcp/handlers.py +0 -400
  252. scitex/diagram/_mcp/tool_schemas.py +0 -157
  253. scitex/diagram/_presets.py +0 -173
  254. scitex/diagram/_schema.py +0 -182
  255. scitex/diagram/_split.py +0 -278
  256. scitex/gen/_ci.py +0 -12
  257. scitex/gen/_title_case.py +0 -89
  258. scitex/plt/_mcp/__init__.py +0 -4
  259. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  260. scitex/plt/_mcp/_handlers_figure.py +0 -195
  261. scitex/plt/_mcp/_handlers_plot.py +0 -252
  262. scitex/plt/_mcp/_handlers_style.py +0 -219
  263. scitex/plt/_mcp/handlers.py +0 -74
  264. scitex/plt/_mcp/tool_schemas.py +0 -497
  265. scitex/plt/mcp_server.py +0 -231
  266. scitex/scholar/data/.gitkeep +0 -0
  267. scitex/scholar/data/README.md +0 -44
  268. scitex/scholar/data/bib_files/bibliography.bib +0 -1952
  269. scitex/scholar/data/bib_files/neurovista.bib +0 -277
  270. scitex/scholar/data/bib_files/neurovista_enriched.bib +0 -441
  271. scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +0 -441
  272. scitex/scholar/data/bib_files/neurovista_processed.bib +0 -338
  273. scitex/scholar/data/bib_files/openaccess.bib +0 -89
  274. scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +0 -2178
  275. scitex/scholar/data/bib_files/pac.bib +0 -698
  276. scitex/scholar/data/bib_files/pac_enriched.bib +0 -1061
  277. scitex/scholar/data/bib_files/pac_processed.bib +0 -0
  278. scitex/scholar/data/bib_files/pac_titles.txt +0 -75
  279. scitex/scholar/data/bib_files/paywalled.bib +0 -98
  280. scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +0 -58
  281. scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +0 -87
  282. scitex/scholar/data/bib_files/seizure_prediction.bib +0 -694
  283. scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
  284. scitex/scholar/data/bib_files/test_complete_enriched.bib +0 -437
  285. scitex/scholar/data/bib_files/test_final_enriched.bib +0 -437
  286. scitex/scholar/data/bib_files/test_seizure.bib +0 -46
  287. scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
  288. scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
  289. scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
  290. scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
  291. scitex/scholar/data/impact_factor.db +0 -0
  292. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  293. scitex/scholar/examples/dev.py +0 -38
  294. scitex-2.14.0.dist-info/METADATA +0 -1238
  295. /scitex/{gen → context}/_detect_environment.py +0 -0
  296. /scitex/{gen → context}/_get_notebook_path.py +0 -0
  297. /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
  298. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/WHEEL +0 -0
  299. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/entry_points.txt +0 -0
  300. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/licenses/LICENSE +0 -0
@@ -369,5 +369,79 @@ def register_scholar_tools(mcp) -> None:
369
369
  result = await get_job_result_handler(job_id=job_id)
370
370
  return _json(result)
371
371
 
372
+ # =========================================================================
373
+ # CrossRef Tools (via crossref-local delegation - 167M+ papers)
374
+ # =========================================================================
375
+
376
+ @mcp.tool()
377
+ async def scholar_crossref_search(
378
+ query: str,
379
+ limit: int = 20,
380
+ offset: int = 0,
381
+ year_min: Optional[int] = None,
382
+ year_max: Optional[int] = None,
383
+ enrich: bool = False,
384
+ ) -> str:
385
+ """[scholar] Search CrossRef database (167M+ papers) via crossref-local. Fast full-text search with optional citation enrichment."""
386
+ from scitex.scholar._mcp.crossref_handlers import crossref_search_handler
387
+
388
+ result = await crossref_search_handler(
389
+ query=query,
390
+ limit=limit,
391
+ offset=offset,
392
+ year_min=year_min,
393
+ year_max=year_max,
394
+ enrich=enrich,
395
+ )
396
+ return _json(result)
397
+
398
+ @mcp.tool()
399
+ async def scholar_crossref_get(
400
+ doi: str,
401
+ include_citations: bool = False,
402
+ include_references: bool = False,
403
+ ) -> str:
404
+ """[scholar] Get paper metadata by DOI from CrossRef database."""
405
+ from scitex.scholar._mcp.crossref_handlers import crossref_get_handler
406
+
407
+ result = await crossref_get_handler(
408
+ doi=doi,
409
+ include_citations=include_citations,
410
+ include_references=include_references,
411
+ )
412
+ return _json(result)
413
+
414
+ @mcp.tool()
415
+ async def scholar_crossref_count(query: str) -> str:
416
+ """[scholar] Count papers matching a query in CrossRef database."""
417
+ from scitex.scholar._mcp.crossref_handlers import crossref_count_handler
418
+
419
+ result = await crossref_count_handler(query=query)
420
+ return _json(result)
421
+
422
+ @mcp.tool()
423
+ async def scholar_crossref_citations(
424
+ doi: str,
425
+ direction: str = "citing",
426
+ limit: int = 100,
427
+ ) -> str:
428
+ """[scholar] Get citation relationships (citing/cited papers) for a DOI."""
429
+ from scitex.scholar._mcp.crossref_handlers import crossref_citations_handler
430
+
431
+ result = await crossref_citations_handler(
432
+ doi=doi,
433
+ direction=direction,
434
+ limit=limit,
435
+ )
436
+ return _json(result)
437
+
438
+ @mcp.tool()
439
+ async def scholar_crossref_info() -> str:
440
+ """[scholar] Get CrossRef database configuration and status info."""
441
+ from scitex.scholar._mcp.crossref_handlers import crossref_info_handler
442
+
443
+ result = await crossref_info_handler()
444
+ return _json(result)
445
+
372
446
 
373
447
  # EOF
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-22
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_tools/social.py
4
+
5
+ """Social media module tools for FastMCP unified server.
6
+
7
+ All MCP tools delegate to socialia CLI for reproducibility.
8
+ Each tool returns the CLI command used, enabling human reproduction.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import subprocess
15
+ import sys
16
+ from typing import Optional
17
+
18
+ # Import platform strategies from socialia for MCP tool descriptions
19
+ try:
20
+ from scitex.social import PLATFORM_STRATEGIES
21
+ except ImportError:
22
+ try:
23
+ from socialia import PLATFORM_STRATEGIES
24
+ except ImportError:
25
+ PLATFORM_STRATEGIES = """
26
+ ## Platform Strategies (install socialia for full guide)
27
+ - twitter: 280 chars, hook first, 1-2 hashtags at end
28
+ - linkedin: 3000 chars, first 2 lines critical, 3-5 hashtags at end
29
+ - reddit: title is key, no hashtags, value first
30
+ - youtube: keyword-rich title <60 chars, 3-5 hashtags in description
31
+ """
32
+
33
+
34
+ def _json(data: dict) -> str:
35
+ return json.dumps(data, indent=2, default=str)
36
+
37
+
38
+ def _run_socialia_cli(*args: str) -> dict:
39
+ """Run socialia CLI and return structured result."""
40
+ cmd = [sys.executable, "-m", "socialia", "--json", *args]
41
+ cli_command = f"socialia {' '.join(args)}"
42
+
43
+ try:
44
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
45
+
46
+ if result.returncode == 0:
47
+ try:
48
+ data = json.loads(result.stdout)
49
+ data["cli_command"] = cli_command
50
+ return data
51
+ except json.JSONDecodeError:
52
+ return {
53
+ "success": True,
54
+ "output": result.stdout,
55
+ "cli_command": cli_command,
56
+ }
57
+ else:
58
+ return {
59
+ "success": False,
60
+ "error": result.stderr or result.stdout,
61
+ "cli_command": cli_command,
62
+ }
63
+ except subprocess.TimeoutExpired:
64
+ return {
65
+ "success": False,
66
+ "error": "Command timed out",
67
+ "cli_command": cli_command,
68
+ }
69
+ except Exception as e:
70
+ return {
71
+ "success": False,
72
+ "error": str(e),
73
+ "cli_command": cli_command,
74
+ }
75
+
76
+
77
+ def register_social_tools(mcp) -> None:
78
+ """Register social media tools with FastMCP server."""
79
+
80
+ @mcp.tool()
81
+ async def social_post(
82
+ platform: str,
83
+ text: str,
84
+ reply_to: Optional[str] = None,
85
+ quote: Optional[str] = None,
86
+ subreddit: Optional[str] = None,
87
+ title: Optional[str] = None,
88
+ dry_run: bool = False,
89
+ ) -> str:
90
+ """[social] Post content to a social media platform (twitter, linkedin, reddit, youtube).
91
+
92
+ PLATFORM STRATEGIES:
93
+ - twitter: 280 chars. Hook first. 1+ emoji. GitHub URL. 3-5 hashtags at END for SEO
94
+ - linkedin: 3000 chars. First 2 lines critical. Short paragraphs. Include project links. 3-5 hashtags at END
95
+ - reddit: Title is key. NO hashtags. Value first, self-promo last. Link in body
96
+ - youtube: Keyword-rich title <60 chars. Links in description. 3-5 hashtags in description
97
+
98
+ BAD: "SciTeX v2.15.0 released! New feature. #Python #AI"
99
+ GOOD: "Your AI agent can now speak to you remotely.
100
+
101
+ Audio relay bridges the gap.
102
+
103
+ github.com/user/repo
104
+
105
+ #AIAgents #Python"
106
+ """
107
+ args = ["post", platform, text]
108
+
109
+ if reply_to:
110
+ args.extend(["--reply-to", reply_to])
111
+ if quote:
112
+ args.extend(["--quote", quote])
113
+ if subreddit and platform == "reddit":
114
+ args.extend(["--subreddit", subreddit])
115
+ if title:
116
+ args.extend(["--title", title])
117
+ if dry_run:
118
+ args.append("--dry-run")
119
+
120
+ result = _run_socialia_cli(*args)
121
+ return _json(result)
122
+
123
+ @mcp.tool()
124
+ async def social_delete(
125
+ platform: str,
126
+ post_id: str,
127
+ ) -> str:
128
+ """[social] Delete a post from a platform (twitter, linkedin, reddit)."""
129
+ result = _run_socialia_cli("delete", platform, post_id)
130
+ return _json(result)
131
+
132
+ @mcp.tool()
133
+ async def social_status() -> str:
134
+ """[social] Check social media configuration and authentication status."""
135
+ result = _run_socialia_cli("status")
136
+ return _json(result)
137
+
138
+ @mcp.tool()
139
+ async def social_analytics(
140
+ platform: str,
141
+ days: int = 7,
142
+ ) -> str:
143
+ """[social] Get analytics for a platform (twitter, youtube, ga)."""
144
+ result = _run_socialia_cli("analytics", platform, "--days", str(days))
145
+ return _json(result)
146
+
147
+ @mcp.tool()
148
+ async def social_thread(
149
+ platform: str,
150
+ posts: list[str],
151
+ delay: int = 2,
152
+ dry_run: bool = False,
153
+ ) -> str:
154
+ """[social] Post a thread of connected posts. Posts are list of strings."""
155
+ import tempfile
156
+ from pathlib import Path
157
+
158
+ # Write posts to temp file (socialia expects file input)
159
+ thread_content = "\n---\n".join(posts)
160
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
161
+ f.write(thread_content)
162
+ temp_path = f.name
163
+
164
+ try:
165
+ args = ["thread", platform, "--file", temp_path, "--delay", str(delay)]
166
+ if dry_run:
167
+ args.append("--dry-run")
168
+ result = _run_socialia_cli(*args)
169
+ result["thread_posts"] = posts
170
+ return _json(result)
171
+ finally:
172
+ Path(temp_path).unlink(missing_ok=True)
173
+
174
+ @mcp.tool()
175
+ async def social_check_availability() -> str:
176
+ """[social] Check if socialia is installed and list available platforms."""
177
+ try:
178
+ from scitex.social import (
179
+ SOCIALIA_AVAILABLE,
180
+ __socialia_version__,
181
+ )
182
+
183
+ if SOCIALIA_AVAILABLE:
184
+ return _json(
185
+ {
186
+ "available": True,
187
+ "version": __socialia_version__,
188
+ "platforms": ["twitter", "linkedin", "reddit", "youtube"],
189
+ "analytics": ["twitter", "youtube", "ga"],
190
+ }
191
+ )
192
+ else:
193
+ return _json(
194
+ {
195
+ "available": False,
196
+ "error": "socialia not installed",
197
+ "install_command": "pip install socialia",
198
+ }
199
+ )
200
+ except Exception as e:
201
+ return _json(
202
+ {
203
+ "available": False,
204
+ "error": str(e),
205
+ }
206
+ )
207
+
208
+ @mcp.tool()
209
+ async def social_check(
210
+ platform: Optional[str] = None,
211
+ ) -> str:
212
+ """[social] Check platform connection status (v0.1.4+)."""
213
+ args = ["check"]
214
+ if platform:
215
+ args.append(platform)
216
+ result = _run_socialia_cli(*args)
217
+ return _json(result)
218
+
219
+ @mcp.tool()
220
+ async def social_feed(
221
+ platform: Optional[str] = None,
222
+ limit: int = 10,
223
+ mentions: bool = False,
224
+ ) -> str:
225
+ """[social] Get recent posts from platform feeds (v0.1.4+)."""
226
+ args = ["feed"]
227
+ if platform:
228
+ args.append(platform)
229
+ args.extend(["--limit", str(limit)])
230
+ if mentions:
231
+ args.append("--mentions")
232
+ result = _run_socialia_cli(*args)
233
+ return _json(result)
234
+
235
+ @mcp.tool()
236
+ async def social_me(
237
+ platform: str,
238
+ ) -> str:
239
+ """[social] Get user profile information (v0.1.4+)."""
240
+ result = _run_socialia_cli("me", platform)
241
+ return _json(result)
242
+
243
+
244
+ # EOF
@@ -62,5 +62,29 @@ def register_template_tools(mcp) -> None:
62
62
  result = await list_git_strategies_handler()
63
63
  return _json(result)
64
64
 
65
+ @mcp.tool()
66
+ async def template_get_code_template(
67
+ template_id: str,
68
+ filepath: Optional[str] = None,
69
+ docstring: Optional[str] = None,
70
+ ) -> str:
71
+ """[template] Get a code template for scripts and modules. Core: session, io, config. Module usage: plt, stats, scholar, audio, capture, diagram, canvas, writer. Use 'all' for all templates combined."""
72
+ from scitex.template._mcp.handlers import get_code_template_handler
73
+
74
+ result = await get_code_template_handler(
75
+ template_id=template_id,
76
+ filepath=filepath,
77
+ docstring=docstring,
78
+ )
79
+ return _json(result)
80
+
81
+ @mcp.tool()
82
+ async def template_list_code_templates() -> str:
83
+ """[template] List all available code templates for scripts and modules."""
84
+ from scitex.template._mcp.handlers import list_code_templates_handler
85
+
86
+ result = await list_code_templates_handler()
87
+ return _json(result)
88
+
65
89
 
66
90
  # EOF
@@ -1,220 +1,37 @@
1
1
  #!/usr/bin/env python3
2
- # Timestamp: 2026-01-15
2
+ # Timestamp: 2026-01-20
3
3
  # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_tools/writer.py
4
- """Writer module tools for FastMCP unified server."""
5
-
6
- from __future__ import annotations
7
-
8
- import json
9
- from typing import List, Optional, Union
4
+ """Writer module tools - delegates to scitex-writer package.
10
5
 
6
+ Provides usage instructions for shell-based compilation workflow.
7
+ """
11
8
 
12
- def _json(data: dict) -> str:
13
- return json.dumps(data, indent=2, default=str)
9
+ from __future__ import annotations
14
10
 
15
11
 
16
12
  def register_writer_tools(mcp) -> None:
17
- """Register writer tools with FastMCP server."""
18
-
19
- @mcp.tool()
20
- async def writer_clone_project(
21
- project_dir: str,
22
- git_strategy: str = "child",
23
- branch: Optional[str] = None,
24
- tag: Optional[str] = None,
25
- ) -> str:
26
- """[writer] Create a new LaTeX manuscript project from template."""
27
- from scitex.writer._mcp.handlers import clone_project_handler
28
-
29
- result = await clone_project_handler(
30
- project_dir=project_dir,
31
- git_strategy=git_strategy,
32
- branch=branch,
33
- tag=tag,
34
- )
35
- return _json(result)
36
-
37
- @mcp.tool()
38
- async def writer_compile_manuscript(
39
- project_dir: str,
40
- timeout: int = 300,
41
- no_figs: bool = False,
42
- ppt2tif: bool = False,
43
- crop_tif: bool = False,
44
- quiet: bool = False,
45
- verbose: bool = False,
46
- force: bool = False,
47
- ) -> str:
48
- """[writer] Compile manuscript LaTeX document to PDF."""
49
- from scitex.writer._mcp.handlers import compile_manuscript_handler
50
-
51
- result = await compile_manuscript_handler(
52
- project_dir=project_dir,
53
- timeout=timeout,
54
- no_figs=no_figs,
55
- ppt2tif=ppt2tif,
56
- crop_tif=crop_tif,
57
- quiet=quiet,
58
- verbose=verbose,
59
- force=force,
60
- )
61
- return _json(result)
62
-
63
- @mcp.tool()
64
- async def writer_compile_supplementary(
65
- project_dir: str,
66
- timeout: int = 300,
67
- no_figs: bool = False,
68
- ppt2tif: bool = False,
69
- crop_tif: bool = False,
70
- quiet: bool = False,
71
- ) -> str:
72
- """[writer] Compile supplementary materials LaTeX document to PDF."""
73
- from scitex.writer._mcp.handlers import compile_supplementary_handler
74
-
75
- result = await compile_supplementary_handler(
76
- project_dir=project_dir,
77
- timeout=timeout,
78
- no_figs=no_figs,
79
- ppt2tif=ppt2tif,
80
- crop_tif=crop_tif,
81
- quiet=quiet,
82
- )
83
- return _json(result)
84
-
85
- @mcp.tool()
86
- async def writer_compile_revision(
87
- project_dir: str,
88
- track_changes: bool = False,
89
- timeout: int = 300,
90
- ) -> str:
91
- """[writer] Compile revision document to PDF with optional change tracking."""
92
- from scitex.writer._mcp.handlers import compile_revision_handler
93
-
94
- result = await compile_revision_handler(
95
- project_dir=project_dir,
96
- track_changes=track_changes,
97
- timeout=timeout,
98
- )
99
- return _json(result)
100
-
101
- @mcp.tool()
102
- async def writer_get_project_info(project_dir: str) -> str:
103
- """[writer] Get writer project structure and status information."""
104
- from scitex.writer._mcp.handlers import get_project_info_handler
13
+ """Register writer tools by delegating to scitex-writer package."""
14
+ try:
15
+ from scitex_writer._server import INSTRUCTIONS
105
16
 
106
- result = await get_project_info_handler(project_dir=project_dir)
107
- return _json(result)
17
+ _SCITEX_WRITER_AVAILABLE = True
18
+ except ImportError:
19
+ _SCITEX_WRITER_AVAILABLE = False
20
+ INSTRUCTIONS = None
108
21
 
109
- @mcp.tool()
110
- async def writer_get_pdf(
111
- project_dir: str,
112
- doc_type: str = "manuscript",
113
- ) -> str:
114
- """[writer] Get path to compiled PDF for a document type."""
115
- from scitex.writer._mcp.handlers import get_pdf_handler
22
+ if not _SCITEX_WRITER_AVAILABLE:
116
23
 
117
- result = await get_pdf_handler(
118
- project_dir=project_dir,
119
- doc_type=doc_type,
120
- )
121
- return _json(result)
24
+ @mcp.tool()
25
+ def writer_usage() -> str:
26
+ """[writer] Get usage guide for SciTeX Writer (not installed)."""
27
+ return "scitex-writer is required. Install with: pip install scitex-writer"
122
28
 
123
- @mcp.tool()
124
- async def writer_list_document_types() -> str:
125
- """[writer] List available document types in a writer project."""
126
- from scitex.writer._mcp.handlers import list_document_types_handler
127
-
128
- result = await list_document_types_handler()
129
- return _json(result)
29
+ return
130
30
 
131
31
  @mcp.tool()
132
- async def writer_csv_to_latex(
133
- csv_path: str,
134
- output_path: Optional[str] = None,
135
- caption: Optional[str] = None,
136
- label: Optional[str] = None,
137
- longtable: bool = False,
138
- ) -> str:
139
- """[writer] Convert CSV file to LaTeX table format."""
140
- from scitex.writer._mcp.handlers import csv2latex_handler
141
-
142
- result = await csv2latex_handler(
143
- csv_path=csv_path,
144
- output_path=output_path,
145
- caption=caption,
146
- label=label,
147
- longtable=longtable,
148
- )
149
- return _json(result)
150
-
151
- @mcp.tool()
152
- async def writer_latex_to_csv(
153
- latex_path: str,
154
- output_path: Optional[str] = None,
155
- table_index: int = 0,
156
- ) -> str:
157
- """[writer] Convert LaTeX table to CSV format."""
158
- from scitex.writer._mcp.handlers import latex2csv_handler
159
-
160
- result = await latex2csv_handler(
161
- latex_path=latex_path,
162
- output_path=output_path,
163
- table_index=table_index,
164
- )
165
- return _json(result)
166
-
167
- @mcp.tool()
168
- async def writer_pdf_to_images(
169
- pdf_path: str,
170
- output_dir: Optional[str] = None,
171
- pages: Optional[Union[int, List[int]]] = None,
172
- dpi: int = 150,
173
- format: str = "png",
174
- ) -> str:
175
- """[writer] Render PDF pages as images."""
176
- from scitex.writer._mcp.handlers import pdf_to_images_handler
177
-
178
- result = await pdf_to_images_handler(
179
- pdf_path=pdf_path,
180
- output_dir=output_dir,
181
- pages=pages,
182
- dpi=dpi,
183
- format=format,
184
- )
185
- return _json(result)
186
-
187
- @mcp.tool()
188
- async def writer_list_figures(
189
- project_dir: str,
190
- extensions: Optional[List[str]] = None,
191
- ) -> str:
192
- """[writer] List all figures in a writer project directory."""
193
- from scitex.writer._mcp.handlers import list_figures_handler
194
-
195
- result = await list_figures_handler(
196
- project_dir=project_dir,
197
- extensions=extensions,
198
- )
199
- return _json(result)
200
-
201
- @mcp.tool()
202
- async def writer_convert_figure(
203
- input_path: str,
204
- output_path: str,
205
- dpi: int = 300,
206
- quality: int = 95,
207
- ) -> str:
208
- """[writer] Convert figure between formats (e.g., PDF to PNG, PNG to JPG)."""
209
- from scitex.writer._mcp.handlers import convert_figure_handler
210
-
211
- result = await convert_figure_handler(
212
- input_path=input_path,
213
- output_path=output_path,
214
- dpi=dpi,
215
- quality=quality,
216
- )
217
- return _json(result)
32
+ def writer_usage() -> str:
33
+ """[writer] Get usage guide for SciTeX Writer LaTeX manuscript compilation system."""
34
+ return INSTRUCTIONS
218
35
 
219
36
 
220
37
  # EOF
@@ -1,14 +1,10 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
- # Timestamp: "2025-09-30 06:38:18 (ywatanabe)"
4
- # File: /home/ywatanabe/proj/scitex_repo/src/scitex/ai/_gen_ai/_PARAMS.py
5
- # ----------------------------------------
6
- from __future__ import annotations
7
- import os
3
+ # Timestamp: "2026-01-16 04:02:17 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/ai/_gen_ai/_PARAMS.py
5
+
8
6
 
9
7
  __FILE__ = __file__
10
- __DIR__ = os.path.dirname(__FILE__)
11
- # ----------------------------------------
12
8
 
13
9
  THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/ai/_gen_ai/PARAMS.py"
14
10
 
@@ -202,6 +198,13 @@ OPENAI_MODELS = [
202
198
  # https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#pricing
203
199
  # https://docs.anthropic.com/en/docs/about-claude/models#model-comparison-table
204
200
  ANTHROPIC_MODELS = [
201
+ {
202
+ "name": "claude-opus-4-5-20251101",
203
+ "input_cost": 5.00,
204
+ "output_cost": 25.00,
205
+ "api_key_env": "ANTHROPIC_API_KEY",
206
+ "provider": "Anthropic",
207
+ },
205
208
  {
206
209
  "name": "claude-opus-4-1-20250805",
207
210
  "input_cost": 15.00,