@wentorai/research-plugins 1.3.2 → 1.4.2

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 (266) hide show
  1. package/README.md +32 -56
  2. package/curated/analysis/README.md +1 -13
  3. package/curated/domains/README.md +1 -5
  4. package/curated/literature/README.md +3 -12
  5. package/curated/research/README.md +1 -18
  6. package/curated/tools/README.md +1 -12
  7. package/curated/writing/README.md +2 -6
  8. package/index.ts +88 -5
  9. package/openclaw.plugin.json +3 -12
  10. package/package.json +3 -5
  11. package/skills/analysis/statistics/SKILL.md +1 -1
  12. package/skills/analysis/statistics/meta-analysis-guide/SKILL.md +1 -1
  13. package/skills/domains/ai-ml/SKILL.md +3 -2
  14. package/skills/domains/ai-ml/generative-ai-guide/SKILL.md +1 -0
  15. package/skills/domains/ai-ml/huggingface-api/SKILL.md +251 -0
  16. package/skills/domains/biomedical/SKILL.md +9 -2
  17. package/skills/domains/biomedical/alphafold-api/SKILL.md +227 -0
  18. package/skills/domains/biomedical/biothings-api/SKILL.md +296 -0
  19. package/skills/domains/biomedical/clinicaltrials-api-v2/SKILL.md +216 -0
  20. package/skills/domains/biomedical/enrichr-api/SKILL.md +264 -0
  21. package/skills/domains/biomedical/ensembl-rest-api/SKILL.md +204 -0
  22. package/skills/domains/biomedical/medical-data-api/SKILL.md +197 -0
  23. package/skills/domains/biomedical/pdb-structure-api/SKILL.md +219 -0
  24. package/skills/domains/business/SKILL.md +2 -3
  25. package/skills/domains/chemistry/SKILL.md +3 -2
  26. package/skills/domains/chemistry/catalysis-hub-api/SKILL.md +171 -0
  27. package/skills/domains/education/SKILL.md +2 -3
  28. package/skills/domains/law/SKILL.md +3 -2
  29. package/skills/domains/law/uk-legislation-api/SKILL.md +179 -0
  30. package/skills/literature/discovery/SKILL.md +1 -1
  31. package/skills/literature/discovery/citation-alert-guide/SKILL.md +2 -2
  32. package/skills/literature/discovery/conference-proceedings-guide/SKILL.md +2 -2
  33. package/skills/literature/discovery/literature-mapping-guide/SKILL.md +1 -1
  34. package/skills/literature/discovery/paper-recommendation-guide/SKILL.md +8 -14
  35. package/skills/literature/discovery/rss-paper-feeds/SKILL.md +20 -14
  36. package/skills/literature/discovery/semantic-paper-radar/SKILL.md +8 -8
  37. package/skills/literature/discovery/semantic-scholar-recs-guide/SKILL.md +103 -86
  38. package/skills/literature/fulltext/SKILL.md +3 -2
  39. package/skills/literature/fulltext/arxiv-latex-source/SKILL.md +195 -0
  40. package/skills/literature/fulltext/open-access-guide/SKILL.md +1 -1
  41. package/skills/literature/fulltext/open-access-mining-guide/SKILL.md +5 -5
  42. package/skills/literature/metadata/citation-network-guide/SKILL.md +3 -3
  43. package/skills/literature/metadata/h-index-guide/SKILL.md +0 -27
  44. package/skills/literature/search/SKILL.md +3 -4
  45. package/skills/literature/search/citation-chaining-guide/SKILL.md +42 -32
  46. package/skills/literature/search/database-comparison-guide/SKILL.md +1 -1
  47. package/skills/literature/search/semantic-scholar-api/SKILL.md +56 -53
  48. package/skills/research/automation/SKILL.md +2 -3
  49. package/skills/research/automation/datagen-research-guide/SKILL.md +1 -0
  50. package/skills/research/automation/mle-agent-guide/SKILL.md +1 -0
  51. package/skills/research/automation/paper-to-agent-guide/SKILL.md +2 -1
  52. package/skills/research/deep-research/auto-deep-research-guide/SKILL.md +1 -0
  53. package/skills/research/deep-research/in-depth-research-guide/SKILL.md +1 -1
  54. package/skills/research/deep-research/kosmos-scientist-guide/SKILL.md +3 -3
  55. package/skills/research/deep-research/llm-scientific-discovery-guide/SKILL.md +1 -1
  56. package/skills/research/deep-research/local-deep-research-guide/SKILL.md +6 -6
  57. package/skills/research/deep-research/open-researcher-guide/SKILL.md +3 -3
  58. package/skills/research/deep-research/tongyi-deep-research-guide/SKILL.md +4 -4
  59. package/skills/research/methodology/SKILL.md +1 -1
  60. package/skills/research/methodology/claude-scientific-guide/SKILL.md +1 -0
  61. package/skills/research/methodology/grad-school-guide/SKILL.md +1 -1
  62. package/skills/research/methodology/qualitative-research-guide/SKILL.md +1 -1
  63. package/skills/research/paper-review/SKILL.md +1 -1
  64. package/skills/research/paper-review/automated-review-guide/SKILL.md +1 -1
  65. package/skills/research/paper-review/peer-review-guide/SKILL.md +1 -1
  66. package/skills/tools/diagram/excalidraw-diagram-guide/SKILL.md +1 -1
  67. package/skills/tools/diagram/mermaid-architect-guide/SKILL.md +1 -1
  68. package/skills/tools/diagram/plantuml-guide/SKILL.md +1 -1
  69. package/skills/tools/document/grobid-pdf-parsing/SKILL.md +1 -1
  70. package/skills/tools/document/paper-parse-guide/SKILL.md +2 -2
  71. package/skills/tools/knowledge-graph/SKILL.md +2 -3
  72. package/skills/tools/knowledge-graph/citation-network-builder/SKILL.md +5 -5
  73. package/skills/tools/knowledge-graph/knowledge-graph-construction/SKILL.md +1 -1
  74. package/skills/tools/ocr-translate/zotero-pdf2zh-guide/SKILL.md +1 -0
  75. package/skills/tools/scraping/academic-web-scraping/SKILL.md +1 -2
  76. package/skills/tools/scraping/google-scholar-scraper/SKILL.md +7 -7
  77. package/skills/writing/citation/SKILL.md +1 -1
  78. package/skills/writing/citation/academic-citation-manager/SKILL.md +20 -17
  79. package/skills/writing/citation/citation-assistant-skill/SKILL.md +72 -58
  80. package/skills/writing/citation/obsidian-citation-guide/SKILL.md +1 -0
  81. package/skills/writing/citation/obsidian-zotero-guide/SKILL.md +1 -0
  82. package/skills/writing/citation/onecite-reference-guide/SKILL.md +1 -1
  83. package/skills/writing/citation/papersgpt-zotero-guide/SKILL.md +1 -0
  84. package/skills/writing/citation/zotero-mdnotes-guide/SKILL.md +1 -0
  85. package/skills/writing/citation/zotero-reference-guide/SKILL.md +2 -1
  86. package/skills/writing/citation/zotero-scholar-guide/SKILL.md +1 -1
  87. package/skills/writing/composition/scientific-writing-resources/SKILL.md +1 -0
  88. package/skills/writing/latex/latex-drawing-collection/SKILL.md +1 -0
  89. package/skills/writing/latex/latex-templates-collection/SKILL.md +1 -0
  90. package/skills/writing/templates/novathesis-guide/SKILL.md +1 -0
  91. package/src/tools/arxiv.ts +81 -30
  92. package/src/tools/biorxiv.ts +158 -0
  93. package/src/tools/crossref.ts +63 -22
  94. package/src/tools/datacite.ts +191 -0
  95. package/src/tools/dblp.ts +125 -0
  96. package/src/tools/doaj.ts +82 -0
  97. package/src/tools/europe-pmc.ts +159 -0
  98. package/src/tools/hal.ts +118 -0
  99. package/src/tools/inspire-hep.ts +165 -0
  100. package/src/tools/openaire.ts +158 -0
  101. package/src/tools/openalex.ts +26 -15
  102. package/src/tools/opencitations.ts +112 -0
  103. package/src/tools/orcid.ts +139 -0
  104. package/src/tools/osf-preprints.ts +104 -0
  105. package/src/tools/pubmed.ts +22 -13
  106. package/src/tools/ror.ts +118 -0
  107. package/src/tools/unpaywall.ts +15 -6
  108. package/src/tools/util.ts +141 -0
  109. package/src/tools/zenodo.ts +157 -0
  110. package/mcp-configs/academic-db/ChatSpatial.json +0 -17
  111. package/mcp-configs/academic-db/academia-mcp.json +0 -17
  112. package/mcp-configs/academic-db/academic-paper-explorer.json +0 -17
  113. package/mcp-configs/academic-db/academic-search-mcp-server.json +0 -17
  114. package/mcp-configs/academic-db/agentinterviews-mcp.json +0 -17
  115. package/mcp-configs/academic-db/all-in-mcp.json +0 -17
  116. package/mcp-configs/academic-db/alphafold-mcp.json +0 -20
  117. package/mcp-configs/academic-db/apple-health-mcp.json +0 -17
  118. package/mcp-configs/academic-db/arxiv-latex-mcp.json +0 -17
  119. package/mcp-configs/academic-db/arxiv-mcp-server.json +0 -17
  120. package/mcp-configs/academic-db/bgpt-mcp.json +0 -17
  121. package/mcp-configs/academic-db/biomcp.json +0 -17
  122. package/mcp-configs/academic-db/biothings-mcp.json +0 -17
  123. package/mcp-configs/academic-db/brightspace-mcp.json +0 -21
  124. package/mcp-configs/academic-db/catalysishub-mcp-server.json +0 -17
  125. package/mcp-configs/academic-db/climatiq-mcp.json +0 -20
  126. package/mcp-configs/academic-db/clinicaltrialsgov-mcp-server.json +0 -17
  127. package/mcp-configs/academic-db/deep-research-mcp.json +0 -17
  128. package/mcp-configs/academic-db/dicom-mcp.json +0 -17
  129. package/mcp-configs/academic-db/enrichr-mcp-server.json +0 -17
  130. package/mcp-configs/academic-db/fec-mcp-server.json +0 -17
  131. package/mcp-configs/academic-db/fhir-mcp-server-themomentum.json +0 -17
  132. package/mcp-configs/academic-db/fhir-mcp.json +0 -19
  133. package/mcp-configs/academic-db/gget-mcp.json +0 -17
  134. package/mcp-configs/academic-db/gibs-mcp.json +0 -20
  135. package/mcp-configs/academic-db/gis-mcp-server.json +0 -22
  136. package/mcp-configs/academic-db/google-earth-engine-mcp.json +0 -21
  137. package/mcp-configs/academic-db/google-researcher-mcp.json +0 -17
  138. package/mcp-configs/academic-db/idea-reality-mcp.json +0 -17
  139. package/mcp-configs/academic-db/legiscan-mcp.json +0 -19
  140. package/mcp-configs/academic-db/lex.json +0 -17
  141. package/mcp-configs/academic-db/m4-clinical-mcp.json +0 -21
  142. package/mcp-configs/academic-db/medical-mcp.json +0 -21
  143. package/mcp-configs/academic-db/nexonco-mcp.json +0 -20
  144. package/mcp-configs/academic-db/omop-mcp.json +0 -20
  145. package/mcp-configs/academic-db/onekgpd-mcp.json +0 -20
  146. package/mcp-configs/academic-db/openedu-mcp.json +0 -20
  147. package/mcp-configs/academic-db/opengenes-mcp.json +0 -20
  148. package/mcp-configs/academic-db/openstax-mcp.json +0 -21
  149. package/mcp-configs/academic-db/openstreetmap-mcp.json +0 -21
  150. package/mcp-configs/academic-db/opentargets-mcp.json +0 -21
  151. package/mcp-configs/academic-db/pdb-mcp.json +0 -21
  152. package/mcp-configs/academic-db/smithsonian-mcp.json +0 -20
  153. package/mcp-configs/ai-platform/Adaptive-Graph-of-Thoughts-MCP-server.json +0 -17
  154. package/mcp-configs/ai-platform/ai-counsel.json +0 -17
  155. package/mcp-configs/ai-platform/atlas-mcp-server.json +0 -17
  156. package/mcp-configs/ai-platform/counsel-mcp.json +0 -17
  157. package/mcp-configs/ai-platform/cross-llm-mcp.json +0 -17
  158. package/mcp-configs/ai-platform/gptr-mcp.json +0 -17
  159. package/mcp-configs/ai-platform/magi-researchers.json +0 -21
  160. package/mcp-configs/ai-platform/mcp-academic-researcher.json +0 -22
  161. package/mcp-configs/ai-platform/open-paper-machine.json +0 -21
  162. package/mcp-configs/ai-platform/paper-intelligence.json +0 -21
  163. package/mcp-configs/ai-platform/paper-reader.json +0 -21
  164. package/mcp-configs/ai-platform/paperdebugger.json +0 -21
  165. package/mcp-configs/browser/decipher-research-agent.json +0 -17
  166. package/mcp-configs/browser/deep-research.json +0 -17
  167. package/mcp-configs/browser/everything-claude-code.json +0 -17
  168. package/mcp-configs/browser/exa-mcp.json +0 -20
  169. package/mcp-configs/browser/gpt-researcher.json +0 -17
  170. package/mcp-configs/browser/heurist-agent-framework.json +0 -17
  171. package/mcp-configs/browser/mcp-searxng.json +0 -21
  172. package/mcp-configs/browser/mcp-webresearch.json +0 -20
  173. package/mcp-configs/cloud-docs/confluence-mcp.json +0 -37
  174. package/mcp-configs/cloud-docs/google-drive-mcp.json +0 -35
  175. package/mcp-configs/cloud-docs/notion-mcp.json +0 -29
  176. package/mcp-configs/communication/discord-mcp.json +0 -29
  177. package/mcp-configs/communication/discourse-mcp.json +0 -21
  178. package/mcp-configs/communication/slack-mcp.json +0 -29
  179. package/mcp-configs/communication/telegram-mcp.json +0 -28
  180. package/mcp-configs/data-platform/4everland-hosting-mcp.json +0 -17
  181. package/mcp-configs/data-platform/automl-stat-mcp.json +0 -21
  182. package/mcp-configs/data-platform/context-keeper.json +0 -17
  183. package/mcp-configs/data-platform/context7.json +0 -19
  184. package/mcp-configs/data-platform/contextstream-mcp.json +0 -17
  185. package/mcp-configs/data-platform/email-mcp.json +0 -17
  186. package/mcp-configs/data-platform/jefferson-stats-mcp.json +0 -22
  187. package/mcp-configs/data-platform/mcp-excel-server.json +0 -21
  188. package/mcp-configs/data-platform/mcp-stata.json +0 -21
  189. package/mcp-configs/data-platform/mcpstack-jupyter.json +0 -21
  190. package/mcp-configs/data-platform/ml-mcp.json +0 -21
  191. package/mcp-configs/data-platform/nasdaq-data-link-mcp.json +0 -20
  192. package/mcp-configs/data-platform/numpy-mcp.json +0 -21
  193. package/mcp-configs/database/neo4j-mcp.json +0 -37
  194. package/mcp-configs/database/postgres-mcp.json +0 -28
  195. package/mcp-configs/database/sqlite-mcp.json +0 -29
  196. package/mcp-configs/dev-platform/geogebra-mcp.json +0 -21
  197. package/mcp-configs/dev-platform/github-mcp.json +0 -31
  198. package/mcp-configs/dev-platform/gitlab-mcp.json +0 -34
  199. package/mcp-configs/dev-platform/latex-mcp-server.json +0 -21
  200. package/mcp-configs/dev-platform/manim-mcp.json +0 -20
  201. package/mcp-configs/dev-platform/mcp-echarts.json +0 -20
  202. package/mcp-configs/dev-platform/panel-viz-mcp.json +0 -20
  203. package/mcp-configs/dev-platform/paperbanana.json +0 -20
  204. package/mcp-configs/dev-platform/texflow-mcp.json +0 -20
  205. package/mcp-configs/dev-platform/texmcp.json +0 -20
  206. package/mcp-configs/dev-platform/typst-mcp.json +0 -21
  207. package/mcp-configs/dev-platform/vizro-mcp.json +0 -20
  208. package/mcp-configs/email/email-mcp.json +0 -40
  209. package/mcp-configs/email/gmail-mcp.json +0 -37
  210. package/mcp-configs/note-knowledge/ApeRAG.json +0 -17
  211. package/mcp-configs/note-knowledge/In-Memoria.json +0 -17
  212. package/mcp-configs/note-knowledge/agent-memory.json +0 -17
  213. package/mcp-configs/note-knowledge/aimemo.json +0 -17
  214. package/mcp-configs/note-knowledge/biel-mcp.json +0 -19
  215. package/mcp-configs/note-knowledge/cognee.json +0 -17
  216. package/mcp-configs/note-knowledge/context-awesome.json +0 -17
  217. package/mcp-configs/note-knowledge/context-mcp.json +0 -17
  218. package/mcp-configs/note-knowledge/conversation-handoff-mcp.json +0 -17
  219. package/mcp-configs/note-knowledge/cortex.json +0 -17
  220. package/mcp-configs/note-knowledge/devrag.json +0 -17
  221. package/mcp-configs/note-knowledge/easy-obsidian-mcp.json +0 -17
  222. package/mcp-configs/note-knowledge/engram.json +0 -17
  223. package/mcp-configs/note-knowledge/gnosis-mcp.json +0 -17
  224. package/mcp-configs/note-knowledge/graphlit-mcp-server.json +0 -19
  225. package/mcp-configs/note-knowledge/local-faiss-mcp.json +0 -21
  226. package/mcp-configs/note-knowledge/mcp-memory-service.json +0 -21
  227. package/mcp-configs/note-knowledge/mcp-obsidian.json +0 -23
  228. package/mcp-configs/note-knowledge/mcp-ragdocs.json +0 -20
  229. package/mcp-configs/note-knowledge/mcp-summarizer.json +0 -21
  230. package/mcp-configs/note-knowledge/mediawiki-mcp.json +0 -21
  231. package/mcp-configs/note-knowledge/openzim-mcp.json +0 -20
  232. package/mcp-configs/note-knowledge/zettelkasten-mcp.json +0 -21
  233. package/mcp-configs/reference-mgr/academic-paper-mcp-http.json +0 -20
  234. package/mcp-configs/reference-mgr/academix.json +0 -20
  235. package/mcp-configs/reference-mgr/arxiv-cli.json +0 -17
  236. package/mcp-configs/reference-mgr/arxiv-research-mcp.json +0 -21
  237. package/mcp-configs/reference-mgr/arxiv-search-mcp.json +0 -17
  238. package/mcp-configs/reference-mgr/chiken.json +0 -17
  239. package/mcp-configs/reference-mgr/claude-scholar.json +0 -17
  240. package/mcp-configs/reference-mgr/devonthink-mcp.json +0 -17
  241. package/mcp-configs/reference-mgr/google-scholar-abstract-mcp.json +0 -19
  242. package/mcp-configs/reference-mgr/google-scholar-mcp.json +0 -20
  243. package/mcp-configs/reference-mgr/mcp-paperswithcode.json +0 -21
  244. package/mcp-configs/reference-mgr/mcp-scholarly.json +0 -20
  245. package/mcp-configs/reference-mgr/mcp-simple-arxiv.json +0 -20
  246. package/mcp-configs/reference-mgr/mcp-simple-pubmed.json +0 -20
  247. package/mcp-configs/reference-mgr/mcp-zotero.json +0 -21
  248. package/mcp-configs/reference-mgr/mendeley-mcp.json +0 -20
  249. package/mcp-configs/reference-mgr/ncbi-mcp-server.json +0 -22
  250. package/mcp-configs/reference-mgr/onecite.json +0 -21
  251. package/mcp-configs/reference-mgr/paper-search-mcp.json +0 -21
  252. package/mcp-configs/reference-mgr/pubmed-search-mcp.json +0 -21
  253. package/mcp-configs/reference-mgr/scholar-mcp.json +0 -21
  254. package/mcp-configs/reference-mgr/scholar-multi-mcp.json +0 -21
  255. package/mcp-configs/reference-mgr/seerai.json +0 -21
  256. package/mcp-configs/reference-mgr/semantic-scholar-fastmcp.json +0 -21
  257. package/mcp-configs/reference-mgr/sourcelibrary.json +0 -20
  258. package/mcp-configs/registry.json +0 -476
  259. package/mcp-configs/repository/dataverse-mcp.json +0 -33
  260. package/mcp-configs/repository/huggingface-mcp.json +0 -29
  261. package/skills/domains/business/xpert-bi-guide/SKILL.md +0 -84
  262. package/skills/domains/education/edumcp-guide/SKILL.md +0 -74
  263. package/skills/literature/search/paper-search-mcp-guide/SKILL.md +0 -107
  264. package/skills/research/automation/mcp-server-guide/SKILL.md +0 -211
  265. package/skills/tools/knowledge-graph/paperpile-notion-guide/SKILL.md +0 -84
  266. package/src/tools/semantic-scholar.ts +0 -66
