@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.
Files changed (121) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +174 -0
  3. package/dist/config/index.d.ts +91 -0
  4. package/dist/config/index.js +324 -0
  5. package/dist/index.d.ts +24 -0
  6. package/dist/index.js +190 -0
  7. package/dist/mcp-server/resources/echoResource/echoResourceLogic.d.ts +79 -0
  8. package/dist/mcp-server/resources/echoResource/echoResourceLogic.js +82 -0
  9. package/dist/mcp-server/resources/echoResource/index.d.ts +13 -0
  10. package/dist/mcp-server/resources/echoResource/index.js +13 -0
  11. package/dist/mcp-server/resources/echoResource/registration.d.ts +30 -0
  12. package/dist/mcp-server/resources/echoResource/registration.js +168 -0
  13. package/dist/mcp-server/server.d.ts +28 -0
  14. package/dist/mcp-server/server.js +159 -0
  15. package/dist/mcp-server/tools/fetchPubMedContent/index.d.ts +6 -0
  16. package/dist/mcp-server/tools/fetchPubMedContent/index.js +6 -0
  17. package/dist/mcp-server/tools/fetchPubMedContent/logic.d.ts +63 -0
  18. package/dist/mcp-server/tools/fetchPubMedContent/logic.js +518 -0
  19. package/dist/mcp-server/tools/fetchPubMedContent/registration.d.ts +10 -0
  20. package/dist/mcp-server/tools/fetchPubMedContent/registration.js +37 -0
  21. package/dist/mcp-server/tools/getPubMedArticleConnections/index.d.ts +6 -0
  22. package/dist/mcp-server/tools/getPubMedArticleConnections/index.js +6 -0
  23. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/citationFormatter.d.ts +9 -0
  24. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/citationFormatter.js +288 -0
  25. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/elinkHandler.d.ts +9 -0
  26. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/elinkHandler.js +208 -0
  27. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/index.d.ts +15 -0
  28. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/index.js +82 -0
  29. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/types.d.ts +27 -0
  30. package/dist/mcp-server/tools/getPubMedArticleConnections/logic/types.js +5 -0
  31. package/dist/mcp-server/tools/getPubMedArticleConnections/logic.d.ts +6 -0
  32. package/dist/mcp-server/tools/getPubMedArticleConnections/logic.js +6 -0
  33. package/dist/mcp-server/tools/getPubMedArticleConnections/registration.d.ts +36 -0
  34. package/dist/mcp-server/tools/getPubMedArticleConnections/registration.js +76 -0
  35. package/dist/mcp-server/tools/pubmedResearchAgent/index.d.ts +6 -0
  36. package/dist/mcp-server/tools/pubmedResearchAgent/index.js +6 -0
  37. package/dist/mcp-server/tools/pubmedResearchAgent/logic/index.d.ts +7 -0
  38. package/dist/mcp-server/tools/pubmedResearchAgent/logic/index.js +9 -0
  39. package/dist/mcp-server/tools/pubmedResearchAgent/logic/inputSchema.d.ts +111 -0
  40. package/dist/mcp-server/tools/pubmedResearchAgent/logic/inputSchema.js +149 -0
  41. package/dist/mcp-server/tools/pubmedResearchAgent/logic/outputTypes.d.ts +106 -0
  42. package/dist/mcp-server/tools/pubmedResearchAgent/logic/outputTypes.js +7 -0
  43. package/dist/mcp-server/tools/pubmedResearchAgent/logic/planOrchestrator.d.ts +10 -0
  44. package/dist/mcp-server/tools/pubmedResearchAgent/logic/planOrchestrator.js +251 -0
  45. package/dist/mcp-server/tools/pubmedResearchAgent/logic.d.ts +12 -0
  46. package/dist/mcp-server/tools/pubmedResearchAgent/logic.js +55 -0
  47. package/dist/mcp-server/tools/pubmedResearchAgent/registration.d.ts +10 -0
  48. package/dist/mcp-server/tools/pubmedResearchAgent/registration.js +36 -0
  49. package/dist/mcp-server/tools/searchPubMedArticles/index.d.ts +6 -0
  50. package/dist/mcp-server/tools/searchPubMedArticles/index.js +6 -0
  51. package/dist/mcp-server/tools/searchPubMedArticles/logic.d.ts +61 -0
  52. package/dist/mcp-server/tools/searchPubMedArticles/logic.js +229 -0
  53. package/dist/mcp-server/tools/searchPubMedArticles/registration.d.ts +10 -0
  54. package/dist/mcp-server/tools/searchPubMedArticles/registration.js +38 -0
  55. package/dist/mcp-server/transports/authentication/authMiddleware.d.ts +29 -0
  56. package/dist/mcp-server/transports/authentication/authMiddleware.js +174 -0
  57. package/dist/mcp-server/transports/httpTransport.d.ts +23 -0
  58. package/dist/mcp-server/transports/httpTransport.js +463 -0
  59. package/dist/mcp-server/transports/stdioTransport.d.ts +42 -0
  60. package/dist/mcp-server/transports/stdioTransport.js +63 -0
  61. package/dist/services/NCBI/ncbiConstants.d.ts +22 -0
  62. package/dist/services/NCBI/ncbiConstants.js +5 -0
  63. package/dist/services/NCBI/ncbiCoreApiClient.d.ts +24 -0
  64. package/dist/services/NCBI/ncbiCoreApiClient.js +118 -0
  65. package/dist/services/NCBI/ncbiRequestQueueManager.d.ts +36 -0
  66. package/dist/services/NCBI/ncbiRequestQueueManager.js +96 -0
  67. package/dist/services/NCBI/ncbiResponseHandler.d.ts +22 -0
  68. package/dist/services/NCBI/ncbiResponseHandler.js +192 -0
  69. package/dist/services/NCBI/ncbiService.d.ts +24 -0
  70. package/dist/services/NCBI/ncbiService.js +57 -0
  71. package/dist/services/index.d.ts +7 -0
  72. package/dist/services/index.js +7 -0
  73. package/dist/services/llm-providers/index.d.ts +7 -0
  74. package/dist/services/llm-providers/index.js +7 -0
  75. package/dist/services/llm-providers/llmFactory.d.ts +69 -0
  76. package/dist/services/llm-providers/llmFactory.js +132 -0
  77. package/dist/services/llm-providers/openRouter/index.d.ts +6 -0
  78. package/dist/services/llm-providers/openRouter/index.js +7 -0
  79. package/dist/services/llm-providers/openRouter/openRouterProvider.d.ts +99 -0
  80. package/dist/services/llm-providers/openRouter/openRouterProvider.js +329 -0
  81. package/dist/types-global/errors.d.ts +119 -0
  82. package/dist/types-global/errors.js +119 -0
  83. package/dist/types-global/pubmedXml.d.ts +350 -0
  84. package/dist/types-global/pubmedXml.js +7 -0
  85. package/dist/utils/index.d.ts +10 -0
  86. package/dist/utils/index.js +18 -0
  87. package/dist/utils/internal/errorHandler.d.ts +176 -0
  88. package/dist/utils/internal/errorHandler.js +335 -0
  89. package/dist/utils/internal/index.d.ts +9 -0
  90. package/dist/utils/internal/index.js +9 -0
  91. package/dist/utils/internal/logger.d.ts +141 -0
  92. package/dist/utils/internal/logger.js +426 -0
  93. package/dist/utils/internal/requestContext.d.ts +83 -0
  94. package/dist/utils/internal/requestContext.js +72 -0
  95. package/dist/utils/metrics/index.d.ts +7 -0
  96. package/dist/utils/metrics/index.js +7 -0
  97. package/dist/utils/metrics/tokenCounter.d.ts +35 -0
  98. package/dist/utils/metrics/tokenCounter.js +110 -0
  99. package/dist/utils/parsing/dateParser.d.ts +73 -0
  100. package/dist/utils/parsing/dateParser.js +107 -0
  101. package/dist/utils/parsing/index.d.ts +8 -0
  102. package/dist/utils/parsing/index.js +8 -0
  103. package/dist/utils/parsing/jsonParser.d.ts +82 -0
  104. package/dist/utils/parsing/jsonParser.js +126 -0
  105. package/dist/utils/parsing/ncbi-parsing/eSummaryResultParser.d.ts +32 -0
  106. package/dist/utils/parsing/ncbi-parsing/eSummaryResultParser.js +295 -0
  107. package/dist/utils/parsing/ncbi-parsing/index.d.ts +8 -0
  108. package/dist/utils/parsing/ncbi-parsing/index.js +8 -0
  109. package/dist/utils/parsing/ncbi-parsing/pubmedArticleStructureParser.d.ts +70 -0
  110. package/dist/utils/parsing/ncbi-parsing/pubmedArticleStructureParser.js +229 -0
  111. package/dist/utils/parsing/ncbi-parsing/xmlGenericHelpers.d.ts +31 -0
  112. package/dist/utils/parsing/ncbi-parsing/xmlGenericHelpers.js +76 -0
  113. package/dist/utils/security/idGenerator.d.ts +134 -0
  114. package/dist/utils/security/idGenerator.js +198 -0
  115. package/dist/utils/security/index.d.ts +9 -0
  116. package/dist/utils/security/index.js +9 -0
  117. package/dist/utils/security/rateLimiter.d.ts +108 -0
  118. package/dist/utils/security/rateLimiter.js +179 -0
  119. package/dist/utils/security/sanitization.d.ts +173 -0
  120. package/dist/utils/security/sanitization.js +439 -0
  121. package/package.json +97 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @fileoverview Orchestrates the generation of the research plan outline
