Chris McMaster commited on
Commit
56881ad
·
1 Parent(s): 819adf9

Enhancements

Browse files
Files changed (4) hide show
  1. .gitignore +3 -1
  2. README.md +1 -0
  3. app.py +319 -250
  4. requirements.txt +3 -1
.gitignore CHANGED
@@ -11,4 +11,6 @@ __pycache__/
11
  *.pyz
12
  *.pywz
13
  *.pyzw
14
- *.pyzwz
 
 
 
11
  *.pyz
12
  *.pywz
13
  *.pyzw
14
+ *.pyzwz
15
+
16
+ chatbot.py
README.md CHANGED
@@ -14,6 +14,7 @@ tags:
14
  - drug-information
15
  - calculator
16
  - gradio
 
17
  ---
18
  # Pharmacist MCP Server
19
 
 
14
  - drug-information
15
  - calculator
16
  - gradio
17
+ - mcp-server-track
18
  ---
19
  # Pharmacist MCP Server
20
 
app.py CHANGED
@@ -166,7 +166,7 @@ def _creatinine_conversion_gradio(value: float, from_unit: str, to_unit: str):
166
  @with_caching(ttl=1800)
167
  def search_adverse_events_mcp(drug_name: str, limit: str = "5") -> str:
168
  """
169
- Search FAERS for adverse events related to a drug and return brief summaries.
170
 
171
  Args:
172
  drug_name (str): Generic or brand name to search (case-insensitive)
@@ -184,7 +184,7 @@ def search_adverse_events_mcp(drug_name: str, limit: str = "5") -> str:
184
  @with_caching(ttl=3600)
185
  def fetch_event_details_mcp(event_id: str) -> str:
186
  """
187
- Fetch full FAERS case details by safety-report ID.
188
 
189
  Args:
190
  event_id (str): Numeric FAERS safetyreportid string
@@ -200,7 +200,7 @@ def fetch_event_details_mcp(event_id: str) -> str:
200
  @with_caching(ttl=7200)
201
  def drug_label_warnings_mcp(drug_name: str) -> str:
202
  """
203
- Get FDA label warnings including boxed warnings, contraindications, and drug interactions.
204
 
205
  Args:
206
  drug_name (str): Generic drug name preferred
@@ -216,7 +216,7 @@ def drug_label_warnings_mcp(drug_name: str) -> str:
216
  @with_caching(ttl=3600)
217
  def drug_recalls_mcp(drug_name: str, limit: str = "5") -> str:
218
  """
219
- Find recent FDA recall events for a drug.
220
 
221
  Args:
222
  drug_name (str): Free-text search string for the drug
@@ -234,7 +234,7 @@ def drug_recalls_mcp(drug_name: str, limit: str = "5") -> str:
234
  @with_caching(ttl=7200)
235
  def drug_pregnancy_lactation_mcp(drug_name: str) -> str:
236
  """
237
- Get pregnancy and lactation information from FDA drug labels.
238
 
239
  Args:
240
  drug_name (str): Generic drug name preferred
@@ -250,7 +250,7 @@ def drug_pregnancy_lactation_mcp(drug_name: str) -> str:
250
  @with_caching(ttl=7200) # 2 hours cache
251
  def drug_dose_adjustments_mcp(drug_name: str) -> str:
252
  """
253
- Get renal and hepatic dose adjustment information from FDA labels.
254
 
255
  Args:
256
  drug_name (str): Generic drug name
@@ -266,7 +266,7 @@ def drug_dose_adjustments_mcp(drug_name: str) -> str:
266
  @with_caching(ttl=1800) # 30 minutes cache
267
  def drug_livertox_summary_mcp(drug_name: str) -> str:
268
  """
269
- Get hepatotoxicity information from the LiverTox database.
270
 
271
  Args:
272
  drug_name (str): Drug name to search for (case-insensitive)
@@ -281,7 +281,7 @@ def drug_livertox_summary_mcp(drug_name: str) -> str:
281
  @with_error_handling
282
  def brand_to_generic_lookup_mcp(brand_name: str) -> str:
283
  """
284
- Look up generic drug information from brand names.
285
 
286
  Args:
287
  brand_name (str): Brand name to look up
@@ -296,11 +296,9 @@ def brand_to_generic_lookup_mcp(brand_name: str) -> str:
296
  @with_error_handling
297
  def calculate_drug_burden_index_mcp(drug_list: str) -> str:
298
  """
299
- Calculate Drug Burden Index (DBI) from a list of medications with automatic route detection.
300
 
301
- This intelligent version automatically detects the route of administration for each medication
302
- (oral, transdermal patches, parenteral injections, etc.) and uses the appropriate reference
303
- data for each route. Perfect for real-world medication lists with mixed formulations.
304
 
305
  Args:
306
  drug_list (str): Drug list (one per line, include dose and frequency - also write "prn" if the drug is a PRN medication)
@@ -324,7 +322,7 @@ def calculate_creatinine_clearance_mcp(
324
  age: str, weight_kg: str, serum_creatinine: str, is_female: str
325
  ) -> str:
326
  """
327
- Calculate creatinine clearance using Cockcroft-Gault equation.
328
 
329
  Args:
330
  age (str): Patient's age in years
@@ -351,7 +349,7 @@ def calculate_egfr_mcp(
351
  age: str, serum_creatinine: str, is_female: str, is_black: str
352
  ) -> str:
353
  """
354
- Calculate estimated glomerular filtration rate using CKD-EPI equation.
355
 
356
  Args:
357
  age (str): Patient's age in years
@@ -376,7 +374,7 @@ def calculate_child_pugh_score_mcp(
376
  bilirubin: str, albumin: str, inr: str, ascites: str, encephalopathy: str
377
  ) -> str:
378
  """
379
- Calculate Child-Pugh score for liver function assessment.
380
 
381
  Args:
