LangChain4j - Spring AI MCP 구축기 (2)

김주엽·2025년 5월 16일
post-thumbnail

✨ 들어가며

LangChain4j 프레임워크로 간단하게 MCP 클라이언트를 구현합니다.


🛠️ 1. 의존성 추가

implementation 'dev.langchain4j:langchain4j-mcp:1.0.0-beta4'
implementation 'dev.langchain4j:langchain4j-google-ai-gemini-spring-boot-starter:1.0.0-beta4'
implementation 'dev.langchain4j:langchain4j-spring-boot-starter:1.0.0-beta4'
  • 위 의존성들은 차례대로 MCP, Google Gemini 모델 그리고 LangChain4j의 스프링 부트 지원을 위한 라이브러리입니다.

🛡️ 2. application.yml 설정

langchain4j:
  mcp:
    sse-url: ${SSE_URL}
  google-ai-gemini:
    chat-model:
      api-key: ${GEMINI_API_KEY}
      model-name: ${GEMINI_MODEL}
      log-requests-and-responses: true # prod에서는 비활성화
  • langchain4j:: LangChain4j 프레임워크 관련 설정을 묶어 관리하는 최상위 설정입니다.
    • mcp:: Model Context Protocol (MCP) 관련 설정을 정의하는 영역입니다.
      • sse-url:: MCP 서버가 제공하는 SSE (Server-Sent Events) 엔드포인트 URL을 설정합니다.
    • google-ai-gemini:: Google의 Gemini AI 모델과 관련된 설정을 정의하는 영역입니다. 다른 LLM을 사용하는 경우 해당 LLM에 맞는 설정을 해야 합니다.
      • chat-model:: Gemini 모델의 채팅 기능을 사용하기 위한 설정을 포함합니다.
        • api-key:: Google Cloud Platform (GCP)에서 발급받은 Gemini API 키를 설정합니다.
          • ${GEMINI_API_KEY}는 보안을 위해 환경 변수 등으로 관리하는 것이 좋습니다.
          • 이 키를 통해 애플리케이션이 Gemini 모델에 접근하고 사용할 수 있습니다.
        • model-name:: 사용할 Gemini 모델의 이름을 지정합니다.
        • log-requests-and-responses:: Gemini 모델과의 요청 및 응답 내용을 로깅할지 여부를 설정합니다.
          • 운영 환경 (prod)에서는 false로 설정하여 비활성화하는 것이 좋습니다.

📝 3. 어시스턴트 인터페이스 정의

public interface AdminAssistant {
    @SystemMessage("""
          당신은 관리자를 위한 AI 도우미입니다.
          사용자 관리 및 기타 관리 작업을 지원할 수 있습니다.
          또한, 관리자가 명령할 때 도구에 대한 조작이 가능합니다.
          도구를 사용해서 조작할 때는 반드시 관리자에게 실행 여부를 물어보세요.
          도구를 사용한 응답을 할 때는 도구 결과를 그대로 내뱉지 말고 재가공해서 응답하세요.
            """)
    String chat(@UserMessage String prompt);
}
  • @SystemMessage: 시스템 메시지로서 LLM에게 전달되어 어시스턴트의 시스템 지침을 전달합니다.
  • @UserMessage: 사용자의 질문이나 요청을 담아 LLM에게 전달합니다.
  • 필요에 따라 여러 어시스턴트를 정의해 역할을 분리할 수 있습니다.

⚙️ 4. Configuration 작성

@Configuration 클래스에서 MCP 통신, 도구 공급자, 챗 메모리, 어시스턴트 등록을 설정합니다.

@Configuration
public class AssistantConfig {
    @Value("${langchain4j.mcp.sse-url}")
    private String sseUrl;

    @Bean
    public McpTransport transport() {
        return new HttpMcpTransport.Builder()
                .sseUrl(sseUrl)
                .timeout(Duration.ofSeconds(604800)) // 7일
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    @Bean
    public McpClient mcpClient(McpTransport transport) {
        return new DefaultMcpClient.Builder()
                .transport(transport)
                .build();
    }

    @Bean
    public McpToolProvider toolProvider(McpClient mcpClient) {
        return McpToolProvider.builder()
                .mcpClients(List.of(mcpClient))
                .build();
    }

    @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.withMaxMessages(10);
    }

