MCP 서버

개요

MCP 서버는 Model Context Protocol(MCP) 아키텍처의 기반 구성 요소로, 클라이언트에 도구/리소스/기능을 제공합니다. 즉, 프로토콜의 서버 측을 구현하며 다음을 담당합니다:

  • 클라이언트가 탐색하고 실행할 수 있는 도구(tools) 노출
  • URI 기반 접근 패턴으로 리소스(resources) 관리
  • 프롬프트(prompts) 템플릿 제공 및 프롬프트 요청 처리
  • 클라이언트와 capability 협상 지원
  • 서버 측 프로토콜 동작 구현
  • 동시 클라이언트 연결 관리
  • 구조화된 로깅 및 알림(notification) 제공

서버는 동기/비동기 API를 모두 지원하므로, 다양한 애플리케이션 컨텍스트에서 유연하게 통합할 수 있습니다.

// Create a server with custom configuration
McpSyncServer syncServer = McpServer.sync(transport)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // Enable resource support
        .tools(true)         // Enable tool support
        .prompts(true)       // Enable prompt support
        .logging()           // Enable logging support
        .build())
    .build();

// Register tools, resources, and prompts
syncServer.addTool(syncToolRegistration);
syncServer.addResource(syncResourceRegistration);
syncServer.addPrompt(syncPromptRegistration);

// Send logging notifications
syncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Server initialized")
    .build());

// Close the server when done
syncServer.close();
// Create an async server with custom configuration
McpAsyncServer asyncServer = McpServer.async(transport)
    .serverInfo("my-server", "1.0.0")
    .capabilities(ServerCapabilities.builder()
        .resources(true)     // Enable resource support
        .tools(true)         // Enable tool support
        .prompts(true)       // Enable prompt support
        .logging()           // Enable logging support
        .build())
    .build();

// Register tools, resources, and prompts
asyncServer.addTool(asyncToolRegistration)
    .doOnSuccess(v -> logger.info("Tool registered"))
    .subscribe();

asyncServer.addResource(asyncResourceRegistration)
    .doOnSuccess(v -> logger.info("Resource registered"))
    .subscribe();

asyncServer.addPrompt(asyncPromptRegistration)
    .doOnSuccess(v -> logger.info("Prompt registered"))
    .subscribe();

// Send logging notifications
asyncServer.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Server initialized")
    .build());

// Close the server when done
asyncServer.close()
    .doOnSuccess(v -> logger.info("Server closed"))
    .subscribe();

서버 전송(transport)

프로세스 기반 전송 생성:

StdioServerTransport transport = new StdioServerTransport(new ObjectMapper());

표준 입력/출력(stdin/stdout) 스트림 위에서 양방향 JSON-RPC 메시지 처리를 제공하며, 논블로킹 메시지 처리, 직렬화/역직렬화, 정상 종료(graceful shutdown)를 지원합니다.

주요 기능:

  • stdin/stdout 기반 양방향 통신
  • 프로세스 기반 통합 지원
  • 간단한 설정과 구성
  • 경량 구현

WebFlux 기반 SSE 서버 전송을 생성합니다. mcp-spring-webflux 의존성이 필요합니다.

@Configuration
class McpConfig {
    @Bean
    WebFluxSseServerTransport webFluxSseServerTransport(ObjectMapper mapper) {
        return new WebFluxSseServerTransport(mapper, "/mcp/message");
    }

    @Bean
    RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransport transport) {
        return transport.getRouterFunction();
    }
}

MCP HTTP+SSE 전송 사양을 구현하며, 다음을 제공합니다:

  • WebFlux 기반 리액티브 HTTP 스트리밍
  • SSE 엔드포인트를 통한 동시 클라이언트 연결
  • 메시지 라우팅 및 세션 관리
  • 정상 종료 기능

WebMvc 기반 SSE 서버 전송을 생성합니다. mcp-spring-webmvc 의존성이 필요합니다.

@Configuration
@EnableWebMvc
class McpConfig {
    @Bean
    WebMvcSseServerTransport webMvcSseServerTransport(ObjectMapper mapper) {
        return new WebMvcSseServerTransport(mapper, "/mcp/message");
    }

    @Bean
    RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransport transport) {
        return transport.getRouterFunction();
    }
}

MCP HTTP+SSE 전송 사양을 구현하며, 다음을 제공합니다:

  • 서버-사이드 이벤트 스트리밍
  • Spring WebMVC 통합
  • 전통적인 웹 애플리케이션 지원
  • 동기 작업 처리

Servlet 기반 SSE 서버 전송을 생성합니다. 코어 mcp 모듈에 포함되어 있습니다. HttpServletSseServerTransport는 어떤 Servlet 컨테이너에서도 사용할 수 있습니다. Spring Web 애플리케이션에서 사용하려면 Servlet 빈으로 등록할 수 있습니다:

