Spring AI MCP 실습: Phase 0~3 로그 기반 실제 오류 정리

Spring AI MCP 실습: Phase 0~3에서 실제로 터진 오류와 검증 기반 해결 정리

Spring AI MCP 실습 과정에서 Phase 0~3까지 진행 중 실제로 터진 오류를 로그 기반으로 정리했습니다.

Spring AI MCP 실습을 하다 보면, 단순한 “Hello World”를 넘어서 실제 운영 환경에 가까운 구조를 만들 때 예상보다 많은 문제를 만나게 됩니다.

특히 다음과 같은 상황은 문서만 보고는 판단하기 어렵습니다.

  • STDIO 방식에서 JSON 파싱 오류가 연쇄적으로 발생하는 경우
  • Phase별로 분리했다고 생각했는데, 다른 Phase의 Bean이 섞여 올라오는 문제
  • Java 빌드 버전과 런타임 버전 불일치로 인한 즉시 종료
  • MCP Inspector에서는 연결되는데 실제 Tool 호출이 실패하는 경우

이 글은 이론 정리나 공식 문서 요약이 아닙니다. 실제 MCP 실습 과정에서 직접 발생한 오류 로그와 그에 대한 검증 결과를 바탕으로, 어디서 왜 막히는지와 어떤 기준으로 다음 Phase로 넘어가야 하는지를 Phase 0부터 Phase 3까지 누락 없이 정리한 기록입니다.


Spring AI MCP 실습 환경 & 전제 (검증 기준)

아래 환경에서 직접 실행해 실패/성공을 재현했습니다.

  • 운영체제: Windows 11
  • IDE: IntelliJ IDEA
  • 빌드 도구: Gradle
  • 프레임워크: Spring Boot + Spring AI MCP
  • Java 런타임: 기본 PATH는 Java 17, 일부 시점에서 Java 21로 빌드된 Jar 실행 시도
  • MCP 테스트 도구: MCP Inspector(UI + Proxy), IntelliJ HTTP Request

중요한 전제

  • Phase별 실행은 서로 완전히 독립적이어야 합니다.
  • 한 Phase에서 문제가 발생하면 다음 Phase로 진행하지 않는 것이 원칙입니다.

이 기준을 지키지 않으면, 이후 문제의 원인이 현재 Phase인지 이전 Phase 잔재인지 구분할 수 없게 됩니다.

실습 소스 코드 기준

이 글에서 다루는 모든 Phase(0~3)는 실제 실행 및 오류 재현이 가능하도록 구성된 실습 코드를 기준으로 검증되었습니다.

실습 저장소: https://github.com/rexx4314/rex-mcp-lab

추가 자료나 다른 글은 블로그 홈에서 확인하실 수 있습니다: Tech > Guides 전체 보기

해당 저장소에는 Phase별 프로파일 분리 구조, MCP Tool 등록 방식, Streamable HTTP/STDIO 실험 환경, DB/Redis/Sandbox/Git 연계 예제 등이 포함됩니다. 이 글은 저장소의 코드를 그대로 설명하는 문서가 아니라, 실행 과정에서 실제로 발생한 오류와 원인을 로그 기준으로 정리한 기록입니다.


Spring AI MCP 실습 Phase 0 — 최소 MCP 서버 검증 (가장 중요)

목적

  • MCP 서버가 정상 기동
  • Inspector에서 tools/list 노출
  • Tool 호출 시 정상 JSON 응답

여기서 막히면 Phase 1~3은 진행하지 않는 것이 맞습니다. 프로토콜/등록/환경 쪽 문제일 때가 많습니다.

✅ Phase 0 요약 카드

핵심 검증: Inspector 연결 성공 → tools/list에서 echo/health 등 확인 → 각 Tool 호출 시 즉시 JSON 응답

여기서 막히면: Phase 1~3 진행 ❌ (등록/프로토콜/환경 문제 가능성)