@@ -0,0 +1,125 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
3
+ import { toolResult, trackedFetch, isTrackedError } from "./util.js";
4
+
5
+ export function createDblpTools(
6
+ _ctx: OpenClawPluginToolContext,
7
+ _api: OpenClawPluginApi,
8
+ ) {
9
+ return [
10
+ {
11
+ name: "search_dblp",
12
+ label: "Search CS Papers (dblp)",
13
+ description:
14
+ "Search dblp computer science bibliography (7M+ records). Covers conferences (NeurIPS, ICML, ACL, etc.) and journals. Best for CS venue-specific search.",
15
+ parameters: Type.Object({
16
+ query: Type.String({
17
+ description: "Search query for publications",
18
+ }),
19
+ max_results: Type.Optional(
20
+ Type.Number({ description: "Max results (default 10, max 1000)" }),
21
+ ),
22
+ offset: Type.Optional(
23
+ Type.Number({ description: "Result offset for pagination" }),
24
+ ),
25
+ }),
26
+ execute: async (input: {
27
+ query: string;
28
+ max_results?: number;
29
+ offset?: number;
30
+ }) => {
31
+ const params = new URLSearchParams({
32
+ q: input.query,
33
+ format: "json",
34
+ h: String(Math.min(input.max_results ?? 10, 1000)),
35
+ });
36
+ if (input.offset) params.set("f", String(input.offset));
37
+
38
+ const tracked = await trackedFetch("dblp", `https://dblp.org/search/publ/api?${params}`);
39
+ if (isTrackedError(tracked)) return tracked;
40
+ const data = await tracked.res.json();
41
+
42
+ const hits = data.result?.hits;
43
+ if (!hits) return toolResult({ total_results: 0, papers: [] });
44
+
45
+ const papers = (hits.hit ?? []).map(
46
+ (h: Record<string, unknown>) => {
47
+ const info = h.info as Record<string, unknown>;
48
+ if (!info) return {};
49
+
50
+ const authorsRaw = info.authors as Record<string, unknown> | undefined;
51
+ let authors: string[] = [];
52
+ if (authorsRaw?.author) {
53
+ const authorList = authorsRaw.author;
54
+ if (Array.isArray(authorList)) {
55
+ authors = authorList.map((a: Record<string, string> | string) =>
56
+ typeof a === "string" ? a : a.text ?? "",
57
+ );
58
+ } else if (typeof authorList === "object") {
59
+ authors = [(authorList as Record<string, string>).text ?? ""];
60
+ }
61
+ }
62
+
63
+ return {
64
+ title: info.title,
65
+ authors,
66
+ venue: info.venue,
67
+ year: info.year ? parseInt(info.year as string, 10) : undefined,
68
+ type: info.type,
69
+ doi: info.doi,
70
+ url: info.ee ?? info.url,
71
+ dblp_url: info.url,
72
+ };
73
+ },
74
+ );
75
+
76
+ return toolResult({
77
+ total_results: parseInt(hits["@total"] ?? "0", 10),
78
+ papers,
79
+ });
80
+ },
81
+ },
82
+ {
83
+ name: "search_dblp_author",
84
+ label: "Search Authors (dblp)",
85
+ description:
86
+ "Search dblp for computer science authors and their publication profiles.",
87
+ parameters: Type.Object({
88
+ query: Type.String({ description: "Author name to search" }),
89
+ max_results: Type.Optional(
90
+ Type.Number({ description: "Max results (default 10)" }),
91
+ ),
92
+ }),
93
+ execute: async (input: { query: string; max_results?: number }) => {
94
+ const params = new URLSearchParams({
95
+ q: input.query,
96
+ format: "json",
97
+ h: String(Math.min(input.max_results ?? 10, 100)),
98
+ });
99
+
100
+ const tracked = await trackedFetch("dblp", `https://dblp.org/search/author/api?${params}`);
101
+ if (isTrackedError(tracked)) return tracked;
102
+ const data = await tracked.res.json();
103
+
104
+ const hits = data.result?.hits;
105
+ if (!hits) return toolResult({ total_results: 0, authors: [] });
106
+
107
+ const authors = (hits.hit ?? []).map(
108
+ (h: Record<string, unknown>) => {
109
+ const info = h.info as Record<string, unknown>;
110
+ return {
111
+ name: info?.author,
112
+ url: info?.url,
113
+ notes: info?.notes,
114
+ };
115
+ },
116
+ );
117
+
118
+ return toolResult({
119
+ total_results: parseInt(hits["@total"] ?? "0", 10),
120
+ authors,
121
+ });
122
+ },
123
+ },
124
+ ];
125
+ }
@@ -0,0 +1,82 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
3
+ import { toolResult, trackedFetch, isTrackedError } from "./util.js";
4
+
5
+ const BASE = "https://doaj.org/api";
6
+
7
+ export function createDoajTools(
8
+ _ctx: OpenClawPluginToolContext,
9
+ _api: OpenClawPluginApi,
10
+ ) {
11
+ return [
12
+ {
13
+ name: "search_doaj",
14
+ label: "Search Open Access Articles (DOAJ)",
15
+ description:
16
+ "Search DOAJ for verified open access articles (9M+ articles from 20K+ OA journals). All results are guaranteed open access.",
17
+ parameters: Type.Object({
18
+ query: Type.String({
19
+ description:
20
+ "Search query. Supports field search: bibjson.title:, bibjson.author.name:, bibjson.keywords:, doi:, bibjson.year:. Boolean AND/OR supported.",
21
+ }),
22
+ max_results: Type.Optional(
23
+ Type.Number({ description: "Max results (default 10, max 100)" }),
24
+ ),
25
+ page: Type.Optional(
26
+ Type.Number({ description: "Page number (starts from 1)" }),
27
+ ),
28
+ sort: Type.Optional(
29
+ Type.String({ description: "Sort field, e.g. 'created_date:desc'" }),
30
+ ),
31
+ }),
32
+ execute: async (input: {
33
+ query: string;
34
+ max_results?: number;
35
+ page?: number;
36
+ sort?: string;
37
+ }) => {
38
+ const pageSize = Math.min(input.max_results ?? 10, 100);
39
+ const page = input.page ?? 1;
40
+
41
+ let url = `${BASE}/search/articles/${encodeURIComponent(input.query)}?page=${page}&pageSize=${pageSize}`;
42
+ if (input.sort) url += `&sort=${encodeURIComponent(input.sort)}`;
43
+
44
+ const tracked = await trackedFetch("doaj", url);
45
+ if (isTrackedError(tracked)) return tracked;
46
+ const data = await tracked.res.json();
47
+
48
+ const articles = (data.results ?? []).map(
49
+ (r: Record<string, unknown>) => {
50
+ const bib = r.bibjson as Record<string, unknown> | undefined;
51
+ if (!bib) return { id: r.id };
52
+
53
+ const identifiers = bib.identifier as Array<{ type: string; id: string }> | undefined;
54
+ const doi = identifiers?.find((i) => i.type === "doi")?.id;
55
+ const links = bib.link as Array<{ url: string; type: string }> | undefined;
56
+ const journal = bib.journal as Record<string, unknown> | undefined;
57
+
58
+ return {
59
+ title: bib.title,
60
+ abstract: bib.abstract,
61
+ authors: (bib.author as Array<{ name: string }> | undefined)
62
+ ?.map((a) => a.name),
63
+ year: bib.year,
64
+ doi,
65
+ journal: journal?.title,
66
+ publisher: journal?.publisher,
67
+ keywords: bib.keywords,
68
+ url: links?.[0]?.url ?? (doi ? `https://doi.org/${doi}` : undefined),
69
+ is_oa: true,
70
+ };
71
+ },
72
+ );
73
+
74
+ return toolResult({
75
+ total_results: data.total,
76
+ page,
77
+ articles,
78
+ });
79
+ },
80
+ },
81
+ ];
82
+ }
@@ -0,0 +1,159 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
3
+ import { toolResult, trackedFetch, isTrackedError } from "./util.js";
4
+
5
+ const BASE = "https://www.ebi.ac.uk/europepmc/webservices/rest";
6
+
7
+ export function createEuropePmcTools(
8
+ _ctx: OpenClawPluginToolContext,
9
+ _api: OpenClawPluginApi,
10
+ ) {
11
+ return [
12
+ {
13
+ name: "search_europe_pmc",
14
+ label: "Search Articles (Europe PMC)",
15
+ description:
16
+ "Search Europe PMC biomedical literature. Covers 33M+ articles including full PubMed, with open access full text, citation counts, and MeSH terms.",
17
+ parameters: Type.Object({
18
+ query: Type.String({
19
+ description:
20
+ "Search query. Supports field tags: TITLE:, AUTH:, JOURNAL:, DOI:, and boolean AND/OR/NOT.",
21
+ }),
22
+ max_results: Type.Optional(
23
+ Type.Number({ description: "Max results (default 10, max 1000)" }),
24
+ ),
25
+ sort: Type.Optional(
26
+ Type.String({
27
+ description: "Sort by: 'RELEVANCE', 'DATE_DESC', 'CITED'",
28
+ }),
29
+ ),
30
+ cursor: Type.Optional(
31
+ Type.String({ description: "Pagination cursor (use value from previous response)" }),
32
+ ),
33
+ }),
34
+ execute: async (input: {
35
+ query: string;
36
+ max_results?: number;
37
+ sort?: string;
38
+ cursor?: string;
39
+ }) => {
40
+ const params = new URLSearchParams({
41
+ query: input.query,
42
+ format: "json",
43
+ pageSize: String(Math.min(input.max_results ?? 10, 1000)),
44
+ resultType: "core",
45
+ });
46
+ if (input.sort) params.set("sort", input.sort);
47
+ params.set("cursorMark", input.cursor ?? "*");
48
+
49
+ const tracked = await trackedFetch("europe_pmc", `${BASE}/search?${params}`);
50
+ if (isTrackedError(tracked)) return tracked;
51
+ const data = await tracked.res.json();
52
+
53
+ const results = (data.resultList?.result ?? []).map(
54
+ (r: Record<string, unknown>) => ({
55
+ pmid: r.pmid,
56
+ pmcid: r.pmcid,
57
+ doi: r.doi,
58
+ title: r.title,
59
+ authors: r.authorString,
60
+ journal: (r.journalInfo as Record<string, unknown>)?.journal
61
+ ? ((r.journalInfo as Record<string, unknown>).journal as Record<string, unknown>)?.title
62
+ : undefined,
63
+ year: r.pubYear,
64
+ abstract: r.abstractText,
65
+ is_oa: r.isOpenAccess === "Y",
66
+ cited_by_count: r.citedByCount,
67
+ source: r.source,
68
+ url: r.doi ? `https://doi.org/${r.doi}` : `https://europepmc.org/article/${r.source}/${r.id}`,
69
+ }),
70
+ );
71
+
72
+ return toolResult({
73
+ total_results: data.hitCount,
74
+ next_cursor: data.nextCursorMark,
75
+ articles: results,
76
+ _source_health: { source: "europe_pmc", latency_ms: tracked.latency_ms },
77
+ });
78
+ },
79
+ },
80
+ {
81
+ name: "get_epmc_citations",
82
+ label: "Get Citations (Europe PMC)",
83
+ description:
84
+ "Get papers that cite a given article. Forward citation tracking for biomedical literature.",
85
+ parameters: Type.Object({
86
+ pmid: Type.String({
87
+ description: "PubMed ID of the article",
88
+ }),
89
+ max_results: Type.Optional(
90
+ Type.Number({ description: "Max citations to return (default 25)" }),
91
+ ),
92
+ page: Type.Optional(Type.Number({ description: "Page number (default 1)" })),
93
+ }),
94
+ execute: async (input: { pmid: string; max_results?: number; page?: number }) => {
95
+ const params = new URLSearchParams({
96
+ format: "json",
97
+ pageSize: String(input.max_results ?? 25),
98
+ page: String(input.page ?? 1),
99
+ });
100
+ const tracked = await trackedFetch("europe_pmc", `${BASE}/MED/${input.pmid}/citations?${params}`);
101
+ if (isTrackedError(tracked)) return tracked;
102
+ const data = await tracked.res.json();
103
+
104
+ return toolResult({
105
+ total_citations: data.hitCount,
106
+ citations: (data.citationList?.citation ?? []).map(
107
+ (c: Record<string, unknown>) => ({
108
+ pmid: c.id,
109
+ source: c.source,
110
+ title: c.title,
111
+ authors: c.authorString,
112
+ journal: c.journalAbbreviation,
113
+ year: c.pubYear,
114
+ cited_by_count: c.citedByCount,
115
+ }),
116
+ ),
117
+ _source_health: { source: "europe_pmc", latency_ms: tracked.latency_ms },
118
+ });
119
+ },
120
+ },
121
+ {
122
+ name: "get_epmc_references",
123
+ label: "Get References (Europe PMC)",
124
+ description:
125
+ "Get the reference list of a paper. Shows what a paper cites.",
126
+ parameters: Type.Object({
127
+ pmid: Type.String({ description: "PubMed ID of the article" }),
128
+ max_results: Type.Optional(
129
+ Type.Number({ description: "Max references to return (default 25)" }),
130
+ ),
131
+ }),
132
+ execute: async (input: { pmid: string; max_results?: number }) => {
133
+ const params = new URLSearchParams({
134
+ format: "json",
135
+ pageSize: String(input.max_results ?? 25),
136
+ });
137
+ const tracked = await trackedFetch("europe_pmc", `${BASE}/MED/${input.pmid}/references?${params}`);
138
+ if (isTrackedError(tracked)) return tracked;
139
+ const data = await tracked.res.json();
140
+
141
+ return toolResult({
142
+ total_references: data.hitCount,
143
+ references: (data.referenceList?.reference ?? []).map(
144
+ (r: Record<string, unknown>) => ({
145
+ pmid: r.id,
146
+ source: r.source,
147
+ title: r.title,
148
+ authors: r.authorString,
149
+ journal: r.journalAbbreviation,
150
+ year: r.pubYear,
151
+ order: r.citedOrder,
152
+ }),
153
+ ),
154
+ _source_health: { source: "europe_pmc", latency_ms: tracked.latency_ms },
155
+ });
156
+ },
157
+ },
158
+ ];
159
+ }
@@ -0,0 +1,118 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
3
+ import { toolResult, trackedFetch, isTrackedError } from "./util.js";
4
+
5
+ const BASE = "https://api.archives-ouvertes.fr";
6
+
7
+ /** Default fields to request from HAL Solr API */
8
+ const DEFAULT_FIELDS = [
9
+ "title_s",
10
+ "authFullName_s",
11
+ "doiId_s",
12
+ "producedDate_s",
13
+ "uri_s",
14
+ "abstract_s",
15
+ "journalTitle_s",
16
+ "keyword_s",
17
+ "docType_s",
18
+ "halId_s",
19
+ ].join(",");
20
+
21
+ export function createHalTools(
22
+ _ctx: OpenClawPluginToolContext,
23
+ _api: OpenClawPluginApi,
24
+ ) {
25
+ return [
26
+ {
27
+ name: "search_hal",
28
+ label: "Search Publications (HAL)",
29
+ description:
30
+ "Search HAL (Hyper Articles en Ligne), the French open archive for scholarly publications. Covers 4M+ documents with strong coverage of French and European research across all disciplines.",
31
+ parameters: Type.Object({
32
+ query: Type.String({
33
+ description:
34
+ "Search query. Supports Solr syntax: field:value, AND/OR/NOT, quoted phrases.",
35
+ }),
36
+ rows: Type.Optional(
37
+ Type.Number({ description: "Max results (default 10, max 100)" }),
38
+ ),
39
+ sort: Type.Optional(
40
+ Type.String({
41
+ description:
42
+ "Sort: 'producedDate_s desc' (newest), 'producedDate_s asc' (oldest). Default: relevance.",
43
+ }),
44
+ ),
45
+ doc_type: Type.Optional(
46
+ Type.String({
47
+ description:
48
+ "Document type filter: 'ART' (journal article), 'COMM' (conference paper), 'THESE' (thesis), 'COUV' (book chapter), 'OUV' (book), 'REPORT', 'HDR', 'POSTER'",
49
+ }),
50
+ ),
51
+ }),
52
+ execute: async (input: {
53
+ query: string;
54
+ rows?: number;
55
+ sort?: string;
56
+ doc_type?: string;
57
+ }) => {
58
+ let q = input.query;
59
+ if (input.doc_type) {
60
+ q = `(${q}) AND docType_s:${input.doc_type}`;
61
+ }
62
+
63
+ const params = new URLSearchParams({
64
+ q,
65
+ fl: DEFAULT_FIELDS,
66
+ rows: String(Math.min(input.rows ?? 10, 100)),
67
+ wt: "json",
68
+ });
69
+ if (input.sort) params.set("sort", input.sort);
70
+
71
+ const result = await trackedFetch(
72
+ "hal",
73
+ `${BASE}/search/?${params}`,
74
+ undefined,
75
+ 10_000,
76
+ );
77
+ if (isTrackedError(result)) return result;
78
+ const data = await result.res.json();
79
+
80
+ const response = data.response as Record<string, unknown> | undefined;
81
+ const docs = response?.docs as Array<Record<string, unknown>> | undefined;
82
+
83
+ return toolResult({
84
+ total_results: response?.numFound,
85
+ source: "hal",
86
+ papers: (docs ?? []).map((doc) => {
87
+ // HAL returns title_s and authFullName_s as arrays
88
+ const titles = doc.title_s as string[] | undefined;
89
+ const authors = doc.authFullName_s as string[] | undefined;
90
+ const keywords = doc.keyword_s as string[] | undefined;
91
+ const abstracts = doc.abstract_s as string[] | undefined;
92
+ const doi = doc.doiId_s as string | undefined;
93
+
94
+ return {
95
+ title: titles?.[0],
96
+ authors,
97
+ doi,
98
+ year: doc.producedDate_s
99
+ ? String(doc.producedDate_s).slice(0, 4)
100
+ : undefined,
101
+ publication_date: doc.producedDate_s,
102
+ journal: doc.journalTitle_s,
103
+ doc_type: doc.docType_s,
104
+ keywords,
105
+ abstract: abstracts?.[0]
106
+ ? String(abstracts[0]).slice(0, 500)
107
+ : undefined,
108
+ url: (doc.uri_s as string) ?? (doi ? `https://doi.org/${doi}` : undefined),
109
+ hal_id: doc.halId_s,
110
+ source: "hal",
111
+ };
112
+ }),
113
+ _latency_ms: result.latency_ms,
114
+ });
115
+ },
116
+ },
117
+ ];
118
+ }
@@ -0,0 +1,165 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
3
+ import { toolResult, trackedFetch, isTrackedError } from "./util.js";
4
+
5
+ const BASE = "https://inspirehep.net/api";
6
+
7
+ interface InspireAuthor {
8
+ full_name: string;
9
+ first_name?: string;
10
+ last_name?: string;
11
+ }
12
+
13
+ interface InspireTitle {
14
+ title: string;
15
+ source?: string;
16
+ }
17
+
18
+ interface InspireAbstract {
19
+ value: string;
20
+ source?: string;
21
+ }
22
+
23
+ interface InspireArxivEprint {
24
+ value: string;
25
+ categories?: string[];
26
+ }
27
+
28
+ interface InspireDoi {
29
+ value: string;
30
+ }
31
+
32
+ interface InspirePublicationInfo {
33
+ year?: number;
34
+ journal_title?: string;
35
+ journal_volume?: string;
36
+ page_start?: string;
37
+ page_end?: string;
38
+ artid?: string;
39
+ }
40
+
41
+ function normalizeHit(meta: Record<string, unknown>): Record<string, unknown> {
42
+ const titles = meta.titles as InspireTitle[] | undefined;
43
+ const authors = meta.authors as InspireAuthor[] | undefined;
44
+ const arxivEprints = meta.arxiv_eprints as InspireArxivEprint[] | undefined;
45
+ const dois = meta.dois as InspireDoi[] | undefined;
46
+ const abstracts = meta.abstracts as InspireAbstract[] | undefined;
47
+ const pubInfo = meta.publication_info as InspirePublicationInfo[] | undefined;
48
+
49
+ const arxivId = arxivEprints?.[0]?.value;
50
+ const doi = dois?.[0]?.value;
51
+
52
+ return {
53
+ title: titles?.[0]?.title,
54
+ authors: authors?.slice(0, 10).map((a) => a.full_name),
55
+ author_count: authors?.length ?? meta.author_count,
56
+ doi,
57
+ arxiv_id: arxivId,
58
+ arxiv_categories: arxivEprints?.[0]?.categories,
59
+ year: pubInfo?.[0]?.year ?? (meta.earliest_date ? String(meta.earliest_date).slice(0, 4) : undefined),
60
+ journal: pubInfo?.[0]?.journal_title,
61
+ journal_volume: pubInfo?.[0]?.journal_volume,
62
+ citation_count: meta.citation_count,
63
+ abstract: abstracts?.[0]?.value,
64
+ url: doi
65
+ ? `https://doi.org/${doi}`
66
+ : arxivId
67
+ ? `https://arxiv.org/abs/${arxivId}`
68
+ : undefined,
69
+ inspire_url: meta.control_number
70
+ ? `https://inspirehep.net/literature/${meta.control_number}`
71
+ : undefined,
72
+ source: "inspire_hep",
73
+ };
74
+ }
75
+
76
+ export function createInspireHepTools(
77
+ _ctx: OpenClawPluginToolContext,
78
+ _api: OpenClawPluginApi,
79
+ ) {
80
+ return [
81
+ {
82
+ name: "search_inspire",
83
+ label: "Search Papers (INSPIRE-HEP)",
84
+ description:
85
+ "Search INSPIRE-HEP for high-energy physics literature. The primary database for particle physics, astrophysics, and related fields. Covers 1.5M+ records with citation tracking.",
86
+ parameters: Type.Object({
87
+ query: Type.String({
88
+ description:
89
+ "Search query. Supports SPIRES-style: 'find a einstein and t relativity', or keywords like 'higgs boson'. Field search: a (author), t (title), j (journal), eprint (arXiv ID).",
90
+ }),
91
+ size: Type.Optional(
92
+ Type.Number({ description: "Max results (default 10, max 100)" }),
93
+ ),
94
+ sort: Type.Optional(
95
+ Type.String({
96
+ description:
97
+ "Sort by: 'mostrecent' (newest), 'mostcited', 'bestmatch' (relevance)",
98
+ }),
99
+ ),
100
+ }),
101
+ execute: async (input: { query: string; size?: number; sort?: string }) => {
102
+ const params = new URLSearchParams({
103
+ q: input.query,
104
+ size: String(Math.min(input.size ?? 10, 100)),
105
+ sort: input.sort ?? "bestmatch",
106
+ });
107
+
108
+ const result = await trackedFetch(
109
+ "inspire_hep",
110
+ `${BASE}/literature?${params}`,
111
+ undefined,
112
+ 10_000,
113
+ );
114
+ if (isTrackedError(result)) return result;
115
+ const data = await result.res.json();
116
+
117
+ return toolResult({
118
+ total_results: data.hits?.total,
119
+ source: "inspire_hep",
120
+ papers: data.hits?.hits?.map(
121
+ (h: Record<string, unknown>) =>
122
+ normalizeHit(h.metadata as Record<string, unknown>),
123
+ ),
124
+ _latency_ms: result.latency_ms,
125
+ });
126
+ },
127
+ },
128
+ {
129
+ name: "get_inspire_paper",
130
+ label: "Get Paper Details (INSPIRE-HEP)",
131
+ description:
132
+ "Get detailed information about a specific paper from INSPIRE-HEP by arXiv ID or DOI.",
133
+ parameters: Type.Object({
134
+ identifier: Type.String({
135
+ description:
136
+ "Paper identifier: arXiv ID (e.g. '1207.7214') or DOI (e.g. '10.1016/j.physletb.2012.08.020')",
137
+ }),
138
+ }),
139
+ execute: async (input: { identifier: string }) => {
140
+ // Determine if it's a DOI or arXiv ID
141
+ const id = input.identifier.trim();
142
+ let url: string;
143
+ if (id.startsWith("10.")) {
144
+ url = `${BASE}/doi/${encodeURIComponent(id)}`;
145
+ } else {
146
+ // arXiv ID — strip any "arXiv:" prefix
147
+ const arxivId = id.replace(/^arXiv:/i, "");
148
+ url = `${BASE}/arxiv/${encodeURIComponent(arxivId)}`;
149
+ }
150
+
151
+ const result = await trackedFetch("inspire_hep", url, undefined, 10_000);
152
+ if (isTrackedError(result)) return result;
153
+ const data = await result.res.json();
154
+
155
+ const meta = data.metadata as Record<string, unknown> | undefined;
156
+ if (!meta) return toolResult({ error: "Paper not found", source: "inspire_hep" });
157
+
158
+ return toolResult({
159
+ ...normalizeHit(meta),
160
+ _latency_ms: result.latency_ms,
161
+ });
162
+ },
163
+ },
164
+ ];
165
+ }