Add configurable production machine constraints

This commit is contained in:
2026-09-26 10:47:53 +02:00
parent e6a7d4da72
commit 3e13d24405
12 changed files with 904 additions and 3 deletions
+28
View File
@@ -10,6 +10,8 @@ from rollcalc_mcp_tools import (
calculate_product_length_result,
calculate_roll_diameter_result,
get_article_result,
get_machine_result,
check_production_feasibility_result,
search_articles_result,
)
from transport_calculation import TransportPresetKey
@@ -34,6 +36,32 @@ def create_server() -> Any:
"""Use search_articles when the user identifies a RollCalc product by name, family, designation, or descriptive article text instead of an exact article number. Do not guess or invent an article number: results are deterministic retrieval candidates from the RollCalc article master data, not product recommendations. For an exact article number, use get_article -> calculate_roll_diameter -> optionally analyze_transport_capacity. For a product name, use search_articles first. Only when total_matches is exactly 1 may you use that candidate's exact article_number and continue through get_article and the requested workflow. When multiple plausible candidates are returned, do NOT select the first or highest-ranked candidate, do not treat ranking as permission to choose, and do not calculate yet: present relevant candidates with their article numbers, distinguishing names, and production_site when supplied; ask the user which article number is intended, then stop until they select it. Ranking/order expresses retrieval relevance only and never authorizes automatic selection. If no candidate is returned, say that no matching RollCalc article was found, ask for a more specific designation or article number, and do not invent an article. production_site=Malaysia is descriptive metadata only: it does not imply Bentofix, Bento 2, or any production machine."""
return search_articles_result(query)
@server.tool()
def get_machine(machine: str) -> dict[str, Any]:
"""Resolve a configured production machine by stable ID, exact name, or configured alias. Machine limits are deterministic configured domain data; aliases and locations are lookup/metadata only and do not imply capabilities."""
return get_machine_result(machine)
@server.tool()
def check_production_feasibility(
machine: str,
roll_weight_kg: float | None = None,
average_diameter_mm: float | None = None,
maximum_diameter_mm: float | None = None,
core_diameter_mm: float | None = None,
product_width_m: float | None = None,
line_speed_m_per_min: float | None = None,
) -> dict[str, Any]:
"""Deterministically check a material-only calculated roll against one configured machine. The tool, not the LLM, decides every independent limit; never override failed constraints. Report returned warnings, especially maximum-diameter variation warnings. Missing configured V1 roll inputs require clarification rather than assumptions. average_diameter_mm and maximum_diameter_mm are the existing RollCalc calculation outputs; line speed is retained but outside the initial roll-feasibility scope."""
return check_production_feasibility_result(
machine=machine,
roll_weight_kg=roll_weight_kg,
average_diameter_mm=average_diameter_mm,
maximum_diameter_mm=maximum_diameter_mm,
core_diameter_mm=core_diameter_mm,
product_width_m=product_width_m,
line_speed_m_per_min=line_speed_m_per_min,
)
@server.tool()
def calculate_material_weight(
roll_length_m: float,