MCP 클라이언트는 서버와 MCP 서버 간의 통신 브리지 역할을 합니다. MCP 서버가 제공하는 모든 도구에 대한 접근 지점이라고 생각하면 됩니다. 외부 도구나 서비스를 사용해야 할 때, 클라이언트가 모든 메시지 전달과 프로토콜 세부 사항을 대신 처리해 줍니다.
전송 방식에 구애받지 않는 통신
MCP의 핵심 강점 중 하나는 전송 방식에 구애받지 않는다는 점입니다 - 즉, 클라이언트와 서버가 다양한 통신 방법을 사용하여 서로 대화할 수 있다는 멋진 표현입니다. 가장 일반적인 설정은 MCP 클라이언트와 서버를 동일한 머신에서 실행하며, 표준 입출력을 통해 통신하는 방식입니다.

하지만 이 방식에만 제한되지는 않습니다. MCP 클라이언트와 서버는 다음을 통해서도 연결할 수 있습니다:
- HTTP
- WebSockets
- 다양한 기타 네트워크 프로토콜

메시지 유형
연결이 이루어지면, 클라이언트와 서버는 MCP 명세에 정의된 특정 메시지 유형을 교환합니다. 작업하게 될 주요 메시지 유형은 다음과 같습니다:

ListToolsRequest/ListToolsResult: 클라이언트가 서버에게 "어떤 도구를 제공하나요?"라고 묻고 사용 가능한 도구 목록을 받습니다.

CallToolRequest/CallToolResult: 클라이언트가 서버에게 특정 인자로 특정 도구를 실행하도록 요청한 다음, 결과를 받습니다.

전체 흐름 예시
실제 시나리오에서 모든 요소가 어떻게 함께 작동하는지 살펴보겠습니다. 사용자가 "내가 가진 저장소는 무엇인가요?"라고 묻는다고 가정해 보겠습니다 - 전체 통신 흐름은 다음과 같습니다:

이 과정은 사용자가 서버에 쿼리를 제출할 때 시작됩니다. 서버는 요청을 하기 전에 Claude에게 사용 가능한 도구 목록을 제공해야 한다는 것을 인식합니다.

서버는 MCP 클라이언트에게 도구를 요청하며, 이는 ListToolsRequest를 MCP 서버로 전송하고 ListToolsResult를 다시 받습니다.

이제 서버는 Claude에게 초기 요청을 하는 데 필요한 모든 것을 갖추었습니다 - 사용자의 질문과 사용 가능한 도구 모두 말입니다.

Claude는 도구를 검토하고 질문에 답하기 위해 도구를 호출해야 한다고 판단합니다. Claude는 도구 사용 요청으로 응답합니다.

서버는 MCP 클라이언트에게 Claude가 요청한 도구를 실행하도록 요청합니다. MCP 클라이언트는 CallToolRequest를 MCP 서버로 전송하고, MCP 서버는 GitHub에 실제 요청을 합니다.

GitHub는 저장소 데이터를 반환하며, 이는 CallToolResult로서 MCP 서버를 거쳐 MCP 클라이언트로, 그리고 최종적으로 서버로 흘러갑니다.

서버는 도구 결과를 후속 메시지로 Claude에게 다시 전송합니다. 이제 Claude는 완전한 응답을 작성하는 데 필요한 모든 정보를 갖추게 됩니다.

마지막으로, Claude는 형식화된 답변으로 응답하며, 서버는 이를 사용자에게 다시 전달합니다.
네, 이 흐름에는 많은 단계가 포함되어 있지만, 각 구성 요소는 명확한 책임을 가지고 있습니다. MCP 클라이언트는 서버 통신의 복잡성을 추상화하여, 애플리케이션 로직을 구축하는 데 집중할 수 있게 해줍니다. 우리가 직접 MCP 클라이언트와 서버를 구현하면서, 각 부분이 실제로 어떻게 맞물려 작동하는지 확인하게 될 것입니다.