@cyanheads/pubmed-mcp-server 2.9.9 → 2.10.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/AGENTS.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.md +19 -4
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_text.d.ts +22 -0
- package/dist/mcp-server/tools/definitions/_text.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/_text.js +32 -0
- package/dist/mcp-server/tools/definitions/_text.js.map +1 -0
- package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts +35 -0
- package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js +634 -123
- package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts +87 -0
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js +195 -0
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts +1 -0
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js +29 -8
- package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js.map +1 -1
- package/dist/services/europe-pmc/api-client.d.ts +14 -1
- package/dist/services/europe-pmc/api-client.d.ts.map +1 -1
- package/dist/services/europe-pmc/api-client.js +21 -25
- package/dist/services/europe-pmc/api-client.js.map +1 -1
- package/dist/services/europe-pmc/europe-pmc-service.d.ts +21 -7
- package/dist/services/europe-pmc/europe-pmc-service.d.ts.map +1 -1
- package/dist/services/europe-pmc/europe-pmc-service.js +39 -6
- package/dist/services/europe-pmc/europe-pmc-service.js.map +1 -1
- package/dist/services/europe-pmc/types.d.ts +9 -0
- package/dist/services/europe-pmc/types.d.ts.map +1 -1
- package/dist/services/openalex/api-client.d.ts +15 -1
- package/dist/services/openalex/api-client.d.ts.map +1 -1
- package/dist/services/openalex/api-client.js +21 -24
- package/dist/services/openalex/api-client.js.map +1 -1
- package/package.json +1 -1
- package/server.json +3 -3
|
@@ -4,12 +4,20 @@
|
|
|
4
4
|
* calls. Retry logic lives in `OpenAlexService`.
|
|
5
5
|
* @module src/services/openalex/api-client
|
|
6
6
|
*/
|
|
7
|
-
import { McpError, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
8
|
-
import { fetchWithTimeout,
|
|
7
|
+
import { JsonRpcErrorCode, McpError, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
8
|
+
import { fetchWithTimeout, logger, requestContextService } from '@cyanheads/mcp-ts-core/utils';
|
|
9
9
|
import { recoveryFor } from '../../services/error-contracts.js';
|
|
10
10
|
import { OPENALEX_API_BASE } from './types.js';
|
|
11
11
|
const USER_AGENT = 'pubmed-mcp-server (+https://github.com/cyanheads/pubmed-mcp-server)';
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Low-level HTTP client for OpenAlex. Single-attempt — retries upstream.
|
|
14
|
+
*
|
|
15
|
+
* Every method here resolves only on HTTP 2xx: `fetchWithTimeout` throws a
|
|
16
|
+
* status-mapped `McpError` for any non-2xx rather than returning the failing
|
|
17
|
+
* `Response`, so a `!response.ok` check after the call can never run. A status
|
|
18
|
+
* that needs graceful handling is converted in the catch block by inspecting
|
|
19
|
+
* `error.code` — see `getWorkByPmid`'s 404 → `null`. (#90)
|
|
20
|
+
*/
|
|
13
21
|
export class OpenAlexApiClient {
|
|
14
22
|
config;
|
|
15
23
|
constructor(config) {
|
|
@@ -18,6 +26,12 @@ export class OpenAlexApiClient {
|
|
|
18
26
|
/**
|
|
19
27
|
* Fetch a single work by PMID. Returns the work record (with related_works
|
|
20
28
|
* and referenced_works populated) or null when the PMID is unknown.
|
|
29
|
+
*
|
|
30
|
+
* `fetchWithTimeout` throws a status-mapped `McpError` on any non-2xx rather
|
|
31
|
+
* than resolving with the `Response` (`expectedStatuses` only lowers the log
|
|
32
|
+
* severity), so a PMID OpenAlex doesn't index arrives here as
|
|
33
|
+
* `McpError(NotFound)` and must be converted in the catch block. Every other
|
|
34
|
+
* failure keeps throwing. (#90)
|
|
21
35
|
*/
|
|
22
36
|
async getWorkByPmid(pmid, signal) {
|
|
23
37
|
const params = new URLSearchParams({
|
|
@@ -39,19 +53,14 @@ export class OpenAlexApiClient {
|
|
|
39
53
|
});
|
|
40
54
|
}
|
|
41
55
|
catch (error) {
|
|
42
|
-
if (error instanceof McpError)
|
|
56
|
+
if (error instanceof McpError) {
|
|
57
|
+
if (error.code === JsonRpcErrorCode.NotFound)
|
|
58
|
+
return null;
|
|
43
59
|
throw error;
|
|
60
|
+
}
|
|
44
61
|
const msg = error instanceof Error ? error.message : String(error);
|
|
45
62
|
throw serviceUnavailable(`OpenAlex request failed: ${msg}`, { reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') }, { cause: error });
|
|
46
63
|
}
|
|
47
|
-
if (response.status === 404)
|
|
48
|
-
return null;
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
throw await httpErrorFromResponse(response, {
|
|
51
|
-
service: 'OpenAlex',
|
|
52
|
-
data: { url, reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') },
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
64
|
const text = await response.text();
|
|
56
65
|
try {
|
|
57
66
|
return JSON.parse(text);
|
|
@@ -114,12 +123,6 @@ export class OpenAlexApiClient {
|
|
|
114
123
|
const msg = error instanceof Error ? error.message : String(error);
|
|
115
124
|
throw serviceUnavailable(`OpenAlex request failed: ${msg}`, { reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') }, { cause: error });
|
|
116
125
|
}
|
|
117
|
-
if (!response.ok) {
|
|
118
|
-
throw await httpErrorFromResponse(response, {
|
|
119
|
-
service: 'OpenAlex',
|
|
120
|
-
data: { url, reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') },
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
126
|
const text = await response.text();
|
|
124
127
|
let parsed;
|
|
125
128
|
try {
|
|
@@ -155,12 +158,6 @@ export class OpenAlexApiClient {
|
|
|
155
158
|
const msg = error instanceof Error ? error.message : String(error);
|
|
156
159
|
throw serviceUnavailable(`OpenAlex request failed: ${msg}`, { reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') }, { cause: error });
|
|
157
160
|
}
|
|
158
|
-
if (!response.ok) {
|
|
159
|
-
throw await httpErrorFromResponse(response, {
|
|
160
|
-
service: 'OpenAlex',
|
|
161
|
-
data: { url, reason: 'openalex_unreachable', ...recoveryFor('openalex_unreachable') },
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
161
|
const text = await response.text();
|
|
165
162
|
let parsed;
|
|
166
163
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/services/openalex/api-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/services/openalex/api-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/pubmed-mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"mcpName": "io.github.cyanheads/pubmed-mcp-server",
|
|
5
5
|
"description": "Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms via MCP. STDIO or Streamable HTTP.",
|
|
6
6
|
"type": "module",
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/cyanheads/pubmed-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.10.0",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
20
20
|
"identifier": "@cyanheads/pubmed-mcp-server",
|
|
21
21
|
"runtimeHint": "bun",
|
|
22
|
-
"version": "2.
|
|
22
|
+
"version": "2.10.0",
|
|
23
23
|
"packageArguments": [
|
|
24
24
|
{
|
|
25
25
|
"type": "positional",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
67
67
|
"identifier": "@cyanheads/pubmed-mcp-server",
|
|
68
68
|
"runtimeHint": "bun",
|
|
69
|
-
"version": "2.
|
|
69
|
+
"version": "2.10.0",
|
|
70
70
|
"packageArguments": [
|
|
71
71
|
{
|
|
72
72
|
"type": "positional",
|