3
+ * by directly mapping detailed client inputs to a structured output format.
4
+ * Omits sections/steps if no relevant input is provided.
5
+ * @module pubmedResearchAgent/logic/planOrchestrator
6
+ */
7
+ import { logger, requestContextService, sanitizeInputForLogging, } from "../../../../utils/index.js";
8
+ // Helper function to conditionally add a prompt prefix or return undefined if input is empty
9
+ function C(userInput, refinedPromptBase, includePrompts) {
10
+ if (!userInput || (Array.isArray(userInput) && userInput.length === 0)) {
11
+ return undefined;
12
+ }
13
+ const joinedInput = Array.isArray(userInput)
14
+ ? userInput.join("; ")
15
+ : userInput;
16
+ if (includePrompts && refinedPromptBase) {
17
+ // Embed the user's input within a more directive prompt
18
+ return `${refinedPromptBase} Based on the provided detail: "${joinedInput}". Ensure critical evaluation and consider alternative interpretations.`;
19
+ }
20
+ return joinedInput;
21
+ }
22
+ // Helper to generate guidance notes
23
+ function G(notes, includePrompts) {
24
+ return includePrompts && notes.length > 0 ? notes : undefined;
25
+ }
26
+ // Helper to check if all properties of an object are undefined
27
+ function allPropertiesUndefined(obj) {
28
+ return Object.values(obj).every((value) => value === undefined);
29
+ }
30
+ // Helper function to recursively remove keys with empty object values
31
+ function removeEmptyObjectsRecursively(obj) {
32
+ // Base cases for recursion
33
+ if (typeof obj !== "object" || obj === null) {
34
+ return obj; // Not an object or array, return as is
35
+ }
36
+ if (Array.isArray(obj)) {
37
+ // If it's an array, recurse on each element
38
+ // And filter out any elements that become empty objects after recursion
39
+ return obj.map(removeEmptyObjectsRecursively).filter((item) => {
40
+ if (typeof item === "object" &&
41
+ item !== null &&
42
+ !Array.isArray(item) &&
43
+ Object.keys(item).length === 0) {
44
+ return false; // Filter out empty objects from arrays
45
+ }
46
+ return true;
47
+ });
48
+ }
49
+ // If it's an object, create a new object with non-empty properties
50
+ const newObj = {};
51
+ for (const key in obj) {
52
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
53
+ const value = removeEmptyObjectsRecursively(obj[key]);
54
+ // Check if the recursed value is an empty object
55
+ if (typeof value === "object" &&
56
+ value !== null &&
57
+ !Array.isArray(value) &&
58
+ Object.keys(value).length === 0) {
59
+ // It's an empty object, so we don't add this key-value pair to newObj
60
+ continue;
61
+ }
62
+ // If value is not an empty object (or not an object at all), add it
63
+ newObj[key] = value;
64
+ }
65
+ }
66
+ return newObj;
67
+ }
68
+ export function generateFullResearchPlanOutline(input, parentRequestContext) {
69
+ const logContext = requestContextService.createRequestContext({
70
+ parentRequestId: parentRequestContext.requestId,
71
+ operation: "generateFullResearchPlanOutlineLog",
72
+ input: sanitizeInputForLogging({ input }), // Add sanitized input here
73
+ });
74
+ logger.debug("Generating full research plan outline.", logContext);
75
+ const inferredGoal = input.primary_research_goal ||
76
+ `to investigate the roles and mechanisms of ${input.research_keywords.join(" and ")}${input.organism_focus ? ` in ${input.organism_focus}` : ""}.`;
77
+ const planTitle = input.project_title_suggestion || `Research Plan Outline: ${inferredGoal}`;
78
+ const addPrompts = input.include_detailed_prompts_for_agent;
79
+ const overallInstructions = `This document is a structured research plan outline, primarily assembled from detailed inputs for project: "${planTitle}". As the research agent, critically evaluate this plan. Your primary function is to fulfill the user's research request by leveraging this structured information alongside your comprehensive knowledge and all available tools (e.g., PubMed search, web search, data analysis, file operations).
80
+ Key responsibilities:
81
+ - Synthesize information to generate scientifically sound content, analyses, or answers.
82
+ - Adapt the level of detail in your final response to precisely match the user's specific query. If a concise answer is requested, use this plan as foundational background.
83
+ - Proactively identify and address potential ambiguities, biases, or limitations in the provided plan or data.
84
+ - Ensure methodological rigor: consider controls, statistical power, reproducibility, and alternative explanations.
85
+ - If critical information is missing or ambiguities hinder robust execution, formulate specific, targeted follow-up questions for the user before proceeding with extensive investigation.
86
+ - Always prioritize accuracy, objectivity, and adherence to scientific best practices.`;
87
+ const p1s1Content = {
88
+ primary_research_question: C(input.p1_specific_research_question, "Critically evaluate and refine the primary research question for clarity, focus, and feasibility", addPrompts),
89
+ knowledge_gap_statement: C(input.p1_knowledge_gap, "Validate and expand on the identified knowledge gap, ensuring it's well-supported by current literature", addPrompts),
90
+ primary_hypothesis: C(input.p1_primary_hypothesis, "Assess the primary hypothesis for testability, specificity, and falsifiability. Consider alternative hypotheses", addPrompts),
91
+ pubmed_search_strategy: C(input.p1_pubmed_search_strategy_description, "Develop a comprehensive PubMed search strategy. Consider MeSH terms, keywords, Boolean operators, and inclusion/exclusion criteria", addPrompts),
92
+ guidance_notes: G([
93
+ "Ensure the research question is SMART (Specific, Measurable, Achievable, Relevant, Time-bound).",
94
+ "Verify the knowledge gap is current and significant.",
95
+ "The hypothesis should directly address the research question.",
96
+ "Consider publication type filters and date ranges for the literature search.",
97
+ ], addPrompts),
98
+ };
99
+ const p1s2Content = {
100
+ literature_review_scope: C(input.p1_literature_review_scope, "Define and justify the scope of the literature review, including timeframes, study types, and key themes to investigate", addPrompts),
101
+ key_databases_and_search_approach: C(input.p1_lit_review_databases_and_approach, "Detail the systematic search approach across specified databases (e.g., PubMed, EMBASE, Scopus). Include strategy for citation searching or snowballing", addPrompts),
102
+ guidance_notes: G([
103
+ "Document search queries and results for reproducibility.",
104
+ "Consider using reference management software.",
105
+ "Plan for screening and selection of articles based on predefined criteria.",
106
+ ], addPrompts),
107
+ };
108
+ const p1s3Content = {
109
+ experimental_paradigm: C(input.p1_experimental_paradigm, "Elaborate on the chosen experimental paradigm, justifying its appropriateness for testing the hypothesis", addPrompts),
110
+ data_acquisition_plan_existing_data: C(input.p1_data_acquisition_plan_existing_data, "Strategize the identification, retrieval, and validation of relevant existing datasets. Specify databases, data types, and access protocols", addPrompts),
111
+ data_acquisition_plan_new_data: C(input.p1_data_acquisition_plan_new_data, "Outline the plan for generating novel data, including experimental models, key procedures, sample size considerations, and data deposition strategy", addPrompts),
112
+ blast_utilization_plan: C(input.p1_blast_utilization_plan, "Specify how sequence alignment tools (e.g., NCBI BLAST) will be employed, including purpose, programs, databases, and interpretation of results", addPrompts),
113
+ controls_and_rigor_measures: C(input.p1_controls_and_rigor, "Detail crucial experimental controls (positive, negative, internal) and measures to ensure scientific rigor, reproducibility, and minimization of bias", addPrompts),
114
+ methodological_challenges_and_mitigation: C(input.p1_methodological_challenges_and_mitigation, "Anticipate potential methodological challenges, their impact, and robust mitigation strategies", addPrompts),
115
+ guidance_notes: G([
116
+ "Ensure sample sizes are adequately powered.",
117
+ "Consider blinding and randomization where appropriate.",
118
+ "Define clear endpoints and outcome measures.",
119
+ "Address potential confounders in the experimental design.",
120
+ ], addPrompts),
121
+ };
122
+ const p2s1Content = {
123
+ data_collection_methods_wet_lab: C(input.p2_data_collection_methods_wet_lab, "Provide detailed wet-lab protocols, including sample preparation, experimental treatments, instrument settings, and data recording procedures", addPrompts),
124
+ data_collection_methods_dry_lab: C(input.p2_data_collection_methods_dry_lab, "Specify execution details for computational data retrieval, including precise queries, API usage, versioning of tools, and data provenance tracking", addPrompts),
125
+ guidance_notes: G([
126
+ "Standardize protocols to ensure consistency.",
127
+ "Implement robust data labeling and organization from the outset.",
128
+ "Document any deviations from planned protocols.",
129
+ ], addPrompts),
130
+ };
131
+ const p2s2Content = {
132
+ data_preprocessing_and_qc_plan: C(input.p2_data_preprocessing_and_qc_plan, "Describe the comprehensive pipeline for data cleaning, normalization, transformation, and quality control. Specify metrics, thresholds, and tools for each step", addPrompts),
133
+ guidance_notes: G([
134
+ "Define criteria for outlier detection and handling.",
135
+ "Assess data quality before and after preprocessing.",
136
+ "Ensure preprocessing steps are appropriate for downstream analyses.",
137
+ ], addPrompts),
138
+ };
139
+ const p3s1Content = {
140
+ data_analysis_strategy: C(input.p3_data_analysis_strategy, "Outline the core statistical and computational methods for data analysis. Specify tests, software, parameters, and how they address the hypotheses", addPrompts),
141
+ bioinformatics_pipeline_summary: C(input.p3_bioinformatics_pipeline_summary, "Summarize the bioinformatics pipeline for high-throughput data, detailing tools, algorithms, parameter settings, and workflow for downstream analyses", addPrompts),
142
+ guidance_notes: G([
143
+ "Justify the choice of statistical tests based on data distribution and assumptions.",
144
+ "Address multiple testing corrections if applicable.",
145
+ "Consider sensitivity analyses to assess robustness of findings.",
146
+ ], addPrompts),
147
+ };
148
+ const p3s2Content = {
149
+ results_interpretation_framework: C(input.p3_results_interpretation_framework, "Establish a clear framework for interpreting analytical findings in the context of the hypotheses, considering statistical significance, effect sizes, and biological relevance", addPrompts),
150
+ comparison_with_literature_plan: C(input.p3_comparison_with_literature_plan, "Develop a strategy for systematically contextualizing results with existing literature, addressing consistencies, discrepancies, and novel contributions", addPrompts),
151
+ guidance_notes: G([
152
+ "Distinguish correlation from causation.",
153
+ "Acknowledge limitations of the study and their impact on interpretation.",
154
+ "Discuss clinical or translational implications if relevant.",
155
+ ], addPrompts),
156
+ };
157
+ const p4s1Content = {
158
+ dissemination_manuscript_plan: C(input.p4_dissemination_manuscript_plan, "Formulate a plan for manuscript preparation, including core message, target journal profile, key figures/tables, and authorship contributions", addPrompts),
159
+ dissemination_data_deposition_plan: C(input.p4_dissemination_data_deposition_plan, "Outline a strategy for depositing research data in public repositories, specifying data types, repository choices, metadata standards, and adherence to FAIR principles", addPrompts),
160
+ guidance_notes: G([
161
+ "Follow journal-specific author guidelines.",
162
+ "Ensure data is de-identified if it contains sensitive information.",
163
+ "Obtain DOIs or accession numbers for deposited data.",
164
+ ], addPrompts),
165
+ };
166
+ const p4s2Content = {
167
+ peer_review_and_publication_approach: C(input.p4_peer_review_and_publication_approach, "Describe the approach to journal submission, navigating peer review, and addressing reviewer comments constructively for publication", addPrompts),
168
+ guidance_notes: G([
169
+ "Prepare a compelling cover letter.",
170
+ "Respond to reviewer comments point-by-point and respectfully.",
171
+ "Consider pre-print servers for early dissemination.",
172
+ ], addPrompts),
173
+ };
174
+ const p4s3Content = {
175
+ future_research_directions: C(input.p4_future_research_directions, "Identify and articulate potential next steps, new research questions, or translational applications arising from the current study's findings and limitations", addPrompts),
176
+ guidance_notes: G([
177
+ "Base future directions on the study's actual outcomes.",
178
+ "Consider how new technologies or approaches could address remaining questions.",
179
+ ], addPrompts),
180
+ };
181
+ const ccContent = {
182
+ record_keeping_and_data_management: C(input.cc_record_keeping_and_data_management, "Detail the comprehensive plan for meticulous record-keeping, version control (code, data, manuscripts), secure data storage, backup strategy, and Data Management Plan (DMP) adherence", addPrompts),
183
+ collaboration_strategy: C(input.cc_collaboration_strategy, "If applicable, describe the strategy for effective collaboration, including communication channels, role delineation, data sharing protocols, and authorship agreements", addPrompts),
184
+ ethical_considerations: C(input.cc_ethical_considerations, "Thoroughly outline all ethical considerations, including plans for IRB/IACUC approval, informed consent, data privacy/anonymization, responsible conduct of research (RCR) training, and conflict of interest management", addPrompts),
185
+ guidance_notes: G([
186
+ "Ensure compliance with institutional and funding agency requirements.",
187
+ "Regularly review and update the DMP.",
188
+ "Promote open science practices where appropriate.",
189
+ ], addPrompts),
190
+ };
191
+ const plan = {
192
+ plan_title: planTitle,
193
+ overall_instructions_for_research_agent: addPrompts
194
+ ? overallInstructions
195
+ : undefined,
196
+ input_summary: {
197
+ keywords_received: input.research_keywords,
198
+ primary_goal_stated_or_inferred: inferredGoal,
199
+ organism_focus: input.organism_focus || "Not Specified",
200
+ // Correctly use the input flag name
201
+ included_detailed_prompts_for_agent: input.include_detailed_prompts_for_agent,
202
+ },
203
+ phase_1_conception_and_planning: {
204
+ title: "Phase 1: Conception and Planning",
205
+ step_1_1_research_question_and_hypothesis: allPropertiesUndefined(p1s1Content)
206
+ ? {}
207
+ : p1s1Content,
208
+ step_1_2_literature_review_strategy: allPropertiesUndefined(p1s2Content)
209
+ ? {}
210
+ : p1s2Content,
211
+ step_1_3_experimental_design_and_data_acquisition: allPropertiesUndefined(p1s3Content)
212
+ ? {}
213
+ : p1s3Content,
214
+ },
215
+ phase_2_data_collection_and_processing: {
216
+ title: "Phase 2: Data Collection and Processing",
217
+ step_2_1_data_collection_retrieval: allPropertiesUndefined(p2s1Content)
218
+ ? {}
219
+ : p2s1Content,
220
+ step_2_2_data_preprocessing_and_qc: allPropertiesUndefined(p2s2Content)
221
+ ? {}
222
+ : p2s2Content,
223
+ },
224
+ phase_3_analysis_and_interpretation: {
225
+ title: "Phase 3: Analysis and Interpretation",
226
+ step_3_1_data_analysis_plan: allPropertiesUndefined(p3s1Content)
227
+ ? {}
228
+ : p3s1Content,
229
+ step_3_2_results_interpretation: allPropertiesUndefined(p3s2Content)
230
+ ? {}
231
+ : p3s2Content,
232
+ },
233
+ phase_4_dissemination_and_iteration: {
234
+ title: "Phase 4: Dissemination and Iteration",
235
+ step_4_1_dissemination_strategy: allPropertiesUndefined(p4s1Content)
236
+ ? {}
237
+ : p4s1Content,
238
+ step_4_2_peer_review_and_publication: allPropertiesUndefined(p4s2Content)
239
+ ? {}
240
+ : p4s2Content,
241
+ step_4_3_further_research_and_iteration: allPropertiesUndefined(p4s3Content)
242
+ ? {}
243
+ : p4s3Content,
244
+ },
245
+ cross_cutting_considerations: {
246
+ title: "Cross-Cutting Considerations",
247
+ content: allPropertiesUndefined(ccContent) ? {} : ccContent,
248
+ },
249
+ };
250
+ return removeEmptyObjectsRecursively(plan);
251
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fileoverview Core logic invocation for the pubmed_research_agent tool.
3
+ * This tool generates a structured research plan outline with instructive placeholders,
4
+ * designed to be completed by a calling LLM (the MCP Client).
5
+ * @module pubmedResearchAgent/logic
6
+ */
7
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
8
+ import { RequestContext } from "../../../utils/index.js";
9
+ import { // Re-export for registration
10
+ PubMedResearchAgentInput, PubMedResearchAgentInputSchema } from "./logic/index.js";
11
+ export { PubMedResearchAgentInput, PubMedResearchAgentInputSchema };
12
+ export declare function pubmedResearchAgentLogic(input: PubMedResearchAgentInput, parentRequestContext: RequestContext): Promise<CallToolResult>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @fileoverview Core logic invocation for the pubmed_research_agent tool.
3
+ * This tool generates a structured research plan outline with instructive placeholders,
4
+ * designed to be completed by a calling LLM (the MCP Client).
5
+ * @module pubmedResearchAgent/logic
6
+ */
7
+ import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
8
+ import { logger, requestContextService, sanitizeInputForLogging, } from "../../../utils/index.js";
9
+ import { generateFullResearchPlanOutline, PubMedResearchAgentInputSchema, // Re-export for registration
10
+ } from "./logic/index.js";
11
+ // Re-export schema and input type for easy access by registration.ts
12
+ export { PubMedResearchAgentInputSchema };
13
+ export async function pubmedResearchAgentLogic(input, parentRequestContext) {
14
+ const operationContext = requestContextService.createRequestContext({
15
+ parentRequestId: parentRequestContext.requestId,
16
+ operation: "pubmedResearchAgentLogicExecution",
17
+ input: sanitizeInputForLogging(input),
18
+ });
19
+ logger.info(`Executing 'pubmed_research_agent' to generate research plan outline. Keywords: ${input.research_keywords.join(", ")}`, operationContext);
20
+ try {
21
+ const researchPlanOutline = generateFullResearchPlanOutline(input, operationContext);
22
+ return {
23
+ content: [
24
+ { type: "text", text: JSON.stringify(researchPlanOutline, null, 2) },
25
+ ],
26
+ isError: false,
27
+ };
28
+ }
29
+ catch (error) {
30
+ logger.error("Execution failed for 'pubmed_research_agent'", error, operationContext);
31
+ const mcpError = error instanceof McpError
32
+ ? error
33
+ : new McpError(BaseErrorCode.INTERNAL_ERROR, // Using a generic internal error
34
+ `'pubmed_research_agent' tool failed during plan outline generation: ${error.message || "Internal server error."}`, {
35
+ originalErrorName: error.name,
36
+ requestId: operationContext.requestId,
37
+ inputKeywords: input.research_keywords, // Adding some input context to error
38
+ });
39
+ return {
40
+ content: [
41
+ {
42
+ type: "text",
43
+ text: JSON.stringify({
44
+ error: {
45
+ code: mcpError.code,
46
+ message: mcpError.message,
47
+ details: mcpError.details,
48
+ },
49
+ }),
50
+ },
51
+ ],
52
+ isError: true,
53
+ };
54
+ }
55
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Registration for the pubmed_research_agent tool.
3
+ * @module pubmedResearchAgent/registration
4
+ */
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ /**
7
+ * Registers the pubmed_research_agent tool with the MCP server.
8
+ * @param server - The McpServer instance.
9
+ */
10
+ export declare function registerPubMedResearchAgentTool(server: McpServer): void;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Registration for the pubmed_research_agent tool.
3
+ * @module pubmedResearchAgent/registration
4
+ */
5
+ import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
6
+ import { ErrorHandler, logger, requestContextService, } from "../../../utils/index.js";
7
+ import { PubMedResearchAgentInputSchema, pubmedResearchAgentLogic, } from "./logic.js";
8
+ /**
9
+ * Registers the pubmed_research_agent tool with the MCP server.
10
+ * @param server - The McpServer instance.
11
+ */
12
+ export function registerPubMedResearchAgentTool(server) {
13
+ const operation = "registerPubMedResearchAgentTool";
14
+ const context = requestContextService.createRequestContext({ operation });
15
+ try {
16
+ server.tool("pubmed_research_agent", "Generates a standardized JSON research plan outline from component details you provide. It accepts granular inputs for all research phases (conception, data collection, analysis, dissemination, cross-cutting concerns). If `include_detailed_prompts_for_agent` is true, the output plan will embed instructive prompts and detailed guidance notes to aid the research agent. The tool's primary function is to organize and structure your rough ideas into a formal, machine-readable plan. This plan is intended for further processing; as the research agent, you should then utilize your full suite of tools (e.g., file manipulation, `get_pubmed_article_connections` for literature/data search via PMID) to execute the outlined research, tailored to the user's request.", PubMedResearchAgentInputSchema.shape, async (validatedInput, mcpProvidedContext) => {
17
+ const handlerRequestContext = requestContextService.createRequestContext({
18
+ parentRequestId: context.requestId,
19
+ operation: "pubmedResearchAgentHandler",
20
+ mcpToolContext: mcpProvidedContext,
21
+ });
22
+ return pubmedResearchAgentLogic(validatedInput, handlerRequestContext);
23
+ });
24
+ logger.notice(`Tool 'pubmed_research_agent' registered.`, context);
25
+ }
26
+ catch (error) {
27
+ ErrorHandler.handleError(new McpError(BaseErrorCode.INITIALIZATION_FAILED, "Failed to register pubmed_research_agent tool", {
28
+ originalError: error instanceof Error ? error.message : String(error),
29
+ }), {
30
+ operation,
31
+ context,
32
+ errorCode: BaseErrorCode.INITIALIZATION_FAILED,
33
+ critical: true,
34
+ });
35
+ }
36
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Barrel file for the searchPubMedArticles tool.
3
+ * Exports the tool's registration function.
4
+ * @module src/mcp-server/tools/searchPubMedArticles/index
5
+ */
6
+ export { registerSearchPubMedArticlesTool } from "./registration.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Barrel file for the searchPubMedArticles tool.
3
+ * Exports the tool's registration function.
4
+ * @module src/mcp-server/tools/searchPubMedArticles/index
5
+ */
6
+ export { registerSearchPubMedArticlesTool } from "./registration.js";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview Logic for the searchPubMedArticles MCP tool.
3
+ * Handles constructing ESearch and ESummary queries, interacting with
4
+ * the NcbiService, and formatting the results.
5
+ * @module src/mcp-server/tools/searchPubMedArticles/logic
6
+ */
7
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
8
+ import { z } from "zod";
9
+ import { RequestContext } from "../../../utils/index.js";
10
+ export declare const SearchPubMedArticlesInputSchema: z.ZodObject<{
11
+ queryTerm: z.ZodString;
12
+ maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
13
+ sortBy: z.ZodDefault<z.ZodOptional<z.ZodEnum<["relevance", "pub_date", "author", "journal_name"]>>>;
14
+ dateRange: z.ZodOptional<z.ZodObject<{
15
+ minDate: z.ZodOptional<z.ZodString>;
16
+ maxDate: z.ZodOptional<z.ZodString>;
17
+ dateType: z.ZodDefault<z.ZodOptional<z.ZodEnum<["pdat", "mdat", "edat"]>>>;
18
+ }, "strip", z.ZodTypeAny, {
19
+ dateType: "pdat" | "mdat" | "edat";
20
+ minDate?: string | undefined;
21
+ maxDate?: string | undefined;
22
+ }, {
23
+ minDate?: string | undefined;
24
+ maxDate?: string | undefined;
25
+ dateType?: "pdat" | "mdat" | "edat" | undefined;
26
+ }>>;
27
+ filterByPublicationTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
28
+ fetchBriefSummaries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ queryTerm: string;
31
+ maxResults: number;
32
+ sortBy: "relevance" | "pub_date" | "author" | "journal_name";
33
+ fetchBriefSummaries: number;
34
+ dateRange?: {
35
+ dateType: "pdat" | "mdat" | "edat";
36
+ minDate?: string | undefined;
37
+ maxDate?: string | undefined;
38
+ } | undefined;
39
+ filterByPublicationTypes?: string[] | undefined;
40
+ }, {
41
+ queryTerm: string;
42
+ maxResults?: number | undefined;
43
+ sortBy?: "relevance" | "pub_date" | "author" | "journal_name" | undefined;
44
+ dateRange?: {
45
+ minDate?: string | undefined;
46
+ maxDate?: string | undefined;
47
+ dateType?: "pdat" | "mdat" | "edat" | undefined;
48
+ } | undefined;
49
+ filterByPublicationTypes?: string[] | undefined;
50
+ fetchBriefSummaries?: number | undefined;
51
+ }>;
52
+ export type SearchPubMedArticlesInput = z.infer<typeof SearchPubMedArticlesInputSchema>;
53
+ /**
54
+ * Logic for the searchPubMedArticles tool.
55
+ * Constructs and executes ESearch and optionally ESummary queries via NcbiService,
56
+ * then formats the results into a CallToolResult.
57
+ * @param input - Validated input arguments for the tool.
58
+ * @param parentRequestContext - The parent request context for logging and correlation.
59
+ * @returns A promise resolving to a CallToolResult.
60
+ */
61
+ export declare function searchPubMedArticlesLogic(input: SearchPubMedArticlesInput, parentRequestContext: RequestContext): Promise<CallToolResult>;