Files
dap-was-dapms/docs/mcp-java-sdk-adoption.md
koseokmin 58d3014a0f
All checks were successful
Deploy Gateway / deploy (push) Successful in 2m52s
저장소 문서를 다시 추적하고 계약 예제를 복원한다
계약 테스트는 docs/contracts 아래 예제를 golden example로 읽는다.
docs/와 README.md가 ignore되어 있어 예제 파일이 사라졌고 9건이
실패하고 있었다. 문서가 온전했던 마지막 상태(3de052a)에서 복원하고
.gitignore에서 두 항목을 제거한다. 에이전트 산출물인
docs/superpowers/ 제외는 유지한다.

initialize 응답의 capabilities.tools.listChanged를 문서는 true로
적고 있었으나 InitializeHandler는 false를 낸다. 현재 HTTP 단발 응답
transport가 notification을 push할 수 없으므로 false가 맞다. 예제와
architecture.md를 코드에 맞추고, ToolListChangedEvent가 발행되지만
아직 소비되지 않는다는 점과 SSE 도입 시 true로 바꾼다는 조건을
남긴다.

169개 테스트 전부 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 17:16:13 +09:00

7.9 KiB

MCP Java SDK 선택적 도입 설계

  • 상태: 적용 완료
  • 적용 버전: io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0
  • 대상 런타임: Java 21, Spring Boot 3.5.11
  • 적용 원칙: 외부 계약과 AX HUB 고유 실행 경계는 유지하고, 표준 프로토콜 모델과 JSON Schema 검증만 SDK에 위임한다.

1. 도입 결론

이 프로젝트는 MCP Java SDK의 서버 Starter나 HTTP transport를 사용하지 않는다. 현재 /mcp endpoint는 Agent Builder와 합의한 동기 JSON, Mcp-Session-Id, protocol version HTTP 400, trace 계약을 이미 구현하고 있으므로 SDK transport를 함께 활성화하면 같은 endpoint에 두 프로토콜 처리 경로가 생길 수 있기 때문이다.

대신 실제 사용 모듈인 mcp-json-jackson2에 직접 의존한다. 이 모듈이 mcp-core를 전이 제공하므로 aggregate artifact를 별도로 선언하지 않는다. 적용 범위는 다음과 같다.

적용 영역 SDK 타입/기능 기존 코드에서의 사용 위치
MCP method 이름 McpSchema.METHOD_* handler와 protocol validator
JSON-RPC 버전과 표준 오류 번호 McpSchema.JSONRPC_VERSION, McpSchema.ErrorCodes request parser, response, error enum
initialize 결과 McpSchema.InitializeResult, Implementation, ServerCapabilities InitializeHandler
tools/list 결과 McpSchema.ListToolsResult, Tool ToolsListHandler
tools/call 결과 McpSchema.CallToolResult, TextContent ToolsCallHandler
Tool arguments schema 검증 DefaultJsonSchemaValidator ToolArgumentValidator

이 서버는 Spring AI API를 사용하지 않으므로 Spring AI BOM을 두지 않는다. MCP SDK 버전은 2.0.0으로 직접 고정한다. Starter를 추가하지 않았기 때문에 Spring AI MCP auto-configuration, 별도 /mcp mapping, SSE/Streamable transport bean은 생성되지 않는다.

2. 전체 요청 경계

Agent Builder
  -> 기존 McpExchangeFilter
     - 호출자 header 추출 (guid, request-id, session, 사원 식별자)
     - guid, x-request-id, MCP Session correlation
     - protocol version HTTP header 검증
     - HTTP/Tool 경계 trace log
  -> 기존 McpController
  -> 기존 JsonRpcRequestParser / McpMethodHandlerRegistry
  -> Handler
     - initialize: SDK InitializeResult 생성
     - tools/list: 기존 Registry metadata -> SDK Tool/ListToolsResult
     - tools/call: 기존 실행 결과 -> SDK CallToolResult/TextContent
  -> 기존 JsonRpcResponse envelope
  -> application/json 응답

Tool 실행 경로는 다음과 같다.

tools/call
  -> 기존 ToolsCallHandler params 검증
  -> 기존 ToolRegistryService
  -> 기존 basic contract + SDK JSON Schema 검증
  -> SDK JSON Schema 2020-12 검증
  -> 기존 ToolRoutingService / ToolClient
  -> 기존 timeout·correlation 처리 (MCP는 인증·인가하지 않음)

SDK 모델은 handler의 표준 MCP payload를 만드는 데만 사용한다. SDK server가 요청을 dispatch하거나 Tool Service를 호출하지 않는다.

3. SDK와 기존 소스의 책임 경계

