Add deterministic article search to MCP
This commit is contained in:
@@ -5,11 +5,12 @@ import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import mcp_server
|
||||
from roll_calculation import calculate_roll, get_article
|
||||
from roll_calculation import ArticleRepository, calculate_roll, get_article
|
||||
from rollcalc_mcp_tools import (
|
||||
analyze_transport_capacity_result,
|
||||
calculate_roll_diameter_result,
|
||||
get_article_result,
|
||||
search_articles_result,
|
||||
)
|
||||
from transport_calculation import analyze_transport, transport_presets
|
||||
|
||||
@@ -39,6 +40,34 @@ class McpAdapterTests(unittest.TestCase):
|
||||
get_article(**arguments),
|
||||
)
|
||||
|
||||
def test_search_articles_delegates_to_domain_and_preserves_candidates(self):
|
||||
query = "Bfix NSP 4900, 5,00 x 40 m"
|
||||
|
||||
result = search_articles_result(query)
|
||||
|
||||
self.assertEqual(result, ArticleRepository.load().search(query))
|
||||
self.assertEqual(result["status"], "search_results")
|
||||
self.assertEqual(
|
||||
[candidate["article_number"] for candidate in result["candidates"]],
|
||||
["180205", "8180205", "182815", "206900"],
|
||||
)
|
||||
self.assertEqual(
|
||||
result["candidates"][1]["production_site"], "Malaysia"
|
||||
)
|
||||
|
||||
def test_search_articles_preserves_ambiguous_and_not_found_domain_results(self):
|
||||
ambiguous = search_articles_result("Bentofix NSP 4900")
|
||||
missing = search_articles_result("not a RollCalc product")
|
||||
|
||||
self.assertGreater(ambiguous["total_matches"], 1)
|
||||
self.assertGreater(len(ambiguous["candidates"]), 1)
|
||||
self.assertEqual(missing, {
|
||||
"status": "search_not_found",
|
||||
"query": "not a RollCalc product",
|
||||
"total_matches": 0,
|
||||
"candidates": [],
|
||||
})
|
||||
|
||||
def test_calculate_roll_diameter_delegates_for_normal_weighted_and_invalid_cases(self):
|
||||
for arguments in (
|
||||
{
|
||||
@@ -111,7 +140,7 @@ class McpAdapterTests(unittest.TestCase):
|
||||
self.assertEqual(result["analysis"]["final_rolls"], 24)
|
||||
self.assertEqual(result["analysis"]["limiting"]["name"], "Weight")
|
||||
|
||||
def test_server_registers_exactly_the_three_stdio_poc_tools(self):
|
||||
def test_server_registers_the_existing_tools_and_article_search(self):
|
||||
mcp = types.ModuleType("mcp")
|
||||
server = types.ModuleType("mcp.server")
|
||||
fastmcp = types.ModuleType("mcp.server.fastmcp")
|
||||
@@ -128,6 +157,7 @@ class McpAdapterTests(unittest.TestCase):
|
||||
[tool.__name__ for tool in instance.tools],
|
||||
[
|
||||
"get_article",
|
||||
"search_articles",
|
||||
"calculate_roll_diameter",
|
||||
"analyze_transport_capacity",
|
||||
],
|
||||
@@ -136,10 +166,16 @@ class McpAdapterTests(unittest.TestCase):
|
||||
def test_server_schema_exposes_weight_and_transport_chaining_contract(self):
|
||||
instance = mcp_server.create_server()
|
||||
tools = instance._tool_manager._tools
|
||||
search_tool = tools["search_articles"]
|
||||
roll_schema = tools["calculate_roll_diameter"].parameters
|
||||
transport_tool = tools["analyze_transport_capacity"]
|
||||
transport_schema = transport_tool.parameters
|
||||
|
||||
self.assertEqual(search_tool.parameters["required"], ["query"])
|
||||
self.assertEqual(
|
||||
search_tool.parameters["properties"]["query"]["type"], "string"
|
||||
)
|
||||
|
||||
self.assertNotIn("include_roll_weight", roll_schema["properties"])
|
||||
preset_schema = transport_schema["properties"]["transport_preset"]
|
||||
self.assertEqual(
|
||||
@@ -195,6 +231,26 @@ class McpAdapterTests(unittest.TestCase):
|
||||
):
|
||||
self.assertIn(text, description)
|
||||
|
||||
search_description = search_tool.description
|
||||
for text in (
|
||||
"name, family, designation, or descriptive article text",
|
||||
"Do not guess or invent an article number",
|
||||
"deterministic candidates from the RollCalc article master data",
|
||||
"total_matches is exactly 1",
|
||||
"use that candidate's exact article_number",
|
||||
"do NOT select the first or highest-ranked candidate",
|
||||
"ask the user which article number is intended",
|
||||
"do not calculate yet",
|
||||
"no matching RollCalc article was found",
|
||||
"more specific designation or article number",
|
||||
"do not invent an article",
|
||||
"production_site=Malaysia is descriptive metadata only",
|
||||
"does not imply Bentofix, Bento 2, or any production machine",
|
||||
"Ranking/order expresses relevance only",
|
||||
"get_article -> calculate_roll_diameter -> optionally analyze_transport_capacity",
|
||||
):
|
||||
self.assertIn(text, search_description)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user