이 글은 Spring AI MCP 실습 과정에서 실제로 겪은 실패 지점을 기준으로, 다음 Phase로 넘어가기 전 무엇을 확인해야 하는지에 초점을 둡니다.

Spring AI MCP 실습 실행 및 확인 절차

실행 명령어 (재현용)

# 공통 빌드
./gradlew clean build

# bootJar 생성
./gradlew clean bootJar

# MCP Inspector 실행
npx @modelcontextprotocol/inspector

위 명령어는 재현을 위한 최소 세트이며, 실습의 핵심은 명령 실행 자체보다 Inspector에서 tools/list와 Tool 호출이 성공하는지 여부입니다.

  • Gradle로 bootJar 생성
  • MCP Inspector 실행
PowerShell에서 npx @modelcontextprotocol/inspector 명령어를 실행한 화면. 
MCP Inspector가 로컬 포트에서 UI와 Proxy를 함께 기동했음을 로그로 확인할 수 있다.
Spring AI MCP 실습에서 MCP Inspector 초기 화면. Transport Type, Command, Arguments 입력 영역이 보이며 서버 연결 전 상태를 나타낸다.
  • Transport를 STDIO 또는 Streamable HTTP 중 하나로 선택
MCP Inspector에서 서버에 연결된 상태의 메인 화면. 
상단 메뉴에 Resources, Prompts, Tools 탭이 있으며, 
아직 tools/list 호출 전 상태이다.
  • 서버 연결 후 tools/list 확인
Spring AI MCP 실습에서 MCP Inspector의 tools/list 호출 결과 화면. health, echo, getTimeUtc 도구가 정상 노출되어 MCP 서버 Tool 등록이 올바름을 확인한다.
Spring AI MCP 실습에서 health 도구 실행 결과 화면. 서버 상태가 정상이며 JSON 응답이 반환되는지 확인한다.
MCP Inspector에서 echo 도구를 실행한 화면. 
입력한 문자열이 그대로 반환되어 MCP Tool 호출이 정상 동작함을 확인한다.
MCP Inspector에서 getTimeUtc 도구 실행 결과. 
UTC 기준 현재 시간이 JSON 응답으로 반환된다.

실제 발생한 오류와 검증된 원인

1) STDIO JSON 파싱 오류 대량 발생

증상: Unexpected token / not valid JSON 오류가 반복 출력

원인(검증됨): STDIO transport는 표준 출력에 MCP JSON만 있어야 하는데, Spring Boot 로그가 stdout으로 섞여 들어가면서 Node MCP SDK가 파싱에 실패합니다.

결론: 실습 단계에서는 Streamable HTTP 방식이 훨씬 안정적입니다. STDIO는 로그 분리/비활성화 등 추가 설정이 없으면 추천하기 어렵습니다.

2) Jar 실행 경로 오류

증상: Unable to access jarfile …

원인: build/libs 경로 누락 또는 상대 경로 기준 혼동

검증 결과: 절대 경로 또는 정확한 build/libs 경로를 사용하면 즉시 해결됩니다.

3) Java 버전 불일치 오류

증상: UnsupportedClassVersionError (예: class file version 65.0 vs runtime 61.0)

원인: Java 21로 빌드된 Jar를 Java 17 런타임으로 실행

해결 선택지: (1) 빌드 버전을 17로 낮추거나 (2) 런타임 Java를 21로 맞춥니다. 실습 속도 기준으로는 Java 17 통일이 가장 빠른 선택인 경우가 많습니다.


Spring AI MCP 실습 Phase 1~3 실행 요약 (공통)

Phase 0이 정상적으로 통과되었다면, 이제 Phase 1~3은 아래 명령어로 각각 실행해 검증할 수 있습니다. 각 Phase는 서로 독립적으로 실행해야 하며, 동시에 띄우지 않는 것이 원칙입니다.

# Phase 1
./gradlew bootRun --args="--spring.profiles.active=phase1"

