13. MCP 서버
도구마다 직접 API 연결 코드를 작성하면 애플리케이션이 늘어날수록 비슷한 래퍼가 반복된다. MCP는 서비스 제공자가 공통 규약으로 도구와 문맥을 노출하고 여러 애플리케이션이 이를 소비하게 하는 방식이다.
13.1 MCP 서버
13.1.1 연결이 많아질 때의 문제
날씨, 검색, 문서 저장소와 업무 API마다 호출 방식과 응답 규격이 다르다. 모델에 제공할 도구 스키마와 실제 API의 인자를 연결하는 코드도 필요하다.
같은 서비스가 여러 에이전트에 사용되면 변환과 오류 처리를 각 애플리케이션에서 반복하게 된다. API가 바뀌면 여러 래퍼를 함께 수정해야 한다.
13.1.2 Model Context Protocol
MCP는 도구와 자료를 제공하는 쪽과 소비하는 쪽 사이에 공통 인터페이스를 둔다. MCP를 사용한다고 서비스 고유의 업무 규칙이 사라지는 것은 아니다. 연결과 발견, 호출을 공통 규약으로 다룰 수 있게 한다.

| 구성 요소 | 역할 |
|---|---|
| Host | 모델과 사용자 상호작용, 연결과 사용 정책을 관리하는 앱 |
| Client | Host 안에서 특정 서버와 통신하는 구성 요소 |
| Server | 도구, 자료와 프롬프트 등을 규약에 맞게 제공하는 프로그램 |
| 원천 서비스 | 실제 날씨 API나 파일, 데이터베이스 |
Client는 모델 자체가 아니다. 서버가 도구를 제공해도 어떤 도구를 사용자에게 허용하고 모델에 노출할지는 Host의 정책이다. 서버에 접근할 수 있다는 사실과 모든 기능을 실행할 권한이 있다는 사실도 다르다.
Tools는 실행 가능한 기능, Resources는 읽을 문맥 자료, Prompts는 재사용 가능한 상호작용 템플릿을 제공하는 개념이다. 이 장의 실습은 그중 도구 노출에 집중한다.
13.1.3 생태계
MCP SDK와 Inspector, 프레임워크 어댑터를 사용하면 직접 메시지 규약을 구현하는 부담을 줄일 수 있다.
서버를 찾는 것과 신뢰하는 것은 다르다. 어떤 코드를 실행하고 어떤 외부 주소에 데이터를 보내는지, 노출한 도구가 필요한 권한만 갖는지 확인해야 한다. 도구 설명과 결과도 무조건 신뢰되는 지시가 아니다.
13.2 서버 구성 방법
13.2.1 문서와 규격
MCP 공식 아키텍처 문서는 참여자와 연결 계층, 도구 및 자료의 개념을 설명한다. 프로토콜은 LLM의 판단 방식이나 에이전트의 업무 정책 전체를 정하지 않는다.
규격은 버전에 따라 바뀐다. 책의 예제와 현재 SDK가 사용하는 프로토콜 버전, 초기 연결과 기능 발견 방식이 호환되는지 확인해야 한다.
13.2.2 언어별 SDK
공식 언어별 SDK와 서버 작성에 사용하는 상위 라이브러리는 구분해야 한다. 책은 FastMCP 계열 도구로 Python 서버를 만든다.
같은 이름의 예제를 보더라도 import 경로와 패키지, 지원 버전이 다른지 확인해야 한다. 라이브러리가 직렬화와 서버 구성을 도와도 외부 API 키와 오류 처리, 권한은 구현의 책임이다.
13.2.3 애플리케이션에서 소비
Host 안의 Client가 서버에 연결해 도구 정의를 얻고, 프레임워크가 사용할 수 있는 도구 형태로 변환한다. 모델은 그 정의로 요청하고 실행은 연결된 Client를 거쳐 서버에 전달된다.
로컬 표준 입출력 연결과 원격 HTTP 연결은 운영 조건이 다르다. 원격에서는 인증과 TLS, 시간 제한과 연결 수명, 네트워크 장애를 다뤄야 한다. 로컬 서버도 Host 권한으로 파일이나 프로세스에 접근할 수 있으므로 검토가 필요하다.
13.3 날씨 MCP 서버
13.3.1 구현
모의 날씨를 실제 외부 날씨 API로 바꾼다. MCP 서버가 장소 입력을 받고 원천 서비스에 질의한 결과를 반환한다.
장소 이름을 실제 위치 식별자로 해석하는 과정이 필요할 수 있다. 같은 이름의 도시와 국가를 구분하고 조회한 위치를 결과에 남겨야 한다.
API 키는 서버 쪽에 보관하고 모델이나 클라이언트 응답에 노출하지 않는다. 실제 호출에서는 인증 실패, 요청 제한, 없는 장소와 빈 응답을 구분한다.
온도 단위와 관측 시간, 현재 날씨인지 예보인지도 응답 계약에 포함해야 한다. 값만 반환하면 에이전트가 다른 시점의 데이터를 현재 상태로 해석할 수 있다.
13.3.2 MCP Inspector
Inspector로 서버에 연결하고 도구 목록과 입력 스키마를 확인한 뒤 직접 호출한다. 이 과정은 LLM의 도구 선택을 제외하고 서버 연결과 실행 자체를 검증한다.
서버 목록이 보이는 것, 특정 도구 호출이 되는 것, 반환한 데이터가 맞는 것은 서로 다른 확인이다. 유효한 위치와 잘못된 위치, 원천 서비스 실패를 나눠 시험해야 한다.
13.3.3 테스트 Host
코드에서 Client를 만들고 도구 발견과 호출을 수행한다. Inspector에서 수동으로 했던 연결을 반복 가능한 테스트로 옮기는 것이다.
테스트에는 입력과 출력 스키마뿐 아니라 시간 제한과 오류 응답도 포함한다. 단순 HTTP 200이 업무상 성공을 뜻하지는 않는다.
13.4 에이전트에 날씨 도구 연결
13.4.1 기존 여행 에이전트 준비
기존 모의 날씨 함수와 도구를 제거하고 실제 MCP 도구를 연결한다. 같은 목적의 모의 도구와 실제 도구가 함께 등록되면 모델이 엉뚱한 쪽을 선택할 수 있다.
로컬 도구와 원격 도구의 이름과 설명이 비슷해도 결과의 신뢰도와 수명은 다르다. 현재 관측 데이터라는 의미가 도구 응답에 드러나야 한다.
13.4.2 원격 도구 통합
서버에서 받은 도구를 프레임워크 도구 형태로 연결한다. 이때 Client와 연결의 수명이 실제 도구 실행까지 유지되는지 확인해야 한다.
도구 목록을 가져온 함수가 끝난 뒤 연결을 닫아 버리면 나중에 모델이 선택한 도구를 실행하지 못할 수 있다. 사용하는 어댑터가 세션과 연결을 어떻게 관리하는지 확인한다.
13.4.3 비동기 대화 루프
원격 I/O를 기다리는 경로에 맞춰 비동기 호출을 사용한다. ainvoke와 도구의 비동기 실행을 연결할 수 있다.
비동기는 기다리는 동안 다른 작업을 처리하는 데 도움을 줄 뿐, 원천 API를 빠르게 만들거나 실패를 없애지는 않는다. 취소와 시간 제한, 동시 요청 수를 따로 관리해야 한다.
13.4.4 로컬과 원격 도구 결합
로컬 여행 검색 도구와 원격 날씨 도구를 함께 등록할 수 있다. 모델은 제공된 정의를 보고 선택하지만 실행 계층은 서로 다르다.
로그에서 로컬 검색 실패와 MCP 연결 실패, 원천 날씨 API 실패를 구분해야 한다. 모두 “도구 오류” 하나로 남기면 원인 조사가 어렵다.
13.4.5 통합 확인
먼저 도구 목록에 기대한 이름과 스키마가 있는지 보고 실제 에이전트 요청에서 서버가 호출됐는지 확인한다.
정상 날씨 답변처럼 보여도 과거 대화나 모델 지식에서 나온 것일 수 있다. 원격 호출 기록과 관측 시점, 반환 장소를 연결해야 실제 도구 사용을 확인할 수 있다.
13.4.6 복합 질의
여행 문서에서 장소를 찾고 각 장소의 날씨를 조회한 뒤 조건을 비교한다. 장소 이름을 전달하는 단계부터 같은 대상인지 확인해야 한다.
날씨가 좋은 곳을 찾는 과정은 계절과 날짜, 사용자 기준에 영향을 받는다. 모든 장소의 실시간 조회가 실패했는데 모의 데이터로 채워 성공처럼 답하는 것은 피해야 한다.
질문
MCP를 붙이면 도구의 권한 문제도 해결되는가?
연결 규약과 권한 정책은 다르다. Host와 서버, 원천 서비스 각각에서 인증과 허용 범위를 확인해야 한다.
Inspector에서 동작하면 에이전트 통합도 끝났을까?
모델이 올바른 도구와 인자를 선택하고 결과를 제대로 해석하는지는 별도 확인이다.