@cyanheads/pubmed-mcp-server 1.2.4 → 1.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.
- package/README.md +2 -2
- package/dist/config/index.d.ts +13 -52
- package/dist/config/index.js +51 -222
- package/dist/mcp-server/server.d.ts +0 -5
- package/dist/mcp-server/server.js +18 -34
- package/dist/mcp-server/tools/fetchPubMedContent/logic.js +2 -2
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/citationFormatter.js +2 -2
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/elinkHandler.js +3 -3
- package/dist/mcp-server/tools/searchPubMedArticles/logic.js +2 -2
- package/dist/mcp-server/transports/auth/authFactory.d.ts +10 -0
- package/dist/mcp-server/transports/auth/authFactory.js +41 -0
- package/dist/mcp-server/transports/auth/authMiddleware.d.ts +19 -0
- package/dist/mcp-server/transports/auth/authMiddleware.js +57 -0
- package/dist/mcp-server/transports/auth/index.d.ts +8 -5
- package/dist/mcp-server/transports/auth/index.js +6 -4
- package/dist/mcp-server/transports/auth/{core → lib}/authTypes.d.ts +0 -5
- package/dist/mcp-server/transports/auth/lib/authTypes.js +8 -0
- package/dist/mcp-server/transports/auth/{core → lib}/authUtils.js +21 -14
- package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts +17 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.js +1 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts +7 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js +112 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts +7 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js +101 -0
- package/dist/mcp-server/transports/core/baseTransportManager.d.ts +17 -0
- package/dist/mcp-server/transports/core/baseTransportManager.js +18 -0
- package/dist/mcp-server/transports/core/honoNodeBridge.d.ts +23 -0
- package/dist/mcp-server/transports/core/honoNodeBridge.js +51 -0
- package/dist/mcp-server/transports/core/statefulTransportManager.d.ts +31 -0
- package/dist/mcp-server/transports/core/statefulTransportManager.js +233 -0
- package/dist/mcp-server/transports/core/statelessTransportManager.d.ts +20 -0
- package/dist/mcp-server/transports/core/statelessTransportManager.js +92 -0
- package/dist/mcp-server/transports/core/transportTypes.d.ts +68 -0
- package/dist/mcp-server/transports/core/transportTypes.js +5 -0
- package/dist/mcp-server/transports/{httpErrorHandler.d.ts → http/httpErrorHandler.d.ts} +4 -9
- package/dist/mcp-server/transports/{httpErrorHandler.js → http/httpErrorHandler.js} +33 -8
- package/dist/mcp-server/transports/http/httpTransport.d.ts +22 -0
- package/dist/mcp-server/transports/http/httpTransport.js +251 -0
- package/dist/mcp-server/transports/http/httpTypes.d.ts +16 -0
- package/dist/mcp-server/transports/http/httpTypes.js +5 -0
- package/dist/mcp-server/transports/http/index.d.ts +7 -0
- package/dist/mcp-server/transports/http/index.js +6 -0
- package/dist/mcp-server/transports/http/mcpTransportMiddleware.d.ts +25 -0
- package/dist/mcp-server/transports/http/mcpTransportMiddleware.js +63 -0
- package/dist/mcp-server/transports/stdio/index.d.ts +5 -0
- package/dist/mcp-server/transports/stdio/index.js +5 -0
- package/dist/mcp-server/transports/{stdioTransport.d.ts → stdio/stdioTransport.d.ts} +2 -2
- package/dist/mcp-server/transports/{stdioTransport.js → stdio/stdioTransport.js} +10 -5
- package/dist/services/NCBI/{ncbiConstants.d.ts → core/ncbiConstants.d.ts} +1 -1
- package/dist/services/NCBI/{ncbiConstants.js → core/ncbiConstants.js} +1 -1
- package/dist/services/NCBI/{ncbiCoreApiClient.d.ts → core/ncbiCoreApiClient.d.ts} +2 -2
- package/dist/services/NCBI/{ncbiCoreApiClient.js → core/ncbiCoreApiClient.js} +4 -4
- package/dist/services/NCBI/{ncbiRequestQueueManager.d.ts → core/ncbiRequestQueueManager.d.ts} +2 -2
- package/dist/services/NCBI/{ncbiRequestQueueManager.js → core/ncbiRequestQueueManager.js} +3 -3
- package/dist/services/NCBI/{ncbiResponseHandler.d.ts → core/ncbiResponseHandler.d.ts} +2 -2
- package/dist/services/NCBI/{ncbiResponseHandler.js → core/ncbiResponseHandler.js} +3 -3
- package/dist/services/NCBI/{ncbiService.d.ts → core/ncbiService.d.ts} +3 -3
- package/dist/services/NCBI/{ncbiService.js → core/ncbiService.js} +2 -2
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/eSummaryResultParser.d.ts +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/eSummaryResultParser.js +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/index.d.ts +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/index.js +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/pubmedArticleStructureParser.d.ts +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/pubmedArticleStructureParser.js +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/xmlGenericHelpers.d.ts +1 -1
- package/dist/{utils/parsing/ncbi-parsing → services/NCBI/parsing}/xmlGenericHelpers.js +1 -1
- package/dist/types-global/errors.d.ts +2 -0
- package/dist/types-global/errors.js +2 -0
- package/dist/utils/internal/errorHandler.js +1 -1
- package/dist/utils/internal/logger.d.ts +13 -1
- package/dist/utils/internal/logger.js +43 -9
- package/dist/utils/network/fetchWithTimeout.d.ts +21 -0
- package/dist/utils/network/fetchWithTimeout.js +59 -0
- package/dist/utils/network/index.d.ts +6 -0
- package/dist/utils/network/index.js +5 -0
- package/dist/utils/scheduling/index.d.ts +6 -0
- package/dist/utils/scheduling/index.js +6 -0
- package/dist/utils/scheduling/scheduler.d.ts +72 -0
- package/dist/utils/scheduling/scheduler.js +150 -0
- package/dist/utils/security/sanitization.js +35 -18
- package/package.json +9 -7
- package/dist/mcp-server/transports/auth/core/authTypes.js +0 -5
- package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.d.ts +0 -27
- package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.js +0 -149
- package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.d.ts +0 -20
- package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.js +0 -124
- package/dist/mcp-server/transports/httpTransport.d.ts +0 -21
- package/dist/mcp-server/transports/httpTransport.js +0 -208
- /package/dist/mcp-server/transports/auth/{core → lib}/authContext.d.ts +0 -0
- /package/dist/mcp-server/transports/auth/{core → lib}/authContext.js +0 -0
- /package/dist/mcp-server/transports/auth/{core → lib}/authUtils.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# PubMed MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.typescriptlang.org/)
|
|
4
|
-
[](https://modelcontextprotocol.io/)
|
|
5
|
+
[](./CHANGELOG.md)
|
|
6
6
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
7
|
[](https://github.com/cyanheads/pubmed-mcp-server/issues)
|
|
8
8
|
[](https://github.com/cyanheads/pubmed-mcp-server)
|
package/dist/config/index.d.ts
CHANGED
|
@@ -4,78 +4,39 @@
|
|
|
4
4
|
* environment variables and `package.json`. It uses Zod for schema validation
|
|
5
5
|
* to ensure type safety and correctness of configuration parameters.
|
|
6
6
|
*
|
|
7
|
-
* Key responsibilities:
|
|
8
|
-
* - Load environment variables from a `.env` file.
|
|
9
|
-
* - Read `package.json` for default server name and version.
|
|
10
|
-
* - Define a Zod schema for all expected environment variables.
|
|
11
|
-
* - Validate environment variables against the schema.
|
|
12
|
-
* - Construct and export a comprehensive `config` object.
|
|
13
|
-
* - Export individual configuration values like `logLevel` and `environment` for convenience.
|
|
14
|
-
*
|
|
15
7
|
* @module src/config/index
|
|
16
8
|
*/
|
|
17
|
-
/**
|
|
18
|
-
* Main application configuration object.
|
|
19
|
-
* Aggregates settings from validated environment variables and `package.json`.
|
|
20
|
-
*/
|
|
21
9
|
export declare const config: {
|
|
22
|
-
|
|
10
|
+
pkg: {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
};
|
|
23
14
|
mcpServerName: string;
|
|
24
|
-
/** MCP server version. Env `MCP_SERVER_VERSION` > `package.json` version > "0.0.0". */
|
|
25
15
|
mcpServerVersion: string;
|
|
26
|
-
/** Logging level. From `MCP_LOG_LEVEL` env var. Default: "debug". */
|
|
27
16
|
logLevel: string;
|
|
28
|
-
/** Defines the logging output mode ('file' or 'stdout'). From `LOG_OUTPUT_MODE`. */
|
|
29
|
-
logOutputMode: "file" | "stdout";
|
|
30
|
-
/** Absolute path to the logs directory (if logOutputMode is 'file'). From `LOGS_DIR`. */
|
|
31
17
|
logsPath: string | null;
|
|
32
|
-
/** Runtime environment. From `NODE_ENV` env var. Default: "development". */
|
|
33
18
|
environment: string;
|
|
34
|
-
/** MCP transport type ('stdio' or 'http'). From `MCP_TRANSPORT_TYPE` env var. Default: "stdio". */
|
|
35
19
|
mcpTransportType: "stdio" | "http";
|
|
36
|
-
|
|
20
|
+
mcpSessionMode: "stateless" | "stateful" | "auto";
|
|
37
21
|
mcpHttpPort: number;
|
|
38
|
-
/** HTTP server host (if http transport). From `MCP_HTTP_HOST` env var. Default: "127.0.0.1". */
|
|
39
22
|
mcpHttpHost: string;
|
|
40
|
-
|
|
23
|
+
mcpHttpEndpointPath: string;
|
|
24
|
+
mcpHttpMaxPortRetries: number;
|
|
25
|
+
mcpHttpPortRetryDelayMs: number;
|
|
26
|
+
mcpStatefulSessionStaleTimeoutMs: number;
|
|
41
27
|
mcpAllowedOrigins: string[] | undefined;
|
|
42
|
-
|
|
28
|
+
mcpAuthMode: "jwt" | "oauth" | "none";
|
|
43
29
|
mcpAuthSecretKey: string | undefined;
|
|
44
|
-
/** Auth mode ('jwt' or 'oauth'). From `MCP_AUTH_MODE`. */
|
|
45
|
-
mcpAuthMode: "jwt" | "oauth";
|
|
46
|
-
/** OAuth Issuer URL. From `OAUTH_ISSUER_URL`. */
|
|
47
30
|
oauthIssuerUrl: string | undefined;
|
|
48
|
-
/** OAuth Audience. From `OAUTH_AUDIENCE`. */
|
|
49
|
-
oauthAudience: string | undefined;
|
|
50
|
-
/** OAuth JWKS URI. From `OAUTH_JWKS_URI`. */
|
|
51
31
|
oauthJwksUri: string | undefined;
|
|
52
|
-
|
|
32
|
+
oauthAudience: string | undefined;
|
|
33
|
+
devMcpClientId: string | undefined;
|
|
34
|
+
devMcpScopes: string[] | undefined;
|
|
53
35
|
ncbiApiKey: string | undefined;
|
|
54
|
-
/** NCBI Tool Identifier. From `NCBI_TOOL_IDENTIFIER`. Defaults to server name/version. */
|
|
55
36
|
ncbiToolIdentifier: string;
|
|
56
|
-
/** NCBI Admin Email. From `NCBI_ADMIN_EMAIL`. */
|
|
57
37
|
ncbiAdminEmail: string | undefined;
|
|
58
|
-
/** NCBI Request Delay in MS. From `NCBI_REQUEST_DELAY_MS`. Dynamically set based on API key presence. */
|
|
59
38
|
ncbiRequestDelayMs: number;
|
|
60
|
-
/** NCBI Max Retries. From `NCBI_MAX_RETRIES`. */
|
|
61
39
|
ncbiMaxRetries: number;
|
|
62
|
-
/** OAuth Proxy configurations. Undefined if no related env vars are set. */
|
|
63
|
-
oauthProxy: {
|
|
64
|
-
authorizationUrl: string | undefined;
|
|
65
|
-
tokenUrl: string | undefined;
|
|
66
|
-
revocationUrl: string | undefined;
|
|
67
|
-
issuerUrl: string | undefined;
|
|
68
|
-
serviceDocumentationUrl: string | undefined;
|
|
69
|
-
defaultClientRedirectUris: string[] | undefined;
|
|
70
|
-
} | undefined;
|
|
71
40
|
};
|
|
72
|
-
/**
|
|
73
|
-
* Configured logging level for the application.
|
|
74
|
-
* Exported for convenience.
|
|
75
|
-
*/
|
|
76
41
|
export declare const logLevel: string;
|
|
77
|
-
/**
|
|
78
|
-
* Configured runtime environment ("development", "production", etc.).
|
|
79
|
-
* Exported for convenience.
|
|
80
|
-
*/
|
|
81
42
|
export declare const environment: string;
|
package/dist/config/index.js
CHANGED
|
@@ -4,14 +4,6 @@
|
|
|
4
4
|
* environment variables and `package.json`. It uses Zod for schema validation
|
|
5
5
|
* to ensure type safety and correctness of configuration parameters.
|
|
6
6
|
*
|
|
7
|
-
* Key responsibilities:
|
|
8
|
-
* - Load environment variables from a `.env` file.
|
|
9
|
-
* - Read `package.json` for default server name and version.
|
|
10
|
-
* - Define a Zod schema for all expected environment variables.
|
|
11
|
-
* - Validate environment variables against the schema.
|
|
12
|
-
* - Construct and export a comprehensive `config` object.
|
|
13
|
-
* - Export individual configuration values like `logLevel` and `environment` for convenience.
|
|
14
|
-
*
|
|
15
7
|
* @module src/config/index
|
|
16
8
|
*/
|
|
17
9
|
import dotenv from "dotenv";
|
|
@@ -21,11 +13,6 @@ import { fileURLToPath } from "url";
|
|
|
21
13
|
import { z } from "zod";
|
|
22
14
|
dotenv.config();
|
|
23
15
|
// --- Determine Project Root ---
|
|
24
|
-
/**
|
|
25
|
-
* Finds the project root directory by searching upwards for package.json.
|
|
26
|
-
* @param startDir The directory to start searching from.
|
|
27
|
-
* @returns The absolute path to the project root, or throws an error if not found.
|
|
28
|
-
*/
|
|
29
16
|
const findProjectRoot = (startDir) => {
|
|
30
17
|
let currentDir = startDir;
|
|
31
18
|
while (true) {
|
|
@@ -35,7 +22,6 @@ const findProjectRoot = (startDir) => {
|
|
|
35
22
|
}
|
|
36
23
|
const parentDir = dirname(currentDir);
|
|
37
24
|
if (parentDir === currentDir) {
|
|
38
|
-
// Reached the root of the filesystem without finding package.json
|
|
39
25
|
throw new Error(`Could not find project root (package.json) starting from ${startDir}`);
|
|
40
26
|
}
|
|
41
27
|
currentDir = parentDir;
|
|
@@ -43,21 +29,17 @@ const findProjectRoot = (startDir) => {
|
|
|
43
29
|
};
|
|
44
30
|
let projectRoot;
|
|
45
31
|
try {
|
|
46
|
-
// For ESM, __dirname is not available directly.
|
|
47
|
-
// import.meta.url gives the URL of the current module.
|
|
48
32
|
const currentModuleDir = dirname(fileURLToPath(import.meta.url));
|
|
49
33
|
projectRoot = findProjectRoot(currentModuleDir);
|
|
50
34
|
}
|
|
51
35
|
catch (error) {
|
|
52
36
|
console.error(`FATAL: Error determining project root: ${error.message}`);
|
|
53
|
-
// Fallback to process.cwd() if project root cannot be determined.
|
|
54
|
-
// This might happen in unusual execution environments.
|
|
55
37
|
projectRoot = process.cwd();
|
|
56
38
|
console.warn(`Warning: Using process.cwd() (${projectRoot}) as fallback project root.`);
|
|
57
39
|
}
|
|
58
40
|
// --- End Determine Project Root ---
|
|
59
|
-
const pkgPath = join(projectRoot, "package.json");
|
|
60
|
-
let pkg = { name: "mcp-
|
|
41
|
+
const pkgPath = join(projectRoot, "package.json");
|
|
42
|
+
let pkg = { name: "pubmed-mcp-server", version: "0.0.0" };
|
|
61
43
|
try {
|
|
62
44
|
pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
63
45
|
}
|
|
@@ -66,90 +48,42 @@ catch (error) {
|
|
|
66
48
|
console.error("Warning: Could not read package.json for default config values. Using hardcoded defaults.", error);
|
|
67
49
|
}
|
|
68
50
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Zod schema for validating environment variables.
|
|
71
|
-
* Provides type safety, validation, defaults, and clear error messages.
|
|
72
|
-
* @private
|
|
73
|
-
*/
|
|
74
51
|
const EnvSchema = z
|
|
75
52
|
.object({
|
|
76
|
-
|
|
53
|
+
// Core Server Config
|
|
77
54
|
MCP_SERVER_NAME: z.string().optional(),
|
|
78
|
-
/** Optional. The version of the MCP server. Defaults to `package.json` version. */
|
|
79
55
|
MCP_SERVER_VERSION: z.string().optional(),
|
|
80
|
-
|
|
56
|
+
NODE_ENV: z.string().default("development"),
|
|
57
|
+
// Logging
|
|
81
58
|
MCP_LOG_LEVEL: z.string().default("debug"),
|
|
82
|
-
/** Directory for log files. Defaults to "logs" in project root. */
|
|
83
59
|
LOGS_DIR: z.string().default(path.join(projectRoot, "logs")),
|
|
84
|
-
|
|
85
|
-
LOG_OUTPUT_MODE: z.enum(["file", "stdout"]).default("file"),
|
|
86
|
-
/** Runtime environment (e.g., "development", "production"). Default: "development". */
|
|
87
|
-
NODE_ENV: z.string().default("development"),
|
|
88
|
-
/** MCP communication transport ("stdio" or "http"). Default: "stdio". */
|
|
60
|
+
// Transport
|
|
89
61
|
MCP_TRANSPORT_TYPE: z.enum(["stdio", "http"]).default("stdio"),
|
|
90
|
-
|
|
62
|
+
MCP_SESSION_MODE: z.enum(["stateless", "stateful", "auto"]).default("auto"),
|
|
91
63
|
MCP_HTTP_PORT: z.coerce.number().int().positive().default(3010),
|
|
92
|
-
/** HTTP server host (if MCP_TRANSPORT_TYPE is "http"). Default: "127.0.0.1". */
|
|
93
64
|
MCP_HTTP_HOST: z.string().default("127.0.0.1"),
|
|
94
|
-
|
|
65
|
+
MCP_HTTP_ENDPOINT_PATH: z.string().default("/mcp"),
|
|
66
|
+
MCP_HTTP_MAX_PORT_RETRIES: z.coerce.number().int().nonnegative().default(15),
|
|
67
|
+
MCP_HTTP_PORT_RETRY_DELAY_MS: z.coerce.number().int().nonnegative().default(50),
|
|
68
|
+
MCP_STATEFUL_SESSION_STALE_TIMEOUT_MS: z.coerce.number().int().positive().default(1800000),
|
|
95
69
|
MCP_ALLOWED_ORIGINS: z.string().optional(),
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.min(32, "MCP_AUTH_SECRET_KEY must be at least 32 characters long for security reasons.")
|
|
100
|
-
.optional(),
|
|
101
|
-
/** Authentication mode ('jwt' or 'oauth'). Default: 'jwt'. */
|
|
102
|
-
MCP_AUTH_MODE: z.enum(["jwt", "oauth"]).default("jwt"),
|
|
103
|
-
/** OAuth: The expected issuer of the JWT. */
|
|
70
|
+
// Authentication
|
|
71
|
+
MCP_AUTH_MODE: z.enum(["jwt", "oauth", "none"]).default("none"),
|
|
72
|
+
MCP_AUTH_SECRET_KEY: z.string().min(32, "MCP_AUTH_SECRET_KEY must be at least 32 characters long.").optional(),
|
|
104
73
|
OAUTH_ISSUER_URL: z.string().url().optional(),
|
|
105
|
-
/** OAuth: The expected audience of the JWT. */
|
|
106
|
-
OAUTH_AUDIENCE: z.string().optional(),
|
|
107
|
-
/** OAuth: The URI of the JWKS endpoint. */
|
|
108
74
|
OAUTH_JWKS_URI: z.string().url().optional(),
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
/** Optional. OAuth provider token endpoint URL. */
|
|
115
|
-
OAUTH_PROXY_TOKEN_URL: z
|
|
116
|
-
.string()
|
|
117
|
-
.url("OAUTH_PROXY_TOKEN_URL must be a valid URL.")
|
|
118
|
-
.optional(),
|
|
119
|
-
/** Optional. OAuth provider revocation endpoint URL. */
|
|
120
|
-
OAUTH_PROXY_REVOCATION_URL: z
|
|
121
|
-
.string()
|
|
122
|
-
.url("OAUTH_PROXY_REVOCATION_URL must be a valid URL.")
|
|
123
|
-
.optional(),
|
|
124
|
-
/** Optional. OAuth provider issuer URL. */
|
|
125
|
-
OAUTH_PROXY_ISSUER_URL: z
|
|
126
|
-
.string()
|
|
127
|
-
.url("OAUTH_PROXY_ISSUER_URL must be a valid URL.")
|
|
128
|
-
.optional(),
|
|
129
|
-
/** Optional. OAuth service documentation URL. */
|
|
130
|
-
OAUTH_PROXY_SERVICE_DOCUMENTATION_URL: z
|
|
131
|
-
.string()
|
|
132
|
-
.url("OAUTH_PROXY_SERVICE_DOCUMENTATION_URL must be a valid URL.")
|
|
133
|
-
.optional(),
|
|
134
|
-
/** Optional. Comma-separated default OAuth client redirect URIs. */
|
|
135
|
-
OAUTH_PROXY_DEFAULT_CLIENT_REDIRECT_URIS: z.string().optional(),
|
|
136
|
-
// NCBI E-utilities Configuration
|
|
137
|
-
/** NCBI API Key. Optional, but highly recommended for higher rate limits. */
|
|
75
|
+
OAUTH_AUDIENCE: z.string().optional(),
|
|
76
|
+
// Dev mode JWT
|
|
77
|
+
DEV_MCP_CLIENT_ID: z.string().optional(),
|
|
78
|
+
DEV_MCP_SCOPES: z.string().optional(),
|
|
79
|
+
// NCBI E-utilities
|
|
138
80
|
NCBI_API_KEY: z.string().optional(),
|
|
139
|
-
/** Tool identifier sent to NCBI. Defaults to MCP_SERVER_NAME/MCP_SERVER_VERSION. */
|
|
140
81
|
NCBI_TOOL_IDENTIFIER: z.string().optional(),
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.string()
|
|
144
|
-
.email("NCBI_ADMIN_EMAIL must be a valid email address.")
|
|
145
|
-
.optional(),
|
|
146
|
-
/** Milliseconds to wait between NCBI requests. Default: 100 (for API key), 334 (without API key). */
|
|
147
|
-
NCBI_REQUEST_DELAY_MS: z.coerce.number().int().positive().optional(), // Default will be set conditionally
|
|
148
|
-
/** Maximum number of retries for failed NCBI requests. Default: 3. */
|
|
82
|
+
NCBI_ADMIN_EMAIL: z.string().email().optional(),
|
|
83
|
+
NCBI_REQUEST_DELAY_MS: z.coerce.number().int().positive().optional(),
|
|
149
84
|
NCBI_MAX_RETRIES: z.coerce.number().int().nonnegative().default(3),
|
|
150
85
|
})
|
|
151
86
|
.superRefine((data, ctx) => {
|
|
152
|
-
// Rule 1: MCP_AUTH_SECRET_KEY is required for http transport in production with jwt auth
|
|
153
87
|
if (data.NODE_ENV === "production" &&
|
|
154
88
|
data.MCP_TRANSPORT_TYPE === "http" &&
|
|
155
89
|
data.MCP_AUTH_MODE === "jwt" &&
|
|
@@ -157,184 +91,79 @@ const EnvSchema = z
|
|
|
157
91
|
ctx.addIssue({
|
|
158
92
|
code: z.ZodIssueCode.custom,
|
|
159
93
|
path: ["MCP_AUTH_SECRET_KEY"],
|
|
160
|
-
message: "MCP_AUTH_SECRET_KEY is required for 'jwt' auth with 'http' transport
|
|
94
|
+
message: "MCP_AUTH_SECRET_KEY is required for 'jwt' auth in production with 'http' transport.",
|
|
161
95
|
});
|
|
162
96
|
}
|
|
163
|
-
// Rule 2: Core OAuth variables are required when MCP_AUTH_MODE is 'oauth'
|
|
164
97
|
if (data.MCP_AUTH_MODE === "oauth") {
|
|
165
98
|
if (!data.OAUTH_ISSUER_URL) {
|
|
166
|
-
ctx.addIssue({
|
|
167
|
-
code: z.ZodIssueCode.custom,
|
|
168
|
-
path: ["OAUTH_ISSUER_URL"],
|
|
169
|
-
message: "OAUTH_ISSUER_URL is required when MCP_AUTH_MODE is 'oauth'.",
|
|
170
|
-
});
|
|
99
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["OAUTH_ISSUER_URL"], message: "OAUTH_ISSUER_URL is required for 'oauth' mode." });
|
|
171
100
|
}
|
|
172
101
|
if (!data.OAUTH_AUDIENCE) {
|
|
173
|
-
ctx.addIssue({
|
|
174
|
-
code: z.ZodIssueCode.custom,
|
|
175
|
-
path: ["OAUTH_AUDIENCE"],
|
|
176
|
-
message: "OAUTH_AUDIENCE is required when MCP_AUTH_MODE is 'oauth'.",
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
if (!data.OAUTH_JWKS_URI) {
|
|
180
|
-
ctx.addIssue({
|
|
181
|
-
code: z.ZodIssueCode.custom,
|
|
182
|
-
path: ["OAUTH_JWKS_URI"],
|
|
183
|
-
message: "OAUTH_JWKS_URI is required when MCP_AUTH_MODE is 'oauth'.",
|
|
184
|
-
});
|
|
102
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["OAUTH_AUDIENCE"], message: "OAUTH_AUDIENCE is required for 'oauth' mode." });
|
|
185
103
|
}
|
|
186
104
|
}
|
|
187
105
|
});
|
|
188
106
|
const parsedEnv = EnvSchema.safeParse(process.env);
|
|
189
107
|
if (!parsedEnv.success) {
|
|
190
108
|
if (process.stdout.isTTY) {
|
|
191
|
-
console.error("❌ Invalid environment variables
|
|
109
|
+
console.error("❌ Invalid environment variables:", parsedEnv.error.flatten().fieldErrors);
|
|
192
110
|
}
|
|
193
|
-
// Consider throwing an error in production for critical misconfigurations.
|
|
194
111
|
}
|
|
195
112
|
const env = parsedEnv.success ? parsedEnv.data : EnvSchema.parse({});
|
|
196
|
-
// --- Directory Ensurance Function ---
|
|
197
|
-
/**
|
|
198
|
-
* Ensures a directory exists and is within the project root.
|
|
199
|
-
* @param dirPath The desired path for the directory (can be relative or absolute).
|
|
200
|
-
* @param rootDir The root directory of the project to contain the directory.
|
|
201
|
-
* @param dirName The name of the directory type for logging (e.g., "logs").
|
|
202
|
-
* @returns The validated, absolute path to the directory, or null if invalid.
|
|
203
|
-
*/
|
|
204
113
|
const ensureDirectory = (dirPath, rootDir, dirName) => {
|
|
205
|
-
const resolvedDirPath = path.isAbsolute(dirPath)
|
|
206
|
-
|
|
207
|
-
: path.resolve(rootDir, dirPath);
|
|
208
|
-
// Ensure the resolved path is within the project root boundary
|
|
209
|
-
if (!resolvedDirPath.startsWith(rootDir + path.sep) &&
|
|
210
|
-
resolvedDirPath !== rootDir) {
|
|
114
|
+
const resolvedDirPath = path.isAbsolute(dirPath) ? dirPath : path.resolve(rootDir, dirPath);
|
|
115
|
+
if (!resolvedDirPath.startsWith(rootDir)) {
|
|
211
116
|
if (process.stdout.isTTY) {
|
|
212
|
-
console.error(`Error: ${dirName} path "${dirPath}"
|
|
117
|
+
console.error(`Error: ${dirName} path "${dirPath}" is outside the project boundary "${rootDir}".`);
|
|
213
118
|
}
|
|
214
119
|
return null;
|
|
215
120
|
}
|
|
216
|
-
|
|
217
|
-
|
|
121
|
+
try {
|
|
122
|
+
if (!existsSync(resolvedDirPath)) {
|
|
218
123
|
mkdirSync(resolvedDirPath, { recursive: true });
|
|
219
|
-
if (process.stdout.isTTY) {
|
|
220
|
-
console.log(`Created ${dirName} directory: ${resolvedDirPath}`);
|
|
221
|
-
}
|
|
222
124
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
console.error(`Error creating ${dirName} directory at ${resolvedDirPath}: ${errorMessage}`);
|
|
227
|
-
}
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
try {
|
|
233
|
-
const stats = statSync(resolvedDirPath);
|
|
234
|
-
if (!stats.isDirectory()) {
|
|
235
|
-
if (process.stdout.isTTY) {
|
|
236
|
-
console.error(`Error: ${dirName} path ${resolvedDirPath} exists but is not a directory.`);
|
|
237
|
-
}
|
|
125
|
+
else {
|
|
126
|
+
if (!statSync(resolvedDirPath).isDirectory()) {
|
|
127
|
+
console.error(`Error: ${dirName} path ${resolvedDirPath} exists but is not a directory.`);
|
|
238
128
|
return null;
|
|
239
129
|
}
|
|
240
130
|
}
|
|
241
|
-
|
|
242
|
-
if (process.stdout.isTTY) {
|
|
243
|
-
console.error(`Error accessing ${dirName} path ${resolvedDirPath}: ${statError.message}`);
|
|
244
|
-
}
|
|
245
|
-
return null;
|
|
246
|
-
}
|
|
131
|
+
return resolvedDirPath;
|
|
247
132
|
}
|
|
248
|
-
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
// --- Logs Directory Handling ---
|
|
252
|
-
let validatedLogsPath = null;
|
|
253
|
-
if (env.LOG_OUTPUT_MODE === "file") {
|
|
254
|
-
validatedLogsPath = ensureDirectory(env.LOGS_DIR, projectRoot, "logs");
|
|
255
|
-
if (!validatedLogsPath) {
|
|
256
|
-
if (process.stdout.isTTY) {
|
|
257
|
-
console.error("FATAL: Log mode is 'file' but logs directory is invalid or could not be created. Please check LOGS_DIR, permissions, and path. Exiting.");
|
|
258
|
-
}
|
|
259
|
-
process.exit(1); // Exit if file logging is configured but directory is not usable
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error(`Error ensuring ${dirName} directory at ${resolvedDirPath}: ${error.message}`);
|
|
135
|
+
return null;
|
|
260
136
|
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Main application configuration object.
|
|
265
|
-
* Aggregates settings from validated environment variables and `package.json`.
|
|
266
|
-
*/
|
|
137
|
+
};
|
|
138
|
+
const validatedLogsPath = ensureDirectory(env.LOGS_DIR, projectRoot, "logs");
|
|
267
139
|
export const config = {
|
|
268
|
-
|
|
140
|
+
pkg,
|
|
269
141
|
mcpServerName: env.MCP_SERVER_NAME || pkg.name,
|
|
270
|
-
/** MCP server version. Env `MCP_SERVER_VERSION` > `package.json` version > "0.0.0". */
|
|
271
142
|
mcpServerVersion: env.MCP_SERVER_VERSION || pkg.version,
|
|
272
|
-
/** Logging level. From `MCP_LOG_LEVEL` env var. Default: "debug". */
|
|
273
143
|
logLevel: env.MCP_LOG_LEVEL,
|
|
274
|
-
/** Defines the logging output mode ('file' or 'stdout'). From `LOG_OUTPUT_MODE`. */
|
|
275
|
-
logOutputMode: env.LOG_OUTPUT_MODE,
|
|
276
|
-
/** Absolute path to the logs directory (if logOutputMode is 'file'). From `LOGS_DIR`. */
|
|
277
144
|
logsPath: validatedLogsPath,
|
|
278
|
-
/** Runtime environment. From `NODE_ENV` env var. Default: "development". */
|
|
279
145
|
environment: env.NODE_ENV,
|
|
280
|
-
/** MCP transport type ('stdio' or 'http'). From `MCP_TRANSPORT_TYPE` env var. Default: "stdio". */
|
|
281
146
|
mcpTransportType: env.MCP_TRANSPORT_TYPE,
|
|
282
|
-
|
|
147
|
+
mcpSessionMode: env.MCP_SESSION_MODE,
|
|
283
148
|
mcpHttpPort: env.MCP_HTTP_PORT,
|
|
284
|
-
/** HTTP server host (if http transport). From `MCP_HTTP_HOST` env var. Default: "127.0.0.1". */
|
|
285
149
|
mcpHttpHost: env.MCP_HTTP_HOST,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
mcpAuthSecretKey: env.MCP_AUTH_SECRET_KEY,
|
|
292
|
-
/** Auth mode ('jwt' or 'oauth'). From `MCP_AUTH_MODE`. */
|
|
150
|
+
mcpHttpEndpointPath: env.MCP_HTTP_ENDPOINT_PATH,
|
|
151
|
+
mcpHttpMaxPortRetries: env.MCP_HTTP_MAX_PORT_RETRIES,
|
|
152
|
+
mcpHttpPortRetryDelayMs: env.MCP_HTTP_PORT_RETRY_DELAY_MS,
|
|
153
|
+
mcpStatefulSessionStaleTimeoutMs: env.MCP_STATEFUL_SESSION_STALE_TIMEOUT_MS,
|
|
154
|
+
mcpAllowedOrigins: env.MCP_ALLOWED_ORIGINS?.split(",").map((o) => o.trim()).filter(Boolean),
|
|
293
155
|
mcpAuthMode: env.MCP_AUTH_MODE,
|
|
294
|
-
|
|
156
|
+
mcpAuthSecretKey: env.MCP_AUTH_SECRET_KEY,
|
|
295
157
|
oauthIssuerUrl: env.OAUTH_ISSUER_URL,
|
|
296
|
-
/** OAuth Audience. From `OAUTH_AUDIENCE`. */
|
|
297
|
-
oauthAudience: env.OAUTH_AUDIENCE,
|
|
298
|
-
/** OAuth JWKS URI. From `OAUTH_JWKS_URI`. */
|
|
299
158
|
oauthJwksUri: env.OAUTH_JWKS_URI,
|
|
300
|
-
|
|
301
|
-
|
|
159
|
+
oauthAudience: env.OAUTH_AUDIENCE,
|
|
160
|
+
devMcpClientId: env.DEV_MCP_CLIENT_ID,
|
|
161
|
+
devMcpScopes: env.DEV_MCP_SCOPES?.split(",").map((s) => s.trim()),
|
|
302
162
|
ncbiApiKey: env.NCBI_API_KEY,
|
|
303
|
-
|
|
304
|
-
ncbiToolIdentifier: env.NCBI_TOOL_IDENTIFIER ||
|
|
305
|
-
`${env.MCP_SERVER_NAME || pkg.name}/${env.MCP_SERVER_VERSION || pkg.version}`,
|
|
306
|
-
/** NCBI Admin Email. From `NCBI_ADMIN_EMAIL`. */
|
|
163
|
+
ncbiToolIdentifier: env.NCBI_TOOL_IDENTIFIER || `${env.MCP_SERVER_NAME || pkg.name}/${env.MCP_SERVER_VERSION || pkg.version}`,
|
|
307
164
|
ncbiAdminEmail: env.NCBI_ADMIN_EMAIL,
|
|
308
|
-
/** NCBI Request Delay in MS. From `NCBI_REQUEST_DELAY_MS`. Dynamically set based on API key presence. */
|
|
309
165
|
ncbiRequestDelayMs: env.NCBI_REQUEST_DELAY_MS ?? (env.NCBI_API_KEY ? 100 : 334),
|
|
310
|
-
/** NCBI Max Retries. From `NCBI_MAX_RETRIES`. */
|
|
311
166
|
ncbiMaxRetries: env.NCBI_MAX_RETRIES,
|
|
312
|
-
/** OAuth Proxy configurations. Undefined if no related env vars are set. */
|
|
313
|
-
oauthProxy: env.OAUTH_PROXY_AUTHORIZATION_URL ||
|
|
314
|
-
env.OAUTH_PROXY_TOKEN_URL ||
|
|
315
|
-
env.OAUTH_PROXY_REVOCATION_URL ||
|
|
316
|
-
env.OAUTH_PROXY_ISSUER_URL ||
|
|
317
|
-
env.OAUTH_PROXY_SERVICE_DOCUMENTATION_URL ||
|
|
318
|
-
env.OAUTH_PROXY_DEFAULT_CLIENT_REDIRECT_URIS
|
|
319
|
-
? {
|
|
320
|
-
authorizationUrl: env.OAUTH_PROXY_AUTHORIZATION_URL,
|
|
321
|
-
tokenUrl: env.OAUTH_PROXY_TOKEN_URL,
|
|
322
|
-
revocationUrl: env.OAUTH_PROXY_REVOCATION_URL,
|
|
323
|
-
issuerUrl: env.OAUTH_PROXY_ISSUER_URL,
|
|
324
|
-
serviceDocumentationUrl: env.OAUTH_PROXY_SERVICE_DOCUMENTATION_URL,
|
|
325
|
-
defaultClientRedirectUris: env.OAUTH_PROXY_DEFAULT_CLIENT_REDIRECT_URIS?.split(",")
|
|
326
|
-
.map((uri) => uri.trim())
|
|
327
|
-
.filter(Boolean),
|
|
328
|
-
}
|
|
329
|
-
: undefined,
|
|
330
167
|
};
|
|
331
|
-
/**
|
|
332
|
-
* Configured logging level for the application.
|
|
333
|
-
* Exported for convenience.
|
|
334
|
-
*/
|
|
335
168
|
export const logLevel = config.logLevel;
|
|
336
|
-
/**
|
|
337
|
-
* Configured runtime environment ("development", "production", etc.).
|
|
338
|
-
* Exported for convenience.
|
|
339
|
-
*/
|
|
340
169
|
export const environment = config.environment;
|
|
@@ -7,16 +7,11 @@
|
|
|
7
7
|
* based on configuration.
|
|
8
8
|
* 4. Handles top-level error management during startup.
|
|
9
9
|
*
|
|
10
|
-
* MCP Specification References:
|
|
11
|
-
* - Lifecycle: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/lifecycle.mdx
|
|
12
|
-
* - Overview (Capabilities): https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/index.mdx
|
|
13
|
-
* - Transports: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/transports.mdx
|
|
14
10
|
* @module src/mcp-server/server
|
|
15
11
|
*/
|
|
16
12
|
import { ServerType } from "@hono/node-server";
|
|
17
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18
14
|
/**
|
|
19
15
|
* Main application entry point. Initializes and starts the MCP server.
|
|
20
|
-
* Orchestrates server startup, transport selection, and top-level error handling.
|
|
21
16
|
*/
|
|
22
17
|
export declare function initializeAndStartServer(): Promise<void | McpServer | ServerType>;
|
|
@@ -7,10 +7,6 @@
|
|
|
7
7
|
* based on configuration.
|
|
8
8
|
* 4. Handles top-level error management during startup.
|
|
9
9
|
*
|
|
10
|
-
* MCP Specification References:
|
|
11
|
-
* - Lifecycle: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/lifecycle.mdx
|
|
12
|
-
* - Overview (Capabilities): https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/index.mdx
|
|
13
|
-
* - Transports: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/transports.mdx
|
|
14
10
|
* @module src/mcp-server/server
|
|
15
11
|
*/
|
|
16
12
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -22,19 +18,11 @@ import { registerGeneratePubMedChartTool } from "./tools/generatePubMedChart/ind
|
|
|
22
18
|
import { registerGetPubMedArticleConnectionsTool } from "./tools/getPubMedArticleConnections/index.js";
|
|
23
19
|
import { registerPubMedResearchAgentTool } from "./tools/pubmedResearchAgent/index.js";
|
|
24
20
|
import { registerSearchPubMedArticlesTool } from "./tools/searchPubMedArticles/index.js";
|
|
25
|
-
import { startHttpTransport } from "./transports/
|
|
26
|
-
import {
|
|
21
|
+
import { startHttpTransport } from "./transports/http/index.js";
|
|
22
|
+
import { startStdioTransport } from "./transports/stdio/index.js";
|
|
27
23
|
/**
|
|
28
24
|
* Creates and configures a new instance of the `McpServer`.
|
|
29
25
|
*
|
|
30
|
-
* This function defines the server's identity and capabilities as presented
|
|
31
|
-
* to clients during MCP initialization.
|
|
32
|
-
*
|
|
33
|
-
* MCP Spec Relevance:
|
|
34
|
-
* - Server Identity (`serverInfo`): `name` and `version` are part of `ServerInformation`.
|
|
35
|
-
* - Capabilities Declaration: Declares supported features (logging, dynamic resources/tools).
|
|
36
|
-
* - Resource/Tool Registration: Makes capabilities discoverable and invocable.
|
|
37
|
-
*
|
|
38
26
|
* @returns A promise resolving with the configured `McpServer` instance.
|
|
39
27
|
* @throws {McpError} If any resource or tool registration fails.
|
|
40
28
|
* @private
|
|
@@ -44,21 +32,16 @@ async function createMcpServerInstance() {
|
|
|
44
32
|
operation: "createMcpServerInstance",
|
|
45
33
|
});
|
|
46
34
|
logger.info("Initializing MCP server instance", context);
|
|
47
|
-
requestContextService.configure({
|
|
48
|
-
appName: config.mcpServerName,
|
|
49
|
-
appVersion: config.mcpServerVersion,
|
|
50
|
-
environment,
|
|
51
|
-
});
|
|
52
35
|
const server = new McpServer({ name: config.mcpServerName, version: config.mcpServerVersion }, {
|
|
53
36
|
capabilities: {
|
|
54
|
-
logging: {},
|
|
55
|
-
resources: { listChanged: true },
|
|
56
|
-
tools: { listChanged: true },
|
|
37
|
+
logging: {},
|
|
38
|
+
resources: { listChanged: true },
|
|
39
|
+
tools: { listChanged: true },
|
|
57
40
|
},
|
|
58
41
|
});
|
|
59
42
|
await ErrorHandler.tryCatch(async () => {
|
|
60
43
|
logger.debug("Registering resources and tools...", context);
|
|
61
|
-
// IMPORTANT: Keep tool registrations in alphabetical order.
|
|
44
|
+
// IMPORTANT: Keep tool registrations in alphabetical order.
|
|
62
45
|
await registerFetchPubMedContentTool(server);
|
|
63
46
|
await registerGeneratePubMedChartTool(server);
|
|
64
47
|
await registerGetPubMedArticleConnectionsTool(server);
|
|
@@ -66,7 +49,7 @@ async function createMcpServerInstance() {
|
|
|
66
49
|
await registerSearchPubMedArticlesTool(server);
|
|
67
50
|
logger.info("Resources and tools registered successfully", context);
|
|
68
51
|
}, {
|
|
69
|
-
operation: "
|
|
52
|
+
operation: "registerAllCapabilities",
|
|
70
53
|
context,
|
|
71
54
|
errorCode: BaseErrorCode.INITIALIZATION_FAILED,
|
|
72
55
|
critical: true,
|
|
@@ -76,11 +59,6 @@ async function createMcpServerInstance() {
|
|
|
76
59
|
/**
|
|
77
60
|
* Selects, sets up, and starts the appropriate MCP transport layer based on configuration.
|
|
78
61
|
*
|
|
79
|
-
* MCP Spec Relevance:
|
|
80
|
-
* - Transport Selection: Uses `config.mcpTransportType` ('stdio' or 'http').
|
|
81
|
-
* - Transport Connection: Calls dedicated functions for chosen transport.
|
|
82
|
-
* - Server Instance Lifecycle: Single instance for 'stdio', per-session for 'http'.
|
|
83
|
-
*
|
|
84
62
|
* @returns Resolves with `McpServer` for 'stdio', `http.Server` for 'http', or `void`.
|
|
85
63
|
* @throws {Error} If transport type is unsupported or setup fails.
|
|
86
64
|
* @private
|
|
@@ -92,25 +70,31 @@ async function startTransport() {
|
|
|
92
70
|
transport: transportType,
|
|
93
71
|
});
|
|
94
72
|
logger.info(`Starting transport: ${transportType}`, context);
|
|
73
|
+
const serverFactory = createMcpServerInstance;
|
|
95
74
|
if (transportType === "http") {
|
|
96
|
-
|
|
75
|
+
const { server } = await startHttpTransport(serverFactory, context);
|
|
76
|
+
return server;
|
|
97
77
|
}
|
|
98
78
|
if (transportType === "stdio") {
|
|
99
|
-
const server = await
|
|
100
|
-
await
|
|
79
|
+
const server = await serverFactory();
|
|
80
|
+
await startStdioTransport(server, context);
|
|
101
81
|
return server;
|
|
102
82
|
}
|
|
103
83
|
throw new Error(`Unsupported transport type: ${transportType}. Must be 'stdio' or 'http'.`);
|
|
104
84
|
}
|
|
105
85
|
/**
|
|
106
86
|
* Main application entry point. Initializes and starts the MCP server.
|
|
107
|
-
* Orchestrates server startup, transport selection, and top-level error handling.
|
|
108
87
|
*/
|
|
109
88
|
export async function initializeAndStartServer() {
|
|
110
89
|
const context = requestContextService.createRequestContext({
|
|
111
90
|
operation: "initializeAndStartServer",
|
|
112
91
|
});
|
|
113
92
|
logger.info("MCP Server initialization sequence started.", context);
|
|
93
|
+
requestContextService.configure({
|
|
94
|
+
appName: config.mcpServerName,
|
|
95
|
+
appVersion: config.mcpServerVersion,
|
|
96
|
+
environment,
|
|
97
|
+
});
|
|
114
98
|
try {
|
|
115
99
|
const result = await startTransport();
|
|
116
100
|
logger.info("MCP Server initialization sequence completed successfully.", context);
|
|
@@ -121,7 +105,7 @@ export async function initializeAndStartServer() {
|
|
|
121
105
|
operation: "initializeAndStartServer",
|
|
122
106
|
context: context,
|
|
123
107
|
critical: true,
|
|
124
|
-
rethrow: false,
|
|
108
|
+
rethrow: false,
|
|
125
109
|
});
|
|
126
110
|
logger.info("Exiting process due to critical initialization error.", context);
|
|
127
111
|
process.exit(1);
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* @module src/mcp-server/tools/fetchPubMedContent/logic
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { getNcbiService } from "../../../services/NCBI/ncbiService.js";
|
|
9
|
+
import { getNcbiService } from "../../../services/NCBI/core/ncbiService.js";
|
|
10
10
|
import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
|
|
11
11
|
import { logger, requestContextService, sanitizeInputForLogging, } from "../../../utils/index.js";
|
|
12
|
-
import { ensureArray, extractAbstractText, extractArticleDates, extractAuthors, extractDoi, extractGrants, extractJournalInfo, extractKeywords, extractMeshTerms, extractPmid, extractPublicationTypes, getText, } from "../../../
|
|
12
|
+
import { ensureArray, extractAbstractText, extractArticleDates, extractAuthors, extractDoi, extractGrants, extractJournalInfo, extractKeywords, extractMeshTerms, extractPmid, extractPublicationTypes, getText, } from "../../../services/NCBI/parsing/index.js";
|
|
13
13
|
export const FetchPubMedContentInputSchema = z
|
|
14
14
|
.object({
|
|
15
15
|
pmids: z
|