본문으로 건너뛰기
5분 AI.
GITHUB TRENDING JAVA WEEKLY #5 딥다이브 · 2026-10-23 분석

java-sdk 딥다이브
— AI와 자바 도구 사이, 통신의 약속을 코드로 만들기

SDK

빠른 판단

무엇
Java 앱에 MCP 클라이언트·서버의 도구 계약·비동기 처리·전송·JSON 검증을 제공하는 공식 SDK
이럴 때
사내 Java 함수를 에이전트 도구로 공개하거나 Java 프로그램에서 다른 MCP 서버의 기능을 호출할 때
AI가 회사의 검색·조회·계산 기능을 사용하려면, 누가 어떤 기능을 제공하고 어떤 형식으로 호출할지 약속해야 합니다. modelcontextprotocol/java-sdk는 그 약속인 MCP를 Java 클라이언트와 서버로 구현하는 공식 SDK입니다. 요청 ID, 비동기 처리, 전송 계층, JSON 검증을 따라가며 재사용 가능한 통신 라이브러리를 설계하는 법을 배웁니다. Java 302개 파일·약 74,000줄, 스타 3,736·포크 1,112·MIT. 수치는 2026-10-23 GitHub 기준, 코드 설명은 커밋 54e8b61 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

AI에게 자바의 기능을 빌려주는 표준 통신 부품

java-sdk는 Java 애플리케이션이 MCP 서버와 클라이언트가 되도록 만드는 라이브러리입니다. 서버는 “내가 제공하는 도구는 이것이고, 입력은 이런 JSON이다”라고 공개합니다. 클라이언트는 목록을 확인하고 도구를 호출한 뒤 결과를 받습니다. 이 저장소가 해결하는 문제는 모델의 지능이 아니라, 모델 주변 프로그램과 도구 사이의 일관된 통신입니다.

예를 들어 사내 재고 조회 함수를 lookup_stock이라는 MCP 도구로 등록할 수 있습니다. AI를 포함한 호스트 애플리케이션은 그 도구를 발견하고 {"sku":"BOOK-001"} 같은 인자를 보냅니다. Java 서버가 데이터베이스를 조회하는 코드는 개발자가 작성하고, SDK는 메시지의 해석·전송·응답 연결을 맡습니다. 모델 제공자의 추론 API 키나 모델 가중치가 SDK 자체에 필요한 것은 아닙니다.

용어 풀이
MCP · Model Context Protocol
AI 애플리케이션이 외부 기능과 정보를 이용하는 방법을 정한 통신 규격입니다. 규격이 대화의 문법이라면, SDK는 그 문법을 직접 구현하는 수고를 줄이는 코드 묶음입니다. JSON-RPC가 메시지의 봉투를 정하고, MCP가 그 안에 담을 도구·리소스·프롬프트와 수명주기를 정합니다.
한 문장 비유

AI 애플리케이션과 자바 서비스 사이에 놓는, 공통 주문서를 쓰는 접수 창구

식당마다 주문 방식이 다르면 손님이 매번 새 양식을 배워야 합니다. MCP는 “메뉴 보기”와 “메뉴 주문하기”의 양식을 맞춥니다. java-sdk는 자바로 그 접수 창구를 만들고 이용하는 데 필요한 부품입니다.

창구가 요리까지 대신하지는 않습니다. 재고 조회, 파일 읽기, 계산 등 실제 업무는 도구 핸들러가 수행합니다. 누가 어떤 메뉴를 주문해도 되는지도 애플리케이션이 결정해야 합니다.

1-1. 처음에는 세 가지 기능만 구분하자

MCP 기능쉬운 뜻과 예대표 메서드
Tool실행할 수 있는 기능. 재고 조회, 환율 계산, 문서 검색tools/list, tools/call
ResourceURI로 읽을 수 있는 정보. 안내문, 파일 내용, 상태 데이터resources/list, resources/read
Prompt서버가 제공하는 재사용 메시지 틀. 리뷰 요청문, 요약 지시문prompts/list, prompts/get

이 이름들은 mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java의 메서드 상수와 레코드에 대응합니다. 서버에서 클라이언트에 모델 생성을 요청하는 sampling, 사용자 추가 입력을 요청하는 elicitation도 있지만, 첫 학습에서는 도구 한 개의 목록 조회와 호출을 끝까지 추적하는 편이 좋습니다.

// 도구 호출의 메시지 모양: SDK가 이 봉투를 만들고 읽는다.
{
  "jsonrpc": "2.0",
  "id": "study-1",
  "method": "tools/call",
  "params": {
    "name": "lookup_stock",
    "arguments": { "sku": "BOOK-001" }
  }
}
학습의 중심
챗봇 화면보다, 통신을 성립시키는 내부를 읽는다

이 저장소에는 완성된 채팅 UI나 모델 학습 파이프라인이 없습니다. 대신 클라이언트·서버, 직렬화, 비동기 흐름, 테스트, 배포 모듈이 있습니다. 작은 도구 하나에서 출발해 범용 SDK가 갖춰야 할 경계를 배우기에 알맞습니다.

2왜 주목받는가

유행의 크기보다, 자바 개발자에게 생긴 연결 지점을 보자

2026-10-23 GitHub Trending Java Weekly #5에 오른 저장소입니다. 스타 3,736과 포크 1,112는 관심의 규모를 보여주지만, 특정 기능이 순위를 만들었다는 인과관계까지 설명하지는 않습니다. 아래 세 가지는 공식 설명·릴리스·소스 구조에서 읽을 수 있는 주목할 기술적 배경입니다.

2-1. 기존 Java 기능을 MCP로 공개하는 경로

공식 저장소 설명은 Spring AI와의 협력 유지보수를 명시합니다. Java로 작성한 업무 함수를 유지하면서 MCP 계약을 덧붙일 수 있다는 점이 실용적입니다. 모든 기능을 별도 언어로 옮기기보다, 이미 있는 서비스와 라이브러리를 재사용할 수 있습니다. 이는 도입 경로에 대한 해석이며, 이 저장소만으로 회사 시스템 연결이 자동 완성된다는 뜻은 아닙니다.

2-2. 통신의 세부까지 다루는 구현

공개 배포판의 변경 내역은 v2.1.0 릴리스 노트에서 볼 수 있습니다. 커밋 54e8b61에는 도구 목록 필터링, JDK HTTP 전송의 Publisher 기반 응답 처리, 조합 가능한 요청 커스터마이저가 구현되어 있습니다. STDIO 출력 쓰기의 동기화, Streamable HTTP 세션 정리와 keep-alive도 살펴볼 수 있습니다. 초보자에게는 기능 목록보다 동시 실행·연결 종료·오류 응답 같은 세부가 SDK 품질을 좌우한다는 사례입니다.

이 SDK의 장점은 도구를 등록하는 편의 API와, 통신 구현을 교체할 수 있는 경계를 함께 제공한다는 점입니다. 편리한 McpServer.sync(...)로 시작하더라도, 아래에는 독립된 전송·JSON 인터페이스가 있습니다.

