상태 없는(Stateless) Streamable-HTTP MCP 서버

상태 없는(Stateless) Streamable-HTTP MCP 서버

상태 없는 Streamable-HTTP MCP 서버는 요청 간에 세션 상태를 유지하지 않는 단순화된 배포를 위해 설계됐어요. 마이크로서비스 아키텍처와 클라우드 네이티브 배포에 이상적인 구조라서, 세션 관리 없이 가볍게 서버를 운영할 수 있어요. 이 글에서 구성 방법과 기능을 살펴볼게요.

출처: 문서

본문

상태 없는 Streamable-HTTP MCP 서버 (Stateless Streamable-HTTP MCP Servers)

상태 없는 Streamable-HTTP MCP 서버는 요청 간에 세션 상태를 유지하지 않는 단순화된 배포를 위해 설계됐어요. 이 서버는 마이크로서비스 아키텍처와 클라우드 네이티브 배포에 이상적이에요.

참고: spring.ai.mcp.server.protocol=STATELESS 프로퍼티를 설정하세요.

참고: 상태 없는 서버에 연결하려면 Streamable-HTTP 클라이언트를 사용하세요.

참고: 상태 없는 서버는 MCP 클라이언트에 대한 메시지 요청(예: elicitation, sampling, ping)을 지원하지 않아요.

상태 없는 WebMVC 서버 (Stateless WebMVC Server)

spring-ai-starter-mcp-server-webmvc 의존성을 사용하세요:

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

그리고 spring.ai.mcp.server.protocol 프로퍼티를 STATELESS로 설정하세요.

spring.ai.mcp.server.protocol=STATELESS
  • Spring MVC 전송을 사용한 상태 없는 동작
  • 세션 상태 관리 없음
  • 단순화된 배포 모델
  • 클라우드 네이티브 환경에 최적화

상태 없는 WebFlux 서버 (Stateless WebFlux Server)

spring-ai-starter-mcp-server-webflux 의존성을 사용하세요:

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

그리고 spring.ai.mcp.server.protocol 프로퍼티를 STATELESS로 설정하세요.

  • WebFlux 전송을 사용한 반응형 상태 없는 동작
  • 세션 상태 관리 없음
  • 블로킹되지 않는 요청 처리
  • 높은 처리량 시나리오에 최적화

구성 프로퍼티 (Configuration Properties)

공통 프로퍼티 (Common Properties)

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

Property Description Default
enabled 상태 없는 MCP 서버 활성화/비활성화 true
protocol MCP 서버 프로토콜 상태 없는 서버를 활성화하려면 STATELESS로 설정해야 함
tool-callback-converter Spring AI ToolCallback을 MCP Tool 스펙으로 변환 활성화/비활성화 true
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
expose-mcp-client-tools 다운스트림 MCP 도구(MCP 클라이언트가 제공)를 이 MCP 서버의 도구로 다시 노출할지 여부 false
tool-response-mime-type 도구 이름별 응답 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

상태 없는 연결 프로퍼티 (Stateless Connection Properties)

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

Property Description Default
mcp-endpoint 커스텀 MCP 엔드포인트 경로 /mcp
disallow-delete delete 작업 금지 false

기능과 역량 (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<McpStatelessServerFeatures.SyncToolSpecification> myTools(...) {
    List<McpStatelessServerFeatures.SyncToolSpecification> tools = ...
    return tools;
}

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

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

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

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

참고: 도구 컨텍스트 지원은 상태 없는 서버에는 적용되지 않아요.

리소스 (Resources)

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

  • 정적·동적 리소스 명세
  • 선택적 변경 알림
  • 리소스 템플릿 지원
  • 동기/비동기 리소스 명세 간 자동 변환
  • Spring 빈을 통한 자동 리소스 명세:
@Bean
public List<McpStatelessServerFeatures.SyncResourceSpecification> myResources(...) {
    var systemInfoResource = McpSchema.Resource.builder(...);
    var resourceSpecification = new McpStatelessServerFeatures.SyncResourceSpecification(systemInfoResource, (context, 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<McpStatelessServerFeatures.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 McpStatelessServerFeatures.SyncPromptSpecification(prompt, (context, 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);
}

완성 (Completion)

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

  • 동기·비동기 완성 명세 모두 지원
  • Spring 빈을 통한 자동 등록:
@Bean
public List<McpStatelessServerFeatures.SyncCompletionSpecification> myCompletions() {
    var completion = new McpStatelessServerFeatures.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);
}

사용 예시 (Usage Examples)

상태 없는 서버 구성 (Stateless Server Configuration)

spring:
  ai:
    mcp:
      server:
        protocol: STATELESS
        name: stateless-mcp-server
        version: 1.0.0
        type: ASYNC
        instructions: "This stateless server is optimized for cloud deployments"
        streamable-http:
          mcp-endpoint: /api/mcp

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을 생성하는 빈이 여러 개 있어도 되며, 자동 설정이 그것들을 병합해요.

더 알아보기 (Learn more)