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에게 전송할 사용 가능한 도구 목록 가져오기
  • Claude가 요청할 때 도구 실행하기

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

두 가지 필수 함수인 list_toolscall_tool을 구현해 보겠습니다.

list_tools의 경우, 세션에 연결하여 사용 가능한 도구를 요청해야 합니다:

python
async def list_tools(self) -> list[types.Tool]:
    result = await self.session().list_tools()
    return result.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)

이게 전부입니다! 세션이 복잡한 통신 세부 사항을 모두 우리를 위해 처리해 줍니다.

클라이언트 테스트하기

클라이언트 파일 하단에는 간단한 테스트 하니스가 포함되어 있습니다. 모든 것이 제대로 작동하는지 확인하기 위해 직접 실행할 수 있습니다:

bash
uv run mcp_client.py

이렇게 하면 MCP 서버에 연결하여 사용 가능한 도구를 출력합니다. 이름, 설명, 입력 스키마를 포함한 도구 정의를 보여주는 출력을 확인할 수 있을 것입니다.

중요한 스키마 차이점

여기 알아두어야 할 주의할 점이 있습니다: MCP 도구 정의는 Claude가 기대하는 것과 정확히 일치하지 않습니다. MCP 스펙은 도구 스키마에 대한 자체 형식을 가지고 있으며, 이는 Bedrock이 요구하는 것과 약간 다릅니다.

걱정하지 마세요 - 이 변환을 자동으로 처리하는 코드가 프로젝트에 이미 있습니다. core/bedrock.pyto_bedrock_tools 함수는 MCP 도구 정의를 Claude가 이해하는 형식으로 변환합니다.

Claude로 테스트하기

이제 서버와 클라이언트가 모두 작동하므로, 전체 흐름을 테스트할 수 있습니다. 메인 애플리케이션을 실행하고 Claude에게 문서를 읽어달라고 요청해 보세요:

bash
uv run main.py

그런 다음 질문하세요: "report.pdf 문서의 내용은 무엇인가요?"

Claude는 다음과 같이 동작합니다:

  1. 클라이언트로부터 사용 가능한 도구 목록을 받습니다
  2. read_doc_contents 도구를 사용하기로 결정합니다
  3. 클라이언트가 MCP 서버에서 해당 도구를 실행합니다
  4. Claude가 문서 내용을 받아 응답합니다

클라이언트는 애플리케이션 코드와 MCP 서버 사이의 다리 역할을 하며, 서버 기능을 Claude 및 시스템의 다른 부분에 쉽게 노출할 수 있게 해줍니다.