382
  bilirubin (str): Total bilirubin in mg/dL
@@ -401,7 +399,7 @@ def calculate_child_pugh_score_mcp(
401
  @with_error_handling
402
  def calculate_bmi_mcp(weight_kg: str, height_cm: str) -> str:
403
  """
404
- Calculate Body Mass Index (BMI) and weight category.
405
 
406
  Args:
407
  weight_kg (str): Weight in kilograms
@@ -420,7 +418,7 @@ def calculate_bmi_mcp(weight_kg: str, height_cm: str) -> str:
420
  @with_error_handling
421
  def calculate_ideal_body_weight_mcp(height_cm: str, is_male: str) -> str:
422
  """
423
- Calculate Ideal Body Weight (IBW) using the Devine formula.
424
 
425
  Args:
426
  height_cm (str): Patient's height in cm
@@ -441,7 +439,7 @@ def recommend_dosing_weight_mcp(
441
  actual_weight: str, height_cm: str, is_male: str
442
  ) -> str:
443
  """
444
- Recommend appropriate weight for medication dosing calculations.
445
 
446
  Args:
447
  actual_weight (str): Patient's actual weight in kg
@@ -462,7 +460,7 @@ def recommend_dosing_weight_mcp(
462
  @with_error_handling
463
  def convert_creatinine_units_mcp(value: str, from_unit: str, to_unit: str) -> str:
464
  """
465
- Convert creatinine values between mg/dL and μmol/L units.
466
 
467
  Args:
468
  value (str): The creatinine value to convert
@@ -481,7 +479,7 @@ def convert_creatinine_units_mcp(value: str, from_unit: str, to_unit: str) -> st
481
  @with_error_handling
482
  def get_cache_stats_mcp() -> str:
483
  """
484
- Get cache statistics for monitoring and debugging.
485
 
486
  Returns:
487
  str: JSON string with cache hit rates, size, and other metrics
@@ -501,7 +499,7 @@ def get_cache_stats_mcp() -> str:
501
  @with_error_handling
502
  def health_check_mcp() -> str:
503
  """
504
- Health check endpoint for monitoring MCP server status.
505
 
506
  Returns:
507
  str: JSON string with server health information
@@ -559,7 +557,8 @@ def enhanced_faers_search_mcp(
559
  limit: str = "100"
560
  ) -> str:
561
  """
562
- Enhanced FAERS search with filtering capabilities for pharmacovigilance analysis.
 
563
 
564
  Args:
565
  drug_name (str): Drug name to search for
@@ -606,10 +605,20 @@ def calculate_naranjo_score_mcp(
606
  reaction_appeared_after_suspected_drug_given: str
607
  ) -> str:
608
  """
609
- Calculate Naranjo Adverse Drug Reaction Probability Scale.
 
610
 
611
  Args:
612
- All parameters should be "yes", "no", or "unknown"
 
 
 
 
 
 
 
 
 
613
 
614
  Returns:
615
  str: JSON string with score, probability category, and detailed breakdown
@@ -637,7 +646,7 @@ def disproportionality_analysis_mcp(
637
  background_limit: str = "10000"
638
  ) -> str:
639
  """
640
- Perform disproportionality analysis to detect potential drug-adverse event signals.
641
 
642
  Args:
643
  drug_name (str): Drug of interest
@@ -665,7 +674,7 @@ def find_similar_cases_mcp(
665
  limit: str = "50"
666
  ) -> str:
667
  """
668
- Find cases similar to a reference case based on patient characteristics, drugs, and adverse events.
669
 
670
  Args:
671
  reference_case_id (str): FAERS safety report ID to use as reference
@@ -698,7 +707,7 @@ def temporal_analysis_mcp(
698
  limit: str = "500"
699
  ) -> str:
700
  """
701
- Analyze temporal patterns of adverse events for a drug.
702
 
703
  Args:
704
  drug_name (str): Drug to analyze
@@ -720,230 +729,290 @@ def temporal_analysis_mcp(
720
  return format_json_output(standardize_response(result, "temporal_analysis"))
721
 
722
 
723
- ae_search_ui = gr.Interface(
724
- fn=search_adverse_events_mcp,
725
- inputs=[gr.Text(label="Drug Name"), gr.Text(label="Limit", value="5")],
726
- outputs=gr.JSON(label="Output"),
727
- title="AE Search",
728
- api_name="ae_search",
729
- description="Search FAERS for adverse events.",
730
- )
731
-
732
- ae_details_ui = gr.Interface(
733
- fn=fetch_event_details_mcp,
734
- inputs=gr.Text(label="FAERS Event ID"),
735
- outputs=gr.JSON(label="Output"),
736
- title="AE Details",
737
- api_name="ae_details",
738
- description="Fetch a full FAERS case by safety-report ID.",
739
- )
740
-
741
- warnings_ui = gr.Interface(
742
- fn=drug_label_warnings_mcp,
743
- inputs=gr.Text(label="Drug Name"),
744
- outputs=gr.JSON(label="Output"),
745
- title="Label Warnings",
746
- api_name="label_warnings",
747
- description="Get FDA label warnings.",
748
- )
749
-
750
- recalls_ui = gr.Interface(
751
- fn=drug_recalls_mcp,
752
- inputs=[gr.Text(label="Drug"), gr.Text(label="Limit", value="5")],
753
- outputs=gr.JSON(label="Output"),
754
- title="Drug Recalls",
755
- api_name="drug_recalls",
756
- description="Return recent FDA recall events for a drug.",
757
- )
758
-
759
- pregnancy_ui = gr.Interface(
760
- fn=drug_pregnancy_lactation_mcp,
761
- inputs=gr.Text(label="Drug"),
762
- outputs=gr.JSON(label="Output"),
763
- title="Pregnancy & Lactation",
764
- api_name="pregnancy_lactation",
765
- description="Return Pregnancy & Lactation text from FDA label.",
766
- )
767
-
768
- adjustments_ui = gr.Interface(
769
- fn=drug_dose_adjustments_mcp,
770
- inputs=gr.Text(label="Drug"),
771
- outputs=gr.JSON(label="Output"),
772
- title="Dose Adjustments",
773
- api_name="dose_adjustments",
774
- description="Return renal & hepatic dosing excerpts from FDA label.",
775
- )
776
-
777
- livertox_ui = gr.Interface(
778
- fn=drug_livertox_summary_mcp,
779
- inputs=gr.Text(label="Drug Name"),
780
- outputs=gr.JSON(label="Output"),
781
- title="LiverTox Summary",
782
- api_name="livertox_summary",
783
- description="Get hepatotoxicity information.",
784
- )
785
-
786
- brand_generic_ui = gr.Interface(
787
- fn=brand_to_generic_lookup_mcp,
788
- inputs=[
789
- gr.Text(label="Brand Name"),
790
- ],
791
- outputs=gr.JSON(label="Output"),
792
- title="Brand to Generic",
793
- api_name="brand_to_generic",
794
- description="Look up generic drug information.",
795
- )
796
-
797
- dbi_calculator_ui = gr.Interface(
798
- fn=calculate_drug_burden_index_mcp,
799
- inputs=[
800
- gr.Textbox(
801
- label="Drug List (one per line, include dose and frequency)",
802
- lines=10,
803
- placeholder="e.g., Fentanyl 25mcg/hr patch daily\nAmitriptyline 25mg tablet twice daily\nMorphine 10mg injection PRN",
804
- ),
805
- ],
806
- outputs=gr.JSON(label="DBI Calculation with Route Detection"),
807
- title="DBI Calculator",
808
- api_name="dbi_calculator",
809
- description="Intelligent DBI calculator that automatically detects routes (oral, patches, injections, etc.) and uses appropriate reference data for each medication.",
810
- )
811
-
812
-
813
-
814
- cockcroft_gault_ui = gr.Interface(
815
- fn=calculate_creatinine_clearance_mcp,
816
- inputs=[
817
- gr.Text(label="Age (years)", value="65"),
818
- gr.Text(label="Weight (kg)", value="70"),
819
- gr.Text(label="Serum Creatinine (mg/dL)", value="1.2"),
820
- gr.Text(label="Is Female (true/false)", value="false"),
821
- ],
822
- outputs=gr.JSON(label="Creatinine Clearance"),
823
- title="Cockcroft-Gault Calculator",
824
- api_name="cockcroft_gault",
825
- description="Calculate creatinine clearance using Cockcroft-Gault equation for dose adjustments.",
826
- )
827
-
828
- ckd_epi_ui = gr.Interface(
829
- fn=calculate_egfr_mcp,
830
- inputs=[
831
- gr.Text(label="Age (years)", value="65"),
832
- gr.Text(label="Serum Creatinine (mg/dL)", value="1.2"),
833
- gr.Text(label="Is Female (true/false)", value="false"),
834
- gr.Text(label="Is Black (true/false)", value="false"),
835
- ],
836
- outputs=gr.JSON(label="eGFR"),
837
- title="CKD-EPI eGFR Calculator",
838
- api_name="ckd_epi",
839
- description="Calculate estimated glomerular filtration rate using CKD-EPI equation.",
840
- )
841
-
842
- child_pugh_ui = gr.Interface(
843
- fn=calculate_child_pugh_score_mcp,
844
- inputs=[
845
- gr.Text(label="Total Bilirubin (mg/dL)", value="1.5"),
846
- gr.Text(label="Serum Albumin (g/dL)", value="3.5"),
847
- gr.Text(label="INR", value="1.3"),
848
- gr.Dropdown(["none", "mild", "moderate-severe"], value="none", label="Ascites"),
849
- gr.Dropdown(
850
- ["none", "grade-1-2", "grade-3-4"], value="none", label="Encephalopathy"
851
- ),
852
- ],
853
- outputs=gr.JSON(label="Child-Pugh Score"),
854
- title="Child-Pugh Score Calculator",
855
- api_name="child_pugh",
856
- description="Calculate Child-Pugh score for liver function assessment and dose adjustments.",
857
- )
858
-
859
- bmi_ui = gr.Interface(
860
- fn=calculate_bmi_mcp,
861
- inputs=[
862
- gr.Text(label="Weight (kg)", value="70"),
863
- gr.Text(label="Height (cm)", value="170"),
864
- ],
865
- outputs=gr.JSON(label="BMI Calculation"),
866
- title="BMI Calculator",
867
- api_name="bmi_calculator",
868
- description="Calculate Body Mass Index and weight category assessment.",
869
- )
870
-
871
- ideal_body_weight_ui = gr.Interface(
872
- fn=calculate_ideal_body_weight_mcp,
873
- inputs=[
874
- gr.Text(label="Height (cm)", value="170"),
875
- gr.Text(label="Is Male (true/false)", value="true"),
876
- ],
877
- outputs=gr.JSON(label="Ideal Body Weight Calculation"),
878
- title="Ideal Body Weight (IBW) Calculator",
879
- api_name="ideal_body_weight",
880
- description="Calculate Ideal Body Weight using the Devine formula.",
881
- )
882
-
883
- dosing_weight_ui = gr.Interface(
884
- fn=recommend_dosing_weight_mcp,
885
- inputs=[
886
- gr.Text(label="Actual Weight (kg)", value="85"),
887
- gr.Text(label="Height (cm)", value="170"),
888
- gr.Text(label="Is Male (true/false)", value="true"),
889
- ],
890
- outputs=gr.JSON(label="Dosing Weight Recommendation"),
891
- title="Dosing Weight Calculator",
892
- api_name="dosing_weight",
893
- description="Recommend appropriate weight for medication dosing calculations.",
894
- )
895
-
896
- creatinine_convert_ui = gr.Interface(
897
- fn=convert_creatinine_units_mcp,
898
- inputs=[
899
- gr.Text(label="Creatinine Value", value="1.2"),
900
- gr.Dropdown(["mg_dl", "umol_l"], value="mg_dl", label="From Unit"),
901
- gr.Dropdown(["mg_dl", "umol_l"], value="umol_l", label="To Unit"),
902
- ],
903
- outputs=gr.JSON(label="Converted Value"),
904
- title="Creatinine Unit Converter",
905
- api_name="creatinine_converter",
906
- description="Convert creatinine values between mg/dL and μmol/L.",
907
- )
908
 
909
- demo = gr.TabbedInterface(
910
- [
911
- ae_search_ui,
912
- ae_details_ui,
913
- warnings_ui,
914
- recalls_ui,
915
- pregnancy_ui,
916
- adjustments_ui,
917
- livertox_ui,
918
- brand_generic_ui,
919
- dbi_calculator_ui,
920
- cockcroft_gault_ui,
921
- ckd_epi_ui,
922
- child_pugh_ui,
923
- bmi_ui,
924
- ideal_body_weight_ui,
925
- dosing_weight_ui,
926
- creatinine_convert_ui,
927
- ],
928
- [
929
- "AE Search",
930
- "AE Details",
931
- "Label Warnings",
932
- "Recalls",
933
- "Pregnancy",
934
- "Dose Adjustments",
935
- "LiverTox",
936
- "Brand to Generic",
937
- "DBI Calculator",
938
- "Creatinine CL",
939
- "eGFR",
940
- "Child-Pugh",
941
- "BMI",
942
- "IBW",
943
- "Dosing Weight",
944
- "Unit Converter",
945
- ],
946
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
947
 
948
  if __name__ == "__main__":
949
  demo.launch(mcp_server=True, show_error=True)
 
166
  @with_caching(ttl=1800)
167
  def search_adverse_events_mcp(drug_name: str, limit: str = "5") -> str:
168
  """
169
+ Searches the FDA Adverse Event Reporting System (FAERS) database for adverse events associated with a specific drug. This tool is useful for initial investigation into a drug's safety profile by retrieving summaries of reported adverse event cases. It provides a quick overview of potential side effects reported by healthcare professionals and the public.
170
 
171
  Args:
172
  drug_name (str): Generic or brand name to search (case-insensitive)
 
184
  @with_caching(ttl=3600)
185
  def fetch_event_details_mcp(event_id: str) -> str:
186
  """
187
+ Retrieves the complete details of a specific adverse event case from the FDA Adverse Event Reporting System (FAERS) using its unique safety report ID. Use this tool when you need to dive deep into a particular case found via 'search_adverse_events_mcp' to understand the full context, including patient demographics, concomitant medications, and the full narrative of the event.
188
 
189
  Args:
190
  event_id (str): Numeric FAERS safetyreportid string
 
200
  @with_caching(ttl=7200)
201
  def drug_label_warnings_mcp(drug_name: str) -> str:
202
  """
203
+ Fetches critical safety information from the official FDA drug label. This includes boxed warnings (the most serious type), contraindications (situations where the drug should not be used), and known drug interactions. This is a primary tool for assessing a drug's major safety risks before prescribing or dispensing.
204
 
205
  Args:
206
  drug_name (str): Generic drug name preferred
 
216
  @with_caching(ttl=3600)
217
  def drug_recalls_mcp(drug_name: str, limit: str = "5") -> str:
218
  """
219
+ Searches for recent FDA-issued recall events for a specific drug product. This is critical for ensuring patient safety by identifying if a drug or specific batch has been recalled due to manufacturing defects, contamination, or other safety concerns. The results include details on the recall reason, status, and affected lots.
220
 
221
  Args:
222
  drug_name (str): Free-text search string for the drug
 
234
  @with_caching(ttl=7200)
235
  def drug_pregnancy_lactation_mcp(drug_name: str) -> str:
236
  """
237
+ Retrieves specific sections from the FDA drug label related to use during pregnancy and lactation. This tool is essential for assessing the safety of a medication for patients who are pregnant, planning to become pregnant, or breastfeeding. It provides the official guidance and available data on potential risks.
238
 
239
  Args:
240
  drug_name (str): Generic drug name preferred
 
250
  @with_caching(ttl=7200) # 2 hours cache
251
  def drug_dose_adjustments_mcp(drug_name: str) -> str:
252
  """
253
+ Extracts dosing adjustment recommendations for patients with kidney (renal) or liver (hepatic) impairment from the official FDA drug label. This is a crucial tool for safe and effective dosing in special populations where standard doses may be harmful or ineffective.
254
 
255
  Args:
256
  drug_name (str): Generic drug name
 
266
  @with_caching(ttl=1800) # 30 minutes cache
267
  def drug_livertox_summary_mcp(drug_name: str) -> str:
268
  """
269
+ Queries the NIH LiverTox database to retrieve a summary of a drug's potential for causing liver injury (hepatotoxicity). This tool is valuable for investigating or assessing the risk of drug-induced liver damage, providing information on the mechanism of injury, and clinical management advice.
270
 
271
  Args:
272
  drug_name (str): Drug name to search for (case-insensitive)
 
281
  @with_error_handling
282
  def brand_to_generic_lookup_mcp(brand_name: str) -> str:
283
  """
284
+ Converts a drug brand name to its generic (active ingredient) name. It can also provide information on the countries where the brand name is marketed. This tool is fundamental for identifying the active component of a branded medication, which is necessary for most other clinical lookups and to avoid therapeutic duplication.
285
 
286
  Args:
287
  brand_name (str): Brand name to look up
 
296
  @with_error_handling
297
  def calculate_drug_burden_index_mcp(drug_list: str) -> str:
298
  """
299
+ Calculates the Drug Burden Index (DBI) for a patient's medication list. The DBI is a measure of a person's total exposure to anticholinergic and sedative drugs, which are associated with an increased risk of falls and cognitive impairment, especially in the elderly.
300
 
301
+ This intelligent version automatically detects the route of administration for each medication (e.g., oral, transdermal patches, parenteral injections) and uses the appropriate reference data for each route, making it suitable for complex, real-world medication regimens.
 
 
302
 
303
  Args:
304
  drug_list (str): Drug list (one per line, include dose and frequency - also write "prn" if the drug is a PRN medication)
 
322
  age: str, weight_kg: str, serum_creatinine: str, is_female: str
323
  ) -> str:
