환율 MCP 서버 만들기 실전: 4개의 도구 설계부터 카카오 PlayMCP 배포까지

먼저 결론부터 말하면 이 프로젝트를 출품했던 공모전은 예선에서 떨어졌다.

하지만 서버는 지금도 카카오 PlayMCP에서 돌아가고 있다.

8월 기준 도구 호출 211회, 누적 사용자 225명.

거창한 숫자는 아니지만 내가 만든 MCP를 모르는 사람들이 실제로 쓰고 있다는 뜻이다.

PlayMCP 대시보드 — foxMate 도구 호출 211회, 누적 사용자 225명

처음 만들어 본 MCP 서버에서 “왜 읽기 전용으로 설계했는가”를 썼다.

이번 글은 그 후속이다.

철학이 아니라 만드는 이야기로 도구를 몇 개로 잡을지부터, 캐시 TTL, 배포에서 헤맨 것까지.

MCP 서버를 처음 만들어보려는 사람이 따라올 수 있게 순서대로 적는다.


🛠️ MCP 도구 정하기

코드보다 먼저 정한 건 도구 목록이었다.

FoxMate가 답하려는 질문은 하나다.

“지금 환전해도 될까?”

이 질문을 쪼개면 도구 4개가 나온다.

도구답하는 질문
get_realtime_rate지금 환율이 얼마인가 (출처·기준일 포함)
compare_exchange_value우대율 80/90/100%별로 실수령액이 얼마나 다른가
fx_report52주 범위에서 지금이 싼 편인가 비싼 편인가
fx_change_backtest한 달 전에 환전했다면 지금과 얼마나 차이 나나

거꾸로 말하면 이 질문에 필요 없는 도구는 만들지 않았다.

송금도, 결제도, 알림도 없다.

도구가 많아질수록 호스트 AI가 어떤 도구를 고를지 헷갈리고 검증할 표면적만 늘어난다.

실제 PlayMCP 채팅에서는 이런 예시 질문으로 노출된다.

PlayMCP AI 채팅의 FoxMate 대화 예시


🎛️ 3계층 구조: tools → adapter → clients

코드는 세 층으로 나눴다.

src/
├── server.py    FastMCP 진입점
├── tools.py     [MCP Layer]  @mcp.tool 4종 — 얇게 유지
├── adapter.py   [Adapter]    검증·정규화·출처 부착 ← 핵심 방어선
├── rates.py     [Service]    소스 선택 (공식 → 폴백)
├── calc.py      [Calc]       순수 계산 (단위테스트 대상)
└── clients/     [Clients]    외부 API 호출 + TTL 캐시

요청 한 번의 흐름은 이렇다.

사용자 질문 → 호스트 AI가 도구 선택 → tools.py 실행 → rates.py가 소스 선택 → clients가 캐시 확인 후 외부 API 호출 → adapter가 검증·정규화 → Markdown 반환.

여기서 제일 중요한 층은 adapter다.

모든 응답에 출처기준일을 강제로 붙인다.

한국은행 데이터가 오면 “한국은행 ECOS · 2026-08-08 기준”, 폴백 데이터면 “ECB 미드마켓”이라고 명시된다.

호스트 AI가 환율을 지어내는 걸 막을 수는 없지만 출처 없는 숫자가 내 서버에서 나가는 일은 없게 만드는 것이다.

읽기 전용 설계와 함께 금융 데이터 MCP에서 타협하지 않은 두 가지 중 하나다.


⏱️ 캐시: 환율은 6시간, 코인은 5분

만들다 보니 금방 보인 문제가 있다.

대화가 이어질 때마다 도구가 호출되는데 그때마다 외부 API를 때리는 건 낭비다.

한국은행 매매기준율은 하루에 한 번 고시된다.

1분 전에 받아온 환율과 지금 환율이 다를 이유가 없다.

그래서 단순한 인프로세스 TTL 캐시를 하나 만들고 데이터의 성격에 따라 TTL을 다르게 줬다.

# 공식 환율(하루 1회 고시) - 6시간
cached = cache.get(ck, 6 * 3600)

# 코인 시세 - 5분
cached = cache.get("upbit:usdt", 300)  # 코인 시세는 빨리 늙는다

포인트는 TTL을 상수 하나로 뒀다는 것.

“6시간이 맞나?”는 확실한건 아니다.

다만 틀렸다는 걸 알게 됐을 때 숫자 하나만 바꾸면 되도록 해뒀다.

처음부터 정답을 맞히는 것보다 바꾸기 쉽게 만드는 게 더 현실적인 목표였다.


