Spring Boot MCP 서버 구축 방법 (2026)
Spring Boot와 Java로 Model Context Protocol 서버 구축하기
Hypereal로 구축 시작하기
단일 API를 통해 Kling, Flux, Sora, Veo 등에 액세스하세요. 무료 크레딧으로 시작하고 수백만으로 확장하세요.
신용카드 불필요 • 10만 명 이상의 개발자 • 엔터프라이즈 지원
Spring Boot MCP 서버 구축 방법 (2026)
Model Context Protocol (MCP)은 Anthropic에서 만든 오픈 표준으로, Claude와 같은 AI 어시스턴트가 외부 도구 및 데이터 소스와 상호작용할 수 있도록 해줍니다. 대부분의 MCP 서버 예제는 TypeScript나 Python을 사용하지만, Java 개발자는 공식 MCP Java SDK를 사용하여 Spring Boot로 MCP 서버를 구축할 수 있습니다. 이 가이드는 처음부터 완전히 작동하는 MCP 서버를 구축하는 과정을 안내합니다.
MCP란 무엇인가요?
MCP (Model Context Protocol)는 AI 어시스턴트가 다음과 같은 작업을 수행할 수 있도록 표준화된 방법을 정의합니다.
- 도구 호출 (Call tools) -- 데이터베이스 쿼리, API 호출 또는 계산 실행과 같은 함수 실행
- 리소스 읽기 (Read resources) -- 파일, 데이터베이스 레코드 또는 API 응답과 같은 데이터에 액세스
- 프롬프트 사용 (Use prompts) -- 미리 빌드된 프롬프트 템플릿 검색
이를 AI를 위한 플러그인 시스템이라고 생각하면 됩니다. Claude가 사용자의 MCP 서버에 연결되면, 사용 가능한 도구가 무엇인지 검색하고 대화 중에 이를 호출할 수 있습니다.
MCP 아키텍처
┌─────────────┐ MCP Protocol ┌──────────────┐
│ Claude │ ◄──────────────────► │ MCP Server │
│ Desktop │ (JSON-RPC over │ (Spring Boot)│
│ 또는 IDE │ stdio 또는 SSE) │ │
└─────────────┘ └──────┬───────┘
│
┌──────┴───────┐
│ 사용자 도구 │
│ - Database │
│ - APIs │
│ - Files │
└──────────────┘
사전 요구 사항
- Java 17 이상
- Maven 또는 Gradle
- Spring Boot 3.2+
- Claude Desktop 또는 모든 MCP 호환 클라이언트
Java 버전 확인:
java --version
# java 17.x.x 이상이 출력되어야 합니다.
mvn --version
# Apache Maven 3.9.x 이상
1단계: Spring Boot 프로젝트 생성
Spring Initializr를 사용하거나 프로젝트를 수동으로 생성합니다.
Spring Initializr 사용
curl https://start.spring.io/starter.zip \
-d type=maven-project \
-d language=java \
-d bootVersion=3.4.2 \
-d baseDir=mcp-server \
-d groupId=com.example \
-d artifactId=mcp-server \
-d name=mcp-server \
-d packageName=com.example.mcpserver \
-d javaVersion=17 \
-d dependencies=web \
-o mcp-server.zip
unzip mcp-server.zip
cd mcp-server
MCP 의존성 추가
pom.xml에 MCP Java SDK를 추가합니다:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MCP Java SDK -->
<dependency>
<groupId>io.modelcontextprotocol</groupId>
<artifactId>mcp-spring-boot-starter</artifactId>
<version>0.6.0</version>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
2단계: MCP 서버 설정
src/main/resources/application.yml에서 애플리케이션 설정을 생성합니다:
server:
port: 8080
mcp:
server:
name: "my-spring-mcp-server"
version: "1.0.0"
transport: sse # CLI 기반 클라이언트의 경우 "stdio" 사용
3단계: 도구(Tools) 정의
MCP 도구는 Claude가 호출할 수 있는 함수입니다. 각 도구는 이름, 설명, 입력 스키마 및 핸들러를 가집니다.
도구 설정 클래스 생성
package com.example.mcpserver.tools;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.Tool;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.TextContent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
@Configuration
public class ToolConfiguration {
private final ObjectMapper objectMapper = new ObjectMapper();
@Bean
public McpServer.ToolRegistration weatherTool() {
// 입력 스키마 정의
String inputSchema = """
{
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name to get weather for"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units",
"default": "celsius"
}
},
"required": ["city"]
}
""";
Tool tool = new Tool(
"get_weather",
"Get the current weather for a given city",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String city = (String) arguments.get("city");
String units = (String) arguments.getOrDefault("units", "celsius");
// 실제 앱에서는 여기서 날씨 API를 호출합니다.
String weather = fetchWeather(city, units);
return new CallToolResult(
List.of(new TextContent(weather)),
false // isError
);
});
}
@Bean
public McpServer.ToolRegistration calculatorTool() {
String inputSchema = """
{
"type": "object",
"properties": {
"operation": {
"type": "string",
"enum": ["add", "subtract", "multiply", "divide"],
"description": "The math operation to perform"
},
"a": {
"type": "number",
"description": "First operand"
},
"b": {
"type": "number",
"description": "Second operand"
}
},
"required": ["operation", "a", "b"]
}
""";
Tool tool = new Tool(
"calculate",
"Perform a basic math calculation",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String operation = (String) arguments.get("operation");
double a = ((Number) arguments.get("a")).doubleValue();
double b = ((Number) arguments.get("b")).doubleValue();
double result = switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> {
if (b == 0) throw new ArithmeticException("Division by zero");
yield a / b;
}
default -> throw new IllegalArgumentException(
"Unknown operation: " + operation
);
};
return new CallToolResult(
List.of(new TextContent(String.valueOf(result))),
false
);
});
}
private String fetchWeather(String city, String units) {
// 플레이스홀더 - 실제 API 호출로 교체하십시오.
return String.format(
"Weather in %s: 22%s, partly cloudy, humidity 65%%",
city,
units.equals("celsius") ? "°C" : "°F"
);
}
}
4단계: 리소스 프로바이더 추가
리소스는 Claude가 서버에서 데이터를 읽을 수 있게 해줍니다.
package com.example.mcpserver.resources;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.spec.McpSchema.Resource;
import io.modelcontextprotocol.spec.McpSchema.ResourceContents;
import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class ResourceConfiguration {
@Bean
public McpServer.ResourceRegistration configResource() {
Resource resource = new Resource(
"config://app/settings",
"Application Settings",
"Current application configuration and settings",
"application/json"
);
return new McpServer.ResourceRegistration(resource, (uri) -> {
String configJson = """
{
"app_name": "My MCP Server",
"version": "1.0.0",
"features": ["weather", "calculator"],
"max_requests_per_minute": 60
}
""";
return new ResourceContents(
List.of(new TextResourceContents(uri, "application/json", configJson))
);
});
}
}
5단계: 데이터베이스 도구 추가 (실무 예제)
다음은 좀 더 현실적인 예제로, 데이터베이스를 쿼리하는 도구입니다.
@Bean
public McpServer.ToolRegistration databaseQueryTool(JdbcTemplate jdbcTemplate) {
String inputSchema = """
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SQL SELECT query to execute (read-only)"
},
"limit": {
"type": "integer",
"description": "Maximum rows to return",
"default": 10
}
},
"required": ["query"]
}
""";
Tool tool = new Tool(
"query_database",
"Execute a read-only SQL query against the application database",
objectMapper.readTree(inputSchema)
);
return new McpServer.ToolRegistration(tool, (arguments) -> {
String query = (String) arguments.get("query");
int limit = ((Number) arguments.getOrDefault("limit", 10)).intValue();
// 보안: SELECT 문만 허용합니다.
if (!query.trim().toUpperCase().startsWith("SELECT")) {
return new CallToolResult(
List.of(new TextContent("Error: Only SELECT queries are allowed")),
true // isError
);
}
// LIMIT이 없으면 추가합니다.
if (!query.toUpperCase().contains("LIMIT")) {
query += " LIMIT " + limit;
}
List<Map<String, Object>> results = jdbcTemplate.queryForList(query);
String json = objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(results);
return new CallToolResult(
List.of(new TextContent(json)),
false
);
});
}
6단계: 실행 및 테스트
빌드 및 실행
mvn clean package
java -jar target/mcp-server-0.0.1-SNAPSHOT.jar
서버는 8080 포트에서 시작되며, /sse 엔드포인트에서 SSE를 지원합니다.
cURL로 테스트
# 서버 실행 여부 확인
curl http://localhost:8080/sse
# 사용 가능한 도구 목록 확인 (MCP 프로토콜 경유)
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
7단계: Claude Desktop에 연결
Claude Desktop의 설정 파일에 MCP 서버를 추가합니다.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
SSE 전송 방식인 경우
{
"mcpServers": {
"spring-mcp": {
"url": "http://localhost:8080/sse"
}
}
}
stdio 전송 방식인 경우
stdio 전송 방식으로 서버를 빌드한 경우, jar 실행 명령을 감싸줍니다:
{
"mcpServers": {
"spring-mcp": {
"command": "java",
"args": [
"-jar",
"/path/to/mcp-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
설정을 업데이트한 후 Claude Desktop을 다시 시작하세요. Claude의 도구 목록에 사용자의 도구가 나타납니다.
트러블슈팅
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| Claude에서 서버를 찾을 수 없음 | 설정 파일 구문 오류 | JSON 유효성 검사 후 Claude Desktop 재시작 |
| "Connection refused" | 서버가 실행 중이 아님 | Spring Boot 앱을 먼저 시작하세요 |
| 도구가 나타나지 않음 | @Bean 어노테이션 누락 |
도구 빈(bean)이 @Configuration 클래스에 있는지 확인 |
| SSE 연결 끊김 | 타임아웃 설정 | server.servlet.session.timeout 설정 조정 |
| JSON 파싱 오류 | 스키마 불일치 | 입력 스키마가 MCP 사양에 맞는지 확인 |
프로젝트 구조
mcp-server/
├── pom.xml
├── src/
│ └── main/
│ ├── java/com/example/mcpserver/
│ │ ├── McpServerApplication.java
│ │ ├── tools/
│ │ │ └── ToolConfiguration.java
│ │ └── resources/
│ │ └── ResourceConfiguration.java
│ └── resources/
│ └── application.yml
결론
Spring Boot로 MCP 서버를 구축하면 Java 개발자가 기존 서비스, 데이터베이스 및 API를 Claude와 같은 AI 어시스턴트에게 노출할 수 있습니다. MCP Java SDK는 Spring Boot의 의존성 주입 및 설정 시스템과 자연스럽게 통합되어 도구와 리소스를 간단하게 등록할 수 있도록 돕습니다.
제품 비디오 제작, 설명으로 이미지 생성 또는 말하는 아바타 인터페이스 구축과 같이 시각적 콘텐츠 생성을 통해 MCP 기반 AI 워크플로우를 확장하려는 팀을 위해, Hypereal AI는 추가 MCP 도구로 쉽게 래핑할 수 있는 비디오, 이미지 및 아바타 생성을 위한 통합 API를 제공합니다.