324
  """
325
+ Calculates a patient's creatinine clearance (CrCl) using the Cockcroft-Gault equation. CrCl is an estimate of the glomerular filtration rate (GFR) and is widely used to determine appropriate dose adjustments for drugs that are cleared by the kidneys. This is a standard clinical calculator for renal function assessment.
326
 
327
  Args:
328
  age (str): Patient's age in years
 
349
  age: str, serum_creatinine: str, is_female: str, is_black: str
350
  ) -> str:
351
  """
352
+ Calculates the estimated Glomerular Filtration Rate (eGFR) using the CKD-EPI 2021 equation. eGFR is a key indicator of kidney function and is used to diagnose, stage, and manage Chronic Kidney Disease (CKD). This is the preferred method for assessing kidney function in many clinical guidelines.
353
 
354
  Args:
355
  age (str): Patient's age in years
 
374
  bilirubin: str, albumin: str, inr: str, ascites: str, encephalopathy: str
375
  ) -> str:
376
  """
377
+ Calculates the Child-Pugh score, a well-established tool for assessing the prognosis of chronic liver disease, primarily cirrhosis. The score is used to determine the severity of liver disease and to guide dosage adjustments for drugs that are metabolized by the liver.
378
 
379
  Args:
380
  bilirubin (str): Total bilirubin in mg/dL
 
399
  @with_error_handling
400
  def calculate_bmi_mcp(weight_kg: str, height_cm: str) -> str:
401
  """
