rowan-python 3.1.6__tar.gz → 3.1.7__tar.gz

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 (192) hide show
  1. {rowan_python-3.1.6 → rowan_python-3.1.7}/.claude-plugin/marketplace.json +1 -1
  2. {rowan_python-3.1.6 → rowan_python-3.1.7}/.codex-plugin/plugin.json +3 -3
  3. {rowan_python-3.1.6 → rowan_python-3.1.7}/.github/workflows/test.yml +1 -0
  4. {rowan_python-3.1.6 → rowan_python-3.1.7}/PKG-INFO +21 -3
  5. {rowan_python-3.1.6 → rowan_python-3.1.7}/README.md +20 -2
  6. {rowan_python-3.1.6 → rowan_python-3.1.7}/pixi.lock +31 -31
  7. {rowan_python-3.1.6 → rowan_python-3.1.7}/pyproject.toml +1 -1
  8. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/protein.py +2 -4
  9. rowan_python-3.1.7/rowan/test_utils.py +54 -0
  10. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/utils.py +40 -0
  11. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/SKILL.md +10 -64
  12. rowan_python-3.1.7/skills/computational-chemistry-and-biology/reference/mcp_execution.md +15 -0
  13. rowan_python-3.1.7/skills/computational-chemistry-and-biology/reference/python_sdk.md +64 -0
  14. {rowan_python-3.1.6 → rowan_python-3.1.7}/.agents/plugins/marketplace.json +0 -0
  15. {rowan_python-3.1.6 → rowan_python-3.1.7}/.envrc +0 -0
  16. {rowan_python-3.1.6 → rowan_python-3.1.7}/.github/workflows/build-and-deploy-docs.yml +0 -0
  17. {rowan_python-3.1.6 → rowan_python-3.1.7}/.github/workflows/publish-skill.yml +0 -0
  18. {rowan_python-3.1.6 → rowan_python-3.1.7}/.github/workflows/python-publish.yml +0 -0
  19. {rowan_python-3.1.6 → rowan_python-3.1.7}/.gitignore +0 -0
  20. {rowan_python-3.1.6 → rowan_python-3.1.7}/.pre-commit-config.yaml +0 -0
  21. {rowan_python-3.1.6 → rowan_python-3.1.7}/AGENTS.md +0 -0
  22. {rowan_python-3.1.6 → rowan_python-3.1.7}/CLAUDE.md +0 -0
  23. {rowan_python-3.1.6 → rowan_python-3.1.7}/GEMINI.md +0 -0
  24. {rowan_python-3.1.6 → rowan_python-3.1.7}/LICENSE +0 -0
  25. {rowan_python-3.1.6 → rowan_python-3.1.7}/docs/images/deciduous-tree-favicon.png +0 -0
  26. {rowan_python-3.1.6 → rowan_python-3.1.7}/docs/index.md +0 -0
  27. {rowan_python-3.1.6 → rowan_python-3.1.7}/docs/stylesheets/colors.css +0 -0
  28. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/PROTAC_solubility.py +0 -0
  29. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/admet.py +0 -0
  30. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/analogue_docking.py +0 -0
  31. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/aqueous_solubility.py +0 -0
  32. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/basic_calculation.py +0 -0
  33. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/basic_calculation_from_json.py +0 -0
  34. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/basic_calculation_with_constraint.py +0 -0
  35. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/basic_calculation_with_solvent.py +0 -0
  36. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/batch_docking.py +0 -0
  37. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/bde.py +0 -0
  38. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/binding_affinity.py +0 -0
  39. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/boltz_paired_msa.py +0 -0
  40. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/boltz_single_msa.py +0 -0
  41. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/chai_paired_msa.py +0 -0
  42. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/chai_single_msa.py +0 -0
  43. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/cofolding_screen.py +0 -0
  44. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/colabfold_paired_msa.py +0 -0
  45. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/colabfold_single_msa.py +0 -0
  46. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/conformer_dependent_redox.py +0 -0
  47. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/conformers.py +0 -0
  48. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/conformers_screen.py +0 -0
  49. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/covalent_docking.py +0 -0
  50. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/covalent_inhibitor_scan.py +0 -0
  51. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/1iep_receptorH.pdb +0 -0
  52. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/Al_FCC.xyz +0 -0
  53. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/citalopram_1iep.xyz +0 -0
  54. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/ibuprofen_conformers.sdf +0 -0
  55. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/tyk2_ligands.sdf +0 -0
  56. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/tyk2_structure.pdb +0 -0
  57. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/data/workflow_example.json +0 -0
  58. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/dcd_download.py +0 -0
  59. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/descriptors.py +0 -0
  60. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/docking.py +0 -0
  61. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/docking_screen.py +0 -0
  62. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/double_ended_ts_search.py +0 -0
  63. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/electronic_properties.py +0 -0
  64. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/estimate_workflow.py +0 -0
  65. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/fukui_index.py +0 -0
  66. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/hydrogen_bond_basicity.py +0 -0
  67. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/interaction_energy_decomposition.py +0 -0
  68. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/ion_mobility.py +0 -0
  69. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/irc.py +0 -0
  70. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/macropka.py +0 -0
  71. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/membrane_permeability.py +0 -0
  72. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/multistage_optimization.py +0 -0
  73. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/nmr.py +0 -0
  74. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/optimization.py +0 -0
  75. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/pdb_download.py +0 -0
  76. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/periodic_dft.py +0 -0
  77. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/phenol_pka.py +0 -0
  78. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/pka.py +0 -0
  79. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/pocket_detection.py +0 -0
  80. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/pose_analysis_md.py +0 -0
  81. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/project_scoped_api_key.py +0 -0
  82. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/protein_binder_design.py +0 -0
  83. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/protein_cofolding.py +0 -0
  84. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/protein_cofolding_with_constraints.py +0 -0
  85. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/protein_cofolding_with_templates.py +0 -0
  86. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/protein_md.py +0 -0
  87. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/rbfe_graph.py +0 -0
  88. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/rbfe_resubmit.py +0 -0
  89. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/redox_potential.py +0 -0
  90. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/relative_binding_free_energy_perturbation.py +0 -0
  91. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/resubmit_with_perturbations.py +0 -0
  92. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/retrieve_workflow.py +0 -0
  93. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/scan.py +0 -0
  94. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/solvent_dependent_conformers.py +0 -0
  95. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/spin_states.py +0 -0
  96. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/strain.py +0 -0
  97. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/tautomer.py +0 -0
  98. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/template.py +0 -0
  99. {rowan_python-3.1.6 → rowan_python-3.1.7}/examples/webhook.py +0 -0
  100. {rowan_python-3.1.6 → rowan_python-3.1.7}/mkdocs.yml +0 -0
  101. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/__init__.py +0 -0
  102. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/api_keys.py +0 -0
  103. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/calculation.py +0 -0
  104. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/config.py +0 -0
  105. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/constants.py +0 -0
  106. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/folder.py +0 -0
  107. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/molecule.py +0 -0
  108. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/project.py +0 -0
  109. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/py.typed +0 -0
  110. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/types.py +0 -0
  111. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/user.py +0 -0
  112. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/__init__.py +0 -0
  113. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/admet.py +0 -0
  114. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/analogue_docking.py +0 -0
  115. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/base.py +0 -0
  116. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/basic_calculation.py +0 -0
  117. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/batch_docking.py +0 -0
  118. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/bde.py +0 -0
  119. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/binding_affinity.py +0 -0
  120. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/conformer_search.py +0 -0
  121. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/constants.py +0 -0
  122. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/covalent_inhibitor_scan.py +0 -0
  123. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/descriptors.py +0 -0
  124. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/docking.py +0 -0
  125. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/double_ended_ts_search.py +0 -0
  126. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/electronic_properties.py +0 -0
  127. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/fukui.py +0 -0
  128. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/hydrogen_bond_donor_acceptor_strength.py +0 -0
  129. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/interaction_energy_decomposition.py +0 -0
  130. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/ion_mobility.py +0 -0
  131. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/irc.py +0 -0
  132. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/macropka.py +0 -0
  133. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/membrane_permeability.py +0 -0
  134. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/msa.py +0 -0
  135. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/multistage_optimization.py +0 -0
  136. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/nmr.py +0 -0
  137. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/pka.py +0 -0
  138. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/pocket_detection.py +0 -0
  139. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/pose_analysis_md.py +0 -0
  140. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/protein_binder_design.py +0 -0
  141. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/protein_cofolding.py +0 -0
  142. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/protein_md.py +0 -0
  143. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/rbfe_graph.py +0 -0
  144. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/redox_potential.py +0 -0
  145. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/relative_binding_free_energy_perturbation.py +0 -0
  146. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/scan.py +0 -0
  147. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/solubility.py +0 -0
  148. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/solvent_dependent_conformers.py +0 -0
  149. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/spin_states.py +0 -0
  150. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/strain.py +0 -0
  151. {rowan_python-3.1.6 → rowan_python-3.1.7}/rowan/workflows/tautomer_search.py +0 -0
  152. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/admet.md +0 -0
  153. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/analogue_docking.md +0 -0
  154. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/basic_calculation.md +0 -0
  155. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/batch_docking.md +0 -0
  156. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/bde.md +0 -0
  157. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/binding_affinity.md +0 -0
  158. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/conformer_search.md +0 -0
  159. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/covalent_inhibitor_scan.md +0 -0
  160. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/descriptors.md +0 -0
  161. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/docking.md +0 -0
  162. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/double_ended_ts_search.md +0 -0
  163. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/electronic_properties.md +0 -0
  164. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/folders_and_projects.md +0 -0
  165. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/fukui.md +0 -0
  166. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/hydrogen_bond_donor_acceptor_strength.md +0 -0
  167. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/interaction_energy_decomposition.md +0 -0
  168. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/ion_mobility.md +0 -0
  169. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/irc.md +0 -0
  170. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/macropka.md +0 -0
  171. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/membrane_permeability.md +0 -0
  172. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/msa.md +0 -0
  173. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/multistage_optimization.md +0 -0
  174. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/nmr.md +0 -0
  175. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/pka.md +0 -0
  176. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/pocket_detection.md +0 -0
  177. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/pose_analysis_md.md +0 -0
  178. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/protein_binder_design.md +0 -0
  179. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/protein_cofolding.md +0 -0
  180. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/protein_md.md +0 -0
  181. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/protein_prep.md +0 -0
  182. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/rbfe_graph.md +0 -0
  183. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/redox_potential.md +0 -0
  184. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/relative_binding_free_energy_perturbation.md +0 -0
  185. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/scan.md +0 -0
  186. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/solubility.md +0 -0
  187. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/solvent_dependent_conformers.md +0 -0
  188. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/spin_states.md +0 -0
  189. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/strain.md +0 -0
  190. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/tautomer_search.md +0 -0
  191. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/reference/webhooks.md +0 -0
  192. {rowan_python-3.1.6 → rowan_python-3.1.7}/skills/computational-chemistry-and-biology/scripts/check_env.py +0 -0
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "computational-chemistry-and-biology",
11
11
  "source": "./skills/computational-chemistry-and-biology",
