wtf-p 0.3.0 → 0.4.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.
- package/README.md +18 -0
- package/bin/commands/install-logic.js +6 -10
- package/bin/lib/analyze-impact.js +105 -0
- package/bin/lib/bib-format.js +161 -0
- package/bin/lib/bib-index.js +104 -0
- package/bin/lib/citation-fetcher.js +299 -0
- package/bin/lib/citation-ranker.js +133 -0
- package/bin/lib/manifest.js +18 -0
- package/bin/lib/scholar-lookup.js +188 -0
- package/bin/lib/semantic-scholar.js +184 -0
- package/package.json +1 -1
- package/vendors/claude/agents/wtfp/citation-expert.md +45 -0
- package/vendors/claude/agents/wtfp/citation-formatter.md +42 -0
- package/vendors/claude/agents/wtfp/citation-retriever.md +31 -0
- package/vendors/claude/commands/wtfp/analyze-bib.md +41 -52
- package/vendors/claude/commands/wtfp/check-refs.md +11 -9
- package/vendors/claude/commands/wtfp/new-paper.md +42 -81
- package/vendors/claude/commands/wtfp/research-gap.md +3 -4
- package/vendors/claude/mcp/research-server/package.json +13 -0
- package/vendors/claude/mcp/research-server/src/index.js +133 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wtf-p-research-server",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "MCP Server for ArXiv and Semantic Scholar citation retrieval",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"wtfp-research": "src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@modelcontextprotocol/sdk": "^0.6.0",
|
|
11
|
+
"node-fetch": "^2.7.0"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
|
|
4
|
+
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5
|
+
const {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
ErrorCode,
|
|
9
|
+
McpError
|
|
10
|
+
} = require("@modelcontextprotocol/sdk/types.js");
|
|
11
|
+
const fetch = require("node-fetch");
|
|
12
|
+
|
|
13
|
+
const SEMANTIC_SCHOLAR_API = "https://api.semanticscholar.org/graph/v1";
|
|
14
|
+
|
|
15
|
+
class ResearchServer {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.server = new Server(
|
|
18
|
+
{
|
|
19
|
+
name: "wtf-p-research",
|
|
20
|
+
version: "0.4.0",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
capabilities: {
|
|
24
|
+
tools: {},
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
this.setupTools();
|
|
30
|
+
|
|
31
|
+
this.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
32
|
+
process.on("SIGINT", async () => {
|
|
33
|
+
await this.server.close();
|
|
34
|
+
process.exit(0);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setupTools() {
|
|
39
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
40
|
+
tools: [
|
|
41
|
+
{
|
|
42
|
+
name: "search_papers",
|
|
43
|
+
description: "Search for academic papers on Semantic Scholar",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
query: { type: "string", description: "Search query (title, authors, keywords)" },
|
|
48
|
+
limit: { type: "number", description: "Max results (default 5)", default: 5 },
|
|
49
|
+
},
|
|
50
|
+
required: ["query"],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "get_bibtex",
|
|
55
|
+
description: "Get BibTeX for a specific paper by its Semantic Scholar ID or DOI",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
paperId: { type: "string", description: "Semantic Scholar ID or DOI (prefix with 'DOI:')" },
|
|
60
|
+
},
|
|
61
|
+
required: ["paperId"],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
68
|
+
switch (request.params.name) {
|
|
69
|
+
case "search_papers":
|
|
70
|
+
return await this.handleSearch(request.params.arguments);
|
|
71
|
+
case "get_bibtex":
|
|
72
|
+
return await this.handleGetBibtex(request.params.arguments);
|
|
73
|
+
default:
|
|
74
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async handleSearch(args) {
|
|
80
|
+
const { query, limit = 5 } = args;
|
|
81
|
+
try {
|
|
82
|
+
const response = await fetch(
|
|
83
|
+
`${SEMANTIC_SCHOLAR_API}/paper/search?query=${encodeURIComponent(query)}&limit=${limit}&fields=title,authors,year,abstract,venue,externalIds`
|
|
84
|
+
);
|
|
85
|
+
if (!response.ok) throw new Error(`API error: ${response.statusText}`);
|
|
86
|
+
const data = await response.json();
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: JSON.stringify(data.data || [], null, 2) }],
|
|
90
|
+
};
|
|
91
|
+
} catch (error) {
|
|
92
|
+
return {
|
|
93
|
+
content: [{ type: "text", text: `Error searching papers: ${error.message}` }],
|
|
94
|
+
isError: true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async handleGetBibtex(args) {
|
|
100
|
+
const { paperId } = args;
|
|
101
|
+
try {
|
|
102
|
+
// In a real implementation, we might need a separate service or to construct BibTeX from the metadata
|
|
103
|
+
// For this prototype, we'll fetch the fields needed to construct a valid BibTeX entry.
|
|
104
|
+
const response = await fetch(
|
|
105
|
+
`${SEMANTIC_SCHOLAR_API}/paper/${paperId}?fields=title,authors,year,venue,externalIds,citationStyles`
|
|
106
|
+
);
|
|
107
|
+
if (!response.ok) throw new Error(`API error: ${response.statusText}`);
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
|
|
110
|
+
const authors = (data.authors || []).map(a => a.name).join(' and ');
|
|
111
|
+
const bibtex = `@article{${data.externalIds?.DOI || data.paperId},\n title={${data.title}},\n author={${authors}},\n journal={${data.venue || 'Unknown'}},\n year={${data.year}}
|
|
112
|
+
}`;
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: bibtex }],
|
|
116
|
+
};
|
|
117
|
+
} catch (error) {
|
|
118
|
+
return {
|
|
119
|
+
content: [{ type: "text", text: `Error fetching BibTeX: ${error.message}` }],
|
|
120
|
+
isError: true,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async run() {
|
|
126
|
+
const transport = new StdioServerTransport();
|
|
127
|
+
await this.server.connect(transport);
|
|
128
|
+
console.error("Research MCP server running on stdio");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const server = new ResearchServer();
|
|
133
|
+
server.run().catch(console.error);
|