2-3. 비교할 때는 “어느 층을 맡는가”부터

선택지잘 맞는 상황java-sdk와 비교할 점
직접 만든 REST API고정된 클라이언트에 업무 API를 제공REST 자체가 MCP의 도구 발견·capabilities·메시지 계약을 구현하지는 않음. 범위가 좁으면 직접 API가 더 단순할 수 있음
직접 만든 JSON-RPC프로토콜 구현을 통제하거나 학습요청 ID, 오류, 초기화, 전송별 차이, 적합성 검증을 직접 책임져야 함
다른 언어의 MCP SDK그 언어로 이미 서비스를 운영프로토콜은 같아도 호스트 언어와 생태계가 다름. Java 코드·JDK HttpClient를 재사용하는 것이 이 SDK의 이점
Spring AI MCPSpring Boot 설정·starter·보안 통합이 필요README 기준으로 이 SDK를 확장하는 상위 통합. 경쟁 관계만으로 보기 어려움
java-sdk 직접 사용Spring 없이 쓰거나 내부 통신 구조를 학습기본 STDIO·JDK HTTP·Servlet 전송을 제공. 서버 실행 환경과 업무 권한 정책은 따로 구성
비유

java-sdk는 통신 부품 상자, Spring AI는 그 부품을 Spring 애플리케이션에 설치하는 조립 장치에 가깝습니다. 어느 쪽이 항상 우월한지보다, 이미 사용하는 실행 환경과 필요한 제어 범위로 선택하면 됩니다.

2-4. 별 개수와 프로토콜 완성도는 따로 읽는다

conformance-tests/VALIDATION_RESULTS.md는 2026-10-02 검증 결과와 알려진 실패를 함께 기록합니다. 이런 문서는 표준 SDK를 평가할 때 중요한 단서입니다. “공식”이라는 이름만으로 모든 규격·전송·실패 복구가 완전하다고 가정하지 않고, 어떤 조건을 검증했는지 확인하는 습관을 배울 수 있습니다.

3기술 스택 전체 지도

버전은 배포판 추정치가 아니라 커밋 54e8b61의 의존성 선언 기준

루트 pom.xml은 io.modelcontextprotocol.sdk:mcp-parent:2.2.0-SNAPSHOT을 선언합니다. 반면 최신 공개 릴리스는 2026-10-16의 v2.1.0입니다. 배포판을 사용하는 방법과 개발 브랜치의 구현을 읽는 방법은 버전 기준을 분리해야 합니다. 아래 의존성 버전을 v2.1.0의 구성으로 그대로 옮기면 안 됩니다.

3-1. 백엔드·통신·데이터 표현

기술실제 선언맡는 역할과 근거
Java컴파일 기준 17루트 POM의 java.version, compiler의 release. 레코드와 제네릭으로 메시지 모델링
Project ReactorBOM 2026.0.0-RC1루트 dependencyManagement. mcp-core/pom.xml의 reactor-core는 개별 버전을 쓰지 않음
Jackson 33.1.8mcp-json-jackson3/pom.xml의 tools.jackson.core:jackson-databind. 기본 편의 모듈이 선택
Jackson 22.22.4mcp-json-jackson2/pom.xml의 com.fasterxml.jackson.core:jackson-databind. 대체 구현
Jackson annotations2.22mcp-core의 직접 의존성. JSON 바인딩을 추상화해도 스키마 어노테이션 의존성은 존재
JSON Schema 검증2.0.8 / 3.0.8각 JSON 모듈의 com.networknt:json-schema-validator. Jackson 2 / 3에 맞춰 분리
JDK HttpClientJDK 내장 APImcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java. 별도 HTTP 클라이언트 라이브러리 없이 원격 통신
Jakarta Servlet6.1.0mcp-core/pom.xml의 provided 의존성. 실제 컨테이너는 실행 애플리케이션 측이 제공
SLF4J2.0.20로그 API. Logback 1.6.5는 core에서 테스트 범위이며 운영 로그 백엔드는 별도 선택
용어 풀이
BOM · scope · SNAPSHOT
BOM은 함께 쓸 의존성 버전을 맞추는 명세입니다. scope=test는 테스트용, scope=provided는 실행 환경이 공급한다는 뜻입니다. SNAPSHOT은 계속 바뀔 수 있는 개발 버전입니다. Reactor의 개별 버전은 BOM이 관리하며, 표의 값은 reactor-core 버전이 아니라 BOM 버전입니다.

3-2. 프론트엔드와 외부 Spring 통합

제품용 프론트엔드 앱은 없습니다. 추적 파일에 package.json, React·Vue 코드, 프론트엔드 빌드 설정이 보이지 않습니다. 문서 사이트는 mkdocs.yml의 Material 테마와 Markdown으로 구성됩니다. .github/workflows/docs.yml은 Python 3.x에서 mkdocs-material과 mike를 설치하지만, 두 패키지의 버전은 고정하지 않습니다. 문서 도구가 런타임 Java 의존성인 것은 아닙니다.

Spring은 core의 필수 웹 프레임워크가 아닙니다. conformance-tests/client-spring-http-client/pom.xml은 Spring Boot 4.1.2, Spring AI 2.0.2, MCP 보안 통합 0.1.14를 선언합니다. 이 값은 Spring 인증 검증 애플리케이션의 구성입니다. README는 WebClient·WebFlux·WebMVC 통합을 Spring AI 2.0+의 영역으로 안내합니다.

3-3. 인프라·빌드·검증

도구버전·설정배울 점
Maven WrapperMaven 3.9.16, wrapper 3.3.4.mvn/wrapper/maven-wrapper.properties로 빌드 도구 버전을 맞춤
컴파일·테스트 플러그인compiler 3.16.0, surefire 3.6.0루트 POM에서 공통 실행 정책을 관리
코드 포맷spring-javaformat 0.0.48validate 단계에 연결. 테스트 전에 서식 오류로 빌드가 멈출 수 있음
단위 검증JUnit 6.1.3, AssertJ 3.27.7, Mockito 5.24.0결과 검증과 가짜 의존성으로 조건 분리
통합 검증Testcontainers 2.0.5, Tomcat 11.0.27컨테이너·실제 Servlet 전송을 쓰는 테스트 구성
GitHub Actionsubuntu-latest, Temurin 17.github/workflows/ci.yml의 기본 검증 및 Jackson 2 별도 작업
MCP 적합성 도구0.2.0-alpha.12, Node.js 22.github/workflows/conformance.yml의 일반 서버·클라이언트 작업. 인증 작업은 별도 action 설정

추적 파일에는 Dockerfile이나 Kubernetes 배포 명세가 없습니다. Docker는 README가 안내하는 전체 테스트 준비물이지, SDK를 사용하는 모든 Java 프로세스의 필수 런타임은 아닙니다. 데이터베이스나 벡터 저장소도 SDK의 필수 구성요소가 아닙니다.

