agentic-mcp-solver 4.2.0__tar.gz → 4.3.0__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 (148) hide show
  1. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/CHANGELOG.md +57 -0
  2. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/INSTALL.md +3 -4
  3. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/PKG-INFO +7 -7
  4. agentic_mcp_solver-4.3.0/minion/CHANGELOG.md +109 -0
  5. agentic_mcp_solver-4.3.0/minion/README.md +136 -0
  6. agentic_mcp_solver-4.3.0/minion/e2e_tests/runs/multi_step/config.json +10 -0
  7. agentic_mcp_solver-4.3.0/minion/e2e_tests/runs/no_tools/config.json +10 -0
  8. agentic_mcp_solver-4.3.0/minion/e2e_tests/runs/simple_add/config.json +10 -0
  9. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/test_e2e.py +1 -1
  10. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/pyproject.toml +2 -2
  11. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/__init__.py +7 -3
  12. agentic_mcp_solver-4.3.0/minion/src/mcp_minion/agent.py +948 -0
  13. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/artifacts.py +44 -17
  14. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/cli.py +118 -67
  15. agentic_mcp_solver-4.3.0/minion/src/mcp_minion/env.py +37 -0
  16. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/logging.py +31 -1
  17. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/mcp_client.py +133 -61
  18. agentic_mcp_solver-4.3.0/minion/src/mcp_minion/test_mcp_server.py +148 -0
  19. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/src/mcp_minion/tools.py +15 -4
  20. agentic_mcp_solver-4.3.0/minion/tests/test_agent.py +1060 -0
  21. agentic_mcp_solver-4.3.0/minion/tests/test_artifacts.py +242 -0
  22. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/tests/test_cli.py +358 -62
  23. agentic_mcp_solver-4.3.0/minion/tests/test_kernel.py +320 -0
  24. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/tests/test_logging.py +9 -0
  25. agentic_mcp_solver-4.3.0/minion/tests/test_mcp_client.py +321 -0
  26. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/tests/test_tools.py +16 -17
  27. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/pyproject.toml +32 -4
  28. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/agent/cli.py +241 -152
  29. agentic_mcp_solver-4.3.0/src/mcp_solver/agent/engine.py +263 -0
  30. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/agent/harness.py +99 -23
  31. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/agent/mcp_server.py +45 -67
  32. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/agent/runfolder.py +67 -16
  33. agentic_mcp_solver-4.3.0/tests/unit/test_cli.py +840 -0
  34. agentic_mcp_solver-4.3.0/tests/unit/test_engine.py +187 -0
  35. agentic_mcp_solver-4.3.0/tests/unit/test_engine_contract.py +175 -0
  36. agentic_mcp_solver-4.3.0/tests/unit/test_harness.py +176 -0
  37. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/unit/test_mcp_server.py +78 -41
  38. agentic_mcp_solver-4.3.0/tests/unit/test_runfolder.py +153 -0
  39. agentic_mcp_solver-4.2.0/minion/CHANGELOG.md +0 -34
  40. agentic_mcp_solver-4.2.0/minion/README.md +0 -143
  41. agentic_mcp_solver-4.2.0/minion/e2e_tests/runs/multi_step/config.json +0 -6
  42. agentic_mcp_solver-4.2.0/minion/e2e_tests/runs/no_tools/config.json +0 -6
  43. agentic_mcp_solver-4.2.0/minion/e2e_tests/runs/simple_add/config.json +0 -6
  44. agentic_mcp_solver-4.2.0/minion/src/mcp_minion/agent.py +0 -593
  45. agentic_mcp_solver-4.2.0/minion/src/mcp_minion/test_mcp_server.py +0 -133
  46. agentic_mcp_solver-4.2.0/minion/tests/test_agent.py +0 -312
  47. agentic_mcp_solver-4.2.0/minion/tests/test_artifacts.py +0 -81
  48. agentic_mcp_solver-4.2.0/minion/tests/test_kernel.py +0 -124
  49. agentic_mcp_solver-4.2.0/minion/tests/test_mcp_client.py +0 -170
  50. agentic_mcp_solver-4.2.0/tests/unit/test_cli.py +0 -411
  51. agentic_mcp_solver-4.2.0/tests/unit/test_runfolder.py +0 -57
  52. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/.gitignore +0 -0
  53. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/LICENSE +0 -0
  54. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/README.md +0 -0
  55. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/.gitignore +0 -0
  56. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/LICENSE +0 -0
  57. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/__init__.py +0 -0
  58. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/runs/mcp_ipython/config.json +0 -0
  59. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/runs/mcp_ipython/task.md +0 -0
  60. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/runs/multi_step/task.md +0 -0
  61. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/runs/no_tools/task.md +0 -0
  62. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/runs/simple_add/task.md +0 -0
  63. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/e2e_tests/test_problems_e2e.py +0 -0
  64. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/tests/__init__.py +0 -0
  65. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/minion/tests/test_system_prompt.py +0 -0
  66. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/__init__.py +0 -0
  67. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/agent/__init__.py +0 -0
  68. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/helpers/__init__.py +0 -0
  69. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/helpers/maxsat.py +0 -0
  70. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/helpers/pysat.py +0 -0
  71. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/helpers/z3.py +0 -0
  72. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/__init__.py +0 -0
  73. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/clingo.md +0 -0
  74. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/cpmpy.md +0 -0
  75. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/didp.md +0 -0
  76. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/maxsat.md +0 -0
  77. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/pysat.md +0 -0
  78. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/src/mcp_solver/templates/z3.md +0 -0
  79. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/README.md +0 -0
  80. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/__init__.py +0 -0
  81. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/birds_fly.md +0 -0
  82. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/birds_fly_ground_truth.py +0 -0
  83. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/company_controls.md +0 -0
  84. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/company_controls_ground_truth.py +0 -0
  85. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/package_status_unsat.md +0 -0
  86. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/package_status_unsat_ground_truth.py +0 -0
  87. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/party_invitation.md +0 -0
  88. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/party_invitation_ground_truth.py +0 -0
  89. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/shift_assignment.md +0 -0
  90. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/shift_assignment_ground_truth.py +0 -0
  91. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/clingo/test.md +0 -0
  92. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/carpet_cutting.md +0 -0
  93. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/carpet_cutting_ground_truth.py +0 -0
  94. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/tsp.md +0 -0
  95. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/tsp_ground_truth.py +0 -0
  96. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/university_scheduling.md +0 -0
  97. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/university_scheduling_ground_truth.py +0 -0
  98. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/university_scheduling_unsat.md +0 -0
  99. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/university_scheduling_unsat_ground_truth.py +0 -0
  100. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/zebra.md +0 -0
  101. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/cpmpy/zebra_ground_truth.py +0 -0
  102. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/knapsack.md +0 -0
  103. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/knapsack_ground_truth.py +0 -0
  104. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/talent_scheduling.md +0 -0
  105. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/talent_scheduling_ground_truth.py +0 -0
  106. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/tardiness.md +0 -0
  107. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/tardiness_ground_truth.py +0 -0
  108. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/tsptw.md +0 -0
  109. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/didp/tsptw_ground_truth.py +0 -0
  110. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/equipment_purchase.md +0 -0
  111. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/equipment_purchase_ground_truth.py +0 -0
  112. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/network_monitoring.md +0 -0
  113. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/network_monitoring_ground_truth.py +0 -0
  114. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/package_selection.md +0 -0
  115. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/package_selection_ground_truth.py +0 -0
  116. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/task_assignment.md +0 -0
  117. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/task_assignment_ground_truth.py +0 -0
  118. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/test.md +0 -0
  119. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/workshop_scheduling_unsat.md +0 -0
  120. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/maxsat/workshop_scheduling_unsat_ground_truth.py +0 -0
  121. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/equitable_coloring_hajos.md +0 -0
  122. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/equitable_coloring_hajos_ground_truth.py +0 -0
  123. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/furniture_arrangement.md +0 -0
  124. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/furniture_arrangement_ground_truth.py +0 -0
  125. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/n_queens.md +0 -0
  126. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/n_queens_ground_truth.py +0 -0
  127. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/no_three_in_line_5x5.md +0 -0
  128. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/no_three_in_line_5x5_ground_truth.py +0 -0
  129. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/petersen_12_coloring_unsat.md +0 -0
  130. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/petersen_12_coloring_unsat_ground_truth.py +0 -0
  131. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/sudoku_16x16.md +0 -0
  132. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/sudoku_16x16_ground_truth.py +0 -0
  133. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/pysat/test.md +0 -0
  134. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/array_property_verifier.md +0 -0
  135. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/array_property_verifier_ground_truth.py +0 -0
  136. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/bounded_sum_unsat.md +0 -0
  137. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/bounded_sum_unsat_ground_truth.py +0 -0
  138. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/cryptarithmetic.md +0 -0
  139. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/cryptarithmetic_ground_truth.py +0 -0
  140. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/processor_verification.md +0 -0
  141. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/processor_verification_ground_truth.py +0 -0
  142. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/sos_induction.md +0 -0
  143. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/sos_induction_ground_truth.py +0 -0
  144. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/problems/z3/test.md +0 -0
  145. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/unit/test_didp_backend.py +0 -0
  146. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/unit/test_helpers_maxsat.py +0 -0
  147. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/unit/test_helpers_pysat.py +0 -0
  148. {agentic_mcp_solver-4.2.0 → agentic_mcp_solver-4.3.0}/tests/unit/test_helpers_z3.py +0 -0
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ### [4.3.0] - 2026-11-14
4
+
5
+ - **Behavior Change:** Requires the MCP Python SDK 2.x (`mcp>=2,<3`; 1.x is no
6
+ longer supported), agentic-python-coder 3.5.0 and mcp-minion 0.3.0.
7
+ - **Behavior Change:** `mcp-solver` caps a run at 2,000,000 total (input +
8
+ output) tokens by default, checked after each step; `--token-limit N`
9
+ changes the cap (`0` = no limit). A run stopped by the cap without an
10
+ accepted submission exits with code 3; the stats JSON reports
11
+ `token_limit_reached` and `token_limit`. `mcp-solver-bench --token-limit`
12
+ passes the value to each solve.
13
+ - **Behavior Change:** New exit code 4: the agent stopped early with an error
14
+ (for example an LLM API failure) after an accepted submission. That
15
+ submission is saved and re-executed, and exit 4 replaces 0 when it runs
16
+ cleanly, since it may not be the agent's final, verified program. Such an
17
+ error before any accepted submission, a failed kernel setup, or an
18
+ exception during the solve exits with 1 and a one-line message instead of
19
+ a traceback.
20
+ - **Behavior Change:** The engine, its kernels and the CLI's re-execution of
21
+ the submitted program (in `mcp-solver` and `mcp-solver-serve`) get a
22
+ filtered environment: the mcp library's default whitelist (`PATH`, `HOME`,
23
+ ...), locale, temp-dir, proxy, CA-bundle and native-build variables, and
24
+ variables starting with `UV_`, `CODER_`, `MCP_SOLVER_`, `XDG_` or `LC_`
25
+ unless the name contains `KEY`, `TOKEN`, `SECRET`, `PASSWORD` or
26
+ `CREDENTIAL` (`UV_ENV_FILE` is dropped too). Other variables no longer
27
+ reach the kernel. This keeps API keys out of model-written code; it is
28
+ hygiene, not a sandbox.
29
+ - **Behavior Change:** `submit_code` on the toolkit server returns an MCP
30
+ error result (`isError`) carrying the engine's reason for a rejected
31
+ program, instead of a normal result with `{"ok": false, ...}`.
32
+ - **New Feature:** `--model` accepts a model config file
33
+ (`--model my_model.json`) in the engine's format, and aliases resolve
34
+ through the engine's `load_model_config`, so a local `<alias>.json`
35
+ overrides a bundled one. A model config may set `base_url` and
36
+ `api_key_env` (another OpenAI-compatible endpoint and the variable that
37
+ holds its key). Its `reasoning`, `provider`, `top_k` and `request_timeout`
38
+ settings are now sent; before they were dropped.
39
+ - **Behavior Change:** `mcp-solver-runfolder --model` resolves aliases and
40
+ model files like the CLI. A full OpenRouter ID gets no sampling settings
41
+ (it used to get `temperature 0` and `max_tokens 8192`), a model with
42
+ `base_url` or `api_key_env` is rejected, and the generated config sets
43
+ `agent.max_tool_result_chars` to at least twice the backend template's
44
+ length (minimum 64,000).
45
+ - **Improvement:** `mcp-solver-bench` runs each solve with its own run
46
+ directory as working directory (path arguments made absolute), saves the
47
+ solve's stderr to `cli_stderr.txt` there, and copies its last 20 lines
48
+ into the result row (`stderr_tail`) of a failed or invalid run.
49
+ - **Improvement:** The CLI and the toolkit server check that the engine
50
+ offers all five tools they use (`python_exec`, `python_reset`,
51
+ `python_status`, `python_interrupt`, `submit_code`) and name the missing
52
+ ones together with the required engine version.
53
+ - **Fix:** The pysat and maxsat kernels install `python-sat[pb]` instead of
54
+ `python-sat` and `pypblib`. The `[pb]` extra installs pindakaas, without
55
+ which every `pysat.pb.PBEnc` encoding call raises.
56
+ - **Fix:** In dev mode, newly started kernels pick up edits to the helper
57
+ sources (the uv build cache is keyed on `src/**/*.py`, not only on
58
+ `pyproject.toml`).
59
+
3
60
  ### [4.2.0] - 2026-11-13
