@cyanheads/pubmed-mcp-server 1.0.12
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/LICENSE +201 -0
- package/README.md +174 -0
- package/dist/config/index.d.ts +91 -0
- package/dist/config/index.js +324 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +190 -0
- package/dist/mcp-server/resources/echoResource/echoResourceLogic.d.ts +79 -0
- package/dist/mcp-server/resources/echoResource/echoResourceLogic.js +82 -0
- package/dist/mcp-server/resources/echoResource/index.d.ts +13 -0
- package/dist/mcp-server/resources/echoResource/index.js +13 -0
- package/dist/mcp-server/resources/echoResource/registration.d.ts +30 -0
- package/dist/mcp-server/resources/echoResource/registration.js +168 -0
- package/dist/mcp-server/server.d.ts +28 -0
- package/dist/mcp-server/server.js +159 -0
- package/dist/mcp-server/tools/fetchPubMedContent/index.d.ts +6 -0
- package/dist/mcp-server/tools/fetchPubMedContent/index.js +6 -0
- package/dist/mcp-server/tools/fetchPubMedContent/logic.d.ts +63 -0
- package/dist/mcp-server/tools/fetchPubMedContent/logic.js +518 -0
- package/dist/mcp-server/tools/fetchPubMedContent/registration.d.ts +10 -0
- package/dist/mcp-server/tools/fetchPubMedContent/registration.js +37 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/index.d.ts +6 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/index.js +6 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/citationFormatter.d.ts +9 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/citationFormatter.js +288 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/elinkHandler.d.ts +9 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/elinkHandler.js +208 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/index.d.ts +15 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/index.js +82 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/types.d.ts +27 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic/types.js +5 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic.d.ts +6 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/logic.js +6 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/registration.d.ts +36 -0
- package/dist/mcp-server/tools/getPubMedArticleConnections/registration.js +76 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/index.d.ts +6 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/index.js +6 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/index.d.ts +7 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/index.js +9 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/inputSchema.d.ts +111 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/inputSchema.js +149 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/outputTypes.d.ts +106 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/outputTypes.js +7 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/planOrchestrator.d.ts +10 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic/planOrchestrator.js +251 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic.d.ts +12 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/logic.js +55 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/registration.d.ts +10 -0
- package/dist/mcp-server/tools/pubmedResearchAgent/registration.js +36 -0
- package/dist/mcp-server/tools/searchPubMedArticles/index.d.ts +6 -0
- package/dist/mcp-server/tools/searchPubMedArticles/index.js +6 -0
- package/dist/mcp-server/tools/searchPubMedArticles/logic.d.ts +61 -0
- package/dist/mcp-server/tools/searchPubMedArticles/logic.js +229 -0
- package/dist/mcp-server/tools/searchPubMedArticles/registration.d.ts +10 -0
- package/dist/mcp-server/tools/searchPubMedArticles/registration.js +38 -0
- package/dist/mcp-server/transports/authentication/authMiddleware.d.ts +29 -0
- package/dist/mcp-server/transports/authentication/authMiddleware.js +174 -0
- package/dist/mcp-server/transports/httpTransport.d.ts +23 -0
- package/dist/mcp-server/transports/httpTransport.js +463 -0
- package/dist/mcp-server/transports/stdioTransport.d.ts +42 -0
- package/dist/mcp-server/transports/stdioTransport.js +63 -0
- package/dist/services/NCBI/ncbiConstants.d.ts +22 -0
- package/dist/services/NCBI/ncbiConstants.js +5 -0
- package/dist/services/NCBI/ncbiCoreApiClient.d.ts +24 -0
- package/dist/services/NCBI/ncbiCoreApiClient.js +118 -0
- package/dist/services/NCBI/ncbiRequestQueueManager.d.ts +36 -0
- package/dist/services/NCBI/ncbiRequestQueueManager.js +96 -0
- package/dist/services/NCBI/ncbiResponseHandler.d.ts +22 -0
- package/dist/services/NCBI/ncbiResponseHandler.js +192 -0
- package/dist/services/NCBI/ncbiService.d.ts +24 -0
- package/dist/services/NCBI/ncbiService.js +57 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.js +7 -0
- package/dist/services/llm-providers/index.d.ts +7 -0
- package/dist/services/llm-providers/index.js +7 -0
- package/dist/services/llm-providers/llmFactory.d.ts +69 -0
- package/dist/services/llm-providers/llmFactory.js +132 -0
- package/dist/services/llm-providers/openRouter/index.d.ts +6 -0
- package/dist/services/llm-providers/openRouter/index.js +7 -0
- package/dist/services/llm-providers/openRouter/openRouterProvider.d.ts +99 -0
- package/dist/services/llm-providers/openRouter/openRouterProvider.js +329 -0
- package/dist/types-global/errors.d.ts +119 -0
- package/dist/types-global/errors.js +119 -0
- package/dist/types-global/pubmedXml.d.ts +350 -0
- package/dist/types-global/pubmedXml.js +7 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/internal/errorHandler.d.ts +176 -0
- package/dist/utils/internal/errorHandler.js +335 -0
- package/dist/utils/internal/index.d.ts +9 -0
- package/dist/utils/internal/index.js +9 -0
- package/dist/utils/internal/logger.d.ts +141 -0
- package/dist/utils/internal/logger.js +426 -0
- package/dist/utils/internal/requestContext.d.ts +83 -0
- package/dist/utils/internal/requestContext.js +72 -0
- package/dist/utils/metrics/index.d.ts +7 -0
- package/dist/utils/metrics/index.js +7 -0
- package/dist/utils/metrics/tokenCounter.d.ts +35 -0
- package/dist/utils/metrics/tokenCounter.js +110 -0
- package/dist/utils/parsing/dateParser.d.ts +73 -0
- package/dist/utils/parsing/dateParser.js +107 -0
- package/dist/utils/parsing/index.d.ts +8 -0
- package/dist/utils/parsing/index.js +8 -0
- package/dist/utils/parsing/jsonParser.d.ts +82 -0
- package/dist/utils/parsing/jsonParser.js +126 -0
- package/dist/utils/parsing/ncbi-parsing/eSummaryResultParser.d.ts +32 -0
- package/dist/utils/parsing/ncbi-parsing/eSummaryResultParser.js +295 -0
- package/dist/utils/parsing/ncbi-parsing/index.d.ts +8 -0
- package/dist/utils/parsing/ncbi-parsing/index.js +8 -0
- package/dist/utils/parsing/ncbi-parsing/pubmedArticleStructureParser.d.ts +70 -0
- package/dist/utils/parsing/ncbi-parsing/pubmedArticleStructureParser.js +229 -0
- package/dist/utils/parsing/ncbi-parsing/xmlGenericHelpers.d.ts +31 -0
- package/dist/utils/parsing/ncbi-parsing/xmlGenericHelpers.js +76 -0
- package/dist/utils/security/idGenerator.d.ts +134 -0
- package/dist/utils/security/idGenerator.js +198 -0
- package/dist/utils/security/index.d.ts +9 -0
- package/dist/utils/security/index.js +9 -0
- package/dist/utils/security/rateLimiter.d.ts +108 -0
- package/dist/utils/security/rateLimiter.js +179 -0
- package/dist/utils/security/sanitization.d.ts +173 -0
- package/dist/utils/security/sanitization.js +439 -0
- package/package.json +97 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the core logic, schemas, and types for the `echo` resource.
|
|
3
|
+
* This module includes a Zod schema for query parameter validation, type definitions,
|
|
4
|
+
* and the main processing function that constructs the resource response.
|
|
5
|
+
* The echo resource is designed to return a message, typically extracted from the
|
|
6
|
+
* request URI's path or query parameters, along with a timestamp.
|
|
7
|
+
* @module src/mcp-server/resources/echoResource/echoResourceLogic
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { logger } from "../../../utils/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Zod schema defining expected query parameters for the echo resource.
|
|
13
|
+
*
|
|
14
|
+
* This schema is intended for validating parameters passed via the URI's query string
|
|
15
|
+
* (e.g., `echo://some_message?message=override_from_query&anotherParam=value`).
|
|
16
|
+
* Path parameters, such as `{message}` in a template like `echo://{message}`,
|
|
17
|
+
* are typically defined in the `ResourceTemplate` (see `registration.ts`) and
|
|
18
|
+
* extracted by the MCP SDK from the URI path. The SDK merges these path
|
|
19
|
+
* parameters into the `params` object passed to the handler.
|
|
20
|
+
*
|
|
21
|
+
* If a path parameter and a query parameter share the same name (e.g., 'message'),
|
|
22
|
+
* the query parameter will take precedence over the path parameter. This schema
|
|
23
|
+
* defines `message` as an optional query parameter.
|
|
24
|
+
*/
|
|
25
|
+
export const EchoResourceQuerySchema = z.object({
|
|
26
|
+
/**
|
|
27
|
+
* Optional message to be echoed back in the response.
|
|
28
|
+
* If the resource template also defines a 'message' path parameter,
|
|
29
|
+
* this query parameter will override the path parameter's value if both are present.
|
|
30
|
+
*/
|
|
31
|
+
message: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Optional message to echo back in the response. If not provided, a default may be used or derived from the path."),
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Processes the core logic for an echo resource request.
|
|
38
|
+
* It constructs a response payload containing a message (derived from path or query parameters),
|
|
39
|
+
* the current timestamp, and the original request URI.
|
|
40
|
+
*
|
|
41
|
+
* The `params` argument is expected to contain validated query parameters. If the resource
|
|
42
|
+
* template (e.g., `echo://{message}`) includes path parameters, the MCP SDK extracts
|
|
43
|
+
* them and merges them into the `params` object. If a query parameter shares the same
|
|
44
|
+
* name as a path parameter, the query parameter's value takes precedence. This function
|
|
45
|
+
* assumes `params.message` will hold the definitive message.
|
|
46
|
+
*
|
|
47
|
+
* @param uri - The full URL object of the incoming resource request.
|
|
48
|
+
* @param params - The validated query parameters for the request.
|
|
49
|
+
* This object also includes path parameters merged by the SDK, with query parameters
|
|
50
|
+
* taking precedence in case of name conflicts.
|
|
51
|
+
* @param context - The request context, used for logging and tracing the operation.
|
|
52
|
+
* @returns The data payload for the response.
|
|
53
|
+
* This payload is typically JSON-stringified by the calling handler.
|
|
54
|
+
*/
|
|
55
|
+
export const processEchoResource = (uri, params, context) => {
|
|
56
|
+
// The `params.message` can originate from a query parameter (validated by `EchoResourceQuerySchema`)
|
|
57
|
+
// or a path parameter (e.g., from a template like `echo://{message_from_path}`).
|
|
58
|
+
// The MCP SDK merges these, with query parameters taking precedence over path parameters if names conflict.
|
|
59
|
+
// The fallback "Default message..." is a safeguard if no message is provided via path or query.
|
|
60
|
+
const messageToEcho = params.message || `Default echo from ${uri.pathname}`;
|
|
61
|
+
logger.debug("Processing echo resource logic.", {
|
|
62
|
+
...context,
|
|
63
|
+
resourceUri: uri.href,
|
|
64
|
+
extractedMessage: messageToEcho,
|
|
65
|
+
queryParamMessage: params.message,
|
|
66
|
+
});
|
|
67
|
+
const responsePayload = {
|
|
68
|
+
message: messageToEcho,
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
requestUri: uri.href,
|
|
71
|
+
};
|
|
72
|
+
logger.debug("Echo resource processed successfully.", {
|
|
73
|
+
...context,
|
|
74
|
+
responsePayloadSummary: {
|
|
75
|
+
messageLength: responsePayload.message.length,
|
|
76
|
+
uriEchoed: responsePayload.requestUri.length > 50
|
|
77
|
+
? `${responsePayload.requestUri.substring(0, 47)}...`
|
|
78
|
+
: responsePayload.requestUri,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
return responsePayload;
|
|
82
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel file for the `echo` resource.
|
|
3
|
+
* This file serves as the public interface for the echo resource module,
|
|
4
|
+
* primarily exporting the `registerEchoResource` function. This function is
|
|
5
|
+
* responsible for registering the echo resource, including its templates and handler,
|
|
6
|
+
* with an MCP server instance. This makes the resource accessible to clients
|
|
7
|
+
* via defined URI patterns.
|
|
8
|
+
*
|
|
9
|
+
* Consuming modules should import from this barrel file to access
|
|
10
|
+
* the echo resource's registration capabilities.
|
|
11
|
+
* @module src/mcp-server/resources/echoResource/index
|
|
12
|
+
*/
|
|
13
|
+
export { registerEchoResource } from "./registration.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel file for the `echo` resource.
|
|
3
|
+
* This file serves as the public interface for the echo resource module,
|
|
4
|
+
* primarily exporting the `registerEchoResource` function. This function is
|
|
5
|
+
* responsible for registering the echo resource, including its templates and handler,
|
|
6
|
+
* with an MCP server instance. This makes the resource accessible to clients
|
|
7
|
+
* via defined URI patterns.
|
|
8
|
+
*
|
|
9
|
+
* Consuming modules should import from this barrel file to access
|
|
10
|
+
* the echo resource's registration capabilities.
|
|
11
|
+
* @module src/mcp-server/resources/echoResource/index
|
|
12
|
+
*/
|
|
13
|
+
export { registerEchoResource } from "./registration.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Handles the registration of the `echo` resource with an MCP server instance.
|
|
3
|
+
* This module defines the resource's template (URI structure), metadata (name, description, examples),
|
|
4
|
+
* and the asynchronous handler function that processes `resources/read` requests matching the template.
|
|
5
|
+
* It utilizes the MCP SDK's `server.resource()` method for registration and integrates
|
|
6
|
+
* robust error handling using the project's `ErrorHandler` utility.
|
|
7
|
+
* @module src/mcp-server/resources/echoResource/registration
|
|
8
|
+
*/
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
/**
|
|
11
|
+
* Registers the 'echo' resource and its handlers with the provided MCP server instance.
|
|
12
|
+
*
|
|
13
|
+
* This function defines:
|
|
14
|
+
* 1. The resource template (e.g., `echo://{message}`), which determines the URI structure.
|
|
15
|
+
* The `{message}` part is a path variable.
|
|
16
|
+
* 2. A `list` operation for the template to provide example/discoverable URIs.
|
|
17
|
+
* 3. Metadata for the resource, including its user-friendly name, description, MIME type,
|
|
18
|
+
* and example URIs.
|
|
19
|
+
* 4. The core asynchronous handler logic for `resources/read` requests that match the template.
|
|
20
|
+
* This handler processes the request and returns the resource content.
|
|
21
|
+
*
|
|
22
|
+
* Error handling is integrated throughout using `ErrorHandler.tryCatch` for robustness.
|
|
23
|
+
*
|
|
24
|
+
* @param server - The MCP server instance to register the resource with.
|
|
25
|
+
* @returns A promise that resolves when the resource registration is complete. It does not return a value upon successful completion.
|
|
26
|
+
* @throws {McpError} If the registration process fails critically, which might halt server startup.
|
|
27
|
+
* @see {@link EchoResourceParams} for the type of parameters passed to the handler.
|
|
28
|
+
* @see {@link processEchoResource} for the core resource logic.
|
|
29
|
+
*/
|
|
30
|
+
export declare const registerEchoResource: (server: McpServer) => Promise<void>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Handles the registration of the `echo` resource with an MCP server instance.
|
|
3
|
+
* This module defines the resource's template (URI structure), metadata (name, description, examples),
|
|
4
|
+
* and the asynchronous handler function that processes `resources/read` requests matching the template.
|
|
5
|
+
* It utilizes the MCP SDK's `server.resource()` method for registration and integrates
|
|
6
|
+
* robust error handling using the project's `ErrorHandler` utility.
|
|
7
|
+
* @module src/mcp-server/resources/echoResource/registration
|
|
8
|
+
*/
|
|
9
|
+
import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
|
|
11
|
+
import { ErrorHandler, logger, requestContextService, } from "../../../utils/index.js";
|
|
12
|
+
import { processEchoResource, } from "./echoResourceLogic.js";
|
|
13
|
+
/**
|
|
14
|
+
* Registers the 'echo' resource and its handlers with the provided MCP server instance.
|
|
15
|
+
*
|
|
16
|
+
* This function defines:
|
|
17
|
+
* 1. The resource template (e.g., `echo://{message}`), which determines the URI structure.
|
|
18
|
+
* The `{message}` part is a path variable.
|
|
19
|
+
* 2. A `list` operation for the template to provide example/discoverable URIs.
|
|
20
|
+
* 3. Metadata for the resource, including its user-friendly name, description, MIME type,
|
|
21
|
+
* and example URIs.
|
|
22
|
+
* 4. The core asynchronous handler logic for `resources/read` requests that match the template.
|
|
23
|
+
* This handler processes the request and returns the resource content.
|
|
24
|
+
*
|
|
25
|
+
* Error handling is integrated throughout using `ErrorHandler.tryCatch` for robustness.
|
|
26
|
+
*
|
|
27
|
+
* @param server - The MCP server instance to register the resource with.
|
|
28
|
+
* @returns A promise that resolves when the resource registration is complete. It does not return a value upon successful completion.
|
|
29
|
+
* @throws {McpError} If the registration process fails critically, which might halt server startup.
|
|
30
|
+
* @see {@link EchoResourceParams} for the type of parameters passed to the handler.
|
|
31
|
+
* @see {@link processEchoResource} for the core resource logic.
|
|
32
|
+
*/
|
|
33
|
+
export const registerEchoResource = async (server) => {
|
|
34
|
+
const resourceName = "echo-resource"; // Internal identifier for this resource registration.
|
|
35
|
+
const registrationContext = requestContextService.createRequestContext({
|
|
36
|
+
operation: "RegisterResource",
|
|
37
|
+
resourceName: resourceName,
|
|
38
|
+
moduleName: "EchoResourceRegistration",
|
|
39
|
+
});
|
|
40
|
+
logger.info(`Attempting to register resource: '${resourceName}'`, registrationContext);
|
|
41
|
+
await ErrorHandler.tryCatch(async () => {
|
|
42
|
+
// Define the resource template. This specifies the URI structure and supported operations.
|
|
43
|
+
// The URI `echo://{message}` uses RFC 6570 syntax, where `{message}` is a path variable.
|
|
44
|
+
const template = new ResourceTemplate("echo://{message}", {
|
|
45
|
+
/**
|
|
46
|
+
* Asynchronous handler for the `resources/list` operation associated with this template.
|
|
47
|
+
* It provides a list of example or discoverable resource URIs that match this template.
|
|
48
|
+
* This allows clients to discover how to interact with the echo resource.
|
|
49
|
+
*
|
|
50
|
+
* @returns A promise resolving to an object containing an array of resource descriptors.
|
|
51
|
+
*/
|
|
52
|
+
list: async () => {
|
|
53
|
+
const listContext = requestContextService.createRequestContext({
|
|
54
|
+
parentContext: registrationContext,
|
|
55
|
+
operation: "ListEchoResourceExamples",
|
|
56
|
+
});
|
|
57
|
+
logger.debug("Executing list operation for echo resource template.", listContext);
|
|
58
|
+
// Return a static list of example URIs.
|
|
59
|
+
return {
|
|
60
|
+
resources: [
|
|
61
|
+
{
|
|
62
|
+
uri: "echo://hello",
|
|
63
|
+
name: "Default Echo Message",
|
|
64
|
+
description: "A simple echo resource example using a default message.",
|
|
65
|
+
},
|
|
66
|
+
// Add more examples as needed
|
|
67
|
+
],
|
|
68
|
+
// nextCursor could be used here if the list were paginated.
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
// The `complete` operation (for URI completion suggestions) is optional and not implemented here.
|
|
72
|
+
});
|
|
73
|
+
logger.debug(`Resource template created for '${resourceName}': ${template.uriTemplate}`, registrationContext);
|
|
74
|
+
// Register the resource with the server.
|
|
75
|
+
// This involves providing the registration name, the template, metadata, and the handler for read operations.
|
|
76
|
+
server.resource(resourceName, template, {
|
|
77
|
+
name: "Echo Message Resource",
|
|
78
|
+
description: "A simple echo resource that returns a message, optionally specified in the URI path.",
|
|
79
|
+
mimeType: "application/json",
|
|
80
|
+
examples: [
|
|
81
|
+
{
|
|
82
|
+
name: "Basic echo",
|
|
83
|
+
uri: "echo://hello",
|
|
84
|
+
description: "Accesses the echo resource to echo the message 'hello'.",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "Custom echo",
|
|
88
|
+
uri: "echo://custom-message-here",
|
|
89
|
+
description: "Accesses the echo resource to echo 'custom-message-here'.",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Asynchronous handler for `resources/read` requests matching the `echo://{message}` template.
|
|
95
|
+
* This function is invoked by the MCP SDK when a client requests to read a resource
|
|
96
|
+
* whose URI matches the registered template.
|
|
97
|
+
*
|
|
98
|
+
* The SDK extracts path variables (like `{message}` from `echo://{message}`) from the URI.
|
|
99
|
+
* These path variables, along with any validated query parameters, are passed in the `params` object.
|
|
100
|
+
*
|
|
101
|
+
* @param uri - The full URL object of the resource being requested.
|
|
102
|
+
* @param params - An object containing parameters derived from the request.
|
|
103
|
+
* For this resource, it's expected to include `message` extracted from the URI
|
|
104
|
+
* path by the SDK. It conforms to {@link EchoResourceParams}.
|
|
105
|
+
* @returns A promise that resolves with the resource content, formatted as a `ReadResourceResult`.
|
|
106
|
+
* This includes the URI, Base64 encoded content blob, and MIME type.
|
|
107
|
+
* If an error is thrown from this handler, the SDK is responsible for catching it and
|
|
108
|
+
* formatting an error response.
|
|
109
|
+
*/
|
|
110
|
+
async (uri, params) => {
|
|
111
|
+
const handlerContext = requestContextService.createRequestContext({
|
|
112
|
+
parentContext: registrationContext,
|
|
113
|
+
operation: "HandleResourceRead",
|
|
114
|
+
resourceName: resourceName,
|
|
115
|
+
resourceUri: uri.href,
|
|
116
|
+
inputParamsSummary: params.message
|
|
117
|
+
? { messageLength: params.message.length }
|
|
118
|
+
: { noMessageParam: true },
|
|
119
|
+
});
|
|
120
|
+
logger.debug(`Handling read request for resource '${resourceName}', URI: ${uri.href}`, handlerContext);
|
|
121
|
+
return await ErrorHandler.tryCatch(async () => {
|
|
122
|
+
const responseData = processEchoResource(uri, params, handlerContext);
|
|
123
|
+
logger.debug(`'${resourceName}' (URI: ${uri.href}) processed successfully. Preparing content.`, handlerContext);
|
|
124
|
+
// Construct the `ReadResourceResult` as expected by the MCP SDK.
|
|
125
|
+
// The content (blob) must be Base64 encoded.
|
|
126
|
+
return {
|
|
127
|
+
contents: [
|
|
128
|
+
{
|
|
129
|
+
uri: uri.href,
|
|
130
|
+
blob: Buffer.from(JSON.stringify(responseData)).toString("base64"),
|
|
131
|
+
mimeType: "application/json",
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}, {
|
|
136
|
+
operation: `ExecutingCoreLogicFor_${resourceName}_Read`,
|
|
137
|
+
context: handlerContext,
|
|
138
|
+
input: { uri: uri.href, params },
|
|
139
|
+
errorMapper: (error) => {
|
|
140
|
+
const baseErrorCode = error instanceof McpError
|
|
141
|
+
? error.code
|
|
142
|
+
: BaseErrorCode.INTERNAL_ERROR;
|
|
143
|
+
const errorMessage = `Error processing read request for resource '${uri.href}': ${error instanceof Error ? error.message : "An unknown error occurred"}`;
|
|
144
|
+
return new McpError(baseErrorCode, errorMessage, {
|
|
145
|
+
...handlerContext,
|
|
146
|
+
originalErrorName: error instanceof Error ? error.name : typeof error,
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
logger.info(`Resource '${resourceName}' (template: '${template.uriTemplate}') registered successfully.`, registrationContext);
|
|
152
|
+
}, {
|
|
153
|
+
operation: `RegisteringResource_${resourceName}`,
|
|
154
|
+
context: registrationContext,
|
|
155
|
+
errorCode: BaseErrorCode.INITIALIZATION_FAILED,
|
|
156
|
+
errorMapper: (error) => {
|
|
157
|
+
const errorMessage = `Failed to register resource '${resourceName}': ${error instanceof Error ? error.message : "An unknown error occurred during registration."}`;
|
|
158
|
+
const code = error instanceof McpError
|
|
159
|
+
? error.code
|
|
160
|
+
: BaseErrorCode.INITIALIZATION_FAILED;
|
|
161
|
+
return new McpError(code, errorMessage, {
|
|
162
|
+
...registrationContext,
|
|
163
|
+
originalErrorName: error instanceof Error ? error.name : typeof error,
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
critical: true,
|
|
167
|
+
});
|
|
168
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Main entry point for the MCP (Model Context Protocol) server.
|
|
3
|
+
* This file orchestrates the server's lifecycle:
|
|
4
|
+
* 1. Initializes the core `McpServer` instance (from `@modelcontextprotocol/sdk`) with its identity and capabilities.
|
|
5
|
+
* 2. Registers available resources and tools, making them discoverable and usable by clients.
|
|
6
|
+
* 3. Selects and starts the appropriate communication transport (stdio or Streamable HTTP)
|
|
7
|
+
* based on configuration.
|
|
8
|
+
* 4. Handles top-level error management during startup.
|
|
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
|
+
* @module src/mcp-server/server
|
|
15
|
+
*/
|
|
16
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
/**
|
|
18
|
+
* Main application entry point. Initializes and starts the MCP server.
|
|
19
|
+
* Orchestrates server startup, transport selection, and top-level error handling.
|
|
20
|
+
*
|
|
21
|
+
* MCP Spec Relevance:
|
|
22
|
+
* - Manages server startup, leading to a server ready for MCP messages.
|
|
23
|
+
* - Handles critical startup failures, ensuring appropriate process exit.
|
|
24
|
+
*
|
|
25
|
+
* @returns For 'stdio', resolves with `McpServer`. For 'http', runs indefinitely.
|
|
26
|
+
* Rejects on critical failure, leading to process exit.
|
|
27
|
+
*/
|
|
28
|
+
export declare function initializeAndStartServer(): Promise<void | McpServer>;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Main entry point for the MCP (Model Context Protocol) server.
|
|
3
|
+
* This file orchestrates the server's lifecycle:
|
|
4
|
+
* 1. Initializes the core `McpServer` instance (from `@modelcontextprotocol/sdk`) with its identity and capabilities.
|
|
5
|
+
* 2. Registers available resources and tools, making them discoverable and usable by clients.
|
|
6
|
+
* 3. Selects and starts the appropriate communication transport (stdio or Streamable HTTP)
|
|
7
|
+
* based on configuration.
|
|
8
|
+
* 4. Handles top-level error management during startup.
|
|
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
|
+
* @module src/mcp-server/server
|
|
15
|
+
*/
|
|
16
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import { config } from "../config/index.js";
|
|
18
|
+
import { ErrorHandler, logger, requestContextService } from "../utils/index.js";
|
|
19
|
+
// import { registerEchoResource } from "./resources/echoResource/index.js"; // To be removed after resource implementations.
|
|
20
|
+
import { registerFetchPubMedContentTool } from "./tools/fetchPubMedContent/index.js";
|
|
21
|
+
import { registerGetPubMedArticleConnectionsTool } from "./tools/getPubMedArticleConnections/index.js";
|
|
22
|
+
import { registerPubMedResearchAgentTool } from "./tools/pubmedResearchAgent/index.js"; // Added import
|
|
23
|
+
import { registerSearchPubMedArticlesTool } from "./tools/searchPubMedArticles/index.js";
|
|
24
|
+
import { startHttpTransport } from "./transports/httpTransport.js";
|
|
25
|
+
import { connectStdioTransport } from "./transports/stdioTransport.js";
|
|
26
|
+
/**
|
|
27
|
+
* Creates and configures a new instance of the `McpServer`.
|
|
28
|
+
*
|
|
29
|
+
* This function defines the server's identity and capabilities as presented
|
|
30
|
+
* to clients during MCP initialization.
|
|
31
|
+
*
|
|
32
|
+
* MCP Spec Relevance:
|
|
33
|
+
* - Server Identity (`serverInfo`): `name` and `version` are part of `ServerInformation`.
|
|
34
|
+
* - Capabilities Declaration: Declares supported features (logging, dynamic resources/tools).
|
|
35
|
+
* - Resource/Tool Registration: Makes capabilities discoverable and invocable.
|
|
36
|
+
*
|
|
37
|
+
* Design Note: This factory is called once for 'stdio' transport and per session for 'http' transport.
|
|
38
|
+
*
|
|
39
|
+
* @returns A promise resolving with the configured `McpServer` instance.
|
|
40
|
+
* @throws {Error} If any resource or tool registration fails.
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
async function createMcpServerInstance() {
|
|
44
|
+
const context = requestContextService.createRequestContext({
|
|
45
|
+
operation: "createMcpServerInstance",
|
|
46
|
+
});
|
|
47
|
+
logger.info("Initializing MCP server instance", context);
|
|
48
|
+
logger.debug("Instantiating McpServer with capabilities", {
|
|
49
|
+
...context,
|
|
50
|
+
serverInfo: {
|
|
51
|
+
name: config.mcpServerName,
|
|
52
|
+
version: config.mcpServerVersion,
|
|
53
|
+
},
|
|
54
|
+
capabilities: {
|
|
55
|
+
logging: {},
|
|
56
|
+
resources: { listChanged: true },
|
|
57
|
+
tools: { listChanged: true },
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
const server = new McpServer({ name: config.mcpServerName, version: config.mcpServerVersion }, {
|
|
61
|
+
capabilities: {
|
|
62
|
+
logging: {}, // Server can receive logging/setLevel and send notifications/message
|
|
63
|
+
resources: { listChanged: true }, // Server supports dynamic resource lists
|
|
64
|
+
tools: { listChanged: true }, // Server supports dynamic tool lists
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
logger.debug("Registering resources and tools...", context);
|
|
69
|
+
// IMPORTANT: Keep tool registrations in alphabetical order. Do not remove this comment.
|
|
70
|
+
await registerFetchPubMedContentTool(server);
|
|
71
|
+
await registerGetPubMedArticleConnectionsTool(server);
|
|
72
|
+
await registerPubMedResearchAgentTool(server); // Added new tool registration
|
|
73
|
+
await registerSearchPubMedArticlesTool(server);
|
|
74
|
+
// Add other tool/resource registrations here
|
|
75
|
+
logger.info("Resources and tools registered successfully", context);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
logger.error("Failed to register resources/tools", {
|
|
79
|
+
...context,
|
|
80
|
+
error: err instanceof Error ? err.message : String(err),
|
|
81
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
82
|
+
});
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
return server;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Selects, sets up, and starts the appropriate MCP transport layer based on configuration.
|
|
89
|
+
*
|
|
90
|
+
* MCP Spec Relevance:
|
|
91
|
+
* - Transport Selection: Uses `config.mcpTransportType` ('stdio' or 'http').
|
|
92
|
+
* - Transport Connection: Calls dedicated functions for chosen transport.
|
|
93
|
+
* - Server Instance Lifecycle: Single instance for 'stdio', per-session for 'http'.
|
|
94
|
+
*
|
|
95
|
+
* @returns Resolves with `McpServer` for 'stdio', or `void` for 'http'.
|
|
96
|
+
* @throws {Error} If transport type is unsupported or setup fails.
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
async function startTransport() {
|
|
100
|
+
const transportType = config.mcpTransportType;
|
|
101
|
+
const context = requestContextService.createRequestContext({
|
|
102
|
+
operation: "startTransport",
|
|
103
|
+
transport: transportType,
|
|
104
|
+
});
|
|
105
|
+
logger.info(`Starting transport: ${transportType}`, context);
|
|
106
|
+
if (transportType === "http") {
|
|
107
|
+
logger.debug("Delegating to startHttpTransport...", context);
|
|
108
|
+
// For HTTP, startHttpTransport manages its own lifecycle and server instances per session.
|
|
109
|
+
await startHttpTransport(createMcpServerInstance, context);
|
|
110
|
+
return; // HTTP server runs indefinitely, no single server instance returned here.
|
|
111
|
+
}
|
|
112
|
+
if (transportType === "stdio") {
|
|
113
|
+
logger.debug("Creating single McpServer instance for stdio transport...", context);
|
|
114
|
+
const server = await createMcpServerInstance();
|
|
115
|
+
logger.debug("Delegating to connectStdioTransport...", context);
|
|
116
|
+
await connectStdioTransport(server, context);
|
|
117
|
+
return server; // Return the single server instance for stdio.
|
|
118
|
+
}
|
|
119
|
+
// Should not be reached if config validation is effective.
|
|
120
|
+
logger.fatal(`Unsupported transport type configured: ${transportType}`, context);
|
|
121
|
+
throw new Error(`Unsupported transport type: ${transportType}. Must be 'stdio' or 'http'.`);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Main application entry point. Initializes and starts the MCP server.
|
|
125
|
+
* Orchestrates server startup, transport selection, and top-level error handling.
|
|
126
|
+
*
|
|
127
|
+
* MCP Spec Relevance:
|
|
128
|
+
* - Manages server startup, leading to a server ready for MCP messages.
|
|
129
|
+
* - Handles critical startup failures, ensuring appropriate process exit.
|
|
130
|
+
*
|
|
131
|
+
* @returns For 'stdio', resolves with `McpServer`. For 'http', runs indefinitely.
|
|
132
|
+
* Rejects on critical failure, leading to process exit.
|
|
133
|
+
*/
|
|
134
|
+
export async function initializeAndStartServer() {
|
|
135
|
+
const context = requestContextService.createRequestContext({
|
|
136
|
+
operation: "initializeAndStartServer",
|
|
137
|
+
});
|
|
138
|
+
logger.info("MCP Server initialization sequence started.", context);
|
|
139
|
+
try {
|
|
140
|
+
const result = await startTransport();
|
|
141
|
+
logger.info("MCP Server initialization sequence completed successfully.", context);
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
logger.fatal("Critical error during MCP server initialization.", {
|
|
146
|
+
...context,
|
|
147
|
+
error: err instanceof Error ? err.message : String(err),
|
|
148
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
149
|
+
});
|
|
150
|
+
// Ensure the error is handled by our centralized handler, which might log more details or perform cleanup.
|
|
151
|
+
ErrorHandler.handleError(err, {
|
|
152
|
+
operation: "initializeAndStartServer", // More specific operation
|
|
153
|
+
context: context, // Pass the existing context
|
|
154
|
+
critical: true, // This is a critical failure
|
|
155
|
+
});
|
|
156
|
+
logger.info("Exiting process due to critical initialization error.", context);
|
|
157
|
+
process.exit(1); // Exit with a non-zero code to indicate failure.
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Logic for the fetch_pubmed_content MCP tool.
|
|
3
|
+
* Handles EFetch queries for specific PMIDs and formats the results.
|
|
4
|
+
* This tool can fetch various details from PubMed including abstracts, full XML,
|
|
5
|
+
* MEDLINE text, and citation data.
|
|
6
|
+
* @module src/mcp-server/tools/fetchPubMedContent/logic
|
|
7
|
+
*/
|
|
8
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { RequestContext } from "../../../utils/index.js";
|
|
11
|
+
export declare const FetchPubMedContentInputSchema: z.ZodEffects<z.ZodObject<{
|
|
12
|
+
pmids: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
13
|
+
queryKey: z.ZodOptional<z.ZodString>;
|
|
14
|
+
webEnv: z.ZodOptional<z.ZodString>;
|
|
15
|
+
retstart: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
retmax: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
detailLevel: z.ZodDefault<z.ZodOptional<z.ZodEnum<["abstract_plus", "full_xml", "medline_text", "citation_data"]>>>;
|
|
18
|
+
includeMeshTerms: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
19
|
+
includeGrantInfo: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
20
|
+
outputFormat: z.ZodDefault<z.ZodOptional<z.ZodEnum<["json", "raw_text"]>>>;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
detailLevel: "abstract_plus" | "full_xml" | "medline_text" | "citation_data";
|
|
23
|
+
includeMeshTerms: boolean;
|
|
24
|
+
includeGrantInfo: boolean;
|
|
25
|
+
outputFormat: "json" | "raw_text";
|
|
26
|
+
pmids?: string[] | undefined;
|
|
27
|
+
queryKey?: string | undefined;
|
|
28
|
+
webEnv?: string | undefined;
|
|
29
|
+
retstart?: number | undefined;
|
|
30
|
+
retmax?: number | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
pmids?: string[] | undefined;
|
|
33
|
+
queryKey?: string | undefined;
|
|
34
|
+
webEnv?: string | undefined;
|
|
35
|
+
retstart?: number | undefined;
|
|
36
|
+
retmax?: number | undefined;
|
|
37
|
+
detailLevel?: "abstract_plus" | "full_xml" | "medline_text" | "citation_data" | undefined;
|
|
38
|
+
includeMeshTerms?: boolean | undefined;
|
|
39
|
+
includeGrantInfo?: boolean | undefined;
|
|
40
|
+
outputFormat?: "json" | "raw_text" | undefined;
|
|
41
|
+
}>, {
|
|
42
|
+
detailLevel: "abstract_plus" | "full_xml" | "medline_text" | "citation_data";
|
|
43
|
+
includeMeshTerms: boolean;
|
|
44
|
+
includeGrantInfo: boolean;
|
|
45
|
+
outputFormat: "json" | "raw_text";
|
|
46
|
+
pmids?: string[] | undefined;
|
|
47
|
+
queryKey?: string | undefined;
|
|
48
|
+
webEnv?: string | undefined;
|
|
49
|
+
retstart?: number | undefined;
|
|
50
|
+
retmax?: number | undefined;
|
|
51
|
+
}, {
|
|
52
|
+
pmids?: string[] | undefined;
|
|
53
|
+
queryKey?: string | undefined;
|
|
54
|
+
webEnv?: string | undefined;
|
|
55
|
+
retstart?: number | undefined;
|
|
56
|
+
retmax?: number | undefined;
|
|
57
|
+
detailLevel?: "abstract_plus" | "full_xml" | "medline_text" | "citation_data" | undefined;
|
|
58
|
+
includeMeshTerms?: boolean | undefined;
|
|
59
|
+
includeGrantInfo?: boolean | undefined;
|
|
60
|
+
outputFormat?: "json" | "raw_text" | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
export type FetchPubMedContentInput = z.infer<typeof FetchPubMedContentInputSchema>;
|
|
63
|
+
export declare function fetchPubMedContentLogic(input: FetchPubMedContentInput, parentRequestContext: RequestContext): Promise<CallToolResult>;
|