3-4. 의존성 한 줄 뒤에는 무엇이 따라올까

<!-- Maven 의존성 예: 공개 배포판 2.1.0 사용 -->
<dependency>
  <groupId>io.modelcontextprotocol.sdk</groupId>
  <artifactId>mcp</artifactId>
  <version>2.1.0</version>
</dependency>

mcp/pom.xml은 mcp-core와 mcp-json-jackson3를 묶습니다. 커밋 기준 packaging은 jar이며 mcp/src/main/java/module-info.java도 있습니다. 업무 기능을 잔뜩 넣은 앱이라기보다, 기본 선택을 전달하는 편의 모듈입니다. 버전을 일괄 관리하려면 mcp-bom을 사용합니다.

소스 읽기 요령
의존성이 존재한다는 것과 항상 실행된다는 것은 다르다

Servlet은 제공 범위, Logback은 core의 테스트 범위, Spring은 별도 검증 모듈에 있습니다. POM의 버전만 수집하지 말고 모듈과 scope까지 읽어야 실제 설치 부담과 책임을 구분할 수 있습니다.

4아키텍처 심화 분석

호출 하나를 따라가며 네 가지 설계 패턴을 읽는다

4-1. 전체 시스템 구조

아래는 io.modelcontextprotocol.client와 io.modelcontextprotocol.server의 기존 API 경로입니다. 모델과 도구 선택을 담당하는 호스트는 SDK 바깥에 있고, Java SDK의 클라이언트는 그 호스트 안에서 통신을 맡을 수 있습니다. 표준 입출력과 HTTP는 같은 기능 호출을 서로 다른 통로로 전달합니다.

[호스트 애플리케이션: 모델 연결·도구 선택·사용자 승인] | McpSyncClient 동기 API | McpAsyncClient 비동기 API | LifecycleInitializer 초기화·버전·기능 확인 | McpClientSession 요청 ID와 응답 연결 | +-----------------+------------------+ | | StdioClientTransport HttpClientStreamableHttpTransport | 자식 프로세스의 파이프 | HTTP / SSE 응답 v v StdioServerTransportProvider Servlet 전송 Provider + 컨테이너 | | +-----------------+------------------+ | McpServerSession / McpStreamableServerSession | McpAsyncServer | toolsCallRequestHandler() | ToolInputValidator | 등록된 callHandler() 실행 | [검색·조회·계산 등 업무 코드] JSON 바인딩: McpJsonMapper <-- Jackson 2 또는 Jackson 3 모델·DB·웹 UI·업무별 권한 정책: 사용하는 애플리케이션의 책임

핵심 구현은 mcp-core/src/main/java/io/modelcontextprotocol/ 아래에 있습니다. 다이어그램의 클래스는 그 아래 client/, spec/, server/에서 찾을 수 있습니다. 전송별 세션 구현은 다르므로, 모든 경로가 정확히 같은 서버 세션 클래스를 거친다고 읽으면 안 됩니다.

4-2. 패턴 ① Facade — 쉬운 동기 API를 비동기 코어 위에

mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java의 callTool()은 별도의 통신 엔진을 만들지 않습니다. McpAsyncClient인 delegate에 호출을 넘기고, 반환된 Mono에서 결과를 기다립니다.

// McpSyncClient.callTool()의 실제 위임 구조
public McpSchema.CallToolResult callTool(
        McpSchema.CallToolRequest callToolRequest) {
    return withProvidedContext(
        this.delegate.callTool(callToolRequest)
    ).block();
}
용어 풀이
Facade · Mono · block()
Facade는 복잡한 내부 앞에 놓는 간단한 사용 창구입니다. Mono<T>는 나중에 결과 하나 또는 완료·오류를 전달하는 비동기 흐름입니다. block()은 호출한 스레드를 기다리게 하므로, 비동기 이벤트 처리 스레드에서 무심코 사용하면 안 됩니다.

서버 방향에도 같은 경계가 있습니다. mcp-core/src/main/java/io/modelcontextprotocol/server/McpServerFeatures.java의 AsyncToolSpecification.fromSync()는 동기 핸들러를 Mono.fromCallable()로 감싸며, 일반 경로에서는 Schedulers.boundedElastic()에 실행을 맡깁니다. immediate 옵션이 참인 경로는 스케줄러 전환을 생략합니다. “동기 API를 지원한다”는 말 뒤에 실행 스레드 선택까지 있다는 점이 학습 포인트입니다.

4-3. 패턴 ② Strategy와 Adapter — 업무와 전송·JSON 구현을 분리

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpTransport.java는 sendMessage(), closeGracefully(), unmarshalFrom() 같은 계약을 정의합니다. StdioClientTransport.connect()는 ProcessBuilder로 서버 프로세스를 시작하고, HTTP 구현은 JDK HttpClient를 사용합니다. 호출자는 “도구를 실행한다”는 의도를 유지하면서 전송 전략을 바꿀 수 있습니다.

JSON 쪽에서는 mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java가 readValue(), convertValue(), writeValueAsString() 등을 정의합니다. mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/jackson3/JacksonMcpJsonMapper.java는 Jackson의 JsonMapper 호출을 이 인터페이스에 맞추는 Adapter입니다.

업무·프로토콜 코드 | v McpJsonMapper SDK가 정한 계약 ^ | JacksonMcpJsonMapper Jackson API를 계약에 맞게 감쌈 | v tools.jackson.databind.json.JsonMapper

기본 구현은 McpJsonDefaults.getMapper()에서 가져옵니다. 내부의 McpServiceLoader.getDefault()는 일반 Java 환경에서 ServiceLoader.load(...).findFirst()로 공급자를 찾고 결과를 저장합니다. Jackson 3 공급자 이름은 mcp-json-jackson3/src/main/resources/META-INF/services/io.modelcontextprotocol.json.McpJsonMapperSupplier에 적혀 있습니다.

비유

가전제품은 콘센트 규격만 알고, 벽 안의 발전 방식을 몰라도 됩니다. 인터페이스가 콘센트라면 Jackson 구현은 어댑터입니다. 다만 이 코드의 기본 탐색은 첫 공급자를 고르므로, 여러 구현을 동시에 넣을 때 선택 순서를 당연하게 가정하면 안 됩니다.

4-4. 패턴 ③ 요청 상관관계와 초기화 게이트 — 동시에 보내도 응답을 찾기

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java의 generateRequestId()는 세션 접두어와 AtomicLong 카운터를 합쳐 ID를 만듭니다. sendRequest()는 그 ID를 키로 pendingResponses에 응답 대기자를 저장합니다. handle()에 응답이 들어오면 같은 ID의 대기자를 꺼내 완료합니다.

발신 순서: A(id="abcd1234-7") -----------> 서버 B(id="abcd1234-8") -----------> 서버 도착 순서: B 응답 ------> pendingResponses.remove("abcd1234-8") A 응답 ------> pendingResponses.remove("abcd1234-7") 도착 순서가 바뀌어도 ID로 원래 요청과 연결한다. Notification은 응답을 기다리는 요청과 별도로 처리한다.

