feat(was-lib): add /tool-manifest/{categoryKey} endpoint for filtered manifest
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 3m19s

This commit is contained in:
jade
2026-08-18 20:51:41 +09:00
parent fbae7618eb
commit 3216148ee2
2 changed files with 17 additions and 1 deletions

View File

@@ -43,12 +43,17 @@ public class ToolManifestService {
} }
public ToolManifestResponse currentManifest() { public ToolManifestResponse currentManifest() {
return currentManifest(null);
}
public ToolManifestResponse currentManifest(String categoryKey) {
String bundleId = properties.getManifest() == null ? null : properties.getManifest().getBundleId(); String bundleId = properties.getManifest() == null ? null : properties.getManifest().getBundleId();
if (bundleId == null || bundleId.isBlank()) { if (bundleId == null || bundleId.isBlank()) {
throw new IllegalStateException("mcp.manifest.bundle-id must be configured"); throw new IllegalStateException("mcp.manifest.bundle-id must be configured");
} }
List<ToolManifestItem> tools = toolSupplier.get().stream() List<ToolManifestItem> tools = toolSupplier.get().stream()
.filter(tool -> categoryKey == null || categoryKey.equals(tool.getCategoryKey()))
.map(this::toManifestItem) .map(this::toManifestItem)
.sorted(Comparator.comparing(ToolManifestItem::name)) .sorted(Comparator.comparing(ToolManifestItem::name))
.toList(); .toList();

View File

@@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PathVariable;
/** Read-only Tool Service manifest endpoint for MCP background discovery. */ /** Read-only Tool Service manifest endpoint for MCP background discovery. */
@RestController @RestController
@@ -22,7 +23,17 @@ public class ToolManifestController {
@GetMapping(value = "/tool-manifest", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/tool-manifest", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ToolManifestResponse> getManifest( public ResponseEntity<ToolManifestResponse> getManifest(
@RequestHeader(value = HttpHeaders.IF_NONE_MATCH, required = false) String ifNoneMatch) { @RequestHeader(value = HttpHeaders.IF_NONE_MATCH, required = false) String ifNoneMatch) {
ToolManifestResponse manifest = toolManifestService.currentManifest(); return handleManifest(toolManifestService.currentManifest(), ifNoneMatch);
}
@GetMapping(value = "/tool-manifest/{categoryKey}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ToolManifestResponse> getManifestByCategory(
@PathVariable("categoryKey") String categoryKey,
@RequestHeader(value = HttpHeaders.IF_NONE_MATCH, required = false) String ifNoneMatch) {
return handleManifest(toolManifestService.currentManifest(categoryKey), ifNoneMatch);
}
private ResponseEntity<ToolManifestResponse> handleManifest(ToolManifestResponse manifest, String ifNoneMatch) {
String eTag = '"' + manifest.revision() + '"'; String eTag = '"' + manifest.revision() + '"';
if (eTag.equals(ifNoneMatch)) { if (eTag.equals(ifNoneMatch)) {
return ResponseEntity.status(304).eTag(eTag).build(); return ResponseEntity.status(304).eTag(eTag).build();