# Phase 2
./gradlew bootRun --args="--spring.profiles.active=phase2"

# Phase 3
./gradlew bootRun --args="--spring.profiles.active=phase3"

각 Phase 실행 시 서버 포트, 활성 프로파일, Inspector 연결 대상이 서로 일치하는지 반드시 로그로 확인한 뒤 다음 Phase로 넘어가야 합니다.


Spring AI MCP 실습 Phase 1 — 내부 HTTP 호출 Tool 검증

✅ Phase 1 요약 카드

목적: MCP Tool → 내부 HTTP API 호출 구조 검증(정상/지연/실패 전파)

자주 발생: Connection refused(포트 혼선), 404(컨트롤러 없음)

목적: MCP Tool → 내부 HTTP API 호출 구조를 안정적으로 검증하고, 지연/실패/타임아웃 전파가 올바르게 되는지 확인합니다.

Spring AI MCP 실습 Phase 1 실행

공통 요약에서 한 번 실행했다면, Phase 1은 아래 명령으로 단독 실행 중인지 다시 확인합니다.

./gradlew bootRun --args="--spring.profiles.active=phase1"

Spring AI MCP 실습 실행 및 테스트 흐름

  • Phase 1 프로파일로 서버 실행
  • IntelliJ HTTP Request로 내부 API 직접 호출(정상/지연/실패)
IntelliJ HTTP Request로 내부 API 직접 호출(정상)
  • 동일 동작을 MCP Tool로 호출

실제 발생 오류

1) Connection refused

원인: 기본 8080으로 요청했으나 실제 서버 포트는 3001 등으로 설정되어 있었던 케이스

검증: server.port 값과 요청 포트를 일치시키면 즉시 해결됩니다.

2) 404 Not Found

원인: 내부 API 컨트롤러/매핑 자체가 없는 상태

중요한 판단: Phase 1은 Tool만으로 검증하기 어렵고, HTTP 엔드포인트가 반드시 존재해야 IntelliJ HTTP Request로 선검증이 가능합니다.


Spring AI MCP 실습 Phase 2 — DB / Redis 연계 (운영 관점 핵심)

✅ Phase 2 요약 카드

목적: DB/Redis 같은 내부 리소스 접근 + 조회 제한/마스킹 같은 운영 요구사항 반영

핵심 검증: limit 강제, 민감정보 마스킹, redis set/get 일치, 프로파일 완전 분리

목적: “사내 리소스 접근” 단계로 넘어가며 DB/Redis 같은 내부 자원과 연결합니다. 이 단계에서는 기능 구현 자체보다도 결과 제한(예: limit 강제), 마스킹, 운영·보안 요구사항이 포함되는지 확인하는 것이 중요합니다.

주요 검증 포인트

  • 검색 결과 limit이 강제로 적용되는지
  • 민감 정보가 마스킹되어 노출되는지
  • Redis set/get이 기대대로 일치하는지

실제로 가장 많이 막힌 문제

1) Phase 0 실행 시 Phase 2 Bean 로딩

증상: Phase 0으로 실행했는데 Repository bean not found 등으로 종료

원인(확인됨): Phase 2 Bean에 Profile 분리가 적용되지 않아 다른 Phase에서도 생성되는 구조

결론: 모든 Phase 전용 Bean(Tools/Service/Repository/Controller/Config)은 반드시 해당 Phase 프로파일로 묶여야 합니다.

2) data.sql 실행 오류

증상: Table not found

원인: JPA 테이블 생성 이전에 data.sql이 먼저 실행되는 초기화 순서 문제

해결 방향: (1) JPA ddl-auto 이후 실행되도록 설정하거나 (2) schema.sql / data.sql 분리 등으로 초기화 책임을 명확히 분리합니다.


Spring AI MCP 실습 Phase 3 — 위험 도구 통제 검증

✅ Phase 3 요약 카드

