refs #743: validate advertised ADB MCP tools at startup
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
package com.cloudhandson.vpdbackoffice.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
class McpAgentToolStartupValidatorTest {
|
||||
|
||||
private final McpToolCatalog toolCatalog = mock(McpToolCatalog.class);
|
||||
private final JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
|
||||
private final McpAgentToolStartupValidator validator =
|
||||
new McpAgentToolStartupValidator(toolCatalog, jdbcTemplate);
|
||||
|
||||
@Test
|
||||
void acceptsEnabledAgentToolsAndChecksDuplicateTargetOnce() {
|
||||
when(toolCatalog.tools()).thenReturn(List.of(
|
||||
agentTool("resolve_hr_term", "HMM_HR_TERM_RESOLVER"),
|
||||
agentTool("resolve_hr_alias", "HMM_HR_TERM_RESOLVER"),
|
||||
agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
|
||||
));
|
||||
when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
|
||||
.thenReturn(List.of(
|
||||
Map.of("TOOL_NAME", "HMM_HR_TERM_RESOLVER", "STATUS", "ENABLED"),
|
||||
Map.of("TOOL_NAME", "HMM_HR_POLICY_SEARCH", "STATUS", "enabled")
|
||||
));
|
||||
|
||||
validator.validateAdvertisedAgentTools();
|
||||
|
||||
verify(jdbcTemplate).queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMissingAgentTool() {
|
||||
when(toolCatalog.tools()).thenReturn(List.of(
|
||||
agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
|
||||
));
|
||||
when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
|
||||
.thenReturn(List.of());
|
||||
|
||||
assertThatThrownBy(validator::validateAdvertisedAgentTools)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("missing=[HMM_HR_POLICY_SEARCH]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsDisabledAgentTool() {
|
||||
when(toolCatalog.tools()).thenReturn(List.of(
|
||||
agentTool("resolve_hr_term", "HMM_HR_TERM_RESOLVER")
|
||||
));
|
||||
when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
|
||||
.thenReturn(List.of(
|
||||
Map.of("tool_name", "hmm_hr_term_resolver", "status", "DISABLED")
|
||||
));
|
||||
|
||||
assertThatThrownBy(validator::validateAdvertisedAgentTools)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("notEnabled=[HMM_HR_TERM_RESOLVER=DISABLED]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void skipsDatabaseLookupForApplicationNativeTools() {
|
||||
when(toolCatalog.tools()).thenReturn(List.of(selectAiTool("search_hr_data")));
|
||||
|
||||
validator.validateAdvertisedAgentTools();
|
||||
|
||||
verify(jdbcTemplate, never())
|
||||
.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMetadataLookupFailure() {
|
||||
when(toolCatalog.tools()).thenReturn(List.of(
|
||||
agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
|
||||
));
|
||||
when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
|
||||
.thenThrow(new DataAccessResourceFailureException("metadata unavailable"));
|
||||
|
||||
assertThatThrownBy(validator::validateAdvertisedAgentTools)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("USER_AI_AGENT_TOOLS")
|
||||
.hasCauseInstanceOf(DataAccessResourceFailureException.class);
|
||||
}
|
||||
|
||||
private McpToolDefinition agentTool(String publicName, String targetName) {
|
||||
return new McpToolDefinition(
|
||||
publicName,
|
||||
publicName,
|
||||
"description",
|
||||
"query",
|
||||
"query description",
|
||||
"AGENT_TOOL",
|
||||
targetName,
|
||||
"P_QUERY"
|
||||
);
|
||||
}
|
||||
|
||||
private McpToolDefinition selectAiTool(String publicName) {
|
||||
return new McpToolDefinition(
|
||||
publicName,
|
||||
publicName,
|
||||
"description",
|
||||
"query",
|
||||
"query description",
|
||||
"SELECT_AI",
|
||||
"",
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user