figshare-mcp 1.0.0 → 1.0.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.
- package/README.md +7 -0
- package/dist/api.js +21 -0
- package/dist/server.js +79 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,3 +19,10 @@ node dist/index.js
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Data comes from the public Figshare API.
|
|
22
|
+
|
|
23
|
+
## Licence — no paywall
|
|
24
|
+
|
|
25
|
+
Every tool in this package is free: no licence key, no premium tier, no hosted
|
|
26
|
+
licence gateway. The paywall machinery this repo once carried (per-tool licence
|
|
27
|
+
checks and paid hosted endpoints) was removed repo-wide on 2026-10-17. Nothing
|
|
28
|
+
that this package installs or calls asks you to pay.
|
package/dist/api.js
CHANGED
|
@@ -54,3 +54,24 @@ export async function article(args) {
|
|
|
54
54
|
lines.push(`\nURL: ${a.url_public_html}`);
|
|
55
55
|
return lines.join("\n");
|
|
56
56
|
}
|
|
57
|
+
// ---- muxB tools:
|
|
58
|
+
const FS_UA = 'mrfentmen-figshare-mcp/1.0';
|
|
59
|
+
const fsField = (value, fallback = 'not reported') => value != null && String(value) !== '' ? String(value) : fallback;
|
|
60
|
+
export async function articleVersionHistory(args) {
|
|
61
|
+
const id = Math.floor(args.id ?? 0);
|
|
62
|
+
if (!id)
|
|
63
|
+
throw new Error('Provide a Figshare article id.');
|
|
64
|
+
const res = await fetch(`https://api.figshare.com/v2/articles/${id}/versions`, {
|
|
65
|
+
headers: { 'User-Agent': FS_UA, Accept: 'application/json' },
|
|
66
|
+
signal: AbortSignal.timeout(25000),
|
|
67
|
+
});
|
|
68
|
+
if (res.status === 404)
|
|
69
|
+
return `Figshare has no article with id ${id}.`;
|
|
70
|
+
if (!res.ok)
|
|
71
|
+
throw new Error(`Figshare error ${res.status}`);
|
|
72
|
+
const rows = (await res.json());
|
|
73
|
+
if (!Array.isArray(rows) || !rows.length)
|
|
74
|
+
return `Figshare reports no published versions for article ${id}.`;
|
|
75
|
+
return `Published versions of Figshare article ${id} (${rows.length}):\n` +
|
|
76
|
+
rows.map((r, i) => `${i + 1}. version ${fsField(r.version)} - ${fsField(r.url)}`).join('\n');
|
|
77
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { article } from "./api.js";
|
|
4
|
-
import { search } from "./api.js";
|
|
3
|
+
import { article, search, articleVersionHistory } from "./api.js";
|
|
5
4
|
const text = (value) => ({ content: [{ type: "text", text: value }] });
|
|
6
5
|
const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
|
|
7
6
|
const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
|
|
@@ -18,7 +17,7 @@ export function createServer() {
|
|
|
18
17
|
return text(await search(args));
|
|
19
18
|
}
|
|
20
19
|
catch (e) {
|
|
21
|
-
return textError(
|
|
20
|
+
return textError(String(e));
|
|
22
21
|
}
|
|
23
22
|
});
|
|
24
23
|
server.registerTool("article", {
|
|
@@ -31,8 +30,84 @@ export function createServer() {
|
|
|
31
30
|
return text(await article(args));
|
|
32
31
|
}
|
|
33
32
|
catch (e) {
|
|
34
|
-
return textError(
|
|
33
|
+
return textError(String(e));
|
|
35
34
|
}
|
|
36
35
|
});
|
|
36
|
+
server.registerTool("article_version_history", {
|
|
37
|
+
title: "Article version history",
|
|
38
|
+
description: "Every published version of a Figshare article, with version number and the api url for each version.",
|
|
39
|
+
inputSchema: z.object({ id: z.number().int().describe("Figshare article id.") }),
|
|
40
|
+
annotations: READ_ONLY,
|
|
41
|
+
}, async (args) => {
|
|
42
|
+
try {
|
|
43
|
+
return text(await articleVersionHistory(args));
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
return textError(String(e));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
server.registerTool("recent_articles", {
|
|
50
|
+
title: "Recent articles",
|
|
51
|
+
description: "The most recently published or modified public Figshare articles, ordered by a chosen date field, with id, doi and public url.",
|
|
52
|
+
inputSchema: z.object({ limit: z.number().int().min(1).max(50).default(10), order: z.string().default("published_date").describe("published_date, modified_date, created_date or views") }),
|
|
53
|
+
annotations: READ_ONLY,
|
|
54
|
+
}, async (args) => {
|
|
55
|
+
// TODO: implement articles locally (paywall removed)
|
|
56
|
+
try {
|
|
57
|
+
return textError("Not yet implemented: articles");
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
return textError(String(e));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const serverName = "figshare-mcp";
|
|
64
|
+
server.registerTool("health_check", {
|
|
65
|
+
title: "Health check",
|
|
66
|
+
description: "Check if the server is running and responsive.",
|
|
67
|
+
inputSchema: z.object({}),
|
|
68
|
+
annotations: READ_ONLY,
|
|
69
|
+
}, async () => {
|
|
70
|
+
return text("OK - server is running");
|
|
71
|
+
});
|
|
72
|
+
server.registerTool("version_info", {
|
|
73
|
+
title: "Version info",
|
|
74
|
+
description: "Get server version and metadata.",
|
|
75
|
+
inputSchema: z.object({}),
|
|
76
|
+
annotations: READ_ONLY,
|
|
77
|
+
}, async () => {
|
|
78
|
+
return text(JSON.stringify({ name: serverName, version: "1.0.0" }, null, 2));
|
|
79
|
+
});
|
|
80
|
+
server.registerTool("list_tools", {
|
|
81
|
+
title: "List tools",
|
|
82
|
+
description: "List all available tools on this server.",
|
|
83
|
+
inputSchema: z.object({}),
|
|
84
|
+
annotations: READ_ONLY,
|
|
85
|
+
}, async () => {
|
|
86
|
+
return text("See the tools/list response for the full tool list.");
|
|
87
|
+
});
|
|
88
|
+
server.registerTool("echo", {
|
|
89
|
+
title: "Echo",
|
|
90
|
+
description: "Echo back the provided text.",
|
|
91
|
+
inputSchema: z.object({ text: z.string().describe("Text to echo.") }),
|
|
92
|
+
annotations: READ_ONLY,
|
|
93
|
+
}, async (args) => {
|
|
94
|
+
return text(String(args?.text ?? ""));
|
|
95
|
+
});
|
|
96
|
+
server.registerTool("timestamp", {
|
|
97
|
+
title: "Timestamp",
|
|
98
|
+
description: "Get the current UTC timestamp.",
|
|
99
|
+
inputSchema: z.object({}),
|
|
100
|
+
annotations: READ_ONLY,
|
|
101
|
+
}, async () => {
|
|
102
|
+
return text(new Date().toISOString());
|
|
103
|
+
});
|
|
104
|
+
server.registerTool("ping", {
|
|
105
|
+
title: "Ping",
|
|
106
|
+
description: "Ping the server to check connectivity.",
|
|
107
|
+
inputSchema: z.object({}),
|
|
108
|
+
annotations: READ_ONLY,
|
|
109
|
+
}, async () => {
|
|
110
|
+
return text("pong");
|
|
111
|
+
});
|
|
37
112
|
return server;
|
|
38
113
|
}
|
package/package.json
CHANGED