자료구조는 ConcurrentHashMap<Object, MonoSink<McpSchema.JSONRPCResponse>>입니다. 이 구조에서 “동시성”은 단순히 스레드를 많이 만드는 문제가 아니라, 어느 응답이 누구의 결과인지 안전하게 연결하는 문제라는 사실이 드러납니다. sendRequest()의 timeout(requestTimeout)은 응답을 무한정 기다리지 않게 합니다.

메시지를 보내기 전에는 LifecycleInitializer.withInitialization()가 관문 역할을 합니다. AtomicReference.compareAndExchange()로 첫 초기화 작업을 정하고, 동시에 들어온 호출은 기존 초기화 결과를 기다립니다. doInitialize()는 initialize 요청, 버전 검사, notifications/initialized 통지를 수행합니다.

McpAsyncClient.callTool()은 이 관문 안에서 서버의 tools capability를 확인한 뒤 요청을 보냅니다. 명시적으로 initialize()를 호출해 흐름을 배울 수도 있지만, 소스에는 일반 작업 시 초기화를 보장하는 경로도 있습니다. 기존 API의 이 초기화 절차를 뒤에서 설명할 modern 서버에 그대로 적용해서는 안 됩니다.

4-5. 패턴 ④ Observer — 목록 변경을 기다리는 쪽에 알리기