402
+ Calculates a person's Body Mass Index (BMI) based on their weight and height. BMI is a widely used screening tool to categorize weight status (e.g., underweight, normal weight, overweight, obese) and identify potential health risks associated with weight.
403
 
404
  Args:
405
  weight_kg (str): Weight in kilograms
 
418
  @with_error_handling
419
  def calculate_ideal_body_weight_mcp(height_cm: str, is_male: str) -> str:
420
  """
421
+ Calculates a patient's Ideal Body Weight (IBW) using the Devine formula. IBW is used in various clinical contexts, including for calculating the dose of certain medications (e.g., aminophylline, digoxin) and for assessing nutritional status.
422
 
423
  Args:
424
  height_cm (str): Patient's height in cm
 
439
  actual_weight: str, height_cm: str, is_male: str
440
  ) -> str:
441
  """
442
+ Recommends the most appropriate weight to use for medication dosing calculations (i.e., actual, ideal, or adjusted body weight) based on the patient's actual weight and height. This is crucial for obese or underweight patients, as using the wrong weight can lead to sub-therapeutic or toxic drug levels for certain medications.
443
 
444
  Args:
445
  actual_weight (str): Patient's actual weight in kg
 
460
  @with_error_handling
461
  def convert_creatinine_units_mcp(value: str, from_unit: str, to_unit: str) -> str:
462
  """
463
+ Converts serum creatinine values between the two standard units of measurement: milligrams per deciliter (mg/dL) and micromoles per liter (μmol/L). This is essential for interoperability, as different laboratories and clinical calculators may use different units.
464
 
465
  Args:
466
  value (str): The creatinine value to convert
 
479
  @with_error_handling
480
  def get_cache_stats_mcp() -> str:
481
  """
482
+ Retrieves statistics about the application's internal cache. This is a debugging and monitoring tool to assess the performance and health of the MCP server, showing metrics like hit rate and cache size. It is not typically used for clinical queries.
483
 
484
  Returns:
485
  str: JSON string with cache hit rates, size, and other metrics
 
499
  @with_error_handling
500
  def health_check_mcp() -> str:
501
  """
502
+ Performs a health check on the MCP server to ensure its core components are operational. This tool is used for system monitoring to verify that the server is running, the cache is working, and basic calculations can be performed. It's not intended for clinical use.
503
 
504
  Returns:
505
  str: JSON string with server health information
 
557
  limit: str = "100"
558
  ) -> str:
559
  """
560
+ Performs an advanced search of the FDA Adverse Event Reporting System (FAERS) database with powerful filtering options. This tool is designed for in-depth pharmacovigilance analysis, allowing users to narrow down adverse event reports by patient age, gender, and the seriousness of the event. It's ideal for identifying trends and patterns in drug safety data.
561
+ Use this tool particularly if the user asks about a specific adverse event or reaction.
562
 
563
  Args:
564
  drug_name (str): Drug name to search for
 
605
  reaction_appeared_after_suspected_drug_given: str
606
  ) -> str:
607
  """
608
+ Calculates the Naranjo score, a standardized and widely used causality assessment tool to determine the probability that an adverse event is related to a specific drug. The score helps clinicians and researchers classify the likelihood of an adverse drug reaction (ADR) as doubtful, possible, probable, or definite.
609
+ Sometimes the user might not have provided all the information, so you will need to ask for the missing information (remember to give them the option to say "unknown" if they don't know the answer)
610
 
611
  Args:
612
+ adverse_reaction_after_drug (str): "yes", "no", "unknown"
613
+ reaction_improved_after_stopping (str): "yes", "no", "unknown"
614
+ reaction_reappeared_after_readministration (str): "yes", "no", "unknown"
615
+ alternative_causes_exist (str): "yes", "no", "unknown"
616
+ reaction_when_placebo_given (str): "yes", "no", "unknown"
617
+ drug_detected_in_blood (str): "yes", "no", "unknown"
618
+ reaction_worse_with_higher_dose (str): "yes", "no", "unknown"
619
+ similar_reaction_to_drug_before (str): "yes", "no", "unknown"
620
+ adverse_event_confirmed_objectively (str): "yes", "no", "unknown"
621
+ reaction_appeared_after_suspected_drug_given (str): "yes", "no", "unknown"
622
 
623
  Returns:
624
  str: JSON string with score, probability category, and detailed breakdown
 
646
  background_limit: str = "10000"
647
  ) -> str:
648
  """