12
- "description": "Run computational chemistry and structural biology calculations on the Rowan platform via the rowan Python package",
12
+ "description": "Run computational chemistry and structural biology calculations through Rowan MCP tools or rowan-python",
13
13
  "skills": ["./"],
14
14
  "strict": false
15
15
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "computational-chemistry-and-biology",
3
- "version": "0.0.1",
4
- "description": "Run computational chemistry and structural biology calculations on the Rowan platform via the rowan-python package",
3
+ "version": "0.0.2",
4
+ "description": "Run computational chemistry and structural biology calculations through Rowan MCP tools or rowan-python",
5
5
  "skills": "./skills/",
6
6
  "author": {
7
7
  "name": "Rowan",
@@ -20,7 +20,7 @@
20
20
  "interface": {
21
21
  "displayName": "Rowan Computational Chemistry",
22
22
  "shortDescription": "Run computational chemistry and structural biology workflows with Rowan.",
23
- "longDescription": "Use Rowan to choose and run molecular and protein workflows, including quantum chemistry, docking, molecular dynamics, protein structure prediction, and cheminformatics. The bundled skill provides workflow selection guidance, safe defaults, result retrieval patterns, and links to detailed workflow references.",
23
+ "longDescription": "Use Rowan to choose and run molecular and protein workflows, including quantum chemistry, docking, molecular dynamics, protein structure prediction, and cheminformatics. The bundled skill provides shared scientific and workflow guidance for Rowan MCP tools and rowan-python, including safe defaults, result retrieval patterns, and detailed references.",
24
24
  "developerName": "Rowan",
25
25
  "category": "Science",
26
26
  "capabilities": [
@@ -31,3 +31,4 @@ jobs:
31
31
  - run: pixi run fmt
32
32
  - run: pixi run lint
33
33
  - run: pixi run types
34
+ - run: pixi run test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rowan-python
3
- Version: 3.1.6
3
+ Version: 3.1.7
4
4
  Summary: Rowan Python Library
5
5
  Project-URL: Homepage, https://github.com/rowansci/rowan-client
6
6
  Project-URL: Bug Tracker, https://github.com/rowansci/rowan-client/issues
@@ -30,9 +30,27 @@ The documentation is available [here](https://docs.rowansci.com/python-api).
30
30
 
31
31
  ## Agent skill
32
32
 
33
- Ships with a [skill](skills/computational-chemistry-and-biology/) that makes it easy for coding agents to use Rowan's tools to power chemistry and biology tasks. To use it, copy the directory into your agent's skills folder.
33
+ Ships with a [computational chemistry and biology skill](skills/computational-chemistry-and-biology/)
34
+ that helps coding agents choose and run Rowan workflows through either Rowan MCP tools or the
35
+ Rowan Python SDK.
34
36
 
35
- Download the latest skill as a zip [here](https://github.com/rowansci/rowan-python/releases/download/skill-latest/computational-chemistry-and-biology-skill.zip), then unzip it into your agent's skills folder.
37
+ ### Claude Code
38
+
39
+ ```bash
40
+ claude plugin marketplace add https://github.com/rowansci/rowan-python.git
41
+ claude plugin install computational-chemistry-and-biology@rowan
42
+ ```
43
+
44
+ ### Codex
45
+
46
+ ```bash
47
+ codex plugin marketplace add rowansci/rowan-python --ref master
48
+ codex plugin add computational-chemistry-and-biology@rowan
49
+ ```
50
+
51
+ Start a new Claude Code or Codex session after installation. For manual installation, download the
52
+ [latest skill ZIP](https://github.com/rowansci/rowan-python/releases/download/skill-latest/computational-chemistry-and-biology-skill.zip)
53
+ and extract it into your agent's skills directory.
36
54
 
37
55
  ## Running examples
38
56
 
@@ -14,9 +14,27 @@ The documentation is available [here](https://docs.rowansci.com/python-api).
14
14
 
15
15
  ## Agent skill
16
16
 
17
- Ships with a [skill](skills/computational-chemistry-and-biology/) that makes it easy for coding agents to use Rowan's tools to power chemistry and biology tasks. To use it, copy the directory into your agent's skills folder.
17
+ Ships with a [computational chemistry and biology skill](skills/computational-chemistry-and-biology/)
18
+ that helps coding agents choose and run Rowan workflows through either Rowan MCP tools or the
19
+ Rowan Python SDK.
18
20
 
19
- Download the latest skill as a zip [here](https://github.com/rowansci/rowan-python/releases/download/skill-latest/computational-chemistry-and-biology-skill.zip), then unzip it into your agent's skills folder.
21
+ ### Claude Code
22
+
23
+ ```bash
24
+ claude plugin marketplace add https://github.com/rowansci/rowan-python.git
25
+ claude plugin install computational-chemistry-and-biology@rowan
26
+ ```
27
+
28
+ ### Codex
29
+
30
+ ```bash
31
+ codex plugin marketplace add rowansci/rowan-python --ref master
32
+ codex plugin add computational-chemistry-and-biology@rowan
33
+ ```
34
+
35
+ Start a new Claude Code or Codex session after installation. For manual installation, download the
36
+ [latest skill ZIP](https://github.com/rowansci/rowan-python/releases/download/skill-latest/computational-chemistry-and-biology-skill.zip)
37
+ and extract it into your agent's skills directory.
20
38
 
21
39
  ## Running examples
22
40
 
@@ -45,7 +45,6 @@ environments:
45
45
  - pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl
46
46
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
47
47
  - pypi: https://files.pythonhosted.org/packages/30/7b/0f6916498687aad6aacc28dfa59cc9b2bf03b869d81522a9fe1bf6c1e72a/rdkit-2026.3.3-cp314-cp314-manylinux_2_28_x86_64.whl
48
- - pypi: https://files.pythonhosted.org/packages/30/b1/1a42ac1eada0a193ecdaa17ce92efa6354bfdcf315c42aaafa69f237ae59/stjames-0.0.228-py3-none-any.whl
49
48
  - pypi: https://files.pythonhosted.org/packages/41/5f/0f992cb24560673496c5d68de61913b57166ce530ffda07c1f280e0cc464/numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
50
49
  - pypi: https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl
51
50
  - pypi: https://files.pythonhosted.org/packages/5c/44/c85361f65dbe00eea8576ee467c768d25129989efb76e94f205e9ca9bb46/pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -56,6 +55,7 @@ environments:
56
55
  - pypi: https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
57
56
  - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
58
57
  - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl
58
+ - pypi: https://files.pythonhosted.org/packages/a6/d7/f6824ea5fc0ac2bcded7fb2626aa7a851a7f487645d5ae7b10f585f935a7/stjames-0.0.230-py3-none-any.whl
59
59
  - pypi: https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl
60
60
  - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
61
61
  - pypi: https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl
@@ -83,7 +83,6 @@ environments:
83
83
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
84
84
  - pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl
85
85
  - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
86
- - pypi: https://files.pythonhosted.org/packages/30/b1/1a42ac1eada0a193ecdaa17ce92efa6354bfdcf315c42aaafa69f237ae59/stjames-0.0.228-py3-none-any.whl
87
86
  - pypi: https://files.pythonhosted.org/packages/45/da/825325da9989d10a309378754464898c07199a2881fd04171613948aa82f/rdkit-2026.3.3-cp314-cp314-macosx_11_0_arm64.whl
88
87
  - pypi: https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl
89
88
  - pypi: https://files.pythonhosted.org/packages/5d/40/e1e72872c6354b306daef1703549e8e83b4d43cfea356311bf722a043752/setuptools-83.0.0-py3-none-any.whl
@@ -93,6 +92,7 @@ environments:
93
92
  - pypi: https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl
94
93
  - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
95
94
  - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl
95
+ - pypi: https://files.pythonhosted.org/packages/a6/d7/f6824ea5fc0ac2bcded7fb2626aa7a851a7f487645d5ae7b10f585f935a7/stjames-0.0.230-py3-none-any.whl
96
96
  - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl
97
97
  - pypi: https://files.pythonhosted.org/packages/bf/64/0e215f2048dd11a55bb989ed41b3585ef57452404e638d703a211a3e4157/numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl
98
98
  - pypi: https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl
@@ -146,7 +146,6 @@ environments:
146
146
  - pypi: https://files.pythonhosted.org/packages/2d/88/17d656aa97406cd509e2be0e6eddcf81fc1666104bf81042b89721d4a44c/griffe_pydantic-1.3.1-py3-none-any.whl
147
147
  - pypi: https://files.pythonhosted.org/packages/30/14/4d0204867623df3f33f86efd3d3692ba5e01321443f4d6eab35a22697618/librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
148
148
  - pypi: https://files.pythonhosted.org/packages/30/7b/0f6916498687aad6aacc28dfa59cc9b2bf03b869d81522a9fe1bf6c1e72a/rdkit-2026.3.3-cp314-cp314-manylinux_2_28_x86_64.whl
149
- - pypi: https://files.pythonhosted.org/packages/30/b1/1a42ac1eada0a193ecdaa17ce92efa6354bfdcf315c42aaafa69f237ae59/stjames-0.0.228-py3-none-any.whl
150
149
  - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl
151
150
  - pypi: https://files.pythonhosted.org/packages/40/3a/948263ca3b9d65bb2b1b0c521b3a49fad5d59ada58724bd87d2bd5ff3f36/ipython-9.15.0-py3-none-any.whl
152
151
  - pypi: https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl
@@ -160,6 +159,7 @@ environments:
160
159
  - pypi: https://files.pythonhosted.org/packages/5d/5b/4c1902e8bdd5c4db63284e9d101dece4038d4025d6d88850ffe0a1578980/mkdocstrings-1.0.6-py3-none-any.whl
161
160
  - pypi: https://files.pythonhosted.org/packages/60/02/be4a57b60c7149b55b9e3b3c13f609cd8eb5307c751f22bd8fb8d262e75b/filelock-3.29.7-py3-none-any.whl
162
161
  - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
162
+ - pypi: https://files.pythonhosted.org/packages/6c/58/821b533b8db9e44cf1d8a97bd525149ced40dde1d0093da02cb78e715244/coverage-7.15.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
163
163
  - pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
164
164
  - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
165
165
  - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
@@ -184,6 +184,7 @@ environments:
184
184
  - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
185
185
  - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
186
186
  - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl
187
+ - pypi: https://files.pythonhosted.org/packages/a6/d7/f6824ea5fc0ac2bcded7fb2626aa7a851a7f487645d5ae7b10f585f935a7/stjames-0.0.230-py3-none-any.whl
187
188
  - pypi: https://files.pythonhosted.org/packages/ae/77/70d7a10732063beb74ad713682cf871e88f5c5fa39bfc8beff8a524bf9cb/mypy-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
188
189
  - pypi: https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
189
190
  - pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl
@@ -203,7 +204,6 @@ environments:
203
204
  - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
204
205
  - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl
205
206
  - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl
206
- - pypi: https://files.pythonhosted.org/packages/e1/53/0d3dd963631259d794c898735d5436e68d6a8d40749c419a07ff7c171469/coverage-7.15.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
207
207
  - pypi: https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl
208
208
  - pypi: https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl
209
209
  - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
@@ -238,7 +238,6 @@ environments:
238
238
  - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
239
239
  - pypi: https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl
240
240
  - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl
241
- - pypi: https://files.pythonhosted.org/packages/13/d2/ee14d715889f216baf47301d9f469e08fff6995552aaf67e897b282865f6/coverage-7.15.1-cp314-cp314-macosx_11_0_arm64.whl
242
241
  - pypi: https://files.pythonhosted.org/packages/15/14/2ba1d61452d7c2a7fe12741e8d374e52b183476b07aa7f9e2a0d02b0720a/mypy-2.3.0-cp314-cp314-macosx_11_0_arm64.whl
243
242
  - pypi: https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl
244
243
  - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl
@@ -249,7 +248,6 @@ environments:
249
248
  - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl
250
249
  - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl
251
250
  - pypi: https://files.pythonhosted.org/packages/2d/88/17d656aa97406cd509e2be0e6eddcf81fc1666104bf81042b89721d4a44c/griffe_pydantic-1.3.1-py3-none-any.whl
252
- - pypi: https://files.pythonhosted.org/packages/30/b1/1a42ac1eada0a193ecdaa17ce92efa6354bfdcf315c42aaafa69f237ae59/stjames-0.0.228-py3-none-any.whl
253
251
  - pypi: https://files.pythonhosted.org/packages/3d/50/51c76d74014d04fb95b6506d286808984b78a2f7a41039094e6b2194ac48/librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl
254
252
  - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl
255
253
  - pypi: https://files.pythonhosted.org/packages/40/3a/948263ca3b9d65bb2b1b0c521b3a49fad5d59ada58724bd87d2bd5ff3f36/ipython-9.15.0-py3-none-any.whl
@@ -262,6 +260,7 @@ environments:
262
260
  - pypi: https://files.pythonhosted.org/packages/5d/5b/4c1902e8bdd5c4db63284e9d101dece4038d4025d6d88850ffe0a1578980/mkdocstrings-1.0.6-py3-none-any.whl
263
261
  - pypi: https://files.pythonhosted.org/packages/60/02/be4a57b60c7149b55b9e3b3c13f609cd8eb5307c751f22bd8fb8d262e75b/filelock-3.29.7-py3-none-any.whl
264
262
  - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
263
+ - pypi: https://files.pythonhosted.org/packages/6b/2c/222ba12a545189017120f8eddfc1a0bd4616b47d5d4a8d99421edb2fe4c6/coverage-7.15.2-cp314-cp314-macosx_11_0_arm64.whl
265
264
  - pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
266
265
  - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
267
266
  - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
@@ -286,6 +285,7 @@ environments:
286
285
  - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
287
286
  - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
288
287
  - pypi: https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl
288
+ - pypi: https://files.pythonhosted.org/packages/a6/d7/f6824ea5fc0ac2bcded7fb2626aa7a851a7f487645d5ae7b10f585f935a7/stjames-0.0.230-py3-none-any.whl
289
289
  - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl
290
290
  - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl
291
291
  - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
@@ -854,13 +854,6 @@ packages:
854
854
  requires_dist:
855
855
  - click>=5.0 ; extra == 'cli'
856
856
  requires_python: '>=3.10'
857
- - pypi: https://files.pythonhosted.org/packages/13/d2/ee14d715889f216baf47301d9f469e08fff6995552aaf67e897b282865f6/coverage-7.15.1-cp314-cp314-macosx_11_0_arm64.whl
858
- name: coverage
859
- version: 7.15.1
860
- sha256: 985657ebd707941de90d488d1cbb5efac20bdf81f7b91eba771624ccda4d36f4
861
- requires_dist:
862
- - tomli ; python_full_version <= '3.11' and extra == 'toml'
863
- requires_python: '>=3.10'
864
857
  - pypi: https://files.pythonhosted.org/packages/15/14/2ba1d61452d7c2a7fe12741e8d374e52b183476b07aa7f9e2a0d02b0720a/mypy-2.3.0-cp314-cp314-macosx_11_0_arm64.whl
865
858
  name: mypy
866
859
  version: 2.3.0
@@ -1023,17 +1016,6 @@ packages:
1023
1016
  requires_dist:
1024
1017
  - numpy
1025
1018
  - pillow
1026
- - pypi: https://files.pythonhosted.org/packages/30/b1/1a42ac1eada0a193ecdaa17ce92efa6354bfdcf315c42aaafa69f237ae59/stjames-0.0.228-py3-none-any.whl
1027
- name: stjames
1028
- version: 0.0.228
1029
- sha256: 52f444feabe0dbe4fa3fe23a18a4e5cf0da2b45dd4ee32a023a431eaf176a464
1030
- requires_dist:
1031
- - pydantic>=2.4
1032
- - numpy
1033
- - requests
1034
- - more-itertools
1035
- - rdkit ; extra == 'rdkit'
1036
- requires_python: '>=3.11'
1037
1019
  - pypi: https://files.pythonhosted.org/packages/3d/50/51c76d74014d04fb95b6506d286808984b78a2f7a41039094e6b2194ac48/librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl
1038
1020
  name: librt
1039
1021
  version: 0.13.0
@@ -1260,6 +1242,20 @@ packages:
1260
1242
  - markupsafe>=2.0
1261
1243
  - babel>=2.7 ; extra == 'i18n'
1262
1244
  requires_python: '>=3.7'
1245
+ - pypi: https://files.pythonhosted.org/packages/6b/2c/222ba12a545189017120f8eddfc1a0bd4616b47d5d4a8d99421edb2fe4c6/coverage-7.15.2-cp314-cp314-macosx_11_0_arm64.whl
1246
+ name: coverage
1247
+ version: 7.15.2
1248
+ sha256: 075560438765b7a2ef43bf7aa7758661b53d889df47f062a31bda6c1ade553a2
1249
+ requires_dist:
1250
+ - tomli ; python_full_version <= '3.11' and extra == 'toml'
1251
+ requires_python: '>=3.10'
1252
+ - pypi: https://files.pythonhosted.org/packages/6c/58/821b533b8db9e44cf1d8a97bd525149ced40dde1d0093da02cb78e715244/coverage-7.15.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
1253
+ name: coverage
1254
+ version: 7.15.2
1255
+ sha256: b9a6367e4aff723e8ee8190836836124284e8fcd4265e307c844010cfa074f3f
1256
+ requires_dist:
1257
+ - tomli ; python_full_version <= '3.11' and extra == 'toml'
1258
+ requires_python: '>=3.10'
1263
1259
  - pypi: https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl
1264
1260
  name: babel
1265
1261
  version: 2.18.0
@@ -1558,6 +1554,17 @@ packages:
1558
1554
  - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks'
1559
1555
  - chardet>=3.0.2,<8 ; extra == 'use-chardet-on-py3'
1560
1556
  requires_python: '>=3.10'
1557
+ - pypi: https://files.pythonhosted.org/packages/a6/d7/f6824ea5fc0ac2bcded7fb2626aa7a851a7f487645d5ae7b10f585f935a7/stjames-0.0.230-py3-none-any.whl
1558
+ name: stjames
1559
+ version: 0.0.230
1560
+ sha256: 003fdbfc703542d6a34fcaca2e6f1575cc8bd0db2a56646bd63ed82e0fd05522
1561
+ requires_dist:
1562
+ - pydantic>=2.4
1563
+ - numpy
1564
+ - requests
1565
+ - more-itertools
1566
+ - rdkit ; extra == 'rdkit'
1567
+ requires_python: '>=3.11'
1561
1568
  - pypi: https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl
1562
1569
  name: pydantic-core
1563
1570
  version: 2.46.4
@@ -1821,13 +1828,6 @@ packages:
1821
1828
  version: '26.2'
1822
1829
  sha256: 5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e
1823
1830
  requires_python: '>=3.8'
1824
- - pypi: https://files.pythonhosted.org/packages/e1/53/0d3dd963631259d794c898735d5436e68d6a8d40749c419a07ff7c171469/coverage-7.15.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
1825
- name: coverage
1826
- version: 7.15.1
1827
- sha256: bde0fe24083d0b7b3dbafa7a09f0796410af1afa2523f28f5f208d8340a4aaca
1828
- requires_dist:
1829
- - tomli ; python_full_version <= '3.11' and extra == 'toml'
1830
- requires_python: '>=3.10'
1831
1831
  - pypi: https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl
1832
1832
  name: griffelib
1833
1833
  version: 2.1.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rowan-python"
3
- version = "3.1.6"
3
+ version = "3.1.7"
4
4
  description = "Rowan Python Library"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -400,22 +400,20 @@ def upload_protein(
400
400
  if isinstance(project_uuid, Project):
401
401
  project_uuid = project_uuid.uuid
402
402
  with api_client() as client:
403
- # Step 1: Read the file and post it to the conversion endpoint.
404
403
  conversion_payload = {"name": name, "text": file_path.read_text()}
405
404
  conversion_response = client.post("/convert/pdb_file_to_protein", json=conversion_payload)
405
+ conversion_response.raise_for_status()
406
406
 
407
- # Extract the JSON data from the conversion response.
408
407
  protein_data = conversion_response.json()
409
408
 
410
- # Step 2: Use the converted data to create the final protein object.
411
409
  creation_payload = {
412
410
  "name": name,
413
411
  "protein_data": protein_data,
414
412
  "project_uuid": project_uuid,
415
413
  }
416
414
  final_response = client.post("/protein", json=creation_payload)
415
+ final_response.raise_for_status()
417
416
 
418
- # Deserialize the final JSON response into a Protein object and return it.
419
417
  return Protein(**final_response.json())
420
418
 
421
419
 
@@ -0,0 +1,54 @@
1
+ """Tests for Rowan request utilities."""
2
+
3
+ import asyncio
4
+
5
+ from pytest import MonkeyPatch, raises
6
+
7
+ import rowan
8
+ from rowan.utils import api_credentials, get_api_key, get_project_uuid
9
+
10
+
11
+ def test_api_credentials_override_global_configuration(monkeypatch: MonkeyPatch) -> None:
12
+ """Prefer context-local credentials without changing global configuration."""
13
+ monkeypatch.setattr(rowan, "api_key", "global-key")
14
+ monkeypatch.setattr(rowan, "project_uuid", "global-project")
15
+ monkeypatch.setenv("ROWAN_API_KEY", "environment-key")
16
+
17
+ with api_credentials("context-key", project_uuid="context-project"):
18
+ assert get_api_key() == "context-key"
19
+ assert get_project_uuid() == "context-project"
20
+
21
+ assert get_api_key() == "global-key"
22
+ assert get_project_uuid() == "global-project"
23
+
24
+
25
+ def test_api_credentials_restore_nested_context() -> None:
26
+ """Restore outer credentials after a nested context exits."""
27
+ with api_credentials("outer-key", project_uuid="outer-project"):
28
+ with api_credentials("inner-key"):
29
+ assert get_api_key() == "inner-key"
30
+ assert get_project_uuid() is None
31
+
32
+ assert get_api_key() == "outer-key"
33
+ assert get_project_uuid() == "outer-project"
34
+
35
+
36
+ def test_api_credentials_isolate_async_tasks() -> None:
37
+ """Keep credentials isolated across concurrent asynchronous tasks."""
38
+
39
+ async def read_after_yield(api_key: str) -> str:
40
+ with api_credentials(api_key):
41
+ await asyncio.sleep(0)
42
+ return get_api_key()
43
+
44
+ async def run_workers() -> list[str]:
45
+ return list(await asyncio.gather(read_after_yield("first"), read_after_yield("second")))
46
+
47
+ assert asyncio.run(run_workers()) == ["first", "second"]
48
+
49
+
50
+ def test_api_credentials_reject_empty_key() -> None:
51
+ """Reject empty context-local API keys."""
52
+ with raises(ValueError, match="cannot be empty"):
53
+ with api_credentials(""):
54
+ pass
@@ -1,5 +1,7 @@
1
1
  import os
2
2
  from contextlib import contextmanager
3
+ from contextvars import ContextVar
4
+ from dataclasses import dataclass
3
5
  from typing import Generator
4
6
 
5
7
  import httpx
@@ -10,6 +12,40 @@ import rowan
10
12
  from .constants import API_URL
11
13
 
12
14
 
15
+ @dataclass(frozen=True, slots=True)
16
+ class _APIContext:
17
+ """Store credentials isolated to the current execution context."""
18
+
19
+ api_key: str
20
+ project_uuid: str | None
21
+
22
+
23
+ _api_context: ContextVar[_APIContext | None] = ContextVar("rowan_api_context", default=None)
24
+
25
+
26
+ @contextmanager
27
+ def api_credentials(api_key: str, project_uuid: str | None = None) -> Generator[None, None, None]:
28
+ """Temporarily use Rowan credentials in the current execution context.
29
+
30
+ Context-local credentials take precedence over module-level and environment configuration.
31
+ Nested contexts restore the previous credentials when they exit, and concurrent threads or
32
+ asynchronous tasks remain isolated from one another.
33
+
34
+ :param api_key: Rowan API key
35
+ :param project_uuid: active project UUID, if any
36
+ :yields: control while the credentials are active
37
+ :raises ValueError: API key is empty
38
+ """
39
+ if not api_key:
40
+ raise ValueError("API key cannot be empty.")
41
+
42
+ token = _api_context.set(_APIContext(api_key=api_key, project_uuid=project_uuid))
43
+ try:
44
+ yield
45
+ finally:
46
+ _api_context.reset(token)
47
+
48
+
13
49
  def get_api_key() -> str:
14
50
  """
15
51
  Get the API key from the environment variable ROWAN_API_KEY or the module-level attribute
@@ -19,6 +55,8 @@ def get_api_key() -> str:
19
55
 
20
56
  :returns: API key.
21
57
  """
58
+ if (context := _api_context.get()) is not None:
59
+ return context.api_key
22
60
  if hasattr(rowan, "api_key") and rowan.api_key:
23
61
  return rowan.api_key
24
62
  elif (api_key := os.environ.get("ROWAN_API_KEY")) is not None:
@@ -36,6 +74,8 @@ def get_project_uuid() -> str | None:
36
74
 
37
75
  :returns: Project UUID string, or None if not set.
38
76
  """
77
+ if (context := _api_context.get()) is not None:
78
+ return context.project_uuid
39
79
  if hasattr(rowan, "project_uuid") and rowan.project_uuid:
40
80
  return rowan.project_uuid
41
81
  return None
@@ -1,76 +1,22 @@
1
1
  ---
2
2
  name: computational-chemistry-and-biology
3
- description: Run computational chemistry and structural biology calculations on the Rowan platform via the `rowan` Python package. Use when the user wants to run Rowan workflows, or mentions Rowan, computational chemistry, structural biology, or molecular or protein simulation.
3
+ description: Run computational chemistry and structural biology calculations on the Rowan platform through Rowan MCP tools or the `rowan` Python package. Use when the user wants to run Rowan workflows, or mentions Rowan, computational chemistry, structural biology, or molecular or protein simulation.
4
4
  ---
5
5
 
6
6
  # Computational Chemistry and Biology with Rowan
7
7
 
8
- Run simulations on the [Rowan](https://rowansci.com) platform via the `rowan` Python package. Every workflow follows the same flow: build an input, submit a workflow, then retrieve the result.
8
+ Run simulations on the [Rowan](https://rowansci.com) platform through Rowan MCP tools or the `rowan` Python package. This skill provides shared scientific strategy and workflow guidance for both interfaces.
9
9
 
10
- **Package is for syntax, skill is for strategy.** For exact arguments, defaults, and valid values, introspect the installed package with `python3 -c "import rowan; help(rowan.submit_pka_workflow)"` (any name works). This skill tells you which workflow to use and recommends settings. If a value here is rejected, trust the package.
10
+ **Interfaces are for syntax; skill is for strategy.** Use this skill and its workflow references to choose scientifically appropriate methods and settings. Trust `discover_workflow` or the installed package when an exact parameter differs from a reference.
11
11
 
12
- ## Setup
12
+ ## Choose an interface
13
13
 
14
- Do this before calling the Rowan API. Use the resulting env's python for every later step.
14
+ Both interfaces are first-class. Use the shared scientific guidance and workflow references below with either one.
15
15
 
16
- **1. Install `rowan`** (PyPI: `rowan-python`). Skip if `python3 -c "import rowan"` already succeeds. Otherwise add it through the project's env manager so it survives syncs. A bare `pip install` into a managed env gets wiped:
16
+ - **MCP-connected chat:** when Rowan tools are available, read [MCP execution](reference/mcp_execution.md) before calling them. Do not install Python or request an API key; authentication belongs to the MCP connection. Use `discover_workflow` as the exact parameter contract.
17
+ - **Python code, scripts, or notebooks:** when the user requests Python or no Rowan MCP tools are available, read [Python SDK](reference/python_sdk.md) before writing or running code. Trust the installed package when its exact API differs from an example.
17
18
 
18
- - **uv** (`uv.lock`): `uv add rowan-python`, then run with `uv run python`
19
- - **pixi** (`pixi.toml`): `pixi add --pypi rowan-python`, then `pixi run python`
20
- - **poetry** (`poetry.lock`): `poetry add rowan-python`, then `poetry run python`
21
- - **plain venv or system**: `python3 -m pip install rowan-python`
22
-
23
- **2. Set the key and verify.** Put `ROWAN_API_KEY=your-key-here` in a project `.env` (gitignored, and create a key at https://labs.rowansci.com/account), then run the preflight. It finds the nearest `.env`, validates the key against the API, and prints remaining credits (workflows cost credits). Run it from your project root, where `.env` lives, and point it at this skill's base dir rather than `cd`-ing into the skill:
24
-
25
- `python3 "<skill_dir>/scripts/check_env.py"`
26
-
27
- It exits with actionable guidance on each failure: a **missing** key (add it via `echo 'ROWAN_API_KEY=...' >> .env`), a **rejected** key (a 401, meaning invalid or expired, so regenerate it and stop to tell the user), or an **unreachable** API. Since shell state doesn't persist between commands, load `.env` in the same command as every later call, like `[ -f .env ] && set -a && source .env && set +a; <python ...>`, or set `rowan.api_key = os.environ["ROWAN_API_KEY"]` in Python.
28
-
29
- ## Run & retrieve
30
-
31
- Every workflow is submitted and retrieved the same way, regardless of type. `submit_*_workflow(...)` returns a `Workflow` immediately, and results are fetched separately.
32
-
33
- ```python
34
- import rowan
35
-
36
- folder = rowan.get_folder("my-project") # path created if it doesn't exist
37
- wf = rowan.submit_<workflow>_workflow( # see its reference file (Workflows below) for scientific args
38
- ..., # workflow-specific arguments
39
- folder=folder,
40
- name="my run",
41
- )
42
- result = wf.result() # blocks until done, returns a typed result
43
- ```
44
-
45
- **Universal submit arguments.** On top of its scientific arguments, every `submit_*_workflow` accepts these, and they are not repeated in the per-workflow files:
46
-
47
- - `folder=` (or `folder_uuid=`) sets where the run lands. `rowan.get_folder("a/b/c")` returns the folder, creating the path if missing. For a specific project or benchmark, make a dedicated folder (e.g. `get_folder("project-name")`, with subpaths like `"project-name/docking"` for sub-experiments) and route all its runs there, so results stay grouped and easy to retrieve later. To browse or navigate an existing folder tree, or switch projects, see [reference/folders_and_projects.md](reference/folders_and_projects.md).
48
- - `name=` sets the label shown in the Rowan UI.
49
- - `max_credits=` caps the credits (≈ minutes of compute) a run may use — its runtime limit. Hitting it, or running out of credits, stops the run **permanently** (methods like DFT can't resume), so set it high enough to finish.
50
- - `webhook_url=` makes Rowan POST the result there on completion. See [reference/webhooks.md](reference/webhooks.md) if you're setting up webhooks.
51
- - `is_draft=True` stages the run without starting it, for estimation (below).
52
-
53
- **Three ways to retrieve results:**
54
-
55
- - **Block (default):** `result = wf.result()` waits (polling every 5 s) and returns a typed result. It raises `rowan.WorkflowError` if the run **failed** or was **stopped**, so catch it to report failures.
56
- - **Partial or progress:** `wf.result(wait=False)` returns whatever is ready now. `for r in wf.stream_result():` yields partial results each poll, then the final one.
57
- - **Fire-and-forget:** keep `wf.uuid`, let the session end, and reconnect later with `rowan.retrieve_workflow(uuid).result()`. `rowan.list_workflows()` lists recent runs. The UUID from `labs.rowansci.com/calculation/<uuid>` is a workflow UUID — use `retrieve_workflow`, not `retrieve_calculation`.
58
-
59
- **Inline calls vs. scripts.** Quick questions or retrieving a single result are fine inline with submit-and-wait (`.result()`). For long-running or multi-step work like experiments or benchmarks, put the calls in a script for reproducibility, and prefer a fire-and-forget run plus `retrieve_workflow(uuid)` later or a `webhook_url=` callback rather than blocking the session.
60
-
61
- **Estimate cost and runtime before committing.** Submit as a draft (nothing runs), inspect, then commit or discard:
62
-
63
- ```python
64
- draft = rowan.submit_<workflow>_workflow(..., folder=folder, is_draft=True)
65
- print(draft.dispatch_info()) # DispatchInfo(to_be_dispatched, compute_hardware, estimated_runtime_minutes)
66
- draft.submit_draft() # commit to running it (or draft.delete() to discard)
67
- ```
68
-
69
- **Status and control** (non-blocking): `wf.done()` and `wf.get_status()` check state without waiting, `wf.stop()` cancels a running workflow, and `wf.delete()` removes it and its data.
70
-
71
- **Resubmit and re-run.** Re-run from a settings dict with the generic `rowan.submit_workflow(workflow_type, workflow_data, initial_molecule=..., folder=folder)`. Pass a prior run's `result.data` unchanged for an identical re-run (insulated from later default or preset changes), edit the dict to change settings, or change `workflow_type` (with matching `workflow_data`) to submit as a different workflow.
72
-
73
- **Resubmit with a perturbed geometry.** `mol.perturb()` adds small Gaussian noise to break symmetry or escape a stuck optimization. `mol.displace_along_mode(mode, displacement)` shifts atoms along a vibrational normal mode — for a transition state, pick the imaginary mode (negative frequency) to slide toward reactant or product; requires `frequencies=True` in a prior calculation. See `examples/resubmit_with_perturbations.py`.
19
+ For project or folder management, also read [folders and projects](reference/folders_and_projects.md). For callbacks, read [webhooks](reference/webhooks.md).
74
20
 
75
21
  ## Molecule inputs
76
22
 
@@ -88,9 +34,9 @@ After loading a protein with `rowan.create_protein_from_pdb_id` or `rowan.upload
88
34
 
89
35
  ## Workflows
90
36
 
91
- Pick the workflow matching the task by reading the descriptions, then open its reference file (linked at the end of each entry) for recommended settings and an example. Universal submit arguments (`folder`, `name`, `max_credits`, and so on) live in **Run & retrieve** above and aren't repeated per workflow.
37
+ Pick the workflow matching the task by reading the descriptions, then open its reference file (linked at the end of each entry) for recommended settings and an example. Python's universal submit arguments live in [Python SDK](reference/python_sdk.md) and aren't repeated per workflow; MCP parameters come from `discover_workflow`.
92
38
 
93
- Not every key can run every workflow `rowan.whoami().enabled_workflows` lists the types yours can submit (a few, e.g. FEP, are gated by plan).
39
+ Not every account can run every workflow. MCP users must consult the `mcp_supported_workflows` field returned by `account_status`; Python users must consult `rowan.whoami().enabled_workflows` (a few workflows, such as FEP, are gated by plan).
94
40
 
95
41
  - **ADMET**: predict ADME-Tox properties (absorption, distribution, metabolism, excretion, toxicity) with an ML model, for fast early developability, PK, and tox triage. See [reference/admet.md](reference/admet.md).
96
42
  - **Analogue docking**: pose analogues of an already-bound reference ligand into consistent, analogous poses, to align and prepare a congeneric series, for example ahead of an RBFE screen. See [reference/analogue_docking.md](reference/analogue_docking.md).
@@ -0,0 +1,15 @@
1
+ # MCP execution
2
+
3
+ Use this path when Rowan MCP tools are available. Authentication is already attached to the MCP connection.
4
+
5
+ 1. Call `account_status` before reading workflow references. Use `mcp_supported_workflows` to limit selection and report available user and organization credits.
6
+ 2. Apply the scientific workflow guidance already selected by the entry skill. Retain its parameter rationale, interpretation guidance, caveats, and useful Python examples, but use `discover_workflow` for the exact MCP parameter contract.
7
+ 3. Call `discover_workflow` with the enabled workflow slug. Treat the returned parameter specification as authoritative; never guess an exact field name, type, default, or enum.
8
+ 4. Build a JSON `parameters` object from the user's inputs and the discovered specification. Ask only for scientifically meaningful missing values. For an attached PDB, SDF, MOL, MOL2, XYZ, EXTXYZ, or CIF file, call `import_structure` and use its `workflow_input` or returned molecule data in the discovered parameter. Inline import is for small text files; do not place a large file into model context.
9
+ 5. Call `create_workflow_draft`. This validates the inputs and creates a non-running draft. Inspect its `dispatch_estimate`, `max_credits`, and `available_credits`. If the user has not granted standing authorization that covers this workflow, its parameters, and its per-run and cumulative credit cost, review the draft with them and request approval.
10
+ 6. After specific draft approval, or when the draft remains within the user's standing authorization, call `submit_workflow_draft` with its `workflow_uuid`. Stop and request approval if its scope or cost exceeds that authorization. Preserve the UUID so the workflow can be recovered in another session.
11
+ 7. Call `workflow_status` without waiting, or set `wait_seconds` to at most 60 for bounded polling. Do not repeatedly occupy a turn waiting for a long workflow. Failed or stopped workflows include a bounded `log_tail`; report the actionable failure without dumping internal logs.
12
+ 8. Call `get_workflow_result` with no fields first. Inspect `available_fields` and `result_preview`, then request at most five desired fields per call. For nested arrays or objects, use `result_path`, `offset`, and `limit` rather than requesting the complete value.
13
+ 9. Use `get_structure_file` for PDB, XYZ, SDF, MOL, or MOL2 output from a protein or calculation reference. Use `get_workflow_file` for MSA and trajectory archives. These return deferred resources so file content is loaded only when the user or host needs it.
14
+
15
+ Pass JSON-native parameters through MCP and use `import_structure` for supported structure files. If discovery requires another Rowan object and does not describe a supported JSON representation or reference, explain that limitation rather than inventing an encoding. A workflow reference remains useful when its executable example is Python: translate its scientific choices through the discovered MCP contract.