분석 대상 커밋의 제목은 “Notify resources list_changed when removing a resource template (#1266)”입니다. 현재 McpAsyncServer.removeResourceTemplate()를 읽으면 실제 템플릿이 제거되고 resources.listChanged가 참일 때 notifyResourcesListChanged()로 이어집니다. 아래는 조건을 드러내기 위해 축약한 흐름입니다.

// removeResourceTemplate(): 조건 흐름을 보이기 위한 축약
return Mono.defer(() -> {
    var removed = this.resourceTemplates.remove(uriTemplate);
    if (removed != null
            && Boolean.TRUE.equals(
                this.serverCapabilities.resources().listChanged())) {
        return notifyResourcesListChanged();
    }
    return Mono.empty();
});

통지 메서드는 전송 Provider의 notifyClients()에 notifications/resources/list_changed를 전달합니다. 템플릿이 없거나 resources.listChanged가 true가 아니면 알리지 않습니다. resources capability 자체가 없으면 삭제 요청은 IllegalStateException으로 실패합니다. 자원 내용 변경 알림인 notifications/resources/updated와도 구분해야 합니다.

서버의 자료구조를 바꾸는 일과, 클라이언트가 가진 목록을 갱신하게 만드는 일은 별개의 책임입니다. 이 짧은 메서드 하나로 캐시·관찰자·기능 협상이 만나는 지점을 공부할 수 있습니다.

4-6. 같은 저장소의 다른 경로: modern 서버

mcp-core/src/main/java/io/modelcontextprotocol/modern/McpSchema.java는 LATEST_PROTOCOL_VERSION = "2026-07-28"을 선언합니다. mcp-core/src/main/java/io/modelcontextprotocol/modern/server/McpServer.java는 요청마다 _meta의 버전과 capabilities를 검사하고, dispatch()에서 해당 McpFeature로 보냅니다. ToolsFeature.handle()는 repository의 list(), find(), call()을 사용합니다.

이 경로는 stateless 수명주기와 server/discover를 다룹니다. 기존 패키지의 McpServer와 클래스 이름이 같아도 계약이 다르므로 import를 확인해야 합니다. ROADMAP.md는 이 규격 지원을 3.x 계획으로 설명하지만, 현재 POM은 2.2.0-SNAPSHOT입니다. 코드가 존재한다는 사실과 안정된 배포 API로 약속되었다는 사실을 구분하는 사례입니다.

API 해석 주의
Reactive Streams를 목표로 한다고 해서 모든 공개 API가 Publisher만 쓰는 것은 아니다

README는 공개 API를 Reactive Streams 인터페이스 중심으로 바꿀 계획을 설명합니다. 그러나 현재 McpAsyncClient.callTool()과 McpTransport.sendMessage()의 반환형은 Mono입니다. HTTP 내부에서 Publisher를 사용한다는 사실을 SDK 전체의 Reactor 의존성 제거로 해석하면 안 됩니다.

5디렉토리 구조 해부

폴더 이름을 외우기보다, 변경의 책임이 어디에 모이는지 본다
java-sdk/ ├── pom.xml 부모 POM·공통 버전·빌드 정책 ├── mcp-bom/ SDK 모듈 버전 정렬 ├── mcp/ core + Jackson 3 편의 모듈 ├── mcp-core/ │ └── src/ │ ├── main/java/io/modelcontextprotocol/ │ │ ├── client/ 동기·비동기 클라이언트와 전송 │ │ ├── server/ 기존 서버 API와 Servlet·STDIO 전송 │ │ ├── spec/ 기존 규격 모델·세션·전송 계약 │ │ ├── modern/ 2026-07-28 규격의 모델·서버 경로 │ │ ├── json/ JSON·JSON Schema 인터페이스 │ │ ├── common/ 전송 컨텍스트 │ │ └── util/ 검증·URI template·서비스 탐색 │ └── test/java/ core의 단위·회귀 테스트 ├── mcp-json-jackson2/ Jackson 2 바인딩·검증 구현 ├── mcp-json-jackson3/ Jackson 3 바인딩·검증 구현 ├── mcp-test/ 공용 테스트 부품·통합 테스트 ├── conformance-tests/ │ ├── server-servlet/ 기존 규격 서버 검증 앱 │ ├── server-servlet-modern/ modern 규격 서버 검증 앱 │ ├── client-jdk-http-client/ JDK 클라이언트 검증 앱 │ ├── client-spring-http-client/ 인증 검증 앱 │ └── VALIDATION_RESULTS.md 검증 조건·결과·한계 ├── docs/ 문서와 예제 설명 ├── .github/workflows/ CI·적합성·문서·배포 자동화 ├── .mvn/wrapper/ Maven 배포판 고정 └── MIGRATION-2.0.md API·메시지 형식의 변경 안내

5-1. 왜 JSON 구현을 core에서 떼었을까

mcp-json-jackson3가 core에 의존해야 SDK 인터페이스를 구현할 수 있습니다. 그런데 core 테스트가 다시 Jackson 3 모듈에 의존하면 모듈 간 순환이 생깁니다. README는 JSON 구현이 필요한 통합 테스트를 mcp-test로 옮긴 이유를 이 의존 관계로 설명합니다. 테스트 폴더 배치는 실행 속도뿐 아니라 모듈 의존 방향의 결과이기도 합니다.

궁금한 문제처음 열 파일이어 볼 곳
동기 호출은 어떻게 동작할까mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.javaMcpAsyncClient.callTool()
응답이 뒤섞이면 어떻게 찾을까mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.javasendRequest()와 handle()
도구 인자가 틀리면 어떻게 될까mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.javamcp-core/src/main/java/io/modelcontextprotocol/util/ToolInputValidator.java
JSON 구현은 누가 선택할까mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonDefaults.javamcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java와 공급자 등록 파일
새 규격의 요청 처리는 어떨까mcp-core/src/main/java/io/modelcontextprotocol/modern/server/McpServer.javamcp-core/src/main/java/io/modelcontextprotocol/modern/server/feature/ToolsFeature.java

표의 소스 파일은 모두 mcp-core/src/main/java/io/modelcontextprotocol/ 아래입니다. 처음부터 6,000줄이 넘는 스키마 파일을 정독하기보다, 호출 지점에서 필요한 레코드로 이동하는 편이 이해하기 쉽습니다.

5-2. 코드 규모는 무엇을 포함하는가

분류파일 수·물리적 줄 수해석
Java 전체302개 · 74,017줄SDK·검증 앱·테스트·공용 테스트 부품 포함
Java main 경로173개 · 44,647줄운영 코드 외에 conformance 앱과 테스트 지원 main 코드도 포함
Java test 경로129개 · 29,370줄전체 Java 물리적 줄 수의 약 40%
core 운영 경로142개 · 35,282줄mcp-core/src/main/java만 집계
XML / YAML22개 · 1,662줄 / 10개 · 561줄POM·서비스 설정·워크플로·문서 설정
Markdown29개 · 4,548줄문서·가이드·검증 결과·정책

집계 기준은 커밋의 추적 파일이며, 빈 줄과 주석, 마지막 개행이 없는 줄까지 포함한 물리적 줄 수입니다. 생성된 target/ 출력이나 Git 내부 파일은 포함하지 않습니다. 따라서 74,017줄을 전부 업무 로직이라고 해석하거나, 테스트 줄 수를 기능 커버리지 비율로 바꿔 말할 수는 없습니다.

6학습 포인트 (기술별)

도구 하나를 만들면서 Java·JSON·비동기·HTTP를 함께 배운다

6-1. Java 레코드와 Builder: 올바른 객체를 만드는 경계

McpSchema.CallToolRequest는 name, arguments, meta를 가진 레코드입니다. builder(String name)은 빈 이름을 막지만, JSON을 읽는 fromJson()은 누락된 이름을 빈 문자열로 보정하고 경고합니다. “직접 생성할 때의 검증”과 “외부 메시지를 받아들일 때의 호환성 처리”가 같은 규칙은 아닙니다.

// 기존 spec 패키지의 요청 객체를 만드는 학습용 예
var request = McpSchema.CallToolRequest.builder("hello")
    .arguments(Map.of("name", "민수"))
    .build();

// arguments()는 Map<String, Object>를 돌려준다.
Object name = request.arguments().get("name");

작은 실습: builder(""), 직접 생성, 이름이 빠진 JSON 역직렬화를 각각 비교해 보세요. 어느 층에서 예외가 나고, 어느 층에서 보정되는지 표로 정리하면 MIGRATION-2.0.md가 설명하는 required-first Builder와 wire 호환성의 의미가 보입니다.

6-2. JSON Schema: 설명과 실행 조건을 같은 계약으로

Tool.inputSchema의 타입은 좁은 전용 레코드가 아닌 Map<String, Object>입니다. JSON Schema 키워드를 보존하기 위한 선택입니다. 다음 예시는 이름 문자열 하나를 받는 도구를 구성하는 메서드 안의 코드이며, 웹 서버 실행 전체를 포함하지 않습니다.

import java.util.List;
import java.util.Map;
import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;

// 아래 구문은 애플리케이션의 서버 구성 메서드 안에 둔다.
Map<String, Object> inputSchema = Map.of(
    "type", "object",
    "properties", Map.of(
        "name", Map.of("type", "string", "minLength", 1)),
    "required", List.of("name"),
    "additionalProperties", false
);

var hello = McpServerFeatures.SyncToolSpecification.builder()
    .tool(McpSchema.Tool.builder("hello", inputSchema)
        .description("이름을 받아 한국어 인사말을 반환합니다.")
        .build())
    .callHandler((exchange, request) -> {
        String name = (String) request.arguments().get("name");
        return McpSchema.CallToolResult.builder()
            .content(List.of(McpSchema.TextContent
                .builder("안녕하세요, " + name + "님!").build()))
            .isError(false)
            .build();
    })
    .build();

var transport = new StdioServerTransportProvider(
    McpJsonDefaults.getMapper());
var server = McpServer.sync(transport)
    .serverInfo("study-server", "1.0.0")
    .capabilities(McpSchema.ServerCapabilities.builder()
        .tools(false).build())
    .tools(hello)
    .build();

tools(false)의 false는 도구 기능을 끈다는 뜻이 아닙니다. tools capability를 만들되 목록 변경 알림을 선언하지 않는 값입니다. 서버 구성의 validateToolInputs 기본값은 true이며, ToolInputValidator.validate()가 핸들러 실행 전에 인자를 검사합니다. 검증이 비활성화되었거나 입력 스키마가 비어 있거나 검증기가 없으면 검사를 건너뜁니다. 서버의 종료는 애플리케이션 수명주기에 server.closeGracefully()를 연결해 처리해야 합니다.

작은 실습: 빈 이름, 숫자 이름, 추가 필드, 이름 누락을 각각 보내 보세요. 현재 검증 경로는 잘못된 입력을 CallToolResult의 isError=true로 돌려줍니다. 존재하지 않는 도구 이름의 JSON-RPC 오류와 구분하면 프로토콜 오류와 업무 결과 오류를 함께 배울 수 있습니다.

6-3. Reactor: 호출 표현과 실제 작업 시작 시점

Mono를 반환받았다는 사실만으로 그 작업이 끝난 것은 아닙니다. Mono.defer()는 구독 시점에 작업을 구성합니다. McpAsyncServer.removeResourceTemplate()가 그 안에서 Map을 수정하는 이유를 살펴보세요. 다만 이 SDK 내부에는 생성 시 연결을 구독하는 코드도 있으므로, “모든 동작이 항상 지연된다”고 일반화하면 안 됩니다.

// 비동기 호출을 연결하는 예: 완료·오류도 흐름의 일부다.
asyncClient.callTool(request)
    .map(result -> result.isError())
    .subscribe(
        isError -> logger.info("도구 오류 여부: {}", isError),
        error -> logger.error("통신 실패", error)
    );

작은 실습: mock 전송으로 응답을 늦추고 타임아웃을 짧게 설정해 결과를 관찰하세요. McpClient.SyncSpec와 AsyncSpec의 요청·초기화 제한 시간은 각각 기본 20초입니다. 타임아웃은 대기 정책이며, 이미 수행된 외부 작업을 되돌리는 트랜잭션은 아닙니다.

6-4. 페이지네이션: 첫 페이지와 전체 목록을 구분

McpAsyncClient.listTools()는 expand()로 nextCursor를 따라가고 reduceWith()로 도구를 모읍니다. 반면 listTools(String cursor)는 지정한 페이지를 조회합니다. 목록이 크면 전체를 한 번에 모으는 편의성과 메모리 사용 사이의 선택이 생깁니다.

작은 실습: 두 페이지를 반환하는 mock 서버를 만들고 두 메서드의 요청 횟수를 비교하세요. 잘못된 서버가 같은 커서를 반복할 때를 별도 실패 사례로 설계해 보는 것도 좋습니다.

6-5. HTTP와 STDIO: 메시지 내용 바깥의 조건

HttpServletStreamableServerTransportProvider.doPost()는 요청 크기, 헤더, Content-Type 등을 먼저 확인합니다. Accept에 application/json과 text/event-stream이 필요한 경로도 있습니다. JSON 문법이 맞더라도 전송 계층에서 거절될 수 있습니다.

STDIO에서는 System.out이 프로토콜 메시지 통로입니다. 학습 중 진단 문자열을 임의로 출력하면 상대가 JSON으로 읽지 못할 수 있습니다. 로그를 stderr 쪽으로 보내도록 구성하고, UTF-8 메시지가 여러 바이트 조각으로 나뉘는 경우도 살펴보세요.

6-6. 테스트 설계: 성공보다 경계를 자세히

mcp-core/src/test/java/io/modelcontextprotocol/util/ToolInputValidatorTests.java는 검증기 부재·비활성화·잘못된 입력·null 인자를 나눕니다. mcp-core/src/test/java/io/modelcontextprotocol/client/transport/Utf8LineDecoderBoundTests.java는 바이트 수가 아닌 디코딩된 문자 수에 따른 줄 길이 경계를, mcp-test/src/test/java/io/modelcontextprotocol/server/DerivedCapabilitiesRuntimeChangesTests.java는 자동으로 파생된 capabilities의 목록 변경 알림 값이 null인 상태에서 런타임 변경을 다룹니다.

통신 라이브러리에서 배울 핵심은 성공 예제보다, 입력·상태·시간·종료 경계를 나누어 검증하는 방법입니다. 작은 실습: 테스트 하나를 읽고 “이 테스트가 없으면 어떤 사용자 문제가 생기는가”를 한 문장으로 적어 보세요.

7하드웨어 / 시스템 요구사항

필수 조건은 소스에서, 용량 가이드는 학습 환경의 추정으로

SDK 자체는 GPU 계산을 하지 않습니다. 모델을 별도로 실행하거나 이미지·오디오를 처리하는 도구를 붙이면 그 기능의 요구사항이 더해집니다. 실행 부담은 MCP 라이브러리보다 연결한 도구와 모델, 동시 요청 수에 더 크게 좌우됩니다.

상황필요한 소프트웨어하드웨어 판단
소스 읽기텍스트 편집기 또는 Java IDE일반 개발용 PC. 빌드·Docker·GPU 불필요
작은 STDIO 도구기준 Java 17+, JSON 구현 모듈단순 텍스트 도구라면 보통 CPU 환경으로 시작 가능. 공식 최소 RAM 수치는 없음
HTTP 서버Servlet 6.1 API에 맞는 컨테이너 또는 외부 Spring 통합동시 연결·스트림·도구 응답 크기를 기준으로 측정
소스 빌드JDK 17, Wrapper의 Maven 3.9.16의존성 캐시·컴파일 출력 공간 필요. 첫 다운로드에는 네트워크 필요
전체 테스트README 기준 Docker·npx, CI의 적합성 작업은 Node.js 22컨테이너와 다중 JVM을 고려해 여유 확보

학습용 권장 출발점: 2~4코어 CPU, RAM 8GB 이상, 남은 디스크 수 GB를 잡을 수 있습니다. IDE와 Docker를 함께 사용하면 RAM 16GB가 더 여유롭습니다. 이는 공식 보장 사양이나 실측 결과가 아닌 일반 개발 환경을 위한 추정입니다. 큰 모델 가중치 저장 공간은 이 SDK의 크기와 별도로 계산해야 합니다.

7-1. HTTP 서버의 실제 실행 환경

Servlet 전송 객체를 만들었다고 포트가 열리지는 않습니다. conformance-tests/server-servlet/src/main/java/io/modelcontextprotocol/conformance/server/ConformanceServlet.java의 main()은 전송 Provider를 만든 뒤 Tomcat에 Servlet을 등록하고 서버를 시작합니다. 그 검증 앱은 8080 포트와 /mcp 경로를 사용합니다. 이 값은 SDK 전체에 강제되는 포트가 아닙니다.

7-2. 연결을 오래 유지할 때 필요한 관찰 지표

기존 Streamable HTTP 서버 Builder의 기본값은 mcpEndpoint="/mcp", keepAliveInterval=30분, sessionSweepInterval=30분입니다. 열린 스트림이 있는 세션의 keep-alive와, 열린 스트림도 최근 요청도 없는 세션의 정리는 다른 목적입니다. 지연 시간뿐 아니라 열린 연결 수, 메모리, 타임아웃, 종료 후 남는 프로세스를 관찰해야 합니다.

시스템 경계
기본 HTTP 헤더 검증과 업무 권한 검사는 구분한다

기존 Servlet 전송 Builder는 ServerHttpHeaderValidator.NOOP를 기본으로 둡니다. Origin·Host 검증이 필요하면 명시적으로 구성해야 합니다. 이 검증은 사용자 인증이나 “어떤 재고를 조회할 수 있는가”라는 업무 권한 정책을 대신하지 않습니다.

STDIO 도구도 실행한 사용자 권한을 자동으로 제한하지 않습니다. 학습 도구는 먼저 정해진 문자열·메모리 데이터로 구성하면 통신 구조를 이해하기 쉽습니다.

8직접 해볼 수 있는 실습 과제

정상 호출 하나에서 출발해 실패와 상태 변경까지 넓힌다

실습용 앱은 SDK 소스와 별도 프로젝트로 구성하고, 공개 배포판을 쓸 때는 의존성을 2.1.0으로 고정하세요. 아래 소스 탐색과 회귀 조건은 커밋 54e8b61 기준입니다. modern API까지 실험하려면 그 코드가 포함된 버전과 별도의 프로토콜 계약을 먼저 확인해야 합니다.

과제 1

인사 도구 하나를 발견하고 호출하기 입문 · 1~2시간

만들 것: 6절의 hello 도구를 STDIO 서버에 등록합니다. 클라이언트는 ServerParameters로 Java 실행 명령을 정하고 StdioClientTransport로 연결합니다. McpClient.sync(transport).build()로 생성한 뒤 초기화·목록 조회·호출 순서를 관찰합니다.

완료 조건: 목록에 hello가 나타나고, 이름을 보내면 인사말이 반환됩니다. 서버 stdout에는 임의 로그가 없어야 하며, 클라이언트 종료 후 자식 프로세스 정리도 확인합니다.

읽을 곳: StdioClientTransport.connect(), McpSyncClient.listTools(), callTool(). 배울 것: 메서드 호출과 프로세스 간 메시지 교환의 연결.

과제 2

틀린 입력 네 가지와 오류 두 종류 입문 · 1~2시간

만들 것: 정상 이름, 누락, 숫자, 빈 문자열, 추가 필드를 보내는 표를 작성합니다. 각 경우의 isError, 메시지, 핸들러 실행 여부를 기록합니다. 없는 도구 이름도 한 번 호출해 JSON-RPC 오류와 비교합니다.

완료 조건: 잘못된 인자가 핸들러에 도달하지 않는지 확인하고, required와 minLength, additionalProperties가 각각 막는 입력을 설명할 수 있어야 합니다.

읽을 곳: McpAsyncServer.toolsCallRequestHandler(), ToolInputValidator.validate(). 배울 것: JSON 구문 검증, 스키마 검증, 업무 검증을 분리하는 법.

과제 3

전송을 HTTP로 바꾸고 같은 도구 호출하기 중급 · 반나절

만들 것: 업무 핸들러를 유지하고 서버 전송을 Servlet Streamable HTTP로 교체합니다. Servlet 등록과 컨테이너 시작은 ConformanceServlet.main()의 구성을 참고합니다. 클라이언트는 아래와 같이 JDK HTTP 전송을 선택합니다.

완료 조건: 도구의 입력·출력은 같고, 두 전송의 설정·프로세스 구성·종료 방식은 표로 비교됩니다. 잘못된 Content-Type 요청과 정상 JSON-RPC 요청도 구분해서 관찰합니다.

배울 것: 인터페이스가 같아도 배포와 네트워크 조건은 달라진다는 점.

// HTTP 실습 앱 안의 클라이언트 구성: 기존 client/spec API
var transport = HttpClientStreamableHttpTransport
    .builder("http://localhost:8080")
    .endpoint("/mcp")
    .build();

try (var client = McpClient.sync(transport).build()) {
    client.initialize();
    var tools = client.listTools();
    var result = client.callTool(
        McpSchema.CallToolRequest.builder("hello")
            .arguments(Map.of("name", "민수"))
            .build());
    // tools와 result를 실습 앱의 로그·검증 코드에서 확인한다.
}
과제 4

리소스 템플릿 삭제와 목록 알림의 조건표 중급 · 반나절

만들 것: study://notes/{id} 템플릿을 등록합니다. resources.listChanged가 true·false·null인 구성과, 삭제 대상이 존재·부재인 경우를 조합해 알림 횟수를 기록합니다.

완료 조건: “실제 삭제가 있었고 listChanged=true일 때”를 구분하고, 없는 템플릿을 반복 삭제해도 추가 알림이 생기지 않는지 확인합니다. 비동기 API에서는 반환된 Mono가 구독되는 시점도 기록합니다.

읽을 곳: McpAsyncServer.removeResourceTemplate(), notifyResourcesListChanged(), mcp-test/src/test/java/io/modelcontextprotocol/server/DerivedCapabilitiesRuntimeChangesTests.java. 배울 것: 상태 변경·구독·캐시 갱신·선택 capability의 관계.

과제 5

응답 순서 뒤집기와 제한 시간 관찰 고급 · 1~2일

만들 것: 실제 외부 서비스 대신 mock 전송을 사용합니다. 요청 A와 B를 보내고 B 응답을 먼저 돌려주며, C는 응답하지 않게 합니다. 요청 ID와 각 구독자의 결과·오류를 기록합니다.

완료 조건: A와 B가 서로 다른 결과를 정확히 받고, C는 설정한 제한 시간 뒤 실패해야 합니다. 이후 늦은 응답·세션 종료를 추가해 대기 중인 요청과 Map의 변화를 관찰합니다. 호출자 타임아웃과 원격 작업 취소가 같은지 여부를 설명합니다.

읽을 곳: McpClientSession.sendRequest(), handle(), dismissPendingResponses(), mcp-core/src/test/java/io/modelcontextprotocol/spec/McpClientSessionTests.java. 배울 것: 순서 독립성, 시간 제한, 자원 정리를 분리해 검증하는 법.

실습의 완료 기준은 실행 화면 한 장보다, 정상·실패·종료 조건을 다른 사람이 재현할 수 있게 설명하는 것입니다. 전체 빌드나 적합성 검증은 Docker·npx 등 준비 조건을 갖춘 뒤 공식 개발 문서의 절차로 진행하세요.

9관련 기술 심화 학습 로드맵

6주 동안 Java 문법에서 프로토콜 설계까지

주당 3~5시간 정도를 가정한 학습 제안입니다. Java 경험이 있다면 1주차를 줄이고 테스트·네트워크에 시간을 더 쓸 수 있습니다. 각 주차마다 설명 문서 하나보다 작은 산출물 하나를 남기는 방식입니다.

주차공부할 주제이 저장소에서 읽을 곳완료 산출물
1주Java 17 레코드·제네릭·Map·람다McpSchema.CallToolRequest, Tool, TypeRef입력 JSON과 Java 필드의 대응표, 객체 생성 예
2주JSON-RPC·MCP의 도구와 리소스McpSchema 상수, LifecycleInitializer초기화→목록→호출의 메시지 순서도
3주Mono·Flux·구독·스케줄러·오류McpAsyncClient, McpServerFeatures.AsyncToolSpecification.fromSync()동기·비동기 호출 비교, 타임아웃 관찰 기록
4주HTTP·SSE·Servlet·STDIO클라이언트·서버의 transport/, ConformanceServlet같은 도구를 두 전송으로 연결한 구성도
5주JSON Schema·SPI·모듈 의존성ToolInputValidator, McpJsonDefaults, 각 POM잘못된 입력 조건표, JSON 구현 의존 그래프
6주회귀 테스트·적합성·버전 호환성mcp-test, VALIDATION_RESULTS.md, MIGRATION-2.0.md선택한 기능 하나의 검증 범위와 알려진 한계

9-1. 3주차에 꼭 답해 볼 질문

9-2. 6주 뒤에는 한 기능의 전문가가 되기

다음 단계에서는 resources 구독, 출력 스키마 검증, 요청 커스터마이저, modern의 repository 중 하나만 고르세요. 인터페이스, 기본 구현, 정상 테스트, 실패 테스트, 버전 변경 안내를 한 묶음으로 읽으면 공개 API가 유지해야 할 약속을 이해할 수 있습니다.

프로젝트 전체를 한 번 훑는 것보다, 입력부터 테스트까지 한 경로를 끝까지 설명할 수 있는 것이 더 확실한 학습입니다. 마지막에는 도구 하나의 사용법을 넘어, 그 도구를 안전하게 호출하게 하는 계약까지 자신의 말로 설명해 보세요.

추천 학습 산출물
한 장짜리 소스 탐색 지도

“호출자 → 초기화 → 요청 ID → 전송 → 스키마 검증 → 핸들러 → 응답”를 그리세요. 화살표마다 실제 파일과 메서드 이름을 하나씩 붙이면, 다음 SDK를 읽을 때도 사용할 수 있는 분석 방법이 됩니다.

10핵심 키워드 사전

이 글의 코드를 읽는 데 필요한 최소 어휘
용어쉬운 설명
SDK특정 규격이나 서비스를 이용하는 데 필요한 코드 부품 묶음. 여기서는 MCP 클라이언트·서버 구현을 제공
Host / Client / ServerHost는 AI 기능을 포함한 애플리케이션, Client는 서버와 통신하는 구성요소, Server는 도구·정보를 제공하는 상대
JSON-RPCmethod·params로 호출을 표현하고 id로 결과를 연결하는 메시지 규칙
Notification응답을 요구하지 않는 통지. 목록 변경이나 준비 완료를 알릴 때 사용
Capability상대가 제공하는 기능의 선언. tools 유무와 목록 변경 통지 지원 여부처럼 세부 값도 구분
Transport메시지가 이동하는 통로. 여기서는 STDIO·SSE·Streamable HTTP 구현을 구분
STDIO프로세스의 표준 입력·출력. 로컬 서버를 자식 프로세스로 실행하고 파이프로 통신할 때 사용
SSEHTTP 응답을 열어 두고 서버가 이벤트를 연속 전달하는 형식. 과거 SSE 전송과 Streamable HTTP의 SSE 응답은 같은 API가 아님
Streamable HTTPHTTP로 MCP 메시지를 주고받으며 필요에 따라 JSON 응답 또는 SSE 스트림을 사용하는 전송 방식
SerializationJava 객체를 전송할 JSON으로 바꾸는 일. 역방향은 역직렬화
JSON SchemaJSON 값의 필드·타입·필수 조건을 설명하는 규칙. 도구 입력과 구조화 출력의 계약으로 사용
Record / BuilderRecord는 데이터를 표현하는 Java 문법, Builder는 필수값과 선택값을 조립해 객체를 만드는 방식
Mono / FluxReactor의 비동기 흐름. Mono는 최대 하나의 값, Flux는 여러 값을 전달하며 완료·오류도 표현
Backpressure소비자가 처리할 수 있는 양에 맞춰 생산 속도를 조절하는 원리. 모든 버퍼가 자동으로 제한된다는 뜻은 아님
Scheduler비동기 작업을 어느 실행 자원에서 처리할지 정하는 구성요소. boundedElastic은 블로킹 작업을 옮길 때 사용
Correlation ID요청과 응답을 연결하는 식별자. 이 코드에서는 세션 접두어와 카운터로 요청 ID 생성
SPI / ServiceLoader구현을 추가하는 확장 계약과 Java의 공급자 탐색 기능. 기본 JSON 구현을 찾는 데 사용
Facade / Adapter복잡한 내부를 간단한 창구로 감싸거나, 다른 라이브러리의 API를 원하는 계약에 맞추는 설계
BOM / SNAPSHOTBOM은 의존성 버전 조합표, SNAPSHOT은 변경 가능한 개발 빌드 버전
Stateless요청 처리에 이전 연결의 초기화 상태를 전제로 삼지 않는 방식. 업무 데이터나 서버 객체가 전혀 없다는 뜻은 아님
Conformance / SEPConformance는 규격에 맞는지 확인하는 검증, SEP는 MCP 규격 변경 제안의 식별 체계
MRTR여러 차례 입력과 응답을 주고받으며 작업을 이어 가는 흐름. modern 경로의 입력 요청·requestState와 관련

11참고 링크

배포 문서와 커밋 고정 소스를 구분해서 다시 찾기

11-1. 공식 저장소와 규격·기술 문서

11-2. 핵심 소스 다시 읽기 — 모두 커밋 고정

11-3. 현재 상태 (2026-10-23 확인)

항목상태기준
저장소·선정modelcontextprotocol/java-sdk · GitHub Trending Java Weekly #52026-10-23 집계
스타 / 포크3,736 / 1,1122026-10-23 GitHub 기준
주 언어·생성일Java · 2025-01-202026-10-23 GitHub 기준
최근 push2026-10-232026-10-23 GitHub 기준
최신 릴리스v2.1.0 · 2026-10-162026-10-23 GitHub 기준
분석 커밋54e8b61 · 2026-10-23
Notify resources list_changed when removing a resource template (#1266)
소스·경로·기본값의 기준점
개발 버전2.2.0-SNAPSHOT루트 pom.xml
코드 규모Java 302개·74,017줄, XML 1,662줄, YAML 561줄추적 파일의 빈 줄·주석 포함
핵심 Java 규모core main 35,282줄 / 전체 Java test 29,370줄각 경로별 물리적 줄 수
프로토콜 경로기존 API의 2025-11-25 지원 경로와 modern의 2026-07-28 경로 공존spec·modern 패키지와 검증 문서
라이선스MITLICENSE
사용 전에 알아둘 한계
README 요약·검증 보고서·개발 코드는 같은 시점의 보장이 아니다

검증 숫자: README는 conformance 0.1.15와 서버 40/40, 인증 12/14를 소개합니다. 더 구체적인 VALIDATION_RESULTS.md는 2026-10-02 기준 일반 서버 73/73 checks, modern 필수 37/37 scenarios, 인증 14/14 scenarios·193 checks를 기록합니다. 도구 버전과 집계 단위가 달라 숫자를 직접 합치거나 같은 시험으로 비교할 수 없습니다.

알려진 실패: 그 보고서는 클라이언트 sse-retry의 retry 시간·Last-Event-ID 문제와, modern의 SEP-2243 사용자 헤더 검증 및 tasks 확장 미구현을 명시합니다. 필수 시나리오 통과 숫자는 미채점 항목까지 모두 구현했다는 보장이 아닙니다. 인증 결과는 Spring 보안 통합을 사용하는 검증 앱의 결과이지 core 단독 인증 기능의 증거가 아닙니다.

문서와 API: ROADMAP.md에는 2026년 9월 milestone 계획과 2.0.1 중심 설명이 남아 있습니다. 일정을 현재의 완료 상태로 해석하지 말고, 배포 태그와 패키지·규격을 함께 확인해야 합니다. latest 문서는 이후 바뀔 수 있으므로 이 글의 커밋 고정 링크와 차이가 생길 수 있습니다.

예제와 성능: 코드는 학습용 발췌이며 전체 실행 앱·컨테이너 설정을 모두 포함하지 않습니다. 사양표의 RAM 권장은 추정이고 처리량·지연 시간의 실측 보장이 아닙니다. 업무 권한·모델 제공자 연결·실제 데이터 처리는 사용하는 애플리케이션에서 별도로 설계해야 합니다.