649
+ Performs a disproportionality analysis (also known as signal detection) on adverse event data. This statistical method compares the reporting rate of a specific drug-event combination to the reporting rate of that event for all other drugs in the database. It calculates metrics like Proportional Reporting Ratio (PRR) and Reporting Odds Ratio (ROR) to identify potential safety signals that may warrant further investigation.
650
 
651
  Args:
652
  drug_name (str): Drug of interest
 
674
  limit: str = "50"
675
  ) -> str:
676
  """
677
+ Identifies and retrieves adverse event cases from the FAERS database that are similar to a given reference case. Similarity is calculated based on a combination of patient demographics (age, gender), reported reactions, and concomitant drugs. This tool is useful for contextualizing a specific case and identifying potential case series for further review.
678
 
679
  Args:
680
  reference_case_id (str): FAERS safety report ID to use as reference
 
707
  limit: str = "500"
708
  ) -> str:
709
  """
710
+ Analyzes the temporal relationship between drug administration and the onset of adverse events. This tool provides insights into the typical time-to-onset for a specific drug-associated adverse event, which can be a critical factor in causality assessment. It helps determine if the timing of the event is consistent with the drug's known pharmacology.
711
 
712
  Args:
713
  drug_name (str): Drug to analyze
 
729
  return format_json_output(standardize_response(result, "temporal_analysis"))
730
 
731
 
