# Spring AI MCP 서버 사용하기

> **대상**: GenOS에서 Spring AI (Java) 기반 MCP 서버를 생성하고 배포하려는 사용자&#x20;
>
> **사전 조건**: GenOS 계정, Spring AI MCP 서버 jar 파일

***

### 1. 개요

GenOS는 Spring AI MCP 서버를 지원합니다. 기존 NPX(Node.js), Python 서버와 동일한 방식으로 Java jar 파일을 업로드하고 배포할 수 있습니다.

#### 전체 흐름

```
1. Spring AI MCP 서버 jar 파일 준비 (로컬에서 빌드)
2. GenOS에 jar 업로드        → 관리 > 리소스 > JAR 패키지
3. MCP 서버 생성 + 배포      → 도구 > MCP 서버 > 생성 > Spring AI 템플릿
4. 도구 동기화 + 테스트      → 서버 상세 > 중요 정보 > 도구 동기화
```

#### 언어별 비교

<table data-header-hidden><thead><tr><th width="107.00006103515625"></th><th width="208.45458984375">NPX (Node.js)</th><th>Python</th><th>Spring AI (Java)</th></tr></thead><tbody><tr><td>도구 작성</td><td>npm 패키지로 배포된 도구 사용</td><td>스크립트 코드 탭에서 직접 작성 가능</td><td><code>@Tool</code> 어노테이션으로 작성</td></tr><tr><td>패키지 형식</td><td><code>.tgz</code> (npm 패키지)</td><td><code>.whl</code> (pip 패키지) 또는 스크립트</td><td><strong><code>.jar</code></strong> (Spring Boot fat jar)</td></tr><tr><td>설치 방식</td><td><code>npm install</code> 자동</td><td><code>pip install</code> 자동</td><td><strong>JAR 패키지 업로드</strong></td></tr><tr><td>도구 수</td><td>패키지당 여러 개</td><td>스크립트당 여러 개</td><td><strong>jar 하나에 여러 개</strong></td></tr></tbody></table>

***

### 2. JAR 파일이란?

#### 하나의 jar = 하나의 MCP 서버 = 여러 개의 도구

jar 파일은 Spring AI MCP 서버 애플리케이션 전체를 담고 있는 **실행 가능한 패키지**입니다.

```
my-mcp-server-1.0.0.jar
  ├── Spring Boot 프레임워크
  ├── Spring AI MCP 라이브러리
  └── 사용자 도구 코드
       ├── @Tool getWeather(city)     → 날씨 조회
       ├── @Tool add(a, b)            → 숫자 더하기
       └── @Tool hello(name)          → 인사말
```

> **1 jar = 1 Pod = N개 도구**. Python에서 하나의 스크립트에 `@mcp.tool()`을 여러 개 정의하는 것과 같습니다.

#### jar 파일과 server.jar의 관계

config.json의 `"args": ["-jar", "server.jar"]`에서 `server.jar`는 **컨테이너 안의 실행 경로**입니다. 사용자가 업로드한 jar 파일명이 뭐든(`my-mcp-server-1.0.0.jar`) 배포 시 자동으로 `/app/server.jar`로 복사됩니다.

```
사용자 업로드: my-mcp-server-1.0.0.jar
      ↓ (배포 시 init.sh가 자동 복사)
컨테이너 내부: /app/server.jar
      ↓
실행: java -jar /app/server.jar
```

***

### 3. JAR 파일 만들기

#### 3.1 필수 요구사항

* **Java 17 이상**
* **Spring AI 1.1 이상** (StreamableHTTP 지원)
* **spring-boot-starter-actuator** 포함 (health check용)

#### 3.2 프로젝트 구조

```
my-mcp-server/
├── pom.xml
└── src/main/java/com/example/
    ├── McpServerApplication.java    ← Spring Boot 메인 클래스
    ├── WeatherService.java          ← @Tool 도구 정의
    └── resources/
        └── application.yml          ← MCP 서버 설정
```

#### 3.3 도구 작성 예시

```java
@Service
public class WeatherService {

    @Tool(description = "도시의 현재 날씨를 조회합니다.")
    public String getWeather(@ToolParam(description = "도시명") String city) {
        return switch (city) {
            case "서울" -> "서울 날씨: 맑음, 22°C";
            case "부산" -> "부산 날씨: 흐림, 18°C";
            default -> city + " 날씨: 정보 없음";
        };
    }

    @Tool(description = "두 숫자를 더합니다.")
    public String add(
            @ToolParam(description = "첫 번째 숫자") int a,
            @ToolParam(description = "두 번째 숫자") int b) {
        return String.valueOf(a + b);
    }
}
```

> `@Tool` 어노테이션을 붙인 메서드가 MCP 도구로 자동 등록됩니다. 하나의 클래스에 여러 도구를 정의할 수 있습니다.