🔫 도메인이 디테일을 만든다: 엔화는 100엔 기준

환율 표기에서 JPY만 예외 처리가 들어가 있다.

USD·EUR는 1단위인데 엔화는 100엔 기준으로 표기한다.

한국 은행·환전소의 관행이 그렇기 때문이다.

“1엔에 9.7원”이라고 쓰면 맞는 숫자여도 읽는 사람이 낯설어한다.

이건 핀테크 회사에서 일하며 몸에 밴 부분이기도 하다.

환율 다루는 화면에서 엔화 단위는 실무자들이 늘 신경 쓰는 디테일이다.

API 문서에는 나오지 않는 도메인이 만들어주는 요구사항.

MCP 도구를 만들 때도 이런 게 결과물의 신뢰도를 가른다.

모델은 한국 환전 관행을 모른다.

그래서 adapter 층에서 정규화(JPY ÷100)를 강제한다.


🐳 역시 가장 헤매이는 건 배포

솔직히 코드보다 배포가 어려웠다.

카카오클라우드는 처음이었다.

MCP 등록 가이드를 열어놓고 하나하나 따라가는 식이었는데 그 과정이 만만치 않았다.

헤맨 것들만 추리면:

  • 아키텍처 고정 – 이미지는 linux/amd64로 빌드해야 한다. Mac(ARM)에서 그냥 빌드하면 안 올라간다.
  • 응답 형식 제약 – PlayMCP는 도구 응답으로 TextContent(텍스트/마크다운)만 받는다. 화려한 UI 응답을 붙이고 싶어도 여기서는 안 된다.
  • 키 주입 – API 키를 코드에 넣지 않고 빌드 시점에 주입하는 구조를 처음부터 잡아야 한다. (지금은 수정했다고 한다)

지나고 보면 당연한 것들인데 처음엔 가이드와 내 화면이 조금씩 달라서 한 단계마다 멈칫했다.

클라우드 배포가 처음인 사람이라면 “코드 절반, 배포 절반”으로 시간을 잡는 걸 추천한다.


🥊 결과는 떨어졌지만, 결국엔 남아있다

공모전 결과는 예선 탈락이었다.

아쉽지 않다면 거짓말이다.

그런데 출품과 무관하게 서버는 심사를 통과해 전체공개로 등록됐고 지금도 Online 상태로 돌아간다.

모르는 사용자 225명이 도구를 호출했다.

실제 대화에서 이렇게 동작한다.

FoxMate 백테스트 응답 — 30일 전 대비 환율 변동률과 원화 가치 차이

한 달 전 환전과 오늘을 비교해 변동률과 원화 가치 차이를 출처 있는 숫자로 답한다.

공모전용으로 만들기 시작했지만 남은 건 상 대신 운영되는 서버와 만드는 근육이었다.

이 정도면 남는 장사라고 생각한다.


💊 따라 만들 사람을 위한 체크리스트

마지막으로, MCP 서버를 처음 만든다면 이 다섯 줄만 기억하자.

  1. 도구보다 질문 먼저 : 답하려는 질문 하나를 정하고, 그걸 쪼갠 것만 도구로 만든다.
  2. 어댑터 층을 둔다 : 외부 데이터는 검증·정규화·출처 부착을 거쳐서만 나가게 한다.
  3. 캐시 TTL은 데이터 성격대로 : 하루 한 번 바뀌는 데이터에 실시간 호출은 낭비다. 상수로 빼서 바꾸기 쉽게.
  4. 도메인 관행을 코드에 박는다 : 엔화 100엔 기준처럼, 문서에 없는 요구사항이 신뢰도를 가른다.
  5. 배포 제약을 먼저 읽는다 : 아키텍처, 응답 형식, 키 주입. 코드 절반, 배포 절반.

그런데 “TextContent만 허용”이라는 PlayMCP의 제약 밖으로 나가면, 같은 서버로 완전히 다른 게 가능해진다.

인터랙티브 차트 UI를 얹어 Claude에 커넥터로 붙인 두 번째 배포 이야기는 다음 글에서 이어간다.


함께 읽으면 좋은 글


글쓴이 · Plutojoshua

핀테크에서 LLM과 AI 에이전트를 실제 서비스에 적용하는 개발자다. 카카오 AI 앰배서더로 Kanana 모델을 앱에 직접 연동해 검증하고, 비전공자로 시작해 실제 코드와 측정값을 근거로 “왜 그렇게 설계했는지”를 1인칭으로 기록한다. 운영자 소개는 About, 코드는 GitHub에서 볼 수 있다.

댓글 남기기