Sign in to save your progressYou can keep reading without an account, but completed lessons won't be saved.
Sign in

이제 MCP 서버가 작동하게 되었으니, 클라이언트 측을 구축할 차례입니다. 클라이언트는 우리 애플리케이션이 MCP 서버와 통신하고 그 기능에 접근할 수 있게 해주는 역할을 합니다.

클라이언트 아키텍처 이해하기

코드를 살펴보기 전에, MCP 프로젝트에 관한 중요한 점을 명확히 해두겠습니다. 일반적으로는 MCP 클라이언트나 MCP 서버 중 하나만 구현하게 됩니다 - 둘 다 구현하지는 않습니다. 이 프로젝트에서는 둘이 어떻게 함께 작동하는지 보여드리기 위해 둘 다 구축하고 있습니다.

MCP 클라이언트는 두 가지 주요 구성 요소로 이루어져 있습니다:

  • MCP Client - 세션 사용을 더 쉽게 만들기 위해 우리가 만드는 커스텀 클래스
  • Client Session - 서버에 대한 실제 연결 (MCP Python SDK의 일부)

클라이언트 세션은 사용이 끝나면 리소스 정리가 필요하며, 이것이 바로 우리가 이를 커스텀 클래스로 감싸는 이유입니다. 이를 통해 연결 관리와 정리가 자동으로 처리됩니다.

클라이언트가 우리 애플리케이션에 어떻게 들어맞는가

우리 애플리케이션의 흐름을 기억하시나요? 우리의 CLI 코드는 두 가지 주요 방식으로 Claude와 상호작용해야 합니다:

클라이언트는 서버의 기능을 우리 코드베이스에 노출시킴으로써 이 두 가지 상호작용을 모두 가능하게 합니다.

핵심 클라이언트 함수 구현하기

우리는 두 가지 필수 함수인 list_toolscall_tool을 구현해야 합니다.

List Tools 함수

이 함수는 서버에서 사용 가능한 모든 도구를 가져옵니다:

python
async def list_tools(self) -> list[types.Tool]:
    result = await self.session().list_tools()
    return result.tools

간단합니다 - 우리의 세션(MCP 서버에 대한 연결)에 접근하여, 내장된 list_tools 함수를 호출하고, 결과에서 도구들을 반환합니다.

Call Tool 함수

이 함수는 서버에서 특정 도구를 실행합니다:

python
async def call_tool(
    self, tool_name: str, tool_input: dict
) -> types.CallToolResult | None:
    return await self.session().call_tool(tool_name, tool_input)

우리는 도구 이름과 입력 매개변수(Claude가 제공)를 서버에 전달하고 결과를 반환합니다.

클라이언트 테스트하기

구현이 제대로 작동하는지 확인하기 위해, 직접 테스트해볼 수 있습니다. 클라이언트 파일에는 MCP 서버에 연결하여 명령을 실행하는 테스트 하니스가 포함되어 있습니다.

uv run mcp_client.py를 실행하면 사용 가능한 도구 목록과 그 설명 및 입력 스키마가 반환되어야 합니다. 우리가 서버에서 정의한 read_doc_contentsedit_document 같은 도구들을 볼 수 있을 것입니다.

엔드투엔드 테스트

이제 클라이언트와 서버가 모두 작동하므로, 전체 흐름을 테스트할 수 있습니다. 메인 애플리케이션을 실행하고 Claude에게 "report.pdf 문서의 내용은 무엇인가요?"라고 물으면 다음과 같은 일이 일어나야 합니다:

  1. 사용 가능한 도구 목록을 Claude에게 전송합니다
  2. Claude가 read_doc_contents 도구를 사용하기로 결정합니다
  3. 우리 클라이언트가 서버에서 도구를 호출합니다
  4. 서버가 문서 내용을 반환합니다
  5. Claude가 해당 정보로 응답합니다

클라이언트는 애플리케이션 코드와 MCP 서버 사이의 다리 역할을 하며, 저수준 연결 세부 사항을 직접 다루지 않고도 서버 기능에 쉽게 접근할 수 있게 해줍니다.