#### 3.4 application.yml

```yaml
spring:
  ai:
    mcp:
      server:
        name: my-mcp-server
        version: 1.0.0
        type: SYNC
        protocol: STREAMABLE
        streamable-http:
          mcp-endpoint: /mcp

server:
  port: ${SERVER_PORT:8080}

management:
  endpoints:
    web:
      exposure:
        include: health
```

#### 3.5 빌드

```bash
mvn package -DskipTests
```

빌드 결과: `target/my-mcp-server-1.0.0.jar` — 이 파일을 GenOS에 업로드합니다.

> 전체 샘플 프로젝트는 `test/mcp/spring-ai-test-server/`를 참고하세요.

***

### 4. JAR 패키지 업로드

#### 4.1 JAR 패키지 메뉴 접근

좌측 사이드 바에서 **관리 > 리소스 > JAR 패키지**를 클릭합니다.

<figure><img src="/files/jbFxNFd2QcI8pPo62vnQ" alt=""><figcaption></figcaption></figure>

#### 4.2 JAR 파일 업로드

**"JAR 패키지 생성 +"** 버튼을 클릭하면 생성 모달이 열립니다.

<figure><img src="/files/rxG4jx2QzBJ0P47HccN9" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="142.1817626953125">필드</th><th width="566.727294921875">설명</th></tr></thead><tbody><tr><td><strong>파일 업로드</strong></td><td><code>.jar</code> 파일을 <strong>드래그 앤 드롭</strong>하거나 해당 영역을 클릭하여 파일탐색기 내에서 선택</td></tr><tr><td><strong>상세 설명</strong></td><td>선택사항</td></tr><tr><td><strong>관리 그룹</strong></td><td>드롭다운에서 선택</td></tr></tbody></table>

> 업로드 완료 후 목록에서 artifact ID, 버전이 자동 추출되어 표시됩니다.
>
> * **Maven 빌드 jar**: `META-INF/maven/*/pom.properties`에서 `artifactId`, `version` 추출
> * **Gradle 빌드 jar**: `META-INF/MANIFEST.MF`의 `Implementation-Title`, `Implementation-Version`에서 추출
> * 추출 실패 시 빈 값으로 표시됩니다 (정상 동작에 영향 없음)

목록에 생성된 항목이 노출됩니다.

<figure><img src="/files/AU5Jv2MK03xL6fAme2eo" alt=""><figcaption></figcaption></figure>

***

### 5. MCP 서버 생성

#### 5.1 MCP 서버 목록

좌측 사이드 바에서 **도구 > MCP 서버**를 클릭합니다.

<figure><img src="/files/q8M5kGm2kjHwuH2PymnM" alt=""><figcaption></figcaption></figure>

#### 5.2 생성 다이얼로그 — 1단계

**"MCP 서버 생성 +"** 버튼을 클릭합니다.

<figure><img src="/files/GXODbFxwRYKYMxYFifqU" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="154.9090576171875">필드</th><th width="566.727294921875">설명</th></tr></thead><tbody><tr><td><strong>제목</strong></td><td>서버 이름 (예: <code>spring-ai-weather-server</code>)</td></tr><tr><td><strong>상세 설명</strong></td><td>선택사항</td></tr><tr><td><strong>관리 그룹</strong></td><td>드롭다운에서 선택</td></tr><tr><td><strong>MCP 서버 타입</strong></td><td><strong>MCP 패키지</strong> 선택</td></tr></tbody></table>

필드 입력/선택 후에 **"다음 →"** 버튼을 클릭합니다.

#### 5.3 생성 다이얼로그 — 2단계

서버 설정 탭에서 **실행 템플릿** 드롭다운을 클릭하여 **"Spring AI (Java)"**&#xB97C; 선택합니다.

<figure><img src="/files/y6hyDnY1UEwhC82bbOSN" alt=""><figcaption></figcaption></figure>

Spring AI 템플릿을 선택하면 config.json이 자동으로 채워집니다:

<figure><img src="/files/HruMrI1fcFVkeq0mAVvF" alt=""><figcaption></figcaption></figure>

#### 5.4 JAR 패키지 선택

Spring AI 템플릿을 선택하면 **JAR 패키지 선택** 드롭다운이 자동으로 표시됩니다. [4.2번](https://app.gitbook.com/o/LZ9WiRmpxWB4qwyrxkns/s/R1SirD7MHs6E1e3QxQcu/~/edit/~/changes/3/basic-tutorials/guides/mcp/spring-ai-mcp#id-4.2-jar)에서 업로드한 JAR 파일을 드롭다운에서 선택합니다.

<figure><img src="/files/ruYVorLuwS8ce6cBUEgr" alt=""><figcaption></figcaption></figure>

> 업로드한 JAR 패키지 목록이 드롭다운에 표시됩니다. 파일명과 버전이 함께 보입니다.

JAR 패키지를 선택하면 자동으로 배포 설정에 반영됩니다. **config.json을 수동으로 수정할 필요가 없습니다.**

<figure><img src="/files/Sc6incx1UM6gNDPmZgsv" alt=""><figcaption></figcaption></figure>

> * 드롭다운에서 JAR를 선택하면 **배포 시 자동으로 해당 jar가 컨테이너에 복사**됩니다
> * config.json에는 `command`, `args`, `env`만 표시됩니다 — `jar_package`는 내부적으로 처리됨
> * `server.jar`는 변경하지 않습니다 — 선택한 jar가 자동으로 `/app/server.jar`에 복사됩니다

#### 5.5 인프라 설정

<table><thead><tr><th width="160.81817626953125">설정</th><th width="252.0909423828125">설명</th><th>권장 값</th></tr></thead><tbody><tr><td><strong>도커 이미지</strong></td><td>MCP 서버 컨테이너 이미지</td><td>GenOS 기본 이미지 선택</td></tr><tr><td><strong>인스턴스 타입</strong></td><td>CPU/메모리 리소스</td><td>500m CPU / 512Mi 이상</td></tr><tr><td><strong>레플리카</strong></td><td>Pod 수</td><td>1 (초기)</td></tr></tbody></table>

모든 설정을 입력한 후 **"생성"** 버튼을 클릭합니다.

***

### 6. 배포 및 도구 확인

#### 6.1 서버 상세 페이지

MCP 서버 생성 후 상세 페이지에서 서버 정보를 확인합니다.

<figure><img src="/files/1MoMFH76Rfo72On9cUvQ" alt=""><figcaption></figcaption></figure>

#### 6.2 배포

상단의 **"배포"** 버튼을 클릭합니다. 승인 프로세스를 거친 후 배포가 시작됩니다.

배포 시 내부 동작:

```
1. K8s Pod 생성
2. init.sh 실행 → config.json에서 command=java 감지
3. jar_package 필드 확인 → NFS에서 jar를 /app/server.jar로 복사
4. java -jar /app/server.jar 실행
5. Health Check: GET /actuator/health → {"status":"UP"}
6. Pod Ready → 도구 조회 가능
```

#### 6.3 도구 동기화

배포 완료 후 **"중요 정보"** 탭에서 **"도구 동기화"** 버튼을 클릭합니다.

<figure><img src="/files/DJ0LfMBhVnINM9GKpB8X" alt=""><figcaption></figcaption></figure>

> jar 파일에 포함된 `@Tool` 메서드가 자동으로 검출되어 동기화됩니다. 위 예시에서는 **add**, **getWeather**, **hello** 3개 도구가 동기화되었습니다.

#### 6.4 테스트 실행

상단의 **"테스트"** 버튼을 클릭하면 MCP 서버 테스트 다이얼로그가 열립니다.

<figure><img src="/files/F54Q7jZtikp1N17zZxqd" alt=""><figcaption></figcaption></figure>

1. **도구 선택**: 드롭다운에서 테스트할 도구를 선택합니다.
2. **파라미터 입력**: 도구의 입력 파라미터를 입력합니다.
3. **테스트 실행**: 버튼을 클릭하면 실시간으로 도구가 호출됩니다.

#### 6.5 테스트 결과

<figure><img src="/files/7S4ceKQYJnboo1UVSX0c" alt=""><figcaption></figcaption></figure>

> `getWeather(city: "서울")` 호출 결과: **"서울 날씨: 맑음, 22°C"**
>
> Spring AI MCP 서버의 `@Tool` 메서드가 GenOS UI에서 정상적으로 호출되었습니다.

***

### 7. 다른 템플릿 사용하기

#### NPX 패키지 (Node.js)

<figure><img src="/files/lEzaj0A7Qtf04KuMoPv0" alt=""><figcaption></figcaption></figure>

```json
{
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-example"],
  "env": {}
}
```

#### Python 모듈

<figure><img src="/files/L6F2Doh3m7naO7WRtz5k" alt=""><figcaption></figcaption></figure>

```json
{
  "command": "python",
  "args": ["-m", "mcp_server"],
  "env": {}
}
```

#### 직접 입력

실행 템플릿에서 **"실행 템플릿"** (빈 값)을 선택하면 config.json을 직접 작성할 수 있습니다. placeholder에 npx 예제가 표시됩니다.

#### 패키지 관리 페이지 참고

| 패키지 유형      | 메뉴 위치               | 파일 형식  | 용도               |
| ----------- | ------------------- | ------ | ---------------- |
| **JAR 패키지** | 관리 > 리소스 > JAR 패키지  | `.jar` | Spring AI (Java) |
| PyPI 패키지    | 관리 > 리소스 > PyPI 패키지 | `.whl` | Python           |
| NPM 패키지     | 관리 > 리소스 > NPM 패키지  | `.tgz` | Node.js          |

***

### 8. config.json 형식 참고

#### Spring AI — 기본

```json
{
  "command": "java",
  "args": ["-jar", "server.jar"],
  "env": {
    "SPRING_PROFILES_ACTIVE": "prod"
  }
}
```

> JAR 패키지는 2단계의 **JAR 패키지 선택** 드롭다운에서 선택합니다. config.json에 직접 입력하지 않습니다.

#### Spring AI — JVM 옵션 커스텀

```json
{
  "command": "java",
  "args": ["-jar", "server.jar"],
  "env": {
    "JAVA_OPTS": "-Xmx1g -Dspring.profiles.active=prod",
    "SPRING_DATASOURCE_URL": "jdbc:mysql://db:3306/mydb"
  }
}
```

> `JAVA_OPTS` 미설정 시 기본값: `-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0`

#### Spring AI — Docker 이미지에 jar 포함 (jar\_package 불필요)

jar를 Docker 이미지에 직접 포함한 경우:

```json
{
  "command": "java",
  "args": ["-jar", "/app/my-server.jar"]
}
```

> 이 경우 `jar_package` 필드 없이 이미지 내 jar 경로를 직접 지정합니다.

#### NPX (Node.js)

```json
{
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem"]
}
```

#### Python

```json
{
  "command": "python",
  "args": ["-m", "mcp_server"],
  "pip_packages": ["my-mcp-package==1.0.0"]
}
```

***

### 9. FAQ

#### Q: 하나의 jar에 도구를 몇 개까지 넣을 수 있나요?

* **제한 없습니다.** `@Tool` 어노테이션을 붙인 메서드 수만큼 도구가 등록됩니다. 여러 `@Service` 클래스에 분산해서 작성할 수도 있습니다.

#### Q: Spring AI 서버에 `spring-boot-starter-actuator`가 필수인가요?

* **권장**입니다. GenOS는 `GET /actuator/health`로 Pod health check를 수행합니다. Actuator가 없으면 startupProbe가 실패하여 Pod가 시작되지 않습니다.

#### Q: Spring AI 최소 버전은?

* **Spring AI 1.1 이상**이 필요합니다. 1.1부터 StreamableHTTP transport를 지원합니다.

#### Q: server.jar는 뭔가요? 직접 만들어야 하나요?

* `server.jar`는 config.json에서 사용하는 **컨테이너 내부 경로명**입니다. 사용자가 직접 만들 필요 없습니다. MCP 서버 생성 시 **JAR 패키지 선택** 드롭다운에서 선택한 jar가 배포 시 자동으로 `/app/server.jar`에 복사됩니다.

#### Q: JAR 패키지를 선택하지 않으면 어떻게 되나요?

* JAR 패키지를 선택하지 않고 `"args": ["-jar", "server.jar"]`만 있으면, 컨테이너 이미지 안에 `server.jar`가 있어야 합니다. GenOS 기본 MCP 이미지에는 jar가 없으므로, **JAR 패키지를 드롭다운에서 선택**하거나 **jar가 포함된 사용자 Docker 이미지**를 사용해야 합니다.

#### Q: JVM 메모리 설정은 어떻게 하나요?

* config.json의 `env`에 `JAVA_OPTS`를 설정합니다:

```json
"env": { "JAVA_OPTS": "-Xmx512m -Xms256m" }
```

* 미설정 시 기본값으로 컨테이너 메모리의 75%를 사용합니다.

#### Q: 기존 npx/python 서버에 영향이 있나요?

* **없습니다.** `command=java`인 경우에만 새 경로가 적용되며, npx/python은 기존 방식을 그대로 사용합니다.

#### Q: jar 파일을 업데이트하려면?

* 1\. 관리 > 리소스 > JAR 패키지에서 해당 패키지를 **수정** (새 jar 파일 업로드)
* 2\. MCP 서버 상세 페이지에서 **재배포**

#### Q: 샘플 프로젝트가 있나요?

`test/mcp/spring-ai-test-server/`에 완전한 Spring AI MCP 서버 샘플이 있습니다:

* `pom.xml` — Spring AI 1.1.3 + Actuator
* `WeatherService.java` — 3개 도구 (getWeather, add, hello)
* `application.yml` — StreamableHTTP 설정
* `Dockerfile` — Docker multi-stage 빌드

***

> 문서 작성일: 2026-03-29 스크린샷: Playwright E2E 자동 테스트에서 캡처 (GenOS v1.8.2, Kind 클러스터 프로덕션 기준)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://genos-docs.gitbook.io/default/v1.8.5/basic-tutorials/guides/mcp/spring-ai-mcp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