732
+ with gr.Blocks(
733
+ theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
734
+ title="Pharmacist MCP",
735
+ analytics_enabled=False
736
+ ) as demo:
737
+ gr.Markdown(
738
+ """
739
+ <div style="text-align: center; padding: 20px;">
740
+ <h1 style="color: #0B579E;">💊 Pharmacist MCP</h1>
741
+ <p style="font-size: 1.1em;">
742
+ <strong>A suite of tools for pharmacists and clinicians.</strong>
743
+ </p>
744
+ <p>
745
+ Access critical drug information, perform clinical calculations, and analyze adverse drug reaction data efficiently.
746
+ </p>
747
+ </div>
748
+ """
749
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
 
751
+ with gr.Tabs():
752
+ with gr.TabItem("Drug Information & Safety"):
753
+ with gr.Tabs():
754
+ with gr.TabItem("AE Search"):
755
+ gr.Interface(
756
+ fn=search_adverse_events_mcp,
757
+ inputs=[gr.Text(label="Drug Name"), gr.Text(label="Limit", value="5")],
758
+ outputs=gr.JSON(label="Output"),
759
+ title="AE Search",
760
+ api_name="ae_search",
761
+ description="Search FAERS for adverse events.",
762
+ )
763
+ with gr.TabItem("AE Details"):
764
+ gr.Interface(
765
+ fn=fetch_event_details_mcp,
766
+ inputs=gr.Text(label="FAERS Event ID"),
767
+ outputs=gr.JSON(label="Output"),
768
+ title="AE Details",
769
+ api_name="ae_details",
770
+ description="Fetch a full FAERS case by safety-report ID.",
771
+ )
772
+ with gr.TabItem("Label Warnings"):
773
+ gr.Interface(
774
+ fn=drug_label_warnings_mcp,
775
+ inputs=gr.Text(label="Drug Name"),
776
+ outputs=gr.JSON(label="Output"),
777
+ title="Label Warnings",
778
+ api_name="label_warnings",
779
+ description="Get FDA label warnings.",
780
+ )
781
+ with gr.TabItem("Recalls"):
782
+ gr.Interface(
783
+ fn=drug_recalls_mcp,
784
+ inputs=[gr.Text(label="Drug"), gr.Text(label="Limit", value="5")],
785
+ outputs=gr.JSON(label="Output"),
786
+ title="Drug Recalls",
787
+ api_name="drug_recalls",
788
+ description="Return recent FDA recall events for a drug.",
789
+ )
790
+ with gr.TabItem("Pregnancy & Lactation"):
791
+ gr.Interface(
792
+ fn=drug_pregnancy_lactation_mcp,
793
+ inputs=gr.Text(label="Drug"),
794
+ outputs=gr.JSON(label="Output"),
795
+ title="Pregnancy & Lactation",
796
+ api_name="pregnancy_lactation",
797
+ description="Return Pregnancy & Lactation text from FDA label.",
798
+ )
799
+ with gr.TabItem("Dose Adjustments"):
800
+ gr.Interface(
801
+ fn=drug_dose_adjustments_mcp,
802
+ inputs=gr.Text(label="Drug"),
803
+ outputs=gr.JSON(label="Output"),
804
+ title="Dose Adjustments",
805
+ api_name="dose_adjustments",
806
+ description="Return renal & hepatic dosing excerpts from FDA label.",
807
+ )
808
+ with gr.TabItem("LiverTox Summary"):
809
+ gr.Interface(
810
+ fn=drug_livertox_summary_mcp,
811
+ inputs=gr.Text(label="Drug Name"),
812
+ outputs=gr.JSON(label="Output"),
813
+ title="LiverTox Summary",
814
+ api_name="livertox_summary",
815
+ description="Get hepatotoxicity information.",
816
+ )
817
+ with gr.TabItem("Brand to Generic"):
818
+ gr.Interface(
819
+ fn=brand_to_generic_lookup_mcp,
820
+ inputs=[gr.Text(label="Brand Name")],
821
+ outputs=gr.JSON(label="Output"),
822
+ title="Brand to Generic",
823
+ api_name="brand_to_generic",
824
+ description="Look up generic drug information.",
825
+ )
826
+
827
+ with gr.TabItem("Clinical Calculators"):
828
+ with gr.Tabs():
829
+ with gr.TabItem("DBI Calculator"):
830
+ gr.Interface(
831
+ fn=calculate_drug_burden_index_mcp,
832
+ inputs=[
833
+ gr.Textbox(
834
+ label="Drug List (one per line, include dose and frequency)",
835
+ lines=10,
836
+ placeholder="e.g., Fentanyl 25mcg/hr patch daily\nAmitriptyline 25mg tablet twice daily\nMorphine 10mg injection PRN",
837
+ ),
838
+ ],
839
+ outputs=gr.JSON(label="DBI Calculation with Route Detection"),
840
+ title="DBI Calculator",
841
+ api_name="dbi_calculator",
842
+ description="Intelligent DBI calculator that automatically detects routes (oral, patches, injections, etc.) and uses appropriate reference data for each medication.",
843
+ )
844
+ with gr.TabItem("Creatinine Clearance"):
845
+ gr.Interface(
846
+ fn=calculate_creatinine_clearance_mcp,
847
+ inputs=[
848
+ gr.Text(label="Age (years)", value="65"),
849
+ gr.Text(label="Weight (kg)", value="70"),
850
+ gr.Text(label="Serum Creatinine (mg/dL)", value="1.2"),
851
+ gr.Radio(["true", "false"], label="Is Female", value="false"),
852
+ ],
853
+ outputs=gr.JSON(label="Creatinine Clearance"),
854
+ title="Cockcroft-Gault Calculator",
855
+ api_name="cockcroft_gault",
856
+ description="Calculate creatinine clearance using Cockcroft-Gault equation for dose adjustments.",
857
+ )
858
+ with gr.TabItem("eGFR"):
859
+ gr.Interface(
860
+ fn=calculate_egfr_mcp,
861
+ inputs=[
862
+ gr.Text(label="Age (years)", value="65"),
863
+ gr.Text(label="Serum Creatinine (mg/dL)", value="1.2"),
864
+ gr.Radio(["true", "false"], label="Is Female", value="false"),
865
+ gr.Radio(["true", "false"], label="Is Black", value="false"),
866
+ ],
867
+ outputs=gr.JSON(label="eGFR"),
868
+ title="CKD-EPI eGFR Calculator",
869
+ api_name="ckd_epi",
870
+ description="Calculate estimated glomerular filtration rate using CKD-EPI equation.",
871
+ )
872
+ with gr.TabItem("Child-Pugh Score"):
873
+ gr.Interface(
874
+ fn=calculate_child_pugh_score_mcp,
875
+ inputs=[
876
+ gr.Text(label="Total Bilirubin (mg/dL)", value="1.5"),
877
+ gr.Text(label="Serum Albumin (g/dL)", value="3.5"),
878
+ gr.Text(label="INR", value="1.3"),
879
+ gr.Dropdown(["none", "mild", "moderate-severe"], value="none", label="Ascites"),
880
+ gr.Dropdown(["none", "grade-1-2", "grade-3-4"], value="none", label="Encephalopathy"),
881
+ ],
882
+ outputs=gr.JSON(label="Child-Pugh Score"),
883
+ title="Child-Pugh Score Calculator",
884
+ api_name="child_pugh",
885
+ description="Calculate Child-Pugh score for liver function assessment and dose adjustments.",
886
+ )
887
+ with gr.TabItem("BMI"):
888
+ gr.Interface(
889
+ fn=calculate_bmi_mcp,
890
+ inputs=[
891
+ gr.Text(label="Weight (kg)", value="70"),
892
+ gr.Text(label="Height (cm)", value="170"),
893
+ ],
894
+ outputs=gr.JSON(label="BMI Calculation"),
895
+ title="BMI Calculator",
896
+ api_name="bmi_calculator",
897
+ description="Calculate Body Mass Index and weight category assessment.",
898
+ )
899
+ with gr.TabItem("Ideal Body Weight"):
900
+ gr.Interface(
901
+ fn=calculate_ideal_body_weight_mcp,
902
+ inputs=[
903
+ gr.Text(label="Height (cm)", value="170"),
904
+ gr.Radio(["true", "false"], label="Is Male", value="true"),
905
+ ],
906
+ outputs=gr.JSON(label="Ideal Body Weight Calculation"),
907
+ title="Ideal Body Weight (IBW) Calculator",
908
+ api_name="ideal_body_weight",
909
+ description="Calculate Ideal Body Weight using the Devine formula.",
910
+ )
911
+ with gr.TabItem("Dosing Weight"):
912
+ gr.Interface(
913
+ fn=recommend_dosing_weight_mcp,
914
+ inputs=[
915
+ gr.Text(label="Actual Weight (kg)", value="85"),
916
+ gr.Text(label="Height (cm)", value="170"),
917
+ gr.Radio(["true", "false"], label="Is Male", value="true"),
918
+ ],
919
+ outputs=gr.JSON(label="Dosing Weight Recommendation"),
920
+ title="Dosing Weight Calculator",
921
+ api_name="dosing_weight",
922
+ description="Recommend appropriate weight for medication dosing calculations.",
923
+ )
924
+ with gr.TabItem("Creatinine Converter"):
925
+ gr.Interface(
926
+ fn=convert_creatinine_units_mcp,
927
+ inputs=[
928
+ gr.Text(label="Creatinine Value", value="1.2"),
929
+ gr.Dropdown(["mg_dl", "umol_l"], value="mg_dl", label="From Unit"),
930
+ gr.Dropdown(["mg_dl", "umol_l"], value="umol_l", label="To Unit"),
931
+ ],
932
+ outputs=gr.JSON(label="Converted Value"),
933
+ title="Creatinine Unit Converter",
934
+ api_name="creatinine_converter",
935
+ description="Convert creatinine values between mg/dL and μmol/L.",
936
+ )
937
+
938
+ with gr.TabItem("Pharmacovigilance Tools"):
939
+ with gr.Tabs():
940
+ with gr.TabItem("Enhanced FAERS Search"):
941
+ gr.Interface(
942
+ fn=enhanced_faers_search_mcp,
943
+ inputs=[
944
+ gr.Text(label="Drug Name", placeholder="e.g., lisinopril"),
945
+ gr.Text(label="Adverse Event (optional)", placeholder="e.g., cough"),
946
+ gr.Text(label="Age Range (optional)", placeholder="e.g., 18-65 or >65"),
947
+ gr.Radio(["", "1", "2"], label="Gender (optional)", info="1=Male, 2=Female", value=""),
948
+ gr.Radio(["true", "false"], label="Serious Events Only", value="false"),
949
+ gr.Number(label="Limit", value=100),
950
+ ],
951
+ outputs=gr.JSON(label="Output"),
952
+ title="Enhanced FAERS Search",
953
+ api_name="enhanced_faers_search",
954
+ description="Enhanced FAERS search with filtering capabilities for pharmacovigilance analysis.",
955
+ )
956
+ with gr.TabItem("Naranjo Score"):
957
+ gr.Interface(
958
+ fn=calculate_naranjo_score_mcp,
959
+ inputs=[
960
+ gr.Radio(["yes", "no", "unknown"], label="Did the adverse reaction appear after the drug was given?", value="unknown", info="Question 2"),
961
+ gr.Radio(["yes", "no", "unknown"], label="Did the reaction improve after stopping the drug?", value="unknown", info="Question 3"),
962
+ gr.Radio(["yes", "no", "unknown"], label="Did the reaction reappear upon readministration?", value="unknown", info="Question 4"),
963
+ gr.Radio(["yes", "no", "unknown"], label="Are there alternative causes for the reaction?", value="unknown", info="Question 5"),
964
+ gr.Radio(["yes", "no", "unknown"], label="Did the reaction reappear with a placebo?", value="unknown", info="Question 6"),
965
+ gr.Radio(["yes", "no", "unknown"], label="Was the drug detected in blood/fluids at a toxic level?", value="unknown", info="Question 7"),
966
+ gr.Radio(["yes", "no", "unknown"], label="Did the reaction change with dose alterations?", value="unknown", info="Question 8"),
967
+ gr.Radio(["yes", "no", "unknown"], label="Did the patient have a similar reaction previously?", value="unknown", info="Question 9"),
968
+ gr.Radio(["yes", "no", "unknown"], label="Was the adverse event confirmed objectively?", value="unknown", info="Question 10"),
969
+ # This argument seems to be a duplicate or a more specific version of the first one. Let's provide a clear label.
970
+ gr.Radio(["yes", "no", "unknown"], label="Are there conclusive reports on this reaction?", value="unknown", info="Question 1"),
971
+ ],
972
+ outputs=gr.JSON(label="Naranjo Score"),
973
+ title="Naranjo Score Calculator",
974
+ api_name="naranjo_score",
975
+ description="Calculate the Naranjo Adverse Drug Reaction Probability Scale.",
976
+ )
977
+ with gr.TabItem("Disproportionality Analysis"):
978
+ gr.Interface(
979
+ fn=disproportionality_analysis_mcp,
980
+ inputs=[
981
+ gr.Text(label="Drug Name", placeholder="e.g., atorvastatin"),
982
+ gr.Text(label="Adverse Event", placeholder="e.g., myalgia"),
983
+ gr.Number(label="Background Limit", value=10000),
984
+ ],
985
+ outputs=gr.JSON(label="Output"),
986
+ title="Disproportionality Analysis (Signal Detection)",
987
+ api_name="disproportionality_analysis",
988
+ description="Perform disproportionality analysis (PRR, ROR, IC) to detect potential drug-adverse event signals.",
989
+ )
990
+ with gr.TabItem("Similar Case Finder"):
991
+ gr.Interface(
992
+ fn=find_similar_cases_mcp,
993
+ inputs=[
994
+ gr.Text(label="Reference FAERS Case ID"),
995
+ gr.Slider(0, 1, value=0.7, label="Similarity Threshold"),
996
+ gr.Number(label="Limit", value=50),
997
+ ],
998
+ outputs=gr.JSON(label="Output"),
999
+ title="Find Similar Cases",
1000
+ api_name="find_similar_cases",
1001
+ description="Find cases similar to a reference case based on patient characteristics, drugs, and adverse events.",
1002
+ )
1003
+ with gr.TabItem("Temporal Analysis"):
1004
+ gr.Interface(
1005
+ fn=temporal_analysis_mcp,
1006
+ inputs=[
1007
+ gr.Text(label="Drug Name"),
1008
+ gr.Text(label="Adverse Event (optional)"),
1009
+ gr.Number(label="Limit", value=500),
1010
+ ],
1011
+ outputs=gr.JSON(label="Output"),
1012
+ title="Temporal Analysis",
1013
+ api_name="temporal_analysis",
1014
+ description="Analyze temporal patterns and time-to-onset of adverse events for a drug.",
1015
+ )
1016
 
1017
  if __name__ == "__main__":
1018
  demo.launch(mcp_server=True, show_error=True)
requirements.txt CHANGED
@@ -4,4 +4,6 @@ gradio
4
  datasets
5
  apscheduler
6
  beautifulsoup4
7
- lxml
 
 
 
4
  datasets
5
  apscheduler
6
  beautifulsoup4
7
+ lxml
8
+ mlx-lm
9
+ huggingface_hub[mcp]>=0.32.0