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
|
- 선택한 사용자는 자연어의 ‘나’, ‘내’, ‘우리 팀’을 해석하는 데모 문맥이다. 현재 HMM MCP의 gateway
|
||||||
token은 공용이므로 이 선택 자체가 DB 행 수준 권한을 강제한다고 표시하지 않는다.
|
token은 공용이므로 이 선택 자체가 DB 행 수준 권한을 강제한다고 표시하지 않는다.
|
||||||
- HMM MCP 허용 도구는 `resolve_hr_term`, `search_hr_data`, `search_hr_policy` 세 개다.
|
- 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):
|
if not isinstance(properties, Mapping):
|
||||||
properties = {}
|
properties = {}
|
||||||
|
|
||||||
if tool.name == preferred_tool:
|
# A server's default/preferred tool still has to obey its discovered schema.
|
||||||
return {"prompt": question, "limit": limit}
|
# HMM tools use `query` and `term`; forcing the legacy `prompt`/`limit` shape
|
||||||
if "prompt" in properties:
|
# makes an otherwise valid tool fail argument validation.
|
||||||
args: dict[str, Any] = {"prompt": question}
|
del preferred_tool
|
||||||
if "limit" in properties:
|
input_name = next(
|
||||||
args["limit"] = limit
|
(name for name in ("prompt", "question", "query", "term", "text") if name in properties),
|
||||||
elif "max_rows" in properties:
|
"",
|
||||||
args["max_rows"] = limit
|
)
|
||||||
return args
|
if not input_name:
|
||||||
if "question" in properties:
|
required = tool.schema.get("required")
|
||||||
args = {"question": question}
|
if isinstance(required, list):
|
||||||
if "max_rows" in properties:
|
input_name = next(
|
||||||
args["max_rows"] = limit
|
(
|
||||||
elif "limit" in properties:
|
str(name)
|
||||||
args["limit"] = limit
|
for name in required
|
||||||
return args
|
if isinstance(properties.get(str(name)), Mapping)
|
||||||
if "query" in properties:
|
and properties[str(name)].get("type") == "string"
|
||||||
args = {"query": question}
|
),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
if input_name:
|
||||||
|
args: dict[str, Any] = {input_name: question}
|
||||||
if "max_evidence" in properties:
|
if "max_evidence" in properties:
|
||||||
args["max_evidence"] = min(limit, 10)
|
args["max_evidence"] = min(limit, 10)
|
||||||
|
elif "max_rows" in properties:
|
||||||
|
args["max_rows"] = limit
|
||||||
elif "limit" in properties:
|
elif "limit" in properties:
|
||||||
args["limit"] = limit
|
args["limit"] = limit
|
||||||
return args
|
return args
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from src.poc4.scenarios import ScenarioConfigError, load_demo_scenarios
|
from src.poc4.scenarios import ScenarioConfigError, load_demo_scenarios
|
||||||
from src.agent_console.profile import load_app_profile
|
from src.agent_console.profile import load_app_profile
|
||||||
|
from src.mcp_tool_router import McpTool, build_mcp_tool_arguments
|
||||||
|
|
||||||
|
|
||||||
class DemoScenarioConfigTest(unittest.TestCase):
|
class DemoScenarioConfigTest(unittest.TestCase):
|
||||||
@@ -74,6 +75,42 @@ class DemoScenarioConfigTest(unittest.TestCase):
|
|||||||
with self.assertRaises(ScenarioConfigError):
|
with self.assertRaises(ScenarioConfigError):
|
||||||
load_demo_scenarios(path)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user