rowan-mcp 1.0.1__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.

Potentially problematic release.


This version of rowan-mcp might be problematic. Click here for more details.

Files changed (70) hide show
  1. rowan_mcp/__init__.py +2 -2
  2. rowan_mcp/__main__.py +3 -5
  3. rowan_mcp/functions_v2/BENCHMARK.md +86 -0
  4. rowan_mcp/functions_v2/molecule_lookup.py +232 -0
  5. rowan_mcp/functions_v2/protein_management.py +141 -0
  6. rowan_mcp/functions_v2/submit_basic_calculation_workflow.py +195 -0
  7. rowan_mcp/functions_v2/submit_conformer_search_workflow.py +158 -0
  8. rowan_mcp/functions_v2/submit_descriptors_workflow.py +52 -0
  9. rowan_mcp/functions_v2/submit_docking_workflow.py +244 -0
  10. rowan_mcp/functions_v2/submit_fukui_workflow.py +114 -0
  11. rowan_mcp/functions_v2/submit_irc_workflow.py +58 -0
  12. rowan_mcp/functions_v2/submit_macropka_workflow.py +99 -0
  13. rowan_mcp/functions_v2/submit_pka_workflow.py +72 -0
  14. rowan_mcp/functions_v2/submit_protein_cofolding_workflow.py +88 -0
  15. rowan_mcp/functions_v2/submit_redox_potential_workflow.py +55 -0
  16. rowan_mcp/functions_v2/submit_scan_workflow.py +82 -0
  17. rowan_mcp/functions_v2/submit_solubility_workflow.py +157 -0
  18. rowan_mcp/functions_v2/submit_tautomer_search_workflow.py +51 -0
  19. rowan_mcp/functions_v2/workflow_management_v2.py +382 -0
  20. rowan_mcp/server.py +109 -144
  21. rowan_mcp/tests/basic_calculation_from_json.py +0 -0
  22. rowan_mcp/tests/basic_calculation_with_constraint.py +33 -0
  23. rowan_mcp/tests/basic_calculation_with_solvent.py +0 -0
  24. rowan_mcp/tests/bde.py +37 -0
  25. rowan_mcp/tests/benchmark_queries.md +120 -0
  26. rowan_mcp/tests/cofolding_screen.py +131 -0
  27. rowan_mcp/tests/conformer_dependent_redox.py +37 -0
  28. rowan_mcp/tests/conformers.py +31 -0
  29. rowan_mcp/tests/data.json +189 -0
  30. rowan_mcp/tests/docking_screen.py +157 -0
  31. rowan_mcp/tests/irc.py +24 -0
  32. rowan_mcp/tests/macropka.py +13 -0
  33. rowan_mcp/tests/multistage_opt.py +13 -0
  34. rowan_mcp/tests/optimization.py +21 -0
  35. rowan_mcp/tests/phenol_pka.py +36 -0
  36. rowan_mcp/tests/pka.py +36 -0
  37. rowan_mcp/tests/protein_cofolding.py +17 -0
  38. rowan_mcp/tests/scan.py +28 -0
  39. {rowan_mcp-1.0.1.dist-info → rowan_mcp-2.0.0.dist-info}/METADATA +49 -33
  40. rowan_mcp-2.0.0.dist-info/RECORD +42 -0
  41. rowan_mcp/functions/admet.py +0 -94
  42. rowan_mcp/functions/bde.py +0 -113
  43. rowan_mcp/functions/calculation_retrieve.py +0 -89
  44. rowan_mcp/functions/conformers.py +0 -80
  45. rowan_mcp/functions/descriptors.py +0 -92
  46. rowan_mcp/functions/docking.py +0 -340
  47. rowan_mcp/functions/docking_enhanced.py +0 -174
  48. rowan_mcp/functions/electronic_properties.py +0 -205
  49. rowan_mcp/functions/folder_management.py +0 -137
  50. rowan_mcp/functions/fukui.py +0 -219
  51. rowan_mcp/functions/hydrogen_bond_basicity.py +0 -94
  52. rowan_mcp/functions/irc.py +0 -125
  53. rowan_mcp/functions/macropka.py +0 -120
  54. rowan_mcp/functions/molecular_converter.py +0 -423
  55. rowan_mcp/functions/molecular_dynamics.py +0 -191
  56. rowan_mcp/functions/molecule_lookup.py +0 -57
  57. rowan_mcp/functions/multistage_opt.py +0 -171
  58. rowan_mcp/functions/pdb_handler.py +0 -200
  59. rowan_mcp/functions/pka.py +0 -137
  60. rowan_mcp/functions/redox_potential.py +0 -352
  61. rowan_mcp/functions/scan.py +0 -536
  62. rowan_mcp/functions/scan_analyzer.py +0 -347
  63. rowan_mcp/functions/solubility.py +0 -277
  64. rowan_mcp/functions/spin_states.py +0 -747
  65. rowan_mcp/functions/system_management.py +0 -368
  66. rowan_mcp/functions/tautomers.py +0 -91
  67. rowan_mcp/functions/workflow_management.py +0 -422
  68. rowan_mcp-1.0.1.dist-info/RECORD +0 -34
  69. {rowan_mcp-1.0.1.dist-info → rowan_mcp-2.0.0.dist-info}/WHEEL +0 -0
  70. {rowan_mcp-1.0.1.dist-info → rowan_mcp-2.0.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,157 @@
1
+ import time
2
+
3
+ import stjames
4
+
5
+ import rowan
6
+
7
+ HARTREE_TO_KCALMOL = 627.5096
8
+
9
+ ligands = [
10
+ "CCC(C)(C)NC1=NCC2(CCC(=O)C2C)N1",
11
+ "CCC(C)CN=C1NCC2(CCCOC2)CN1",
12
+ "CC(C)CCNC1=NCC2CC(COC2=N)O1",
13
+ "CCC(CC)NC1=NCC2CC(CO)CC12",
14
+ "CCC(C)CN=C1NC=C2CCC(O)CC2=N1",
15
+ "CC(C#CC#N)C1=NC=C2C=CC(=O)CN12",
16
+ "CCC(CCN)C1NCC2=C(CC)SC(O)=C12",
17
+ "CCC(CC)N=C1NC=C2C=C(F)C=C(N)N12",
18
+ "CC(C)(C)C(N)C1=NCC2=CC(I)=NC=C2O1",
19
+ "CCC(CC)NC1=NCC2CC(N1)C(C)CN2",
20
+ "CCCC(C)N=C1NCC2CCNC2(C)CO1",
21
+ "CC(C)CC(N)C1NCC2=CC(N)=C(Br)N=C12",
22
+ "CC(C)C(CN)C1=NC=C2C=CN(C)C2=C1Br",
23
+ "CC(CC#C)NC1=NCC2=C(C)N(C)C=C2O1",
24
+ "CCCC(C)(N)C1=NCC2=CC(N)=CC=C2O1",
25
+ "CCCCC(N)C1=NC=C2C=CN(C)C(C)=C12",
26
+ "CCC(CC)N=C1NCC2CC(N)CCCN12",
27
+ "CC(C)C(C)(N)C1=NC=C2C=CNC(=N)C2=N1",
28
+ "CC(C)(CC#N)C1=NCC2CCN=COC2O1",
29
+ "C#CCC(C#N)C1=NC=C2C=CNN=C12",
30
+ "CCCCCNC1=NCC2=C(C)NN=C2N1",
31
+ "CCCCC(N)C1=NC=C2C(C)=NOC2=C1Br",
32
+ "CCCCCNC1=NCC2(CC#N)OCC1O2",
33
+ "CC(C)CCNC1=NC=C2CC(=N)OCCN12",
34
+ "CCCC(C#N)C1N(C)C2=C(C=NS2)C1=O",
35
+ "CCC(CC#N)C1=NCC2=C(CO1)OC(=N)S2",
36
+ "CCC(CCN)C1=NCC2=C(CO1)SC=N2",
37
+ "CCC(C(C)N)C1NCC2CCOC1C2(C)C",
38
+ "CC(C)(C)CNC1=NCC2CCOC1(O2)C#C",
39
+ "CCCCCN=C1N(C)C2CCOC2C1(C)C",
40
+ "CC(C)CCN=C1NCC2(CCOC2O1)C#C",
41
+ "CC(C)C(C#N)C1NCC2=CC(O)=C(Br)N=C12",
42
+ "CCC(C(C)N)C1(N)CC2CC(OC)C1C2C",
43
+ "CC(C)(C)CN=C1NC=C2CC(O)CC2O1",
44
+ "CCC(C)(C#N)C1=NC=C2CC(=O)C(C=O)N12",
45
+ "CCCC(C)NC1=NCC2(CCOC=N2)CC1",
46
+ "CCCC(C)N=C1N=CC2=CC(=O)N=C2C1=N",
47
+ "CC(C)C(C#N)C1=NC=C2C=C(O)OC2=C1N",
48
+ "CCCC(CN=C1NCC2=C(C)SC=C12)C=O",
49
+ "CC(C)(C)CN=C1NCC2=CNC3=C2C1=CN3",
50
+ "CCCCC(N)C1=NC=C2CNCC2=C1I",
51
+ "CC(CC#C)NC1=NCC2=C(NC(=C2)C#C)N1",
52
+ "CCC#CCN=C1NCC2=CNC=C2N1",
53
+ "CCCC(C#N)C1N(C)C2=C(NC=C2)OC1=O",
54
+ "CC(C)(C)CN=C1NC=C2C=NC=C2SC1=N",
55
+ "CC(C)C(C#N)C1NCC2=CN=C(C=C12)C#N",
56
+ "CC(C)C(C#N)C1(N)CC2CN(C)CC2C1C",
57
+ "CCC(C)(C)N=C1NCC2=C(NC(C)=C2)C1O",
58
+ "CC(C)C(C)NC1=NCC2CNC(C)C(C2)C1",
59
+ "CCC(C)CN=C1NCC2C(N)C(C)C(C)C12",
60
+ "CCC(C)(C#N)C1=NC=C2CNC(C)C(C)N12",
61
+ "CC(C)C(C#N)C1NCC2=C(N=C(C)N2)C1C",
62
+ "CCC(C)(C)NC1=NCC2=C(N=C(C)N2)C1C",
63
+ "CCC(C)(C)N=C1N=CC2=CN(C)N=C2N1C",
64
+ "CC(C)CCN=C1NC=C2C=NC(=NN12)C#C",
65
+ "CC(C)C(CN=C1NCC2(CN=CO2)O1)C#N",
66
+ "CCC(CC)N=C1N(C)C2=C(NC(=O)S2)C1=O",
67
+ "CCCC(C#N)C1NCC2=C(N=CS2)S1(=O)=O",
68
+ "CCC(C)(C)NC1=NCC2=CNN=C2C(=N)N1",
69
+ "CC(C)CCN=C1NC=C2C(N)=NC(C)=C2S1",
70
+ "CCC(C)(C)NC1=NC=C2C(=N)N=CNC2=N1",
71
+ "CCC(CC)N=C1N(C)C2=C(NN=N2)C1=NO",
72
+ "CCC(C)(C)NC1=NCC2=CN=NN2CCC1",
73
+ "CCC(C)CN=C1N=CC2=CNN=NC2=N1",
74
+ "CCC(CCN)C1=NC=C2C(N)=NSC2=N1",
75
+ "CCC(C)(CN)C1NCC2=C(N)OC=C2C1C",
76
+ "CC(C)(CCN)C1=NC=C2C(=N)SN=C2C=N1",
77
+ "CC(C)(C)CNC1=NC=C2C(=N)SN=C2O1",
78
+ "CCC(C)C(N)C1=NCC2=C(O1)C=CC(=N)S2",
79
+ "CCCCCN=C1NCC2=C(O1)N=C(S2)C#N",
80
+ "CCC(C)(CNC1=NCC2=C(O1)SC=N2)C=O",
81
+ "CC#CC(CN)C1=NCC2=C(O1)SN=C2C",
82
+ "CCCC(C#N)C1NCC2COC1(C2)C(C)=O",
83
+ "CC(C)(C)C(N)C1(N)CC2COC1C(C)(C)C2",
84
+ "CCCC(C#N)C1NCC2COC1(C)CN2C",
85
+ "CCC(C)(C)N=C1N(C)C2COC1(C)OC2C",
86
+ "CC(C)CCN=C1NCC2=C(OC1=N)N=NN2",
87
+ "CCC(CC#N)(C1NCC2=COC=C12)N(C)C",
88
+ "CCCC(C)(N)C1NCC2=C(OC=C12)N(C)C",
89
+ "CC(C)(C)CNC1=NCC2=C(OCC1)N=CS2",
90
+ "CC#CCCN=C1NCC2=COC=C2C=C1",
91
+ "CCCCCNC1=NC=C2C(OCC2(C)O)=C1",
92
+ "CCC(C)(C#N)C1N(C)C2=COC=C2N=C1N",
93
+ "CCC(C)(C)N=C1NCC2(C)OC(CC12)=NC",
94
+ "CCC(C)(CN)C1NCC2C(O)CCC1C2C",
95
+ "CCCC(C)NC1=NCC2COCC(C1)C2C",
96
+ "CC(C)C(C)NC1=NCC2COCCC2(C)O1",
97
+ "CC(C)CC(N)C1=NC=C2COC(C)C(C)N12",
98
+ "CCC(C)(C)NC1=NCC2COC(C)(O1)C2N",
99
+ "CCCC(C)(N)C1=NC=C2COCCOC2=N1",
100
+ "CCCC(C)N=C1N(C)C2=COC(N)=C2C1=O",
101
+ "CCCCCNC1=NCC2(C)OC=NCCC12",
102
+ "CCC(C(C)N)C1=NC=C2COC(N)=NC2=C1",
103
+ "CCCC(C)NC1=NCC2(C)OC(=O)OC2O1",
104
+ "CCCCC(N)C1NCC2=CON=C2C1C#C",
105
+ "CC(C)C(C)N=C1NCC2=C(O)N(C)C=C2O1",
106
+ "CCCC(C)N=C1N=CC2=C(O)N(C)C=CN12",
107
+ "CC(C)C(C#N)C1=NC=C2C(O)=NSC2=C1O",
108
+ "CCC(CC)N=C1NCC2=C(O)SC(=N)N=C12",
109
+ "CC(C)C(CN)C1NCC2=C(SC=C2C)C1C",
110
+ ]
111
+
112
+
113
+ workflows = []
114
+ results = {}
115
+
116
+ docking_result_folder = rowan.create_folder(name="Docking results")
117
+
118
+
119
+ protein = rowan.create_protein_from_pdb_id("CDK2", "1HCK")
120
+
121
+ protein.sanitize()
122
+ time.sleep(60)
123
+ protein.refresh()
124
+
125
+ for ligand in ligands:
126
+ workflow = rowan.submit_docking_workflow(
127
+ protein.uuid,
128
+ pocket=[[103.55, 100.59, 82.99], [27.76, 32.67, 48.79]],
129
+ initial_molecule=stjames.Molecule.from_smiles(ligand),
130
+ folder_uuid=docking_result_folder.uuid,
131
+ name=f"Docking {ligand}",
132
+ )
133
+ workflows.append(workflow)
134
+
135
+
136
+ for workflow in workflows:
137
+ workflow.wait_for_result()
138
+ workflow.fetch_latest(in_place=True)
139
+
140
+ lowest_conformer_energy = 0
141
+ for workflow in workflows:
142
+ conformers = workflow.data["conformers"]
143
+ for conformer in conformers:
144
+ energy = rowan.retrieve_calculation_molecules(
145
+ conformer[0] if isinstance(conformer, list) else conformer
146
+ )[0]["energy"]
147
+ lowest_conformer_energy = min(lowest_conformer_energy, energy)
148
+
149
+ sorted_scores = sorted(workflow.data["scores"], key=lambda x: float(x["score"]))
150
+ for score in sorted_scores:
151
+ pose_energy = rowan.retrieve_calculation_molecules(score["pose"])[0]["energy"]
152
+ strain = (pose_energy - lowest_conformer_energy) * HARTREE_TO_KCALMOL
153
+ if score["posebusters_valid"] and strain < 4:
154
+ results[workflow.name] = score
155
+ break
156
+
157
+ print(results)
rowan_mcp/tests/irc.py ADDED
@@ -0,0 +1,24 @@
1
+ from stjames import Molecule
2
+
3
+ import rowan
4
+
5
+ # rowan.api_key = ""
6
+
7
+ result = rowan.submit_irc_workflow(
8
+ initial_molecule=Molecule.from_xyz_lines(
9
+ """7
10
+ SMILES `N=C([O-])[OH2+]`
11
+ N -0.15519741 -1.36979175 -0.20679433
12
+ C 1.11565384 -1.23943631 -0.14797646
13
+ O 2.17614993 -1.72950370 -0.04017850
14
+ H -0.55869366 -2.29559315 -0.23834737
15
+ O 1.02571386 0.42871733 -0.27925360
16
+ H -0.09029954 -0.04166676 -0.31495768
17
+ H 1.26740151 0.88347299 0.53620841
18
+ """.splitlines()
19
+ ),
20
+ name="HNCO + H₂O - IRC",
21
+ preopt=False,
22
+ )
23
+
24
+ print(result)
@@ -0,0 +1,13 @@
1
+ import rowan
2
+
3
+ # Set ROWAN_API_KEY environment variable to your API key or set rowan.api_key directly
4
+ # rowan.api_key = "rowan-sk..."
5
+
6
+ result = rowan.submit_macropka_workflow(
7
+ # oseltamivir
8
+ initial_smiles="C1CCOC(=O)C1=C[C@@H](OC(CC)CC)[C@H](NC(C)=O)[C@@H]([NH3+])C1CCC1",
9
+ name="Oseltamivir macropka",
10
+ )
11
+
12
+
13
+ print(result)
@@ -0,0 +1,13 @@
1
+ import rowan
2
+
3
+ # Set ROWAN_API_KEY environment variable to your API key or set rowan.api_key directly
4
+ # rowan.api_key = "rowan-sk..."
5
+
6
+ result = rowan.submit_macropka_workflow(
7
+ # oseltamivir
8
+ initial_smiles="C1CCOC(=O)C1=C[C@@H](OC(CC)CC)[C@H](NC(C)=O)[C@@H]([NH3+])C1CCC1",
9
+ name="Oseltamivir macropka",
10
+ )
11
+
12
+
13
+ print(result)
@@ -0,0 +1,21 @@
1
+ """
2
+ Run an optimization calculation on a molecule using Rowan.
3
+
4
+ See documentation at: https://docs.rowansci.com/science/quantum-chemistry/geometry-optimization
5
+ """
6
+
7
+ from stjames import Molecule
8
+
9
+ import rowan
10
+
11
+ # rowan.api_key = ""
12
+
13
+ result = rowan.submit_basic_calculation_workflow(
14
+ initial_molecule=Molecule.from_smiles("O"),
15
+ method="GFN2-xTB",
16
+ tasks=["optimize"],
17
+ engine="xtb",
18
+ name="Water Optimization",
19
+ )
20
+
21
+ print(result)
@@ -0,0 +1,36 @@
1
+ import stjames
2
+
3
+ import rowan
4
+
5
+ phenols_to_compute = {
6
+ "p-nitrophenol": "Oc1ccc(N(=O)=O)cc1",
7
+ "p-(trifluoromethyl)phenol": "Oc1ccc(C(F)(F)F)cc1",
8
+ "methyl p-hydroxybenzoate": "COC(=O)c1ccc(O)cc1",
9
+ "p-fluorophenol": "Oc1ccc(F)cc1",
10
+ "p-chlorophenol": "Oc1ccc(Cl)cc1",
11
+ "phenol": "Oc1ccccc1",
12
+ "p-cresol": "Oc1ccc(C)cc1",
13
+ "p-methoxyphenol": "COc1ccc(O)cc1",
14
+ "p-(dimethylamino)phenol": "CN(C)c1ccc(O)cc1",
15
+ }
16
+
17
+ pka_folder = rowan.create_folder(name="phenol pKa results")
18
+
19
+ workflows = []
20
+ for name, smiles in phenols_to_compute.items():
21
+ stjames_molecule = stjames.Molecule.from_smiles(smiles)
22
+ workflows.append(
23
+ rowan.submit_pka_workflow(
24
+ stjames_molecule,
25
+ name=f"pKa {name}",
26
+ folder_uuid=pka_folder.uuid,
27
+ deprotonate_elements=[8],
28
+ )
29
+ )
30
+
31
+
32
+ for workflow in workflows:
33
+ workflow.wait_for_result()
34
+ workflow.fetch_latest(in_place=True)
35
+
36
+ print([(workflow.name, workflow.data["conjugate_bases"][0]["pka"]) for workflow in workflows])
rowan_mcp/tests/pka.py ADDED
@@ -0,0 +1,36 @@
1
+ import stjames
2
+
3
+ import rowan
4
+
5
+ phenols_to_compute = {
6
+ "p-nitrophenol": "Oc1ccc(N(=O)=O)cc1",
7
+ "p-(trifluoromethyl)phenol": "Oc1ccc(C(F)(F)F)cc1",
8
+ "methyl p-hydroxybenzoate": "COC(=O)c1ccc(O)cc1",
9
+ "p-fluorophenol": "Oc1ccc(F)cc1",
10
+ "p-chlorophenol": "Oc1ccc(Cl)cc1",
11
+ "phenol": "Oc1ccccc1",
12
+ "p-cresol": "Oc1ccc(C)cc1",
13
+ "p-methoxyphenol": "COc1ccc(O)cc1",
14
+ "p-(dimethylamino)phenol": "CN(C)c1ccc(O)cc1",
15
+ }
16
+
17
+ pka_folder = rowan.create_folder(name="phenol pKa results")
18
+
19
+ workflows = []
20
+ for name, smiles in phenols_to_compute.items():
21
+ stjames_molecule = stjames.Molecule.from_smiles(smiles)
22
+ workflows.append(
23
+ rowan.submit_pka_workflow(
24
+ stjames_molecule,
25
+ name=f"pKa {name}",
26
+ folder_uuid=pka_folder.uuid,
27
+ deprotonate_elements=[8],
28
+ )
29
+ )
30
+
31
+
32
+ for workflow in workflows:
33
+ workflow.wait_for_result()
34
+ workflow.fetch_latest(in_place=True)
35
+
36
+ print([(workflow.name, workflow.data["conjugate_bases"][0]["pka"]) for workflow in workflows])
@@ -0,0 +1,17 @@
1
+ import rowan
2
+
3
+ # rowan.api_key = ""
4
+
5
+ # Run calculation remotely
6
+ result = rowan.submit_protein_cofolding_workflow(
7
+ initial_protein_sequences=[
8
+ "ASKGTSHEAGIVCRITKPALLVLNHETAKVIQTAFQRASYPDITGEKAMMLLGQVKYGLHNIQISHLSIASSQVELVEAKSIDVSIQDVSVVFKGTLKYGYTTAWWLGIDQSIDFEIDSAIDLQINTQLTADSGRVRTDAPDCYLSFHKLLLHLQGEREPGWIKQLFTNFISFTLKLVLKGQICKEINVISNIMADFVQTRAASILSDGDIGVDISLTGDPVITASYLESHHKGHFIYKDVSEDLPLPTFSPTLLGDSRMLYFWFSERVFHSLAKVAFQDGRLMLSLMGDEFKAVLETWGFNTNQEIFQEVVGGFPSQAQVTVHCLKMPKISCQNKGVVVDSSVMVKFLFPRPDQQHSVAYTFEEDIVTTVQASYSKKKLFLSLLDFQITPKTVSNLTESSSESIQSFLQSMITAVGIPEVMSRLEVVFTALMNSKGVSLFDIINPEIITRDGFLLLQMDFGFPEHLLVDFLQSLS"
9
+ ],
10
+ initial_smiles_list=[
11
+ "CCOC(=O)N1c2ccc(C(F)(F)F)cc2[C@@H](N(Cc2cc(C(F)(F)F)cc(C(F)(F)F)c2)C(=O)OC)C[C@H]1CC"
12
+ ],
13
+ ligand_binding_affinity_index=0,
14
+ name="Torcetrapib Cofolding",
15
+ )
16
+
17
+ print(result)
@@ -0,0 +1,28 @@
1
+ """
2
+ Run an scan calculation on a molecule using Rowan.
3
+
4
+ See documentation at: https://docs.rowansci.com/science/workflows/scan
5
+ """
6
+
7
+ from stjames import Molecule
8
+
9
+ import rowan
10
+
11
+ # rowan.api_key = ""
12
+
13
+ # Run calculation remotely
14
+ result = rowan.submit_scan_workflow(
15
+ initial_molecule=Molecule.from_smiles("O"),
16
+ name="Water Angle scan",
17
+ scan_settings={
18
+ "type": "angle",
19
+ "atoms": [2, 1, 3], # 1-indexed
20
+ "start": 100,
21
+ "stop": 110,
22
+ "num": 5,
23
+ },
24
+ calculation_method="GFN2-xTB",
25
+ calculation_engine="xtb",
26
+ )
27
+
28
+ print(result)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rowan-mcp
3
- Version: 1.0.1
3
+ Version: 2.0.0
4
4
  Summary: Model Context Protocol server for Rowan computational chemistry platform
5
5
  Project-URL: Homepage, https://github.com/k-yenko/rowan-mcp
6
6
  Author-email: Katherine Yenko <katherineayenko@gmail.com>
@@ -13,14 +13,15 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Topic :: Scientific/Engineering :: Chemistry
16
- Requires-Python: >=3.10
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: aiohttp>=3.12.15
17
18
  Requires-Dist: fastapi>=0.104.0
18
- Requires-Dist: fastmcp>=0.2.0
19
+ Requires-Dist: fastmcp>=2.11.3
19
20
  Requires-Dist: pubchempy>=1.0.4
20
21
  Requires-Dist: pydantic>=2.0.0
21
22
  Requires-Dist: python-dotenv>=1.0.0
22
23
  Requires-Dist: rdkit>=2025.3.2
23
- Requires-Dist: rowan-python>=0.1.0
24
+ Requires-Dist: rowan-python>=2.1.1
24
25
  Requires-Dist: typing-extensions>=4.0.0
25
26
  Requires-Dist: uvicorn>=0.24.0
26
27
  Provides-Extra: dev
@@ -32,7 +33,7 @@ Description-Content-Type: text/markdown
32
33
 
33
34
  # Rowan MCP Server
34
35
 
35
- This project wraps an MCP (Model Context Protocol) around Rowan's tools, making it easy for users to design molecuels and run simulations in natural everyday language.
36
+ MCP server for making it easy to run Rowan's molecular design and simulation tools.
36
37
 
37
38
  ---
38
39
 
@@ -56,34 +57,25 @@ That's it - no command line setup needed!
56
57
 
57
58
  Just add this to your MCP configuration and it will automatically install and run:
58
59
 
59
- **Using uvx (simplest):**
60
+ **HTTP/SSE configuration:**
60
61
  ```json
61
62
  {
62
63
  "mcpServers": {
63
64
  "rowan": {
64
- "command": "uvx",
65
- "args": ["--from", "rowan-mcp", "rowan-mcp"],
66
- "env": {
67
- "ROWAN_API_KEY": "your_api_key_here"
68
- }
65
+ "type": "http",
66
+ "url": "http://127.0.0.1:6276/sse"
69
67
  }
70
68
  }
71
69
  }
72
70
  ```
73
71
 
74
- **Using uv run (alternative):**
75
- ```json
76
- {
77
- "mcpServers": {
78
- "rowan": {
79
- "command": "uv",
80
- "args": ["run", "--with", "rowan-mcp", "-m", "rowan_mcp"],
81
- "env": {
82
- "ROWAN_API_KEY": "your_api_key_here"
83
- }
84
- }
85
- }
86
- }
72
+ Then start the server:
73
+ ```bash
74
+ # Set your API key
75
+ export ROWAN_API_KEY="your_api_key_here"
76
+
77
+ # Start the HTTP server
78
+ uvx --from rowan-mcp rowan-mcp
87
79
  ```
88
80
 
89
81
  ### **Option 2: Manual Installation**
@@ -100,20 +92,24 @@ uv add rowan-mcp
100
92
  pip install rowan-mcp
101
93
  ```
102
94
 
103
- Then use this configuration:
95
+ Then configure and start:
104
96
  ```json
105
97
  {
106
98
  "mcpServers": {
107
99
  "rowan": {
108
- "command": "rowan-mcp",
109
- "env": {
110
- "ROWAN_API_KEY": "your_api_key_here"
111
- }
100
+ "type": "http",
101
+ "url": "http://127.0.0.1:6276/sse"
112
102
  }
113
103
  }
114
104
  }
115
105
  ```
116
106
 
107
+ ```bash
108
+ # Set API key and start server
109
+ export ROWAN_API_KEY="your_api_key_here"
110
+ rowan-mcp
111
+ ```
112
+
117
113
  ### **Get API Key**
118
114
 
119
115
  Visit [labs.rowansci.com](https://labs.rowansci.com) → Create account → Generate API key
@@ -142,7 +138,8 @@ Ask the LLM to:
142
138
  **Development commands** (if you cloned the repo):
143
139
  ```bash
144
140
  # Run from source
145
- uv run python -m rowan_mcp --http
141
+ export ROWAN_API_KEY="your_api_key_here"
142
+ uv run python -m rowan_mcp
146
143
  ```
147
144
 
148
145
  ---
@@ -189,16 +186,18 @@ uv run python -m rowan_mcp --http
189
186
 
190
187
  ## **Todo**
191
188
 
192
- - [ ] Remove unnecessary AI spaghetti formatting 🙃
189
+ - [X] Remove unnecessary AI spaghetti formatting
190
+ - [X] Remove no longer necessary API config lines
193
191
  - [ ] Some complex conformer searches hang on "running"
194
- - [ ] Edit MCP one-liner context
192
+ - [X] Edit MCP one-liner context
195
193
  - [ ] Transition state finding and IRC
196
194
  - [X] `rowan_scan` - Potential energy surfaces
197
195
  - [ ] `rowan_docking` - Protein-ligand docking
198
196
  - [X] add in h-bond, BDE and macroscopic pka, logD, BBB
199
197
  - [ ] Folder listing API bug (returns 500 error) - Rowan side?
200
198
  - [ ] Multistage optimization sometimes shows unexpected imaginary frequencies
201
- - [ ] Some calculations show as finished in logs but not in Rowan UI
199
+ - [X] Some calculations show as finished in logs but not in Rowan UI
200
+ - [ ] Can you hook up Rowan's visual capabilites?
202
201
 
203
202
  ## **Citation**
204
203
 
@@ -225,3 +224,20 @@ uv publish
225
224
  # Or publish to TestPyPI first
226
225
  uv publish --index-url https://test.pypi.org/simple/
227
226
  ```
227
+
228
+ To update the dxt file:
229
+ ```bash
230
+ # After updating the PyPI package, update all changed tools/functions
231
+
232
+ # Then update the desktop extension
233
+ dxt pack rowan-dxt
234
+ ```
235
+ ### MCP inspector
236
+ ```bash
237
+ # Start the server first
238
+ export ROWAN_API_KEY="your_api_key_here"
239
+ uv run python -m rowan_mcp &
240
+
241
+ # Then inspect
242
+ npx @modelcontextprotocol/inspector http://127.0.0.1:6276/sse
243
+ ```
@@ -0,0 +1,42 @@
1
+ rowan_mcp/__init__.py,sha256=1YLhdt94grBE3m3twzj4dpxSrYngceJIP_WG90ItmZo,376
2
+ rowan_mcp/__main__.py,sha256=a4ojXN6YhHy7tTSqwCznYP6luVP6OrbVqwnkPfPFBbU,264
3
+ rowan_mcp/server.py,sha256=w8194y9pSXKSxyOy4ADjuqAVrHxbMhUKloTUmWvTcJI,4286
4
+ rowan_mcp/functions_v2/BENCHMARK.md,sha256=QzSrpJyKYo3FlnuiTxxGYcalMFTobury9G0PvXgVVM0,3026
5
+ rowan_mcp/functions_v2/molecule_lookup.py,sha256=Ox7PKhjtQYMChaHbqo68IHhuxt5vXU_pOfytyJ3T09c,7795
6
+ rowan_mcp/functions_v2/protein_management.py,sha256=6f53SOiRkYGSho4rkqm8rKxTDEmyNPcXzBbULRvLb0k,3429
7
+ rowan_mcp/functions_v2/submit_basic_calculation_workflow.py,sha256=q3i6bx0ET_XnMHh33nCeGxyOjOeOt6CVADXhy3QUNQk,8100
8
+ rowan_mcp/functions_v2/submit_conformer_search_workflow.py,sha256=NWNxtTHTbHl8se9fBWOb0DKqEREDBFQlJFSr2HRYtko,6839
9
+ rowan_mcp/functions_v2/submit_descriptors_workflow.py,sha256=wKr1NVRCSCM4iGhBoAXcpqs9tqKu39VfYSKBgU7bn2I,2044
10
+ rowan_mcp/functions_v2/submit_docking_workflow.py,sha256=GlkdkqXBXTHpiF-xQkByyARSODKv8HuIyF-Sz4-59Rk,10976
11
+ rowan_mcp/functions_v2/submit_fukui_workflow.py,sha256=BM4yFXSJp-s0u2av2-R00o14xASQJv9a7DRWMEOMPmA,5203
12
+ rowan_mcp/functions_v2/submit_irc_workflow.py,sha256=uYI0JnPG6MaQH30h2tmSWDpEbrYZipPCq5KGzQ5M-vU,2666
13
+ rowan_mcp/functions_v2/submit_macropka_workflow.py,sha256=6UEEqvGwgYKcKTBuKnhydWSonBZuw1rPuXvryAL7CE0,3879
14
+ rowan_mcp/functions_v2/submit_pka_workflow.py,sha256=fZzDzcZBPBMPqe7DrM9Uamc4-EEMksu2dbiKrhegEVg,3388
15
+ rowan_mcp/functions_v2/submit_protein_cofolding_workflow.py,sha256=DxK3gT6LhGbnOIpPCvPRj3kvZLEFH6hdsEZQrOxDjhQ,4919
16
+ rowan_mcp/functions_v2/submit_redox_potential_workflow.py,sha256=v54oCmb2d6noiORMYJ_f5cEp2KaPp6kaN4TLlmIbX9U,2427
17
+ rowan_mcp/functions_v2/submit_scan_workflow.py,sha256=yohqRCFTLTupUxkLjd1rL-sDvwcX4qn7n44eCTJhoKo,4162
18
+ rowan_mcp/functions_v2/submit_solubility_workflow.py,sha256=ijtfOtQsXNkXpFLdN-HCWzltVm_MDeXWJWnn1xg4RLo,6739
19
+ rowan_mcp/functions_v2/submit_tautomer_search_workflow.py,sha256=uc1RDyC1cTOdBgzukUSyt5DTTsmeLUwnpyNbmLy5oJ0,2086
20
+ rowan_mcp/functions_v2/workflow_management_v2.py,sha256=e0r4-lfnbMj_rx2rs17AAUvbLWWZwpY3sG2cbfT5acY,13055
21
+ rowan_mcp/tests/basic_calculation_from_json.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ rowan_mcp/tests/basic_calculation_with_constraint.py,sha256=By_3zEA2pXI6NSV9KKkCcoGtj-3Sx5JOpZDXXFf_rFk,757
23
+ rowan_mcp/tests/basic_calculation_with_solvent.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ rowan_mcp/tests/bde.py,sha256=wJnNA-Vf_EQf4uEJzg72wi_7Dt2ytxzbbQtfFE5BGd8,1195
25
+ rowan_mcp/tests/benchmark_queries.md,sha256=xUGNkJKPqiwYd3sI0BlZE2EBxHJCtcuFdmFF3RN007w,3967
26
+ rowan_mcp/tests/cofolding_screen.py,sha256=OLfUz-GOTFgpS7jA94vBPlV55SguR09kDyIlAApsmaM,4782
27
+ rowan_mcp/tests/conformer_dependent_redox.py,sha256=fyEQ0yIQPEyuXnntkHDHo5kx6zCJGmNir2Y-RE7hJOI,1114
28
+ rowan_mcp/tests/conformers.py,sha256=gRUc1kWlWzxai4RnAeDweepW5fdv_JiL5F3dyJZS2KQ,1316
29
+ rowan_mcp/tests/data.json,sha256=deKhTb9Xb8vdqGoH8i8n5bqV_fXYqGGajJccVluHQIY,3750
30
+ rowan_mcp/tests/docking_screen.py,sha256=CDUVqax7Aial3-6d4tt8NSrJoPlmeoVqT9IeG0obcO0,5262
31
+ rowan_mcp/tests/irc.py,sha256=ZoSVw4jBpwU82hr6rAORY29MdkJPW5uakYZlyhOTwqU,576
32
+ rowan_mcp/tests/macropka.py,sha256=i5CUIIIJQDyeUdYgC_IPCJWZBmCHdnPGDiTS68n-c6c,330
33
+ rowan_mcp/tests/multistage_opt.py,sha256=i5CUIIIJQDyeUdYgC_IPCJWZBmCHdnPGDiTS68n-c6c,330
34
+ rowan_mcp/tests/optimization.py,sha256=x3a-n_H1cUVUAVmqd0nSSFbpoItSVr4J-DxvbKhkess,441
35
+ rowan_mcp/tests/phenol_pka.py,sha256=XoCl__rXAlUcbvqZAEssvFVnos74dBI2iS_znwL91_8,1030
36
+ rowan_mcp/tests/pka.py,sha256=XoCl__rXAlUcbvqZAEssvFVnos74dBI2iS_znwL91_8,1030
37
+ rowan_mcp/tests/protein_cofolding.py,sha256=5EC5P4yKb6M1NvZehydadkJbHC_w7Mo7qjIE1pmZp3c,854
38
+ rowan_mcp/tests/scan.py,sha256=DFAOMp4itWNFn5BGMhIUD7fyvxBVP9uMkuxMx3otOSM,574
39
+ rowan_mcp-2.0.0.dist-info/METADATA,sha256=2RgfjiMWN6BBSEy4blJ3Z7iDMM_RPBwKf-gzFBhAK2Q,6597
40
+ rowan_mcp-2.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
41
+ rowan_mcp-2.0.0.dist-info/entry_points.txt,sha256=QkmK3GHkTNA6gqyTIFrl2V2eVBm-VBdRAlDNsvi4Rl0,52
42
+ rowan_mcp-2.0.0.dist-info/RECORD,,
@@ -1,94 +0,0 @@
1
- """
2
- Rowan ADMET properties function for drug discovery.
3
- """
4
-
5
- import os
6
- import logging
7
- import time
8
- import traceback
9
- from typing import Optional
10
-
11
- try:
12
- import rowan
13
- except ImportError:
14
- rowan = None
15
-
16
- # Setup logging
17
- logger = logging.getLogger(__name__)
18
-
19
- # Setup API key
20
- api_key = os.getenv("ROWAN_API_KEY")
21
- if rowan and api_key:
22
- rowan.api_key = api_key
23
-
24
-
25
- def log_rowan_api_call(workflow_type: str, **kwargs):
26
- """Log Rowan API calls with detailed parameters."""
27
-
28
- try:
29
- start_time = time.time()
30
- result = rowan.compute(workflow_type=workflow_type, **kwargs)
31
- api_time = time.time() - start_time
32
-
33
- return result
34
-
35
- except Exception as e:
36
- api_time = time.time() - start_time
37
-
38
- raise e
39
-
40
-
41
- def rowan_admet(
42
- name: str,
43
- molecule: str,
44
- folder_uuid: Optional[str] = None,
45
- blocking: bool = True,
46
- ping_interval: int = 5
47
- ) -> str:
48
- """Predict ADME-Tox properties for drug discovery.
49
-
50
- ADMET (Absorption, Distribution, Metabolism, Excretion, Toxicity) properties are crucial
51
- for drug development. This workflow predicts drug-like properties including:
52
- - Bioavailability and permeability
53
- - Metabolic stability and clearance
54
- - Toxicity indicators and safety profiles
55
- - Drug-likeness metrics
56
-
57
- Use this for: Drug discovery, pharmaceutical development, toxicity screening
58
-
59
- Args:
60
- name: Name for the calculation
61
- molecule: Molecule SMILES string
62
- folder_uuid: Optional folder UUID for organization
63
- blocking: Whether to wait for completion (default: True)
64
- ping_interval: Check status interval in seconds (default: 5)
65
-
66
- Returns:
67
- ADMET prediction results
68
- """
69
- result = log_rowan_api_call(
70
- workflow_type="admet",
71
- name=name,
72
- molecule=molecule,
73
- folder_uuid=folder_uuid,
74
- blocking=blocking,
75
- ping_interval=ping_interval
76
- )
77
- return str(result)
78
-
79
-
80
- def test_rowan_admet():
81
- """Test the rowan_admet function."""
82
- try:
83
- # Test with a simple molecule (non-blocking to avoid long wait)
84
- result = rowan_admet("test_admet", "CCO", blocking=False)
85
- print("ADMET test successful!")
86
- print(f"Result length: {len(result)} characters")
87
- return True
88
- except Exception as e:
89
- print(f"ADMET test failed: {e}")
90
- return False
91
-
92
-
93
- if __name__ == "__main__":
94
- test_rowan_admet()