pyrestoolbox 3.8.1__tar.gz → 3.8.3__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 (152) hide show
  1. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/workflows/tests.yml +26 -0
  2. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/Cargo.lock +1 -1
  3. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/Cargo.toml +1 -1
  4. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/PKG-INFO +2 -2
  5. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/README.rst +1 -1
  6. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/Dockerfile +1 -1
  7. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyproject.toml +2 -2
  8. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/server.py +24 -14
  9. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/tests/test_server.py +41 -10
  10. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyproject.toml +1 -1
  11. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_salting_library.py +1 -1
  12. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_vle_engine.py +206 -79
  13. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/brine.py +31 -10
  14. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/pr_vphi.py +10 -2
  15. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/vphi_route.py +2 -1
  16. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/constants.py +3 -2
  17. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/brine.rst +59 -13
  18. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/changelist.rst +14 -0
  19. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/gas.rst +110 -26
  20. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/matbal.rst +4 -1
  21. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal.rst +2 -2
  22. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/recommend.rst +10 -4
  23. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/_hydrate.py +7 -3
  24. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/gas.py +139 -122
  25. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/matbal.py +6 -3
  26. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/nodal.py +6 -7
  27. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/plyasunov_model.py +1 -0
  28. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/recommend.py +11 -6
  29. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/shared_fns.py +4 -12
  30. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/bessel.rs +5 -0
  31. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/critical_properties/mod.rs +8 -4
  32. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/gas_viscosity/mod.rs +29 -24
  33. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/pseudopressure.rs +14 -14
  34. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/bip.rs +23 -0
  35. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/components.rs +9 -4
  36. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/flash.rs +178 -9
  37. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/k_init.rs +13 -1
  38. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/zfactor/mod.rs +67 -53
  39. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/complexity-baseline.json +0 -0
  40. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/scripts/check_complexity.py +0 -0
  41. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/workflows/build-wheels.yml +0 -0
  42. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.gitignore +0 -0
  43. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/LICENSE +0 -0
  44. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/MANIFEST.in +0 -0
  45. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/ResToolbox/privacy_policy.md +0 -0
  46. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/build_pure_python.py +0 -0
  47. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/clippy.toml +0 -0
  48. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/README.md +0 -0
  49. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/__init__.py +0 -0
  50. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/serialize.py +0 -0
  51. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/__init__.py +0 -0
  52. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/_accelerator.py +0 -0
  53. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/__init__.py +0 -0
  54. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_dielectric.py +0 -0
  55. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_maoduan_viscosity.py +0 -0
  56. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_pitzer_params.py +0 -0
  57. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/appelo_volumes.py +0 -0
  58. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/iapws_viscosity.py +0 -0
  59. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/jones_dole_viscosity.py +0 -0
  60. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/kestin_nacl_viscosity.py +0 -0
  61. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/viscosity_route.py +0 -0
  62. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/__init__.py +0 -0
  63. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/classes.py +0 -0
  64. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/__init__.py +0 -0
  65. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/__init__.py +0 -0
  66. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/dca.py +0 -0
  67. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/dca.rst +0 -0
  68. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/examples.ipynb +0 -0
  69. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot.png +0 -0
  70. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_PVTO.png +0 -0
  71. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_img.png +0 -0
  72. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/dry_gas.png +0 -0
  73. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/grid_sat_df.png +0 -0
  74. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/influence.png +0 -0
  75. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/properties_df.png +0 -0
  76. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/sgof.png +0 -0
  77. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/swof.png +0 -0
  78. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/index.rst +0 -0
  79. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/layer.rst +0 -0
  80. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/library.rst +0 -0
  81. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_examples.ipynb +0 -0
  82. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_hydrate_demo.ipynb +0 -0
  83. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/oil.rst +0 -0
  84. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/plyasunov.rst +0 -0
  85. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/sensitivity.rst +0 -0
  86. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/simtools.rst +0 -0
  87. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/__init__.py +0 -0
  88. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/__init__.py +0 -0
  89. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/layer.py +0 -0
  90. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/__init__.py +0 -0
  91. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/component_library.xlsx +0 -0
  92. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/library.py +0 -0
  93. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/__init__.py +0 -0
  94. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/__init__.py +0 -0
  95. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/__init__.py +0 -0
  96. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_compressibility.py +0 -0
  97. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_constants.py +0 -0
  98. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_correlations.py +0 -0
  99. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_density.py +0 -0
  100. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_harmonize.py +0 -0
  101. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_pvt_class.py +0 -0
  102. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_rate.py +0 -0
  103. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_separator.py +0 -0
  104. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_tables.py +0 -0
  105. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_utils.py +0 -0
  106. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/__init__.py +0 -0
  107. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/iapws_if97.py +0 -0
  108. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/water_properties.py +0 -0
  109. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/__init__.py +0 -0
  110. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/__init__.py +0 -0
  111. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/sensitivity.py +0 -0
  112. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/__init__.py +0 -0
  113. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/__init__.py +0 -0
  114. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_aquifer.py +0 -0
  115. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_decks.py +0 -0
  116. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_pvt_tables.py +0 -0
  117. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_relperm.py +0 -0
  118. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_vfp.py +0 -0
  119. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/simtools.py +0 -0
  120. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/__init__.py +0 -0
  121. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/validate.py +0 -0
  122. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/setup.cfg +0 -0
  123. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/setup.py +0 -0
  124. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/mod.rs +0 -0
  125. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/salt.rs +0 -0
  126. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/water.rs +0 -0
  127. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/hyperbolic.rs +0 -0
  128. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/mod.rs +0 -0
  129. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/ransac.rs +0 -0
  130. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/gwr.rs +0 -0
  131. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/lib.rs +0 -0
  132. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/matbal/mod.rs +0 -0
  133. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/matbal/objective.rs +0 -0
  134. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/oil/density.rs +0 -0
  135. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/oil/mod.rs +0 -0
  136. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/spycher_pruess/mod.rs +0 -0
  137. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/spycher_pruess/solubility.rs +0 -0
  138. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/alpha.rs +0 -0
  139. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/eos.rs +0 -0
  140. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/fugacity.rs +0 -0
  141. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/mod.rs +0 -0
  142. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/rachford_rice.rs +0 -0
  143. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/constants.rs +0 -0
  144. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/friction.rs +0 -0
  145. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_bb.rs +0 -0
  146. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_gray.rs +0 -0
  147. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_wg.rs +0 -0
  148. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/ift.rs +0 -0
  149. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/march.rs +0 -0
  150. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/mod.rs +0 -0
  151. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/pvt_helpers.rs +0 -0
  152. {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/static_column.rs +0 -0
@@ -63,6 +63,32 @@ jobs:
63
63
  - name: Run full test suite (Rust + parity)
64
64
  run: python3 -m pytest pyrestoolbox/tests/ -q
65
65
 
66
+ # ── MCP server (separate distribution in mcp/) on both SDK majors ────
67
+ # The server picks FastMCP (1.x) or MCPServer (2.x) at import; test both so
68
+ # an SDK release that breaks either path fails here, not in a deployment.
69
+ test-mcp:
70
+ name: MCP server (${{ matrix.mcp }})
71
+ runs-on: ubuntu-latest
72
+ strategy:
73
+ fail-fast: false
74
+ matrix:
75
+ mcp: ["mcp>=1.2,<2", "mcp>=2,<3"]
76
+ steps:
77
+ - uses: actions/checkout@v5
78
+
79
+ - uses: actions/setup-python@v6
80
+ with:
81
+ python-version: "3.12"
82
+
83
+ - name: Install dependencies
84
+ run: pip install numpy scipy pandas tabulate openpyxl mpmath ilt-inversion pytest "${{ matrix.mcp }}"
85
+
86
+ # Library from the source tree (pure Python), server from mcp/.
87
+ - name: Run MCP tests
88
+ env:
89
+ PYRESTOOLBOX_NO_RUST: "1"
90
+ run: PYTHONPATH="$PWD:$PWD/mcp" python3 -m pytest mcp/tests/ -q
91
+
66
92
  # ── Complexity ratchet (new code only; existing offenders baselined) ─
67
93
  complexity:
68
94
  name: Complexity ratchet
@@ -152,7 +152,7 @@ dependencies = [
152
152
 
153
153
  [[package]]
154
154
  name = "pyrestoolbox-native"
155
- version = "3.8.1"
155
+ version = "3.8.3"
156
156
  dependencies = [
157
157
  "pyo3",
158
158
  "rug",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pyrestoolbox-native"
3
- version = "3.8.1"
3
+ version = "3.8.3"
4
4
  edition = "2021"
5
5
  license = "GPL-3.0-or-later"
6
6
  description = "Rust acceleration extensions for pyResToolbox"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrestoolbox
3
- Version: 3.8.1
3
+ Version: 3.8.3
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -45,7 +45,7 @@ Includes functions to perform calculations including;
45
45
  - Nodal analysis operating point determination
46
46
  - Eclipse VFP table generation (VFPPROD and VFPINJ keywords)
47
47
  - PVT Calculations for oil
48
- - PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2 and H2
48
+ - PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2, H2 and He
49
49
  - Gas caloric properties (enthalpy, Cp, Cv, Joule-Thomson coefficient) from the BNS tuned Peng Robinson EOS
50
50
  - Gas hydrate formation prediction with thermodynamic inhibitor calculations
51
51
  - Return critical parameters for typical components
@@ -20,7 +20,7 @@ Includes functions to perform calculations including;
20
20
  - Nodal analysis operating point determination
21
21
  - Eclipse VFP table generation (VFPPROD and VFPINJ keywords)
22
22
  - PVT Calculations for oil
23
- - PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2 and H2
23
+ - PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2, H2 and He
24
24
  - Gas caloric properties (enthalpy, Cp, Cv, Joule-Thomson coefficient) from the BNS tuned Peng Robinson EOS
25
25
  - Gas hydrate formation prediction with thermodynamic inhibitor calculations
26
26
  - Return critical parameters for typical components
@@ -7,7 +7,7 @@ FROM python:3.11-slim
7
7
 
8
8
  # Pin the library version for reproducible corporate deployments; bump
9
9
  # deliberately and rebuild.
10
- ARG PYRESTOOLBOX_VERSION=3.7.0
10
+ ARG PYRESTOOLBOX_VERSION=3.8.2
11
11
 
12
12
  WORKDIR /app
13
13
  COPY . /app/mcp
@@ -11,8 +11,8 @@ authors = [{name = "Mark W. Burgoyne", email = "mark.w.burgoyne@gmail.com"}]
11
11
  keywords = ["mcp", "petroleum", "reservoir", "pyrestoolbox"]
12
12
  requires-python = ">=3.10"
13
13
  dependencies = [
14
- "mcp>=1.2,<2",
15
- "pyrestoolbox>=3.7",
14
+ "mcp>=1.2,<3",
15
+ "pyrestoolbox>=3.8.2",
16
16
  ]
17
17
  readme = "README.md"
18
18
 
@@ -17,7 +17,12 @@ as MCP resources (docs://gas, docs://oil, ...).
17
17
  import importlib
18
18
  import inspect
19
19
 
20
- from mcp.server.fastmcp import FastMCP
20
+ try: # mcp >= 2 renamed FastMCP to MCPServer
21
+ from mcp.server.mcpserver import MCPServer as _MCPServer
22
+ _MCP_V2 = True
23
+ except ImportError: # mcp 1.x
24
+ from mcp.server.fastmcp import FastMCP as _MCPServer
25
+ _MCP_V2 = False
21
26
 
22
27
  from pyrestoolbox_mcp.serialize import to_jsonable
23
28
 
@@ -37,7 +42,7 @@ ALLOWED_MODULES = {
37
42
  "sensitivity": "Parameter sweeps and tornado analysis",
38
43
  }
39
44
 
40
- mcp = FastMCP(
45
+ mcp = _MCPServer(
41
46
  "pyrestoolbox",
42
47
  instructions=(
43
48
  "Petroleum/reservoir engineering calculations from the pyrestoolbox "
@@ -250,7 +255,7 @@ def _construct(dotted, key, spec):
250
255
  @mcp.tool()
251
256
  def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
252
257
  n2: float = 0, h2: float = 0, api: float | None = None,
253
- deviation: float = 0, well_type: str = "gas") -> dict:
258
+ deviation: float = 0, well_type: str = "gas", he: float = 0) -> dict:
254
259
  """Recommend correlation methods for a fluid/well, with rationale.
255
260
 
256
261
  Composition fractions are molar. api: stock tank oil gravity (include to
@@ -263,7 +268,7 @@ def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
263
268
  from pyrestoolbox import recommend
264
269
  recs = recommend.recommend_methods(sg=sg, co2=co2, h2s=h2s, n2=n2, h2=h2,
265
270
  api=api, deviation=deviation,
266
- well_type=well_type)
271
+ well_type=well_type, he=he)
267
272
  return to_jsonable(recs)
268
273
 
269
274
 
@@ -291,12 +296,12 @@ def co2_brine_props(pres: float, temp: float, ppm: float = 0,
291
296
  def sw_brine_props(pres: float, temp: float, ppm: float = 0,
292
297
  y_CO2: float = 0, y_H2S: float = 0, y_N2: float = 0,
293
298
  y_H2: float = 0, sg: float = 0.65, cw_sat: bool = False,
294
- metric: bool = False) -> dict:
299
+ metric: bool = False, y_He: float = 0) -> dict:
295
300
  """Multicomponent gas-saturated brine properties (Soreide-Whitson VLE).
296
301
 
297
302
  pres: pressure (psia, or barsa if metric=True). temp: temperature
298
303
  (deg F, or deg C if metric=True). ppm: NaCl-equivalent salinity.
299
- y_*: molar fractions of CO2/H2S/N2/H2 in the equilibrium gas; the
304
+ y_*: molar fractions of CO2/H2S/N2/H2/He in the equilibrium gas; the
300
305
  remainder is hydrocarbon gas of specific gravity sg. Returns aqueous
301
306
  composition, brine density/viscosity triplets, Rs, water content and
302
307
  compressibilities.
@@ -304,7 +309,7 @@ def sw_brine_props(pres: float, temp: float, ppm: float = 0,
304
309
  from pyrestoolbox import brine
305
310
  sw = brine.SoreideWhitson(pres=pres, temp=temp, ppm=ppm, y_CO2=y_CO2,
306
311
  y_H2S=y_H2S, y_N2=y_N2, y_H2=y_H2, sg=sg,
307
- cw_sat=cw_sat, metric=metric)
312
+ cw_sat=cw_sat, metric=metric, y_He=y_He)
308
313
  keys = ("x", "bDen", "bVis", "bw", "Rs", "Rs_total", "water_content",
309
314
  "Cf_usat", "Cf_sat")
310
315
  return {k: to_jsonable(getattr(sw, k, None)) for k in keys}
@@ -382,13 +387,18 @@ def build_parser():
382
387
 
383
388
  def main():
384
389
  args = build_parser().parse_args()
385
- if args.transport == "streamable-http":
386
- mcp.settings.host = args.host
387
- mcp.settings.port = args.port
388
- # Independent request handling; no server-side session affinity needed
389
- # behind a load balancer.
390
- mcp.settings.stateless_http = True
391
- mcp.run(transport=args.transport)
390
+ if args.transport != "streamable-http":
391
+ mcp.run(transport=args.transport)
392
+ return
393
+ # stateless_http: independent request handling; no server-side session
394
+ # affinity needed behind a load balancer.
395
+ http = {"host": args.host, "port": args.port, "stateless_http": True}
396
+ if _MCP_V2:
397
+ mcp.run(transport=args.transport, **http)
398
+ else: # 1.x reads these from settings, not run()
399
+ for key, value in http.items():
400
+ setattr(mcp.settings, key, value)
401
+ mcp.run(transport=args.transport)
392
402
 
393
403
 
394
404
  if __name__ == "__main__":
@@ -4,9 +4,9 @@ Run from the repo root:
4
4
  PYTHONPATH=/home/mark/projects/pyResToolbox:/home/mark/projects/pyResToolbox/mcp \
5
5
  python3 -m pytest mcp/tests/ -q
6
6
 
7
- Most tests exercise the tool functions directly (FastMCP's @tool decorator
7
+ Most tests exercise the tool functions directly (the SDK's @tool decorator
8
8
  returns the undecorated function). test_client_session_* run the full MCP
9
- protocol over an in-process transport.
9
+ protocol over an in-process transport. The suite runs on mcp 1.x and 2.x.
10
10
  """
11
11
 
12
12
  import os
@@ -186,15 +186,19 @@ def test_fit_and_forecast_exponential():
186
186
 
187
187
  # ------------------------------------------------- full MCP protocol session
188
188
 
189
+ def _in_memory_client():
190
+ """In-process client session: mcp 2.x Client takes the server directly;
191
+ 1.x needs the memory-stream helper and the low-level server."""
192
+ if srv._MCP_V2:
193
+ from mcp.client import Client
194
+ return Client(srv.mcp)
195
+ from mcp.shared.memory import create_connected_server_and_client_session
196
+ return create_connected_server_and_client_session(srv.mcp._mcp_server)
197
+
198
+
189
199
  @pytest.mark.anyio
190
200
  async def test_client_session_tools_and_resources():
191
- try:
192
- from mcp.shared.memory import create_connected_server_and_client_session
193
- except ImportError:
194
- pytest.skip('mcp.shared.memory helper not available in this SDK version')
195
-
196
- async with create_connected_server_and_client_session(
197
- srv.mcp._mcp_server) as client:
201
+ async with _in_memory_client() as client:
198
202
  tools = await client.list_tools()
199
203
  names = {t.name for t in tools.tools}
200
204
  assert {'list_functions', 'describe', 'call', 'recommend_methods',
@@ -204,7 +208,8 @@ async def test_client_session_tools_and_resources():
204
208
  result = await client.call_tool(
205
209
  'call', {'name': 'gas.gas_z',
206
210
  'arguments': {'p': 2000, 'sg': 0.75, 'degf': 200}})
207
- assert not result.isError
211
+ # 2.x result fields are snake_case
212
+ assert not (result.is_error if srv._MCP_V2 else result.isError)
208
213
  assert '0.868265' in result.content[0].text
209
214
 
210
215
  resources = await client.list_resources()
@@ -230,3 +235,29 @@ def test_cli_parser_defaults_and_http():
230
235
  '--host', '0.0.0.0', '--port', '9000'])
231
236
  assert (args.transport, args.host, args.port) == ('streamable-http',
232
237
  '0.0.0.0', 9000)
238
+
239
+
240
+ def test_main_passes_http_settings_to_the_sdk(monkeypatch):
241
+ """host, port and stateless_http reach the SDK: as run() keywords on
242
+ mcp 2.x, through mcp.settings on 1.x."""
243
+ calls = []
244
+ monkeypatch.setattr(srv.mcp, 'run', lambda **kw: calls.append(kw))
245
+ monkeypatch.setattr('sys.argv', ['pyrestoolbox-mcp', '--transport', 'streamable-http',
246
+ '--host', '0.0.0.0', '--port', '9000'])
247
+ srv.main()
248
+ want = {'host': '0.0.0.0', 'port': 9000, 'stateless_http': True}
249
+ if srv._MCP_V2:
250
+ assert calls == [dict(transport='streamable-http', **want)]
251
+ else:
252
+ assert calls == [{'transport': 'streamable-http'}]
253
+ assert {k: getattr(srv.mcp.settings, k) for k in want} == want
254
+ calls.clear()
255
+ monkeypatch.setattr('sys.argv', ['pyrestoolbox-mcp'])
256
+ srv.main()
257
+ assert calls == [{'transport': 'stdio'}]
258
+
259
+
260
+ def test_sw_brine_props_helium():
261
+ out = srv.sw_brine_props(pres=3000, temp=150, ppm=50000, y_He=1.0)
262
+ assert out['x']['He'] > 0
263
+ assert out['bDen'][0] < out['bDen'][1]
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pyrestoolbox"
7
- version = "3.8.1"
7
+ version = "3.8.3"
8
8
  description = "pyResToolbox - A collection of Reservoir Engineering Utilities"
9
9
  license = {text = "GPL-3.0-or-later"}
10
10
  authors = [{name = "Mark W. Burgoyne", email = "mark.w.burgoyne@gmail.com"}]
@@ -26,7 +26,7 @@ LN10 = np.log(10.0) # 2.302585...
26
26
  # ====================================================================
27
27
  # Boiling points (K) for S&W gases
28
28
  TB_K = {
29
- 'H2': 20.3, 'N2': 77.4, 'CO2': 194.7, 'H2S': 212.8, # H2S NBP 212.87 K (NIST)
29
+ 'H2': 20.3, 'He': 4.2238, 'N2': 77.4, 'CO2': 194.7, 'H2S': 212.8, # H2S NBP 212.87 K (NIST)
30
30
  'CH4': 111.6, 'C2H6': 184.6, 'C3H8': 231.1,
31
31
  'iC4H10': 261.4, 'nC4H10': 272.7, 'iC5H12': 301.0,
32
32
  'nC5H12': 309.2, 'nC6H14': 341.9, 'nC7H16': 371.6,