블로그에 AI 기능 붙이기 (2편) - MCP와 REST API의 경계
시리즈: 블로그에 AI 기능 붙이기
2 / 3편
- 11편 - 월 35원으로 OpenAI + Netlify Functions
- 22편 - MCP와 REST API의 경계지금 읽는 중
- 33편 - 응답 캐시로 API 호출 줄이기

목차
블로그 글이 쌓이면서 AI에게 매번 문서를 복사해 주는 일이 번거로워졌습니다. 그래서 글 검색과 본문 조회를 도구로 제공했습니다. 이 글에서는 저장소에 실제로 들어 있는 두 서버를 구분해서 설명합니다.
이전 글은 FastAPI REST 서버를 그대로 “원격 MCP 서버”라고 불렀습니다. REST 엔드포인트를 만든 것만으로 MCP 클라이언트가 연결되는 것은 아니므로 정정합니다. 문서를 도구로 읽게 하는 작업은 모델 재학습이나 파인튜닝도 아닙니다.
같은 검색 로직, 다른 연결 방식
공개 저장소의 mcp-server/src에 두 진입점이 있습니다.
| 파일 | 역할 | 연결 방식 |
|---|---|---|
| server.py | MCP 도구와 리소스 등록 | Python MCP SDK의 stdio_server |
| rest_api.py | 관리자 화면용 검색·조회 API와 웹훅 | FastAPI HTTP REST |
두 서버가 검색 핸들러를 공유할 수는 있지만 프로토콜은 별개입니다. stdio 서버는 클라이언트가 로컬 프로세스를 실행하고 표준 입출력으로 메시지를 교환합니다. FastAPI 서버에 POST 요청이 된다는 사실은 MCP 초기화나 tools/list, tools/call이 된다는 뜻이 아닙니다.
원격 MCP로 제공하려면 SDK가 지원하는 Streamable HTTP 등 MCP transport를 구현하고 클라이언트의 지원 여부를 확인해야 합니다. SDK 버전에 따라 API도 달라집니다. MCP transport 명세와 공식 SDK 목록을 기준으로 확인하는 편이 안전합니다. Python은 제가 선택한 언어이지 MCP의 필수 조건이 아닙니다.
검색 도구가 모델에게 주는 것
도구는 모델에게 검색 결과를 반환합니다. 모델의 가중치에 블로그 내용이 저장되는 것이 아닙니다. 따라서 검색에서 빠진 글은 답변의 근거에서도 빠질 수 있습니다.
검색 결과에는 제목만 넘기기보다 글 식별자, canonical URL, 수정 시각, 짧은 발췌를 함께 제공하는 편이 좋습니다. 사용자가 본문을 요청하면 해당 식별자로 원문을 조회하게 하고, 답변에는 읽은 문서 링크를 남기도록 합니다. 이 부분은 도구 인터페이스를 개선할 때의 기준이며 모든 항목이 현재 서버에 구현되어 있다는 뜻은 아닙니다.
Cloud Run에 올렸던 것은 REST API입니다
저장소의 실행 명령은 다음 형태입니다.
python -m uvicorn src.rest_api:app --host 0.0.0.0 --port 8001이는 FastAPI 애플리케이션 실행 명령입니다. Cloud Run의 컨테이너 포트 설정과 일치시켜야 하고, 원격 MCP 배포를 완료했다는 증거로 사용할 수 없습니다. CLI나 관리자 화면이 REST를 호출하는 것과 Claude의 MCP 설정에 서버를 연결하는 것은 각각 검증해야 합니다.
Cloud Run의 쓰기 가능한 컨테이너 파일시스템은 메모리를 사용하며 인스턴스 수명에 종속됩니다. “읽기 전용이라 /tmp만 가능하다”는 이전 설명은 잘못입니다. /tmp에 clone한 파일도 영구 저장소가 아닙니다. Cloud Run 컨테이너 실행 계약을 참고하세요.