목적: 파일/Git 같은 위험 도구를 “안전하게” 노출하고 통제가 올바른지 검증

성공 기준: “작동”이 아니라 “차단”이 기대대로 되는지(화이트리스트/샌드박스/경로 차단)

목적: Phase 3은 “되게 만드는 단계”가 아니라 안전하게 막는 단계입니다. 샌드박스, 화이트리스트, 경로 traversal 차단, 승인(approval) 같은 통제가 핵심입니다.

핵심 검증 케이스

  • 디렉터리 traversal(예: ../) 차단
  • 허용된 파일만 접근 가능
  • 허용 리스트 밖 명령은 무조건 DENY
  • Git status는 저장소(.git) 루트가 아니면 명확한 에러를 반환

각 케이스는 가능하면 MCP Inspector에서 직접 호출한 결과 화면을 함께 남겨두면, 나중에 원인 분리가 훨씬 쉬워집니다.

파일이 안 바뀐 것처럼 보이는 경우(혼동 지점)

writeSandbox 같은 호출을 했는데 파일이 안 바뀐 것처럼 보이는 상황은 현업에서도 흔합니다. 이번 실습 흐름 기준으로 가장 가능성이 높은 원인은 다음 3가지였습니다.

  • 서버 프로세스가 여러 개 떠 있음 (IDE 실행 + jar 실행 + Inspector 재연결 등)
  • Inspector가 다른 포트/다른 프로파일 서버에 붙어 있음
  • 내가 보고 있는 파일 경로와 실제 sandbox-dir 경로가 다름

검증 방법: 서버 로그에서 active profile 확인 → 포트 리슨 PID 하나만 남기기 → readSandbox로 “서버가 보는 내용”을 교차검증하면 원인 분리가 쉬워집니다.


Spring AI MCP 실습 공통 트러블슈팅 플로우 (의사결정 기준)

Phase가 올라갈수록 문제가 복잡해지므로, 아래 순서를 고정하면 원인 분리가 매우 쉬워집니다.

  1. 서버가 뜨는가?
  2. active profile이 의도한 Phase인가?
  3. tools/list가 보이는가?
  4. HTTP로 먼저 검증 가능한가?
  5. 그 다음 MCP Tool 호출로 동일 결과가 나오는가?

이 순서를 지키면 “현재 Phase 문제인지, 이전 Phase 잔재인지”를 빠르게 분리할 수 있습니다.


마무리

Spring AI MCP 실습에서 가장 크게 느낀 점은 하나였습니다.

MCP는 “되게 만드는 기술”이 아니라, 통제와 분리를 얼마나 정확히 하느냐가 핵심입니다.

이 글이 도움이 되는 분들은 보통 아래 상황에 해당하는 경우가 많습니다.

  • MCP / Spring AI를 실제 프로젝트에 쓰려다 막힌 경우
  • 로그는 많은데 어디서부터 정리해야 할지 모르는 경우
  • 다음 단계로 넘어가도 되는지 판단이 어려운 경우

요약

  • Spring AI MCP 실습기(Phase 0~3) 실제 오류 기반 정리
  • STDIO vs Streamable HTTP: 실습에서는 HTTP가 안정적인 경향
  • 프로파일 분리, Java 버전 불일치, DB 초기화 순서 이슈가 대표적인 장애 포인트
  • Phase 3은 “작동”보다 “차단”이 성공 기준

이직·퇴사, 지금 결정해도 되는 단계인지 5분 만에 점검해보세요

감정이 아니라 체크리스트로 현재 상태를 구조화합니다.
결과는 “정답”이 아니라
혼자 판단해도 되는지 / 지금 움직이면 위험한지를 가르는 기준입니다.

체크가 많다면,
다음 단계는 더 고민이 아니라 선택지 정리입니다.

✅ 무료 체크리스트 받기

체크리스트부터 할지 고민된다면,
지금 판단해도 되는 단계인지 먼저 확인해보세요

위로 스크롤