SDK에 위임한 책임

  • 표준 MCP method 문자열과 JSON-RPC 상수
  • initialize, Tool definition, list result, call result의 표준 필드 구조
  • text content의 type: "text" 표현
  • JSON Schema 2020-12 기반 arguments 검증과 schema 컴파일 재사용
  • minLength, pattern, enum, additionalProperties, 중첩 객체 등 기존 기본 validator보다 넓은 schema keyword

기존 구현이 계속 소유하는 책임

  • /mcp HTTP mapping과 항상 application/json을 반환하는 transport 정책
  • Accept: application/json, text/event-stream 수용
  • Mcp-Session-Id 생성과 stateless correlation
  • MCP-Protocol-Version 누락·미지원 시 HTTP 400 처리
  • JSON-RPC parse/invalid request/invalid params의 현재 오류 envelope와 메시지
  • Tool Service 매니페스트 pull, Redis/memory fallback, local fixture
  • Tool endpoint/timeout/version 진단 정보와 dynamic metadata
  • 호출자 header 추출·검증과 Tool Service bypass 정책 (인증·인가는 하지 않음, ADR-0006)
  • guid·x-request-id 전파, 요청 context 정리, HTTP/Tool 경계 로그
  • Tool 선택 금지, exactly-one Tool 실행, outbound routing과 업무 오류 변환

4. 기존 계약 보존 방법

위험 회피 방식
SDK Starter가 기존 /mcp와 충돌 Starter를 사용하지 않고 core 모델과 Jackson 2 validator만 의존
SDK가 Tool 검증 실패를 isError=true로 바꿈 SDK server handler를 사용하지 않고 검증 실패를 기존 -32602 Invalid params로 변환
기존 required/type 오류 문구 변경 공개된 기본 검증을 SDK보다 먼저 실행해 기존 메시지를 그대로 유지
Mcp-Session-Id/protocol header 동작 변경 기존 filter, controller, validator를 유지
tools/call 결과 필드 위치 변경 직렬화 계약 테스트로 content[0]._meta.searchTimeisError를 고정
local tools/list 공개 필드 누락 SDK Tool 변환 전 _meta만 제거하고 title/outputSchema/annotations를 직렬화 비교
Registry의 기존 Tool에 inputSchema 누락 SDK 필수 조건을 만족하는 빈 object schema로 정규화
dynamic Registry를 annotation Tool로 고정 @McpTool을 사용하지 않고 요청마다 기존 Registry service를 조회
correlation·Trace 기능이 SDK 내부로 사라짐 transport와 실행 orchestration을 기존 코드에 유지
SDK 업그레이드로 wire payload 변경 SDK 버전을 명시하고 initialize/list/call golden serialization 테스트를 통과한 경우에만 변경

5. JSON Schema 검증 정책

SDK 검증은 ToolExecutionService가 Registry 기반 argument validation을 수행하는 위치에 연결했다. 검증 순서는 다음과 같다.

  1. 기존 object/required/basic type 검증으로 공개된 오류 문구를 보존한다.
  2. SDK JSON Schema validator로 나머지 2020-12 keyword를 검증한다.
  3. 실패하면 Tool Service를 호출하지 않고 기존 JsonRpcException(INVALID_PARAMS)으로 종료한다. SDK 원문 오류는 입력값을 포함할 수 있으므로 외부에는 arguments do not match inputSchema만 반환한다.

SDK validator는 Spring singleton으로 한 번 생성되며 동일 schema의 컴파일 결과를 재사용한다. Registry가 제공하는 schema 자체의 허용 dialect와 $ref 원격 해석 정책은 운영 Registry 계약으로 별도 통제해야 한다.

6. 의도적으로 도입하지 않은 SDK 기능

  • spring-ai-starter-mcp-server-webmvc
  • SDK sync/async/stateless server와 transport provider
  • SSE 또는 Streamable HTTP 응답
  • SDK authorization/security 구현
  • annotation 기반 정적 @McpTool 등록
  • SDK가 소유하는 Tool lifecycle, list-changed notification
  • Resources, Prompts, Sampling, Elicitation

이 기능들은 현재 요구사항을 해결하지 않거나 기존 계약과 중복된다. 실제 필요가 생기면 별도 ADR과 Agent Builder contract test를 먼저 추가한다.

7. 변경 및 검증 기준

SDK 버전을 올릴 때는 다음을 모두 확인한다.

  1. Spring Boot/Java/MCP Java SDK 조합의 dependency resolution
  2. SDK McpSchema 필드와 Jackson 2 직렬화 변경 여부
  3. initialize, tools/list, tools/call 성공·실패 JSON의 기존 예제 일치
  4. JSON-RPC 오류 code/message/data 및 HTTP status
  5. Accepttext/event-stream이 있어도 JSON 응답을 유지하는지
  6. Mcp-Session-Id, protocol version, guid, x-request-id 전파
  7. local profile, Registry 장애 fallback, Redis 비필수 동작
  8. .\gradlew.bat clean test

참고: