STDIO 및 SSE MCP 서버

STDIO 및 SSE MCP 서버 (STDIO and SSE MCP Servers)

STDIO와 SSE MCP 서버는 각각 전용 starter가 있는 여러 전송 메커니즘을 지원해요. STDIO는 명령줄·데스크톱 도구에 적합하고, SSE는 Spring MVC 또는 WebFlux 기반의 HTTP 실시간 스트리밍을 제공해요. 이 글에서 구성 프로퍼티와 기능을 차근차근 살펴볼게요.

출처: 문서

본문

STDIO 및 SSE MCP 서버 (STDIO and SSE MCP Servers)

STDIO와 SSE MCP 서버는 각각 전용 starter가 있는 여러 전송 메커니즘을 지원해요.

참고: STDIO 및 SSE 서버에 연결하려면 STDIO 클라이언트 또는 SSE 클라이언트를 사용하세요.

STDIO MCP 서버

STDIO 서버 전송과 함께 완전한 MCP 서버 기능 지원.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
  • 명령줄과 데스크톱 도구에 적합
  • 추가 웹 의존성 불필요
  • 기본 서버 컴포넌트 구성
  • 도구, 리소스, 프롬프트 명세 처리
  • 서버 기능과 변경 알림 관리
  • 동기·비동기 서버 구현 모두 지원

SSE WebMVC 서버

Spring MVC 기반의 SSE(Server-Sent Events) 서버 전송과 선택적 STDIO 전송과 함께 완전한 MCP 서버 기능 지원.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
  • Spring MVC를 사용한 HTTP 기반 전송 (WebMvcSseServerTransportProvider)
  • 자동 구성된 SSE 엔드포인트
  • 선택적 STDIO 전송 (spring.ai.mcp.server.stdio=true로 활성화)
  • spring-boot-starter-web과 org.springframework.ai:mcp-spring-webmvc 의존성 포함

SSE WebFlux 서버

Spring WebFlux 기반의 SSE(Server-Sent Events) 서버 전송과 선택적 STDIO 전송과 함께 완전한 MCP 서버 기능 지원.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>

이 starter는 McpWebFluxServerAutoConfiguration와 McpServerAutoConfiguration 자동 구성을 활성화해 다음을 제공해요:

  • Spring WebFlux를 사용한 반응형 전송 (WebFluxSseServerTransportProvider)
  • 자동 구성된 반응형 SSE 엔드포인트
  • 선택적 STDIO 전송 (spring.ai.mcp.server.stdio=true로 활성화)
  • spring-boot-starter-webflux와 org.springframework.ai:mcp-spring-webflux 의존성 포함

참고: Spring Boot의 기본 동작 때문에 org.springframework.web.servlet.DispatcherServlet과 org.springframework.web.reactive.DispatcherHandler가 모두 클래스패스에 있으면 Spring Boot는 DispatcherServlet을 우선시해요. 따라서 프로젝트가 spring-boot-starter-web을 사용한다면 spring-ai-starter-mcp-server-webflux 대신 spring-ai-starter-mcp-server-webmvc를 사용하는 것이 권장돼요.

구성 프로퍼티 (Configuration Properties)

공통 프로퍼티 (Common Properties)

모든 공통 프로퍼티는 spring.ai.mcp.server 프리픽스가 붙어요:

Property Description Default
enabled MCP 서버 활성화/비활성화 true
tool-callback-converter Spring AI ToolCallback을 MCP Tool 스펙으로 변환 활성화/비활성화 true
stdio STDIO 전송 활성화/비활성화 false
name 식별을 위한 서버 이름 mcp-server
version 서버 버전 1.0.0
instructions 클라이언트가 이 서버와 상호작용하는 방법에 대한 지침을 제공하는 선택적 지시사항 null
type 서버 타입 (SYNC/ASYNC) SYNC
capabilities.resource 리소스 기능 활성화/비활성화 true
capabilities.tool 도구 기능 활성화/비활성화 true
capabilities.prompt 프롬프트 기능 활성화/비활성화 true
capabilities.completion 완성 기능 활성화/비활성화 true
resource-change-notification 리소스 변경 알림 활성화 true
prompt-change-notification 프롬프트 변경 알림 활성화 true
tool-change-notification 도구 변경 알림 활성화 true
expose-mcp-client-tools 다운스트림 MCP 도구(MCP 클라이언트가 제공)를 이 MCP 서버의 도구로 다시 노출할지 여부 false
tool-response-mime-type 도구 이름별 선택적 응답 MIME 타입. 예를 들어 spring.ai.mcp.server.tool-response-mime-type.generateImage=image/png는 generateImage() 도구 이름에 image/png MIME 타입을 연결해요 -
request-timeout 요청이 타임아웃되기 전에 서버 응답을 기다리는 기간. 도구 호출, 리소스 접근, 프롬프트 작업을 포함해 클라이언트를 통해 이루어지는 모든 요청에 적용돼요 20 seconds

MCP 어노테이션 프로퍼티 (MCP Annotations Properties)

MCP 서버 어노테이션은 Java 어노테이션을 사용해 MCP 서버 핸들러를 선언적으로 구현하는 방법을 제공해요. 서버 mcp-annotations 프로퍼티는 spring.ai.mcp.server.annotation-scanner 프리픽스가 붙어요:

Property Description Default Value
enabled MCP 서버 어노테이션 자동 스캔 활성화/비활성화 true

SSE 프로퍼티 (SSE Properties)

모든 SSE 프로퍼티는 spring.ai.mcp.server 프리픽스가 붙어요:

Property Description Default
sse-message-endpoint 클라이언트가 메시지를 보내기 위해 사용하는 웹 전송용 커스텀 SSE 메시지 엔드포인트 경로 /mcp/message
sse-endpoint 웹 전송용 커스텀 SSE 엔드포인트 경로 /sse
base-url 선택적 URL 프리픽스. 예를 들어 base-url=/api/v1이면 클라이언트는 /api/v1 + sse-endpoint에서 SSE 엔드포인트에, 메시지 엔드포인트는 /api/v1 + sse-message-endpoint에서 접근해야 해요 -
keep-alive-interval 연결 keep-alive 간격 null (비활성)

참고: 하위 호환성 때문에 SSE 프로퍼티에는 추가 접미사(예: .sse)가 없어요.

기능과 역량 (Features and Capabilities)

MCP Server Boot Starter는 서버가 도구, 리소스, 프롬프트를 클라이언트에 노출할 수 있게 해 줘요. Spring 빈으로 등록된 커스텀 기능 핸들러를 서버 타입에 따라 자동으로 동기/비동기 명세로 변환해요:

도구 (Tools)

언어 모델이 호출할 수 있는 도구를 서버가 노출할 수 있게 해 줘요. MCP Server Boot Starter는 다음을 제공해요:

  • 변경 알림 지원
  • Spring AI 도구를 서버 타입에 따라 자동으로 동기/비동기 명세로 변환
  • Spring 빈을 통한 자동 도구 명세:
@Bean
public ToolCallbackProvider myTools(...) {
    List<ToolCallback> tools = ...
    return ToolCallbackProvider.from(tools);
}

또는 저수준 API 사용:

@Bean
public List<McpServerFeatures.SyncToolSpecification> myTools(...) {
    List<McpServerFeatures.SyncToolSpecification> tools = ...
    return tools;
}

자동 설정은 다음에서 모든 도구 콜백을 자동으로 감지하고 등록해요:

  • 개별 ToolCallback 빈
  • ToolCallback 빈 목록
  • ToolCallbackProvider 빈

도구는 이름으로 중복 제거되며, 각 도구 이름의 첫 번째 등장이 사용돼요.

참고: tool-callback-converter를 false로 설정하면 모든 도구 콜백의 자동 감지·등록을 비활성화할 수 있어요.

도구 컨텍스트 지원 (Tool Context Support)

ToolContext가 지원되어 도구 호출에 컨텍스트 정보를 전달할 수 있어요. exchange 키 아래에 McpSyncServerExchange 인스턴스를 담고 있으며, McpToolUtils.getMcpExchange(toolContext)로 접근할 수 있어요. exchange.loggingNotification(…)과 exchange.createMessage(…)을 보여 주는 예제를 참고하세요.

리소스 (Resources)

서버가 클라이언트에 리소스를 노출하는 표준화된 방법을 제공해요.

  • 정적·동적 리소스 명세
  • 선택적 변경 알림
  • 리소스 템플릿 지원
  • 동기/비동기 리소스 명세 간 자동 변환
  • Spring 빈을 통한 자동 리소스 명세:
@Bean
public List<McpServerFeatures.SyncResourceSpecification> myResources(...) {
    var systemInfoResource = McpSchema.Resource.builder(...);
    var resourceSpecification = new McpServerFeatures.SyncResourceSpecification(systemInfoResource, (exchange, request) -> {
        try {
            var systemInfo = Map.of(...);
            String jsonContent = new JsonMapper().writeValueAsString(systemInfo);
            return McpSchema.ReadResourceResult.builder(
                    List.of(McpSchema.TextResourceContents.builder(request.uri(), jsonContent).mimeType("application/json").build())).build();
        }
        catch (Exception e) {
            throw new RuntimeException("Failed to generate system info", e);
        }
    });

    return List.of(resourceSpecification);
}

프롬프트 (Prompts)

서버가 클라이언트에 프롬프트 템플릿을 노출하는 표준화된 방법을 제공해요.

  • 변경 알림 지원
  • 템플릿 버전 관리
  • 동기/비동기 프롬프트 명세 간 자동 변환
  • Spring 빈을 통한 자동 프롬프트 명세:
@Bean
public List<McpServerFeatures.SyncPromptSpecification> myPrompts() {
    var prompt = McpSchema.Prompt.builder("greeting").description("A friendly greeting prompt")
        .arguments(List.of(McpSchema.PromptArgument.builder("name").description("The name to greet").required(true).build())).build();

    var promptSpecification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, getPromptRequest) -> {
        String nameArgument = (String) getPromptRequest.arguments().get("name");
        if (nameArgument == null) { nameArgument = "friend"; }
        var userMessage = PromptMessage.builder(Role.USER, TextContent.builder("Hello " + nameArgument + "! How can I assist you today?").build()).build();
        return GetPromptResult.builder(List.of(userMessage)).description("A personalized greeting message").build();
    });

    return List.of(promptSpecification);
}

완성 (Completions)

서버가 클라이언트에 완성 기능을 노출하는 표준화된 방법을 제공해요.

  • 동기·비동기 완성 명세 모두 지원
  • Spring 빈을 통한 자동 등록:
@Bean
public List<McpServerFeatures.SyncCompletionSpecification> myCompletions() {
    var completion = new McpServerFeatures.SyncCompletionSpecification(
        McpSchema.PromptReference.builder("code-completion").title("Provides code completion suggestions").build(),
        (exchange, request) -> {
            // Implementation that returns completion suggestions
            return new McpSchema.CompleteResult(List.of("python", "pytorch", "pyside"), 10, true);
        }
    );

    return List.of(completion);
}

로깅 (Logging)

서버가 구조화된 로그 메시지를 클라이언트에 보내는 표준화된 방법을 제공해요. 도구, 리소스, 프롬프트 또는 완성 호출 핸들러 안에서 제공된 McpSyncServerExchange/McpAsyncServerExchange exchange 객체를 사용해 로깅 메시지를 보내요:

(exchange, request) -> {
        exchange.loggingNotification(LoggingMessageNotification.builder(LoggingLevel.INFO, "This is a test log message")
            .logger("test-logger")
            .build());
}

MCP 클라이언트에서 로깅 consumer를 등록해 이 메시지를 처리할 수 있어요:

mcpClientSpec.loggingConsumer((McpSchema.LoggingMessageNotification log) -> {
    // Handle log messages
});

진행 (Progress)

서버가 클라이언트에 진행 업데이트를 보내는 표준화된 방법을 제공해요. 도구, 리소스, 프롬프트 또는 완성 호출 핸들러 안에서 제공된 McpSyncServerExchange/McpAsyncServerExchange exchange 객체를 사용해 진행 알림을 보내요:

(exchange, request) -> {
        exchange.progressNotification(ProgressNotification.builder("test-progress-token", 0.25)
            .total(1.0)
            .message("tool call in progress")
            .build());
}

MCP 클라이언트는 진행 알림을 받아 그에 맞게 UI를 업데이트할 수 있어요. 이를 위해 진행 consumer를 등록해야 해요.

mcpClientSpec.progressConsumer((McpSchema.ProgressNotification progress) -> {
    // Handle progress notifications
});

루트 목록 변경 (Root List Changes)

roots가 변경되면 listChanged를 지원하는 클라이언트가 루트 변경 알림을 보내요.

  • 루트 변경 모니터링 지원
  • 반응형 애플리케이션을 위한 비동기 consumer 자동 변환
  • Spring 빈을 통한 선택적 등록
@Bean
public BiConsumer<McpSyncServerExchange, List<McpSchema.Root>> rootsChangeHandler() {
    return (exchange, roots) -> {
        logger.info("Registering root resources: {}", roots);
    };
}

핑 (Ping)

서버가 클라이언트가 아직 살아 있는지 확인하는 핑 메커니즘. 도구, 리소스, 프롬프트 또는 완성 호출 핸들러 안에서 제공된 McpSyncServerExchange/McpAsyncServerExchange exchange 객체를 사용해 핑 메시지를 보내요:

(exchange, request) -> {
        exchange.ping();
}

Keep Alive

서버는 선택적으로 연결된 클라이언트에 주기적으로 핑을 보내 연결 상태를 확인할 수 있어요. 기본적으로 keep-alive는 비활성화돼 있어요. keep-alive를 활성화하려면 구성에서 keep-alive-interval 프로퍼티를 설정하세요:

spring:
  ai:
    mcp:
      server:
        keep-alive-interval: 30s

사용 예시 (Usage Examples)

표준 STDIO 서버 구성 (Standard STDIO Server Configuration)

# Using spring-ai-starter-mcp-server
spring:
  ai:
    mcp:
      server:
        name: stdio-mcp-server
        version: 1.0.0
        type: SYNC

WebMVC 서버 구성 (WebMVC Server Configuration)

# Using spring-ai-starter-mcp-server-webmvc
spring:
  ai:
    mcp:
      server:
        name: webmvc-mcp-server
        version: 1.0.0
        type: SYNC
        instructions: "This server provides weather information tools and resources"
        capabilities:
          tool: true
          resource: true
          prompt: true
          completion: true
        # sse properties
        sse-message-endpoint: /mcp/messages
        keep-alive-interval: 30s

WebFlux 서버 구성 (WebFlux Server Configuration)

# Using spring-ai-starter-mcp-server-webflux
spring:
  ai:
    mcp:
      server:
        name: webflux-mcp-server
        version: 1.0.0
        type: ASYNC  # Recommended for reactive applications
        instructions: "This reactive server provides weather information tools and resources"
        capabilities:
          tool: true
          resource: true
          prompt: true
          completion: true
        # sse properties
        sse-message-endpoint: /mcp/messages
        keep-alive-interval: 30s

MCP 서버로 Spring Boot 애플리케이션 만들기

@Service
public class WeatherService {

    @Tool(description = "Get weather information by city name")
    public String getWeather(String cityName) {
        // Implementation
    }
}

@SpringBootApplication
public class McpServerApplication {

    private static final Logger logger = LoggerFactory.getLogger(McpServerApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }

	@Bean
	public ToolCallbackProvider weatherTools(WeatherService weatherService) {
		return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
	}
}

자동 설정은 도구 콜백을 MCP 도구로 자동으로 등록해요. ToolCallback을 생성하는 빈이 여러 개 있어도 되며, 자동 설정이 그것들을 병합해요.

예제 애플리케이션 (Example Applications)

더 알아보기 (Learn more)