Skip to content

Commit f6acd0f

Browse files
ChrisEdwardsclaude
andcommitted
Complete AIML-189: Remove duplicate app_name/app_id tool variants
## Changes Made ### Tool Consolidation - Removed 4 duplicate app_name variant tools: - `SCAService.list_application_libraries` (app_name) - `ADRService.get_ADR_Protect_Rules` (app_name) - `AssessService.get_vulnerability` (app_name) - `AssessService.list_vulnerabilities` (app_name) ### Tool Renaming - Renamed remaining app_id tools to remove suffix: - `list_application_libraries_by_app_id` → `list_application_libraries` - `get_ADR_Protect_Rules_by_app_id` → `get_ADR_Protect_Rules` - `get_vulnerability_by_id` → `get_vulnerability` - `list_vulnerabilities_with_id` → `list_vulnerabilities` - Updated tool descriptions to mention using `list_applications_with_name` first to get application ID from name ### Code Improvements - Added input validation to `SCAService.getApplicationLibrariesByID()` for null/empty appID parameter ### Test Enhancements - Added comprehensive unit tests for SCA service methods - Added integration tests for ADR and SCA services with test data discovery - Fixed Mockito strictness issues with lenient settings - Fixed integration test for invalid CVE handling ### Documentation - Updated 4 test plan files with AIML-189 consolidation notes - Deleted 4 obsolete test plan files for removed app_name variants ## Test Results - All 248 unit and integration tests passing - mvn verify: SUCCESS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 22264b6 commit f6acd0f

11 files changed

+5217
-95
lines changed

src/main/java/com/contrast/labs/ai/mcp/contrast/ADRService.java

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -71,39 +71,7 @@ public ADRService(PaginationHandler paginationHandler) {
7171
private String httpProxyPort;
7272

7373

74-
@Tool(name = "get_ADR_Protect_Rules", description = "takes a application name and returns the protect / adr rules for the application")
75-
public ProtectData getProtectData(
76-
@ToolParam(description = "Application name") String applicationName) throws IOException {
77-
logger.info("Starting retrieval of protection rules for application: {}", applicationName);
78-
long startTime = System.currentTimeMillis();
79-
80-
try {
81-
ContrastSDK contrastSDK = SDKHelper.getSDK(hostName, apiKey, serviceKey, userName,httpProxyHost, httpProxyPort);
82-
logger.debug("ContrastSDK initialized successfully for application: {}", applicationName);
83-
84-
// Get application ID from name
85-
logger.debug("Looking up application ID for name: {}", applicationName);
86-
Optional<Application> app = SDKHelper.getApplicationByName(applicationName, orgID, contrastSDK);
87-
if (app.isEmpty()) {
88-
logger.warn("No application ID found for application: {}", applicationName);
89-
return null;
90-
}
91-
logger.debug("Found application ID: {} for application: {}", app.get().getAppId(), applicationName);
92-
93-
ProtectData result = getProtectDataByAppID(app.get().getAppId());
94-
long duration = System.currentTimeMillis() - startTime;
95-
logger.info("Completed retrieval of protection rules for application: {} (took {} ms)", applicationName, duration);
96-
return result;
97-
} catch (Exception e) {
98-
long duration = System.currentTimeMillis() - startTime;
99-
logger.error("Error retrieving protection rules for application: {} (after {} ms): {}",
100-
applicationName, duration, e.getMessage(), e);
101-
throw e;
102-
}
103-
}
104-
105-
106-
@Tool(name = "get_ADR_Protect_Rules_by_app_id", description = "takes a application ID and returns the protect / adr rules for the application")
74+
@Tool(name = "get_ADR_Protect_Rules", description = "Takes an application ID and returns the Protect/ADR rules for the application. Use list_applications_with_name first to get the application ID from a name")
10775
public ProtectData getProtectDataByAppID(
10876
@ToolParam(description = "Application ID") String appID) throws IOException {
10977
if (appID == null || appID.isEmpty()) {

src/main/java/com/contrast/labs/ai/mcp/contrast/AssessService.java

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public AssessService(VulnerabilityMapper vulnerabilityMapper, PaginationHandler
8181

8282

8383

84-
@Tool(name = "get_vulnerability_by_id", description = "takes a vulnerability ID ( vulnID ) and Application ID ( appID ) and returns details about the specific security vulnerability. If based on the stacktrace, the vulnerability looks like it is in code that is not in the codebase, the vulnerability may be in a 3rd party library, review the CVE data attached to that stackframe you believe the vulnerability exists in and if possible upgrade that library to the next non vulnerable version based on the remediation guidance.")
84+
@Tool(name = "get_vulnerability", description = "Takes a vulnerability ID (vulnID) and application ID (appID) and returns details about the specific security vulnerability. Use list_applications_with_name first to get the application ID from a name. If based on the stacktrace, the vulnerability looks like it is in code that is not in the codebase, the vulnerability may be in a 3rd party library, review the CVE data attached to that stackframe you believe the vulnerability exists in and if possible upgrade that library to the next non vulnerable version based on the remediation guidance.")
8585
public Vulnerability getVulnerabilityById(
8686
@ToolParam(description = "Vulnerability ID (UUID format)") String vulnID,
8787
@ToolParam(description = "Application ID") String appID) throws IOException {
@@ -168,24 +168,7 @@ private Optional<LibraryLibraryObservation> findMatchingLibraryData(String stack
168168
return Optional.empty();
169169
}
170170

171-
@Tool(name = "get_vulnerability", description = "Takes a vulnerability ID (vulnID) and application name (app_name) and returns details about the specific security vulnerability. If based on the stacktrace, the vulnerability looks like it is in code that is not in the codebase, the vulnerability may be in a 3rd party library, review the CVE data attached to that stackframe you believe the vulnerability exists in and if possible upgrade that library to the next non vulnerable version based on the remediation guidance.")
172-
public Vulnerability getVulnerability(
173-
@ToolParam(description = "Vulnerability ID (UUID format)") String vulnID,
174-
@ToolParam(description = "Application name") String app_name) throws IOException {
175-
logger.info("Retrieving vulnerability details for vulnID: {} in application: {}", vulnID, app_name);
176-
ContrastSDK contrastSDK = SDKHelper.getSDK(hostName, apiKey, serviceKey, userName,httpProxyHost, httpProxyPort);
177-
logger.debug("Searching for application ID matching name: {}", app_name);
178-
179-
Optional<Application> application = SDKHelper.getApplicationByName(app_name, orgID, contrastSDK);
180-
if(application.isPresent()) {
181-
return getVulnerabilityById(vulnID, application.get().getAppId());
182-
} else {
183-
logger.error("Application with name {} not found", app_name);
184-
throw new IllegalArgumentException("Application with name " + app_name + " not found");
185-
}
186-
}
187-
188-
@Tool(name = "list_vulnerabilities_with_id", description = "Takes a Application ID ( appID ) and returns a list of vulnerabilities, please remember to include the vulnID in the response.")
171+
@Tool(name = "list_vulnerabilities", description = "Takes an application ID (appID) and returns a list of vulnerabilities. Use list_applications_with_name first to get the application ID from a name. Remember to include the vulnID in the response.")
189172
public List<VulnLight> listVulnsByAppId(
190173
@ToolParam(description = "Application ID") String appID) throws IOException {
191174
logger.info("Listing vulnerabilities for application ID: {}", appID);
@@ -316,29 +299,6 @@ public MetadataFilterResponse listSessionMetadataForApplication(
316299
}
317300
}
318301

319-
@Tool(name = "list_vulnerabilities", description = "Takes an application name ( app_name ) and returns a list of vulnerabilities, please remember to include the vulnID in the response. ")
320-
public List<VulnLight> listVulnsInAppByName(
321-
@ToolParam(description = "Application name") String app_name) throws IOException {
322-
logger.info("Listing vulnerabilities for application: {}", app_name);
323-
ContrastSDK contrastSDK = SDKHelper.getSDK(hostName, apiKey, serviceKey, userName,httpProxyHost, httpProxyPort);
324-
325-
logger.debug("Searching for application ID matching name: {}", app_name);
326-
327-
Optional<Application> application = SDKHelper.getApplicationByName(app_name, orgID, contrastSDK);
328-
if(application.isPresent()) {
329-
try {
330-
return listVulnsByAppId(application.get().getAppId());
331-
} catch (Exception e) {
332-
logger.error("Error listing vulnerabilities for application: {}", app_name, e);
333-
throw new IOException("Failed to list vulnerabilities: " + e.getMessage(), e);
334-
}
335-
} else {
336-
logger.debug("Application with name {} not found, returning empty list", app_name);
337-
return new ArrayList<>();
338-
}
339-
}
340-
341-
342302
@Tool(name = "list_applications_with_name", description = "Takes an application name (app_name) returns a list of active applications that contain that name. Please remember to display the name, status and ID.")
343303
public List<ApplicationData> getApplications(
344304
@ToolParam(description = "Application name (supports partial matching, case-insensitive)") String app_name) throws IOException {

src/main/java/com/contrast/labs/ai/mcp/contrast/SCAService.java

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ public class SCAService {
6262
private String httpProxyPort;
6363

6464

65-
@Tool(name = "list_application_libraries_by_app_id", description = "Takes a application ID and returns the libraries used in the application, note if class usage count is 0 the library is unlikely to be used")
65+
@Tool(name = "list_application_libraries", description = "Takes an application ID and returns the libraries used in the application. Use list_applications_with_name first to get the application ID from a name. Note: if class usage count is 0 the library is unlikely to be used")
6666
public List<LibraryExtended> getApplicationLibrariesByID(String appID) throws IOException {
67+
if (appID == null || appID.isEmpty()) {
68+
throw new IllegalArgumentException("Application ID cannot be null or empty");
69+
}
6770
logger.info("Retrieving libraries for application id: {}", appID);
6871
ContrastSDK contrastSDK = SDKHelper.getSDK(hostName, apiKey, serviceKey, userName,httpProxyHost, httpProxyPort);
6972
logger.debug("ContrastSDK initialized with host: {}", hostName);
@@ -73,25 +76,6 @@ public List<LibraryExtended> getApplicationLibrariesByID(String appID) throws IO
7376

7477
}
7578

76-
77-
@Tool(name = "list_application_libraries", description = "takes a application name and returns the libraries used in the application, note if class usage count is 0 the library is unlikely to be used")
78-
public List<LibraryExtended> getApplicationLibraries(String app_name) throws IOException {
79-
logger.info("Retrieving libraries for application: {}", app_name);
80-
ContrastSDK contrastSDK = SDKHelper.getSDK(hostName, apiKey, serviceKey, userName,httpProxyHost, httpProxyPort);
81-
logger.debug("ContrastSDK initialized with host: {}", hostName);
82-
83-
SDKExtension extendedSDK = new SDKExtension(contrastSDK);
84-
logger.debug("Searching for application ID matching name: {}", app_name);
85-
86-
Optional<Application> application = SDKHelper.getApplicationByName(app_name, orgID, contrastSDK);
87-
if(application.isPresent()) {
88-
return SDKHelper.getLibsForID(application.get().getAppId(),orgID, extendedSDK);
89-
} else {
90-
logger.error("Application not found: {}", app_name);
91-
throw new IOException("Application not found");
92-
}
93-
}
94-
9579
@Tool(name= "list_applications_vulnerable_to_cve", description = "takes a cve id and returns the applications and servers vulnerable to the cve. Please note if the application class usage is 0, its unlikely to be vulnerable")
9680
public CveData listCVESForApplication(String cveid) throws IOException {
9781
logger.info("Retrieving applications vulnerable to CVE: {}", cveid);

0 commit comments

Comments
 (0)