@kak4343/scholar-mcp 0.3.0

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +162 -0
  3. package/README.md +156 -0
  4. package/dist/cache/disk_cache.d.ts +27 -0
  5. package/dist/cache/disk_cache.js +82 -0
  6. package/dist/cache/disk_cache.js.map +1 -0
  7. package/dist/cache/index.d.ts +47 -0
  8. package/dist/cache/index.js +67 -0
  9. package/dist/cache/index.js.map +1 -0
  10. package/dist/cache/memory_cache.d.ts +17 -0
  11. package/dist/cache/memory_cache.js +36 -0
  12. package/dist/cache/memory_cache.js.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +166 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/notion/push.d.ts +43 -0
  17. package/dist/notion/push.js +190 -0
  18. package/dist/notion/push.js.map +1 -0
  19. package/dist/sources/arxiv.d.ts +5 -0
  20. package/dist/sources/arxiv.js +57 -0
  21. package/dist/sources/arxiv.js.map +1 -0
  22. package/dist/sources/pubmed.d.ts +15 -0
  23. package/dist/sources/pubmed.js +133 -0
  24. package/dist/sources/pubmed.js.map +1 -0
  25. package/dist/sources/semantic_scholar.d.ts +7 -0
  26. package/dist/sources/semantic_scholar.js +61 -0
  27. package/dist/sources/semantic_scholar.js.map +1 -0
  28. package/dist/types.d.ts +25 -0
  29. package/dist/types.js +2 -0
  30. package/dist/types.js.map +1 -0
  31. package/package.json +43 -0
  32. package/scripts/smoke_test.mjs +120 -0
  33. package/src/cache/disk_cache.ts +94 -0
  34. package/src/cache/index.ts +95 -0
  35. package/src/cache/memory_cache.ts +43 -0
  36. package/src/index.ts +212 -0
  37. package/src/notion/push.ts +237 -0
  38. package/src/sources/arxiv.ts +61 -0
  39. package/src/sources/pubmed.ts +143 -0
  40. package/src/sources/semantic_scholar.ts +67 -0
  41. package/src/types.ts +28 -0
  42. package/tsconfig.json +19 -0
@@ -0,0 +1,67 @@
1
+ import type { SearchParams, SearchResult, SourceSearcher } from "../types.js";
2
+
3
+ const BASE_URL = "https://api.semanticscholar.org/graph/v1";
4
+ const USER_AGENT = "scholar-mcp/0.2.1 (https://github.com/kak4343/scholar-mcp)";
5
+ const FIELDS = "title,authors,abstract,year,publicationDate,externalIds,citationCount,venue,url";
6
+
7
+ export class SemanticScholarSearcher implements SourceSearcher {
8
+ private apiKey?: string;
9
+
10
+ constructor(apiKey?: string) {
11
+ this.apiKey = apiKey;
12
+ }
13
+
14
+ async search(params: SearchParams): Promise<SearchResult[]> {
15
+ const url = new URL(`${BASE_URL}/paper/search`);
16
+ url.searchParams.set("query", params.query);
17
+ url.searchParams.set("limit", String(params.max_results ?? 10));
18
+ url.searchParams.set("fields", FIELDS);
19
+ if (params.date_from || params.date_to) {
20
+ const from = params.date_from ?? "1900-01-01";
21
+ const to = params.date_to ?? new Date().toISOString().substring(0, 10);
22
+ url.searchParams.set("publicationDateOrYear", `${from}:${to}`);
23
+ }
24
+
25
+ const headers: Record<string, string> = { "User-Agent": USER_AGENT };
26
+ if (this.apiKey) headers["x-api-key"] = this.apiKey;
27
+
28
+ const r = await fetch(url, { headers });
29
+ if (!r.ok) {
30
+ if (r.status === 429) throw new Error("Semantic Scholar rate limit exceeded");
31
+ throw new Error(`Semantic Scholar search failed: ${r.status}`);
32
+ }
33
+ const data = await r.json() as { data?: any[] };
34
+ return (data.data ?? []).map((p: any) => this.parsePaper(p)).filter((r): r is SearchResult => r !== null);
35
+ }
36
+
37
+ private parsePaper(paper: any): SearchResult | null {
38
+ const id = String(paper.paperId ?? "");
39
+ if (!id) return null;
40
+
41
+ const title = String(paper.title ?? "").trim();
42
+ const abstract = String(paper.abstract ?? "").trim();
43
+ const authors = (paper.authors ?? []).map((a: any) => String(a.name ?? "")).filter(Boolean);
44
+ const published_date = String(paper.publicationDate ?? (paper.year ? `${paper.year}-01-01` : ""));
45
+ const doi = paper.externalIds?.DOI ? String(paper.externalIds.DOI) : undefined;
46
+ const pmid = paper.externalIds?.PubMed ? String(paper.externalIds.PubMed) : undefined;
47
+ const arxiv_id = paper.externalIds?.ArXiv ? String(paper.externalIds.ArXiv) : undefined;
48
+ const venue = String(paper.venue ?? "");
49
+ const citation_count = typeof paper.citationCount === "number" ? paper.citationCount : undefined;
50
+ const url = String(paper.url ?? `https://www.semanticscholar.org/paper/${id}`);
51
+
52
+ return {
53
+ source: "semantic_scholar",
54
+ title,
55
+ authors,
56
+ abstract,
57
+ doi,
58
+ pmid,
59
+ arxiv_id,
60
+ semantic_scholar_id: id,
61
+ published_date,
62
+ venue,
63
+ citation_count,
64
+ url,
65
+ };
66
+ }
67
+ }
package/src/types.ts ADDED
@@ -0,0 +1,28 @@
1
+ export type Source = "pubmed" | "arxiv" | "semantic_scholar";
2
+
3
+ export interface SearchResult {
4
+ source: Source;
5
+ title: string;
6
+ authors: string[];
7
+ abstract: string;
8
+ doi?: string;
9
+ arxiv_id?: string;
10
+ pmid?: string;
11
+ semantic_scholar_id?: string;
12
+ published_date: string;
13
+ venue?: string;
14
+ citation_count?: number;
15
+ url: string;
16
+ }
17
+
18
+ export interface SearchParams {
19
+ query: string;
20
+ sources?: Source[];
21
+ max_results?: number;
22
+ date_from?: string;
23
+ date_to?: string;
24
+ }
25
+
26
+ export interface SourceSearcher {
27
+ search(params: SearchParams): Promise<SearchResult[]>;
28
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true,
12
+ "declaration": true,
13
+ "sourceMap": true,
14
+ "allowSyntheticDefaultImports": true,
15
+ "forceConsistentCasingInFileNames": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }