매니페스트가 선언한 inputSchema는 외부가 정하는 입력이다. JSON Schema 검증기는 문서 밖 $ref를 만나면 그 주소로 직접 조회하므로 매니페스트가 서버의 outbound 호출 대상을 정하는 통로가 된다. pattern은 joni와 graal-js가 없어 java.util.regex의 백트래킹 경로로 처리되고, 인증이 없는 경계(ADR-0006)라 호출 빈도를 줄여 주는 계층도 없다. ToolSchemaReferencePolicy가 문서 밖 참조와 미지원 dialect를 막고, ToolSchemaPatternPolicy가 정규식 길이·무한 수량자 개수·중첩 반복을 검사하며 pattern을 쓰는 필드에 maxLength를 요구한다. 길이를 묶을 수 없는 patternProperties는 거부한다. 검사는 ToolMetadata의 표준 생성자 한 곳에서만 한다. Portal 매니페스트 파싱, local 파일 로딩, Redis snapshot 역직렬화가 모두 이 생성자를 지나므로 조회 경로가 늘어도 검사 지점은 하나로 남는다. 위반은 IllegalStateException이라 기존 매니페스트 형식 오류와 같게 다뤄지고 bundle 단위 실패 격리가 그대로 적용된다. 근거와 한계는 ADR-0011, ADR-0012에 있다. ADR-0012가 classpath 근거로 인용하는 docs/sbom도 함께 가져온다. 192개 테스트 전부 통과. 기존 169건은 새 검사에 걸리지 않는다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.5 KiB
SBOM — AXHUB MCP&Tool Service
- 산출물:
AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json(CycloneDX 1.5 정본),AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx(검토용) - 대상: AXHUB MCP Server와 Tool Service의 공통 스택 (Java 21 / Spring Boot 3.5.11)
- 산출 기준 빌드:
ax-hub-mcp-server@0.1.0 - 생성 기준일: 2026-08-18
대상 범위
MCP Server와 Tool Service는 같은 기술 스택과 같은 MCP SDK를 쓰므로 이 SBOM을 공통으로 적용한다.
build.gradle이 직접 선언한 오픈소스는 io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0
하나이며, 이 SBOM은 그 런타임 전이 의존 전체와 빌드 환경을 담는다. Spring Boot starter
계열(web / validation / data-redis / actuator)은 glow f/w가 제공하는 플랫폼 구성이라 범위 밖이다.
다만 목록은 MCP Server 빌드(ax-hub-mcp-server@0.1.0) 하나에서 산출했다. Tool Service가 이
스택 밖의 의존(예: DB 드라이버, 연계 라이브러리)을 추가하면 그만큼은 이 SBOM에 없으므로, 해당
빌드에서 다시 산출해 합쳐야 한다.
| 구분 | 개수 | 내용 |
|---|---|---|
| 런타임 의존성 (scope: required) | 12 | 실행 산출물 classpath에 올라가는 라이브러리 |
| 빌드 환경 (scope: optional) | 2 | JDK 21, Gradle 8.14.3 |
| 합계 | 14 |
라이선스는 Apache-2.0 9건, MIT 3건, MIT-0 1건, GPL-2.0 with Classpath Exception 1건(JDK)이다. 라이브러리 12건은 모두 permissive이고, copyleft는 JDK 하나뿐이다. JDK는 Classpath Exception이 있어 이 JDK로 실행하는 애플리케이션에 소스 공개 의무가 생기지 않는다.
JDK 배포판은 표준가이드가 정한 Eclipse Temurin
(openjdk21u-jdk_x64_windows_hotspot_21.0.5)이며, build.gradle의 toolchain에
vendor = JvmVendorSpec.ADOPTIUM으로 고정해 다른 배포판으로 빌드되지 않게 했다. 실행 컨테이너도
같은 계열인 eclipse-temurin:21-jre를 쓴다.
제외 항목
제외 항목과 사유는 엑셀 Exclusions 시트가 정본이다. 요약하면 다음과 같다.
- test scope와 annotationProcessor — 선언 4건. 산출물에 포함되지 않는다.
spring-boot-starter-test,com.squareup.okhttp3:mockwebserver:4.12.0,org.junit.platform:junit-platform-launcher(test scope)org.springframework.boot:spring-boot-configuration-processor(annotationProcessor)
joni,graal-js,graal-sdk— json-schema-validator의optional. ECMA262 정규식 검증을 쓰지 않아 해석되지 않으므로 약 50MB가 빠진다.jakarta.servlet-api:6.1.0— mcp-core의provided. 산출물에 포함되지 않고 서블릿 컨테이너가 제공한다.mcp:2.0.0(aggregate),mcp-json-jackson3:2.0.0— Jackson 3 경로를 쓰지 않아 선언하지 않는다. 자세한 배경은 mcp-java-sdk-adoption.md 참고.
산출 방법과 한계
버전과 해시는 build.gradle 선언에서 출발해 Gradle 로컬 캐시의 실제 pom을 따라가 그래프를
만들고, 캐시된 실제 jar 바이너리에서 SHA-512 / SHA-1을 직접 계산했다. Gradle 배포본의 SHA-256은
wrapper의 distributionSha256Sum 값을 그대로 옮겼다.
gradlew dependencies로 해석 결과를 대조하려 했으나 sandbox에서 gradle daemon이 뜨지 않아
(Unable to establish loopback connection) 실행하지 못했다. 따라서 다음 버전 정렬은 pom과
Spring Boot BOM 판독에 근거한 것이며, 빌드 환경에서 한 번 확인해야 한다.
./gradlew dependencies --configuration runtimeClasspath
| 컴포넌트 | pom 요청 버전 | 수록 버전 | 근거 |
|---|---|---|---|
| jackson-databind | 2.20.1 (mcp-json-jackson2) | 2.19.4 | Spring Boot 3.5.11 → jackson-bom 2.19.4 |
| jackson-databind | 2.18.3 (json-schema-validator) | 2.19.4 | 위와 동일 |
| reactor-core | 3.7.0 (mcp-core) | 3.7.16 | Spring Boot 3.5.11 → reactor-bom 2024.0.15 |
| slf4j-api | 2.0.16 (mcp-core) | 2.0.17 | Spring Boot 3.5.11 관리 버전 |
가장 확인이 필요한 항목은 jackson-databind다. SDK가 요청한 2.20.1이 io.spring.dependency-management에
의해 2.19.4로 내려가므로, initialize / tools/list / tools/call 직렬화 계약 테스트로 동작을 확인한다.
CycloneDX 1.5 공식 JSON Schema 원본 대조는 폐쇄망이라 수행하지 않았다. 대신 생성 시점에
dependencies의 모든 ref / dependsOn이 실재하는 bom-ref를 가리키는지, 컴포넌트가 빠짐없이
dependencies에 등장하는지 구조 점검을 통과시켰다.