    @Bean
    public UserAssistant userAssistant(ChatLanguageModel chatLanguageModel,
                                       ChatMemory chatMemory) {
        return AiServices.builder(UserAssistant.class)
                .chatLanguageModel(chatLanguageModel)
                .chatMemory(chatMemory)
                .build();
    }

    @Bean
    public AdminAssistant adminAssistant(ChatLanguageModel chatLanguageModel,
                                         McpToolProvider toolProvider, ChatMemory chatMemory) {
        return AiServices.builder(AdminAssistant.class)
                .chatLanguageModel(chatLanguageModel)
                .toolProvider(toolProvider)
                .chatMemory(chatMemory)
                .build();
    }
}
  • McpTransport: LangChain4j는 MCP 서버와의 통신을 위해 두 가지 유형의 전송 방식을 지원합니다.
    • HTTP: SSE (Server-Sent Events) 채널을 통해 서버로부터 이벤트를 수신하고, HTTP POST 요청을 사용하여 서버와 통신합니다.
      • 위 예시에서는 HTTP 방식을 사용하여 MCP 서버와 통신하도록 구성했습니다.
    • stdio: 표준 입출력을 통해 MCP 서버와 통신합니다.
    • sseUrl: MCP 서버에 설정된 SSE 채널의 URL을 지정합니다.
      • 이 URL은 애플리케이션 설정 파일 (application.properties 또는 application.yml)에서 관리할 수 있습니다.
    • timeout: MCP 서버와의 연결 타임아웃 시간을 설정합니다.
      • 현재 LangChain4j는 타임아웃 시 자동 재연결 기능을 제공하지 않으며, 이는 추후 개발될 예정이라고 합니다.
    • logRequests, logResponses: HTTP 요청 및 응답 로깅 여부를 설정합니다.
  • McpClient: MCP 서버와 실제로 연결을 수행하는 클라이언트 객체를 생성합니다.
    • 생성 시 McpTransport Bean을 주입받아 사용합니다.
  • McpToolProvider: MCP 클라이언트에 연결할 도구 제공자를 생성합니다. 이를 통해 LLM이 외부 도구를 사용할 수 있게 됩니다.
  • ChatMemory: LLM과의 대화 내용을 기억하는 메모리 값을 설정합니다.
    • 위 예시에서는 최근 10개의 메시지만을 기억하도록 설정되어 있습니다.
  • Assistant: AiServices의 빌더 패턴을 사용하여 어시스턴트 인터페이스의 구현체를 Bean으로 등록합니다.
    • 사용할 LLM 모델 (chatLanguageModel), MCP 도구 제공자 (toolProvider), 그리고 채팅 메모리 (chatMemory)를 설정합니다.
    • 위 예시에서는 일반 사용자를 위한 UserAssistant와 도구 사용 권한이 있는 AdminAssistant 두 가지 어시스턴트를 정의했습니다.

🚀 5. 어시스턴트 사용 예시

생성된 어시스턴트 Bean을 서비스 클래스에서 주입받아 다음과 같이 사용할 수 있습니다.

@Service
@RequiredArgsConstructor
@Slf4j
public class ChatServiceImpl implements ChatService {
    private final UserAssistant userAssistant;
    private final AdminAssistant adminAssistant;

    @Override
    public String userChat(String prompt) {
        log.info("user prompt: {}", prompt);
        return userAssistant.chat(prompt);
    }

    @Override
    public String adminChat(String prompt) {
        log.info("admin prompt: {}", prompt);
        return adminAssistant.chat(prompt);
    }
}

이제 ChatServiceuserChat 메서드를 호출하면 일반 사용자 어시스턴트와, adminChat 메서드를 호출하면 관리자 어시스턴트와 상호작용할 수 있습니다.


📘 예제 코드

GitHub - kjyy08/langchain4j-mcp-client-example


📄 참고자료

profile
나야 루이지

0개의 댓글