4
61
 
5
62
  - **Major Change:** Published on PyPI as `agentic-mcp-solver`, since the name
@@ -186,11 +186,10 @@ You installed the bare package without the product layer. Install the `[agent]`
186
186
  extra: `uv pip install "agentic-mcp-solver[agent]"`, or
187
187
  `uv pip install -e ".[agent]"` from a checkout (see [Install](#install)).
188
188
 
189
- **`the ipython_mcp server does not provide submit_code`** (CLI) or
190
- **`the ipython_mcp engine is unavailable or lacks submit_code`** (server)
191
- Your installed `agentic-python-coder` is older than 3.4.3, or missing from
189
+ **`the ipython_mcp engine lacks the tools ...`** (CLI and server)
190
+ Your installed `agentic-python-coder` is older than 3.5.0, or missing from
192
191
  the environment the server runs in. Upgrade it:
193
- `uv pip install "agentic-python-coder>=3.4.3"` (or `-e` from a checkout).
192
+ `uv pip install "agentic-python-coder>=3.5.0"` (or `-e` from a checkout).
194
193
 
195
194
  **`uv: command not found` (or the solve fails to start a kernel).**
196
195
  uv is missing from your PATH. Install it (see Prerequisites) and make sure its
@@ -1,23 +1,23 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentic-mcp-solver
3
- Version: 4.2.0
3
+ Version: 4.3.0
4
4
  Summary: LLM-driven constraint solving (SAT, MaxSAT, SMT, CP, ASP) on top of agentic-python-coder
5
5
  Author-email: Stefan Szeider <stefan@szeider.net>
6
6
  License: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: <3.15,>=3.13
9
9
  Provides-Extra: agent
10
- Requires-Dist: agentic-python-coder>=3.4.4; extra == 'agent'
11
- Requires-Dist: mcp-minion>=0.2.2; extra == 'agent'
12
- Requires-Dist: mcp<3,>=1.25; extra == 'agent'
10
+ Requires-Dist: agentic-python-coder>=3.5.0; extra == 'agent'
11
+ Requires-Dist: mcp-minion>=0.3.0; extra == 'agent'
12
+ Requires-Dist: mcp<3,>=2; extra == 'agent'
13
13
  Requires-Dist: python-dotenv>=1.0.0; extra == 'agent'
14
14
  Provides-Extra: all
15
- Requires-Dist: agentic-python-coder>=3.4.4; extra == 'all'
15
+ Requires-Dist: agentic-python-coder>=3.5.0; extra == 'all'
16
16
  Requires-Dist: clingo>=5.8.0; extra == 'all'
17
17
  Requires-Dist: cpmpy>=0.9.24; extra == 'all'
18
18
  Requires-Dist: didppy<0.12,>=0.11.1; extra == 'all'
19
- Requires-Dist: mcp-minion>=0.2.2; extra == 'all'
20
- Requires-Dist: mcp<3,>=1.25; extra == 'all'
19
+ Requires-Dist: mcp-minion>=0.3.0; extra == 'all'
20
+ Requires-Dist: mcp<3,>=2; extra == 'all'
21
21
  Requires-Dist: pytest-asyncio>=0.26; extra == 'all'
22
22
  Requires-Dist: pytest>=8.3.5; extra == 'all'
23
23
  Requires-Dist: python-dotenv>=1.0.0; extra == 'all'
@@ -0,0 +1,109 @@
1
+ # Changelog
2
+
3
+ Changes to the `mcp-minion` package. The monorepo's root `CHANGELOG.md`
4
+ tracks `mcp-solver` releases, which version independently of this package.
5
+
6
+ ### [0.3.0] - 2026-11-14
7
+
8
+ - **Behavior Change:** `MCPManager.call_tool` returns a `ToolOutcome`
9
+ (`text`, `is_error`, `links`) instead of a JSON string `{"result": ...}` or
10
+ `{"error": ...}`. An MCP `isError` result and client-side failures (unknown
11
+ tool, non-object arguments, server not connected, timeout, transport
12
+ error) come back with `is_error` set; nothing is raised for them.
13
+ `Tool.execute` returns a `ToolOutcome` too (a string return value is the
14
+ text, other values are JSON-encoded). The model sees the text, prefixed
15
+ with `ERROR: ` for an error outcome.
16
+ - **Behavior Change:** Step records (`AgentResult.steps` and the run log)
17
+ hold each tool call as `{"name", "arguments", "result", "is_error"}`, where
18
+ `result` is the plain tool text, no longer a JSON envelope. Steps carry
19
+ `reasoning_details` or `reasoning` when the model returns them, and a step
20
+ cut off at `max_tokens` carries `truncated: true`. The run log also
21
+ records `system_prompt` and `kernel_setup`. `extract_last_submission`
22
+ reads the new records and run logs of 0.2.x.
23
+ - **Behavior Change:** An LLM API failure no longer raises out of
24
+ `run_async`. The run ends with `AgentResult.error` set (one line with the
25
+ exception type), the steps and token totals so far, and the answer
26
+ `[Agent stopped: LLM call failed: ...]`; the CLI then exits with 1. Error
27
+ responses the SDK parses without raising (HTTP 200 with an error body,
28
+ `finish_reason: "error"`, malformed or non-JSON bodies) are retried 3
29
+ times, after 5, 10 and 15 seconds, before the run ends this way.
30
+ - **Behavior Change:** The flat `config.json` format (`modelstring`,
31
+ top-level `max_steps`, `temperature`, ...) is no longer read; a flat
32
+ config or any unknown top-level key is an error. New keys in the nested
33
+ format: `model.reasoning`, `model.provider`, `model.top_k` and
34
+ `model.extra_body` (sent in the request body), `model.request_timeout`,
35
+ `agent.max_tool_result_chars`, and `cwd` for an MCP server.
36
+ - **Behavior Change:** Requires the MCP Python SDK 2.x (`mcp>=2,<3`); 1.x
37
+ is no longer supported.
38
+ - **Behavior Change:** A server's `env` in `mcpServers` is merged over the
39
+ mcp library's default environment whitelist (`PATH`, `HOME`, ...) instead
40
+ of over the full parent environment, so other variables (API keys, for
41
+ instance) reach the server only when listed. A server without `env` gets
42
+ the whitelist, as before.
43
+ - **Behavior Change:** Tool results longer than
44
+ `agent.max_tool_result_chars` (default 64,000; `0` disables the cut) reach
45
+ the model as head and tail around a marker line; step records and the run
46
+ log keep the full text.
47
+ - **Behavior Change:** With `packages` configured and a server offering
48
+ `python_reset`, the kernel is set up with those packages at the start of
49
+ the run, before the first LLM call (previously before the first
50
+ `python_exec`), and a failed setup ends the run with `AgentResult.error`.
51
+ The tracked `kernel_id` is added to every kernel tool call that lacks one
52
+ (`python_exec`, `python_reset`, `python_status`, `python_interrupt`), so a
53
+ `python_reset` from the model restarts the same kernel; a model reset
54
+ with its own `packages` list keeps the configured packages.
55
+ - **Behavior Change:** The `reasoning_details` (or `reasoning`) of each
56
+ assistant message are replayed unmodified in the conversation history, as
57
+ OpenRouter requires for reasoning models.
58
+ - **Behavior Change:** The agent calls the API through `AsyncOpenAI`, with
59
+ one client created per run and closed when the run ends, so one `Agent`
60
+ can run several times and LLM calls no longer block the event loop. A
61
+ client set on `agent.client` is used for every run and not closed; it
62
+ must provide an async `chat.completions.create`. The
63
+ `Agent.SYSTEM_PROMPT_BASE` class attribute is gone; use the module-level
64
+ `SYSTEM_PROMPT_BASE`.
65
+ - **Behavior Change:** The CLI offers its arithmetic demo tools only when
66
+ no MCP server is configured.
67
+ - **New Feature:** Server instructions from the MCP `initialize` result
68
+ appear in the system prompt. Image, audio and blob content renders as a
69
+ one-line note (type, MIME type, size) instead of base64 or an object repr.
70
+ - **New Feature:** `mcp_minion.find_api_key()` looks the key up in the
71
+ environment, a run folder's `.env`, extra dotenv files and
72
+ `~/.mcp-minion`, without loading the files into `os.environ`; the CLI uses
73
+ it.
74
+ - **Fix:** A rejected `submit_code` call (`{"ok": false, ...}`) is no longer
75
+ taken as the last submission. A reply cut off at `max_tokens` without
76
+ tool calls is no longer accepted as the final answer; the model is asked
77
+ to continue. Missing or empty tool arguments count as `{}`, arguments
78
+ that are not a JSON object give an error result, and the history echoes
79
+ valid JSON arguments back to the API.
80
+
81
+ ### [0.2.2] - 2026-11-13
82
+
83
+ - **New Feature:** Supports the MCP Python SDK 2.x alongside 1.x
84
+ (`mcp>=1.25.0,<3`): paginated listing through `PaginatedRequestParams`,
85
+ protocol fields read under both the 2.x snake_case and the 1.x camelCase
86
+ names, and `read_resource` called with a plain string URI.
87
+ - **Behavior Change:** Requires Python 3.13 or 3.14 (`>=3.13,<3.15`).
88
+
89
+ ### [0.2.1] - 2026-08-04
90
+
91
+ - **Fix:** Pin `mcp>=1.25.0,<2`. The `mcp` 2.0.0 SDK changed the client API
92
+ (`ClientSession.list_tools` no longer takes `cursor`), so fresh installs of
93
+ 0.1.0 and 0.2.0 failed to connect to any MCP server. The workspace lockfile
94
+ masked this by resolving `mcp` 1.28.1.
95
+
96
+ ### [0.2.0] - 2026-08-04
97
+
98
+ - **New Feature:** Per-run token cap, `agent.max_total_tokens` in
99
+ `config.json` (absent or `0` = unlimited). The cumulative input+output
100
+ tokens are checked after each completed step; once they exceed the cap the
101
+ loop stops, the answer becomes `[Agent stopped: per-run token cap of N
102
+ exceeded (cumulative M)]`, and the run log records `token_cap_reached`
103
+ (on the last step and in the result). `max_steps` alone does not bound
104
+ spending, since one step can be arbitrarily expensive.
105
+ - **Behavior Change:** A configured MCP server that fails to start now aborts
106
+ the run with a `RuntimeError` naming the server and the underlying error,
107
+ after closing any servers already started. Previously the failure was a
108
+ warning on stderr and the agent continued with a reduced tool set, which
109
+ produced plausible-looking but unusable runs.
@@ -0,0 +1,136 @@
1
+ # mcp-minion
2
+
3
+ A minimal ReAct agent that drives one or more [MCP](https://modelcontextprotocol.io)
4
+ servers through an OpenAI-compatible API (OpenRouter by default). It reads a
5
+ task from a *run folder*, loops "think → call tool → observe" until the model
6
+ produces a final answer, and writes a complete JSON log of the run.
7
+
8
+ `mcp-minion` is developed in the [mcp-solver](https://github.com/szeider/mcp-solver)
9
+ monorepo, where it runs solver templates over code-execution MCP servers, but
10
+ it has no dependency on the solver and works with any MCP server. It requires
11
+ Python 3.13 or 3.14 and the MCP Python SDK 2.x.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ uv tool install mcp-minion # the mcp-minion command
17
+ uv add mcp-minion # as a library in a uv project
18
+ uv sync --package mcp-minion # inside the monorepo (workspace member)
19
+ ```
20
+
21
+ The OpenRouter API key is looked up in this order: the `OPENROUTER_API_KEY`
22
+ environment variable, the run folder's `.env`, then `~/.mcp-minion`
23
+ (`OPENROUTER_API_KEY=sk-...`). The files are read, not loaded into the process
24
+ environment; `mcp_minion.find_api_key()` does the same lookup for library users.
25
+
26
+ ## Run folder
27
+
28
+ | File | Purpose |
29
+ | --- | --- |
30
+ | `config.json` | Model, agent, MCP server and kernel settings (required) |
31
+ | `task.md` | The task for this run (required) |
32
+ | `project.md` | Shared instructions prepended to the task (optional) |
33
+ | `files.system` target | System-prompt body (optional, see below) |
34
+ | `run_*.json` | Per-run JSON log, including the system prompt sent (written automatically) |
35
+ | `submission.py` | Code of the last accepted `submit_code` call, if any |
36
+ | `server.log` | stderr of the MCP servers and their children |
37
+
38
+ `config.json` uses the nested format; the pre-0.3 flat format
39
+ (`modelstring`, top-level `max_steps`, ...) is rejected with an error:
40
+
41
+ ```json
42
+ {
43
+ "model": {
44
+ "name": "google/gemini-3.1-flash-lite-preview",
45
+ "temperature": 0,
46
+ "max_tokens": 2048,
47
+ "reasoning": { "effort": "low" },
48
+ "request_timeout": 120
49
+ },
50
+ "agent": { "max_steps": 10, "max_total_tokens": 500000 },
51
+ "files": { "system": "system.md" },
52
+ "packages": ["z3-solver"],
53
+ "mcpServers": {
54
+ "ipython": { "command": "ipython_mcp", "args": [], "env": {}, "cwd": "." }
55
+ }
56
+ }
57
+ ```
58
+
59
+ - **`model.*`** — `name` is the OpenRouter model id. `reasoning`, `provider`,
60
+ `top_k` and the entries of an optional `extra_body` object go into the
61
+ request body (`AgentConfig.extra_body`; OpenRouter usage accounting stays
62
+ on). `request_timeout` is the per-request timeout in seconds. Every other
63
+ key (`temperature`, `max_tokens`, ...) is passed to the API call as is.
64
+ - **`agent.max_total_tokens`** — cap on the cumulative input+output tokens of
65
+ a run, checked after each step; the run then stops with
66
+ `[Agent stopped: per-run token cap of N exceeded (cumulative M)]` and the
67
+ log records `token_cap_reached`. Absent or `0` means no cap.
68
+ - **`agent.max_tool_result_chars`** — tool results longer than this are cut
69
+ for the model (see Tool results); default 64000, `0` disables.
70
+ - **`files.system`** — markdown file (relative to the run folder) used as the
71
+ system prompt. A literal `{tool_sections}` placeholder is replaced by the
72
+ generated tool list (other braces are left alone); without it the list is
73
+ appended. Absent: a built-in default prompt.
74
+ - **`mcpServers`** — servers to start, each with `command` and optional
75
+ `args`, `env` (merged by the mcp library over its default environment
76
+ whitelist) and `cwd`. A server that fails to start aborts the run. Each
77
+ server's `instructions` from its initialize result appear in the system
78
+ prompt under that server's heading. Without any server, the CLI offers four
79
+ arithmetic demo tools (`add`, `subtract`, `multiply`, `divide`).
80
+ - **`packages`** — for the kernel server
81
+ [`ipython_mcp`](https://pypi.org/project/agentic-python-coder/) (PyPI
82
+ package `agentic-python-coder`): before the first LLM call, `mcp-minion`
83
+ calls `python_reset` with these packages; if that fails the run ends with an
84
+ error. The returned `kernel_id` is added to every `python_exec`,
85
+ `python_reset`, `python_status` and `python_interrupt` call that lacks one,
86
+ so a `python_reset` by the model restarts the same kernel with its packages.
87
+ If the model's `python_reset` passes its own `packages` list, the configured
88
+ packages are sent first, followed by the model's entries they do not already
89
+ cover (same distribution name, ignoring extras, versions and case).
90
+
91
+ ## Tool results
92
+
93
+ `MCPManager.call_tool` returns a `ToolOutcome(text, is_error, links)`. The
94
+ model sees `text` unchanged (prefixed with `ERROR: ` for errors), cut to
95
+ `agent.max_tool_result_chars` in config.json (`AgentConfig.max_tool_result_chars`,
96
+ default 64000; head and tail kept, `0` disables); the step records and the run log keep the full text as
97
+ `"result"` plus `"is_error"`. Images, audio and blobs appear as one line such
98
+ as `[image mime=image/png bytes=1234]`. A `resource_link` appears as a
99
+ `[resource_link] URI (name)` line; the built-in `read_resource` tool fetches
100
+ it, or any resource a server announced, from its origin server only.
101
+ Reasoning that the model returns (`reasoning_details`, or a plain
102
+ `reasoning` string) is passed back unmodified on the next request and kept in
103
+ the step records and log.
104
+
105
+ `mcp_minion.extract_last_submission(log_or_steps, tool_name="submit_code")`
106
+ returns the `code` argument of the last accepted submission: one without
107
+ `is_error` whose text is not a JSON object with `"ok": false`. Run logs of
108
+ mcp-minion 0.2 and earlier are read too.
109
+
110
+ ## Example
111
+
112
+ The package ships a small MCP test server (`echo`, `add`, a resource and
113
+ instructions):
114
+
115
+ ```json
116
+ {
117
+ "model": { "name": "google/gemini-3.1-flash-lite-preview", "temperature": 0 },
118
+ "agent": { "max_steps": 5 },
119
+ "mcpServers": {
120
+ "test": { "command": "python", "args": ["-m", "mcp_minion.test_mcp_server"] }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ```bash
126
+ mcp-minion path/to/run_folder -v
127
+ ```
128
+
129
+ ## Tests
130
+
131
+ ```bash
132
+ cd minion && uv run pytest -q
133
+ ```
134
+
135
+ The end-to-end tests under `minion/e2e_tests/` make real API calls and are
136
+ skipped unless `OPENROUTER_API_KEY` is set.
@@ -0,0 +1,10 @@
1
+ {
2
+ "model": {
3
+ "name": "google/gemini-3.1-flash-lite-preview",
4
+ "temperature": 0,
5
+ "max_tokens": 2048
6
+ },
7
+ "agent": {
8
+ "max_steps": 10
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "model": {
3
+ "name": "google/gemini-3.1-flash-lite-preview",
4
+ "temperature": 0,
5
+ "max_tokens": 512
6
+ },
7
+ "agent": {
8
+ "max_steps": 3
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "model": {
3
+ "name": "google/gemini-3.1-flash-lite-preview",
4
+ "temperature": 0,
5
+ "max_tokens": 1024
6
+ },
7
+ "agent": {
8
+ "max_steps": 5
9
+ }
10
+ }
@@ -129,7 +129,7 @@ class TestLogIntegrity:
129
129
 
130
130
  def test_log_has_all_fields(self) -> None:
131
131
  folder = E2E_RUNS / "simple_add"
132
- result, logger = run_agent_from_folder(folder)
132
+ _result, logger = run_agent_from_folder(folder)
133
133
 
134
134
  log_data = json.loads(logger.log_path.read_text())
135
135
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "mcp-minion"
7
- version = "0.2.2"
7
+ version = "0.3.0"
8
8
  description = "A minimal ReAct agent over MCP servers via OpenRouter"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -15,7 +15,7 @@ requires-python = ">=3.13,<3.15"
15
15
  dependencies = [
16
16
  "openai>=1.0.0",
17
17
  "python-dotenv>=1.0.0",
18
- "mcp>=1.25.0,<3",
18
+ "mcp>=2,<3",
19
19
  ]
20
20
 
21
21
  [project.optional-dependencies]
@@ -4,14 +4,16 @@ from importlib.metadata import PackageNotFoundError, version
4
4
 
5
5
  from mcp_minion.agent import Agent, AgentConfig, AgentResult
6
6
  from mcp_minion.artifacts import extract_last_submission
7
+ from mcp_minion.env import find_api_key
7
8
  from mcp_minion.logging import RunLogger
8
- from mcp_minion.mcp_client import MCPManager, MCPResourceInfo, MCPToolInfo
9
+ from mcp_minion.mcp_client import MCPManager, MCPResourceInfo, MCPToolInfo, ToolOutcome
9
10
  from mcp_minion.tools import Tool, ToolRegistry, create_default_registry
10
11
 
11
12
  try:
12
13
  __version__ = version("mcp-minion")
13
- except PackageNotFoundError: # pragma: no cover - source checkout without install
14
- __version__ = "0.2.1"
14
+ except PackageNotFoundError: # pragma: no cover - source tree without install
15
+ # A sentinel, not a release number, so it cannot go stale.
16
+ __version__ = "0+unknown"
15
17
 
16
18
  __all__ = [
17
19
  "Agent",
@@ -22,8 +24,10 @@ __all__ = [
22
24
  "MCPToolInfo",
23
25
  "RunLogger",
24
26
  "Tool",
27
+ "ToolOutcome",
25
28
  "ToolRegistry",
26
29
  "__version__",
27
30
  "create_default_registry",
28
31
  "extract_last_submission",
32
+ "find_api_key",
29
33
  ]