refs #699: honor MCP tool input schemas

This commit is contained in:
devmrko
2026-07-22 20:13:17 +09:00
parent ee355a9282
commit d6a558e45a
3 changed files with 63 additions and 18 deletions

View File

@@ -24,6 +24,8 @@ vpd_token_presets.json (사용자 ID·역할·팀·테스트 문맥·mcp_token_e
- 선택한 사용자는 자연어의 ‘나’, ‘내’, ‘우리 팀’을 해석하는 데모 문맥이다. 현재 HMM MCP의 gateway
token은 공용이므로 이 선택 자체가 DB 행 수준 권한을 강제한다고 표시하지 않는다.
- HMM MCP 허용 도구는 `resolve_hr_term`, `search_hr_data`, `search_hr_policy` 세 개다.
- 호출 인자는 `tools/list`의 schema를 기준으로 생성한다. 기본 도구에도 레거시 `prompt`/`limit`
강제하지 않으며 `search_hr_data`·`search_hr_policy``query`, `resolve_hr_term``term`을 전달한다.
## 런타임 구성

View File

@@ -154,26 +154,32 @@ def build_mcp_tool_arguments(
if not isinstance(properties, Mapping):
properties = {}
if tool.name == preferred_tool:
return {"prompt": question, "limit": limit}
if "prompt" in properties:
args: dict[str, Any] = {"prompt": question}
if "limit" in properties:
args["limit"] = limit
elif "max_rows" in properties:
args["max_rows"] = limit
return args
if "question" in properties:
args = {"question": question}
if "max_rows" in properties:
args["max_rows"] = limit
elif "limit" in properties:
args["limit"] = limit
return args
if "query" in properties:
args = {"query": question}
# A server's default/preferred tool still has to obey its discovered schema.
# HMM tools use `query` and `term`; forcing the legacy `prompt`/`limit` shape
# makes an otherwise valid tool fail argument validation.
del preferred_tool
input_name = next(
(name for name in ("prompt", "question", "query", "term", "text") if name in properties),
"",
)
if not input_name:
required = tool.schema.get("required")
if isinstance(required, list):
input_name = next(
(
str(name)
for name in required
if isinstance(properties.get(str(name)), Mapping)
and properties[str(name)].get("type") == "string"
),
"",
)
if input_name:
args: dict[str, Any] = {input_name: question}
if "max_evidence" in properties:
args["max_evidence"] = min(limit, 10)
elif "max_rows" in properties:
args["max_rows"] = limit
elif "limit" in properties:
args["limit"] = limit
return args

View File

@@ -8,6 +8,7 @@ from unittest.mock import patch
from src.poc4.scenarios import ScenarioConfigError, load_demo_scenarios
from src.agent_console.profile import load_app_profile
from src.mcp_tool_router import McpTool, build_mcp_tool_arguments
class DemoScenarioConfigTest(unittest.TestCase):
@@ -74,6 +75,42 @@ class DemoScenarioConfigTest(unittest.TestCase):
with self.assertRaises(ScenarioConfigError):
load_demo_scenarios(path)
def test_default_mcp_tool_arguments_follow_discovered_query_schema(self) -> None:
tool = McpTool(
name="search_hr_data",
description="",
schema={
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
},
read_only=True,
)
arguments = build_mcp_tool_arguments(
tool, "직원 E1005의 휴가 신청 내역", 50, preferred_tool="search_hr_data"
)
self.assertEqual(arguments, {"query": "직원 E1005의 휴가 신청 내역"})
def test_term_tool_arguments_follow_discovered_term_schema(self) -> None:
tool = McpTool(
name="resolve_hr_term",
description="",
schema={
"type": "object",
"properties": {"term": {"type": "string"}},
"required": ["term"],
},
read_only=True,
)
arguments = build_mcp_tool_arguments(
tool, "반차", 50, preferred_tool="search_hr_data"
)
self.assertEqual(arguments, {"term": "반차"})
if __name__ == "__main__":
unittest.main()