@Configuration
@EnableWebMvc
public class McpServerConfig implements WebMvcConfigurer {

    @Bean
    public HttpServletSseServerTransport servletSseServerTransport() {
        return new HttpServletSseServerTransport(new ObjectMapper(), "/mcp/message");
    }

    @Bean
    public ServletRegistrationBean customServletBean(HttpServletSseServerTransport servlet) {
        return new ServletRegistrationBean(servlet);
    }
}

전통적인 Servlet API를 사용해 MCP HTTP+SSE 전송 사양을 구현하며, 다음을 제공합니다:

  • Servlet 6.0 async 지원을 활용한 비동기 메시지 처리
  • 다중 클라이언트 연결을 위한 세션 관리
  • 두 종류의 엔드포인트:
    • 서버→클라이언트 이벤트를 위한 SSE 엔드포인트(/sse)
    • 클라이언트→서버 요청을 위한 메시지 엔드포인트(구성 가능)
  • 오류 처리 및 응답 포맷팅
  • 정상 종료 지원

서버 capability

서버는 다양한 capability로 구성할 수 있습니다:

var capabilities = ServerCapabilities.builder()
    .resources(false, true)  // Resource support with list changes notifications
    .tools(true)            // Tool support with list changes notifications
    .prompts(true)          // Prompt support with list changes notifications
    .logging()              // Enable logging support (enabled by default with logging level INFO)
    .build();

로깅 지원

서버는 구조화된 로깅 기능을 제공하며, 다양한 심각도 수준으로 클라이언트에 로그 메시지를 전송할 수 있습니다:

// Send a log message to clients
server.loggingNotification(LoggingMessageNotification.builder()
    .level(LoggingLevel.INFO)
    .logger("custom-logger")
    .data("Custom log message")
    .build());

클라이언트는 mcpClient.setLoggingLevel(level) 요청을 통해 수신할 최소 로깅 레벨을 제어할 수 있습니다. 설정된 레벨보다 낮은 메시지는 필터링됩니다. 지원 로깅 레벨(심각도 증가 순): DEBUG (0), INFO (1), NOTICE (2), WARNING (3), ERROR (4), CRITICAL (5), ALERT (6), EMERGENCY (7)

도구 등록

// Sync tool registration
var syncToolRegistration = new McpServerFeatures.SyncToolRegistration(
    new Tool("calculator", "Basic calculator", Map.of(
        "operation", "string",
        "a", "number",
        "b", "number"
    )),
    arguments -> {
        // Tool implementation
        return new CallToolResult(result, false);
    }
);
// Async tool registration
var asyncToolRegistration = new McpServerFeatures.AsyncToolRegistration(
    new Tool("calculator", "Basic calculator", Map.of(
        "operation", "string",
        "a", "number",
        "b", "number"
    )),
    arguments -> {
        // Tool implementation
        return Mono.just(new CallToolResult(result, false));
    }
);

리소스 등록

// Sync resource registration
var syncResourceRegistration = new McpServerFeatures.SyncResourceRegistration(
    new Resource("custom://resource", "name", "description", "mime-type", null),
    request -> {
        // Resource read implementation
        return new ReadResourceResult(contents);
    }
);
// Async resource registration
var asyncResourceRegistration = new McpServerFeatures.AsyncResourceRegistration(
    new Resource("custom://resource", "name", "description", "mime-type", null),
    request -> {
        // Resource read implementation
        return Mono.just(new ReadResourceResult(contents));
    }
);

프롬프트 등록

// Sync prompt registration
var syncPromptRegistration = new McpServerFeatures.SyncPromptRegistration(
    new Prompt("greeting", "description", List.of(
        new PromptArgument("name", "description", true)
    )),
    request -> {
        // Prompt implementation
        return new GetPromptResult(description, messages);
    }
);
// Async prompt registration
var asyncPromptRegistration = new McpServerFeatures.AsyncPromptRegistration(
    new Prompt("greeting", "description", List.of(
        new PromptArgument("name", "description", true)
    )),
    request -> {
        // Prompt implementation
        return Mono.just(new GetPromptResult(description, messages));
    }
);

오류 처리

SDK는 McpError 클래스를 통해 포괄적인 오류 처리를 제공합니다. 여기에는 프로토콜 호환성, 전송 통신, JSON-RPC 메시징, 도구 실행, 리소스 관리, 프롬프트 처리, 타임아웃, 연결 문제 등이 포함됩니다. 이처럼 통합된 오류 처리 접근은 동기/비동기 작업 전반에서 일관되고 신뢰할 수 있는 오류 관리를 보장합니다.