Spring Boot에서 MCP 서버 만들기 — Spring AI 실전
Claude Code, Antigravity, Gemini Code Assist처럼 요즘 나오는 AI 코딩 도구들은 하나같이 "MCP 서버"를 통해 외부 도구·데이터에 연결된다는 설명이 붙는다. MCP(Model Context Protocol)는 Anthropic이 처음 제안한 개방형 프로토콜로, LLM 애플리케이션이 외부 데이터 소스·도구와 통신하는 방식을 표준화한다. Spring AI는 이 MCP를 위한 전용 Boot Starter를 제공하기 때문에, Spring Boot 개발자라면 기존 서비스 로직을 몇 줄 설정만으로 MCP 서버로 노출할 수 있다. 이 글에서는 Spring Boot 프로젝트에 MCP 서버를 붙이는 과정을 코드로 정리한다.
MCP가 해결하는 문제
MCP 이전에는 AI 모델이 외부 서비스(사내 API, DB, 파일 시스템 등)와 연동하려면 서비스마다 별도의 연동 코드를 짜야 했다. MCP는 이 문제를 gRPC나 LSP(Language Server Protocol)처럼 표준화된 인터페이스로 풀어낸다. AI 모델은 MCP라는 하나의 "언어"만 학습하면, MCP를 지원하는 어떤 서비스와도 통신할 수 있다.
구조는 클라이언트-서버 모델이다.
- MCP 서버: 도구(tool)·리소스(resource)를 외부에 노출하는 쪽. 예: "저자로 책을 검색하는 도구"를 제공하는 백엔드
- MCP 클라이언트: AI 모델을 대신해 MCP 서버의 도구를 발견하고 호출하는 쪽. Claude Desktop, Claude Code, Antigravity 같은 AI 코딩 도구가 여기 해당
Spring AI MCP Boot Starter 의존성 추가
Spring은 MCP 생태계에 초기부터 참여해 공식 MCP Java SDK 개발에 기여해왔고, Spring AI는 이 SDK 위에 Boot Starter와 애노테이션 기반 API를 얹어 제공한다.
dependencies {
// MCP 서버로 동작 (WebMVC 기반 SSE 전송)
implementation 'org.springframework.ai:spring-ai-starter-mcp-server-webmvc'
}
dependencies {
// 다른 MCP 서버에 접속하는 클라이언트로 동작할 때
implementation 'org.springframework.ai:spring-ai-starter-mcp-client'
}
기존 서비스를 MCP 도구로 노출하기
기존에 있던 평범한 서비스 클래스를 예로 들어보자.
@Service
public class BookService {
private final BookRepository bookRepository;
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
public List<Book> findByAuthor(String author) {
return bookRepository.findByAuthorContaining(author);
}
public List<Book> findByCategory(String category) {
return bookRepository.findByCategory(category);
}
}
이 메서드들을 MCP 도구로 노출하려면, @Tool 애노테이션과 설명을 붙인 별도 컴포넌트로 감싸면 된다.
@Component
public class BookMcpTools {
private final BookService bookService;
public BookMcpTools(BookService bookService) {
this.bookService = bookService;
}
@Tool(description = "저자 이름으로 책 목록을 검색한다")
public List<Book> searchBooksByAuthor(
@ToolParam(description = "검색할 저자 이름") String author) {
return bookService.findByAuthor(author);
}
@Tool(description = "카테고리로 책 목록을 검색한다")
public List<Book> searchBooksByCategory(
@ToolParam(description = "검색할 카테고리") String category) {
return bookService.findByCategory(category);
}
}
@Configuration
public class McpServerConfig {
@Bean
public ToolCallbackProvider bookTools(BookMcpTools bookMcpTools) {
return MethodToolCallbackProvider.builder()
.toolObjects(bookMcpTools)
.build();
}
}
application.yml에는 서버 이름과 전송 방식을 지정한다.
spring:
ai:
mcp:
server:
name: book-mcp-server
version: 1.0.0
이렇게만 해두면 애플리케이션이 뜰 때 BookMcpTools에 있는 두 메서드가 자동으로 MCP 도구로 등록되고, MCP를 지원하는 클라이언트(Claude Desktop, Claude Code 등)가 이 서버에 접속해 "저자로 책 검색"이라는 도구를 발견하고 호출할 수 있게 된다.
클라이언트 쪽에서 외부 MCP 서버 붙이기
반대로 우리 Spring Boot 애플리케이션이 다른 MCP 서버(예: 파일 시스템, JetBrains IDE 등)의 도구를 가져다 쓰고 싶을 때는 클라이언트 스타터를 쓴다.
spring:
ai:
mcp:
client:
stdio:
connections:
filesystem:
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
이렇게 등록해두면 Spring AI의 ChatClient가 대화 중 필요할 때 이 외부 MCP 서버의 도구를 자동으로 호출할 수 있다.
실무에서 유의할 점
- 도구 설명(description)이 곧 프롬프트다:
@Tool,@ToolParam의 설명 문구를 LLM이 그대로 읽고 언제 이 도구를 호출할지 판단한다. 모호하게 쓰면 엉뚱한 상황에서 호출되거나, 반대로 필요할 때 호출되지 않는다. - 인증 프록시가 필요한 클라이언트도 있다: 일부 AI 클라이언트는 MCP 서버 접속 시 별도 프록시나 인증 절차를 요구한다. 403 응답이 나온다면 이 부분부터 점검한다.
- 전송 방식(stdio vs SSE)을 용도에 맞게 고른다: 로컬 프로세스 실행형 도구는 stdio, 네트워크 너머의 장기 실행 서버는 SSE/WebMVC 기반이 자연스럽다.
- 도구 노출 범위를 최소화한다: 기존 서비스 전체를 무분별하게 도구로 노출하기보다, AI가 실제로 필요로 하는 조회·조회성 작업 위주로 범위를 좁히는 편이 안전하다.
마무리
MCP는 AI 코딩 도구뿐 아니라 사내 시스템을 AI 에이전트에 연결하는 표준 창구로 자리 잡아가고 있다. Spring Boot로 이미 서비스 로직을 짜둔 팀이라면, 새로 뭔가를 만들기보다 기존 서비스 계층을 MCP 도구로 얇게 감싸는 것만으로 AI 연동을 시작할 수 있다는 점이 핵심이다.
참고 자료
- Spring 공식 블로그 — Connect Your AI to Everything: Spring AI's MCP Boot Starters (spring.io/blog)
- Spring AI 공식 문서 — Model Context Protocol (docs.spring.io/spring-ai)
- Anthropic — Model Context Protocol 소개 (anthropic.com/news/model-context-protocol)
'AI > AI' 카테고리의 다른 글
| AI 에이전트 평가 지표 7가지: 정확도만 보면 운영에 실패하는 이유 (0) | 2026.07.27 |
|---|---|
| 2026년 7월 AI 업계 총정리: 구글의 반격, 커서 인수, 메타의 피벗 (0) | 2026.07.23 |
| DeepSeek V4 정식 출시, 개발자가 알아야 할 가격 전략 (0) | 2026.07.20 |
| Gemini Code Assist 종료, Antigravity로 옮겨야 하는 이유 (0) | 2026.07.20 |
| GPT-5.6 vs Claude Fable 5, 어떤 모델을 써야 할까 (0) | 2026.07.13 |