refs #699: honor MCP tool input schemas
This commit is contained in:
@@ -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`을 전달한다.
|
||||
|
||||
## 런타임 구성
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user