지난 글에서 환율 MCP ‘FoxMate’를 카카오 PlayMCP에 배포한 이야기를 썼다.
그때 마지막에 한 줄 남겨둔 게 있다.
“TextContent만 허용”이라는 제약 밖으로 나가면, 같은 서버로 완전히 다른 게 가능해진다.
이번 글이 그 이야기다.
같은 코어를 가진 서버에 인터랙티브 차트 UI를 얹어서 Claude에 커스텀 커넥터로 붙였다.

🤖 UI를 넣었더니 모델이 읽었다
원래는 카카오 PlayMCP를 개발할 때 처음부터 UI를 넣고 싶었다.
환율은 숫자 나열보다 차트 한 장이 압도적으로 잘 읽히는 데이터니까.
그런데 카카오 공모전 환경에서 UI를 시도했을 때 벌어진 일은 예상 밖이었다.
UI를 붙이면 호스트 모델이 그 UI를 읽어서 텍스트로 출력한다.
진짜로 그랬다.
사람에게 보여주려고 만든 화면이 화면에 뜨는 게 아니라 모델의 입력이 되어 텍스트 요약으로 돌아왔다.
황당했지만 덕분에 방향이 명확해졌다.
특정 플랫폼의 예외적 지원을 기다리는 대신 더 범용적인 표준을 찾아가자.
그렇게 찾은 게 MCP Apps다.
도구 응답에 HTML UI 리소스를 함께 실어 보내면
이를 지원하는 호스트(Claude 등)가 대화 안에 실제 화면으로 렌더링해주는 확장 스펙이다.
모델이 읽고 요약하는 게 아니라, 사용자가 직접 만지는 UI가 뜬다.
🐳 두 배포, 두 세계
그래서 지금 FoxMate는 배포가 두 갈래다.
| PlayMCP (1편) | Claude 커넥터 (이번) | |
|---|---|---|
| 인프라 | 카카오클라우드 | GCP Cloud Run |
| 응답 형식 | 텍스트(Markdown)만 | 텍스트 + 인터랙티브 UI |
| 도구 | 4개 | 6개 (환헤지 리포트·가이드 추가) |
| API 키 | 빌드 시점 주입 | 런타임 주입 |
| 브랜치 | 동결 | 계속 개발 |
포인트는 이 둘을 머지하지 않는다는 것.
처음엔 브랜치 두 개가 임시 상태처럼 보여서 합칠 궁리를 했는데 곧 생각이 바뀌었다.
배포 대상이 응답 계약을 결정한다.
PlayMCP용 브랜치는 “텍스트만 반환한다”는 그 플랫폼의 사양서이고
커넥터용 브랜치는 “UI 리소스를 함께 반환한다”는 또 다른 사양서다.
억지로 합치면 조건문 범벅이 될 뿐이다.
같은 코어(어댑터·캐시·계산)를 공유하고 플랫폼별 차이는 브랜치로 남겨뒀다.
🛠️ 화면이 생기니 도구가 달라진다
텍스트만 반환할 때는 못 만들던 도구가 생긴다.
대표가 환헤지 시뮬레이터다.

“석 달 뒤 125,000달러를 결제해야 하는데 환율이 움직이면 얼마나 손해인가”를 다루는 화면이다.
핸들을 끌어 환율 시나리오를 바꾸면 무헤지 손익과 환선물 80% 고정 손익이 실시간으로 다시 계산된다.
위 화면에서는 환율이 65원 오르는 시나리오에서 무헤지 -810만원 vs 80% 헤지 -162만원.
이런 “직접 끌어보며 비교”는 텍스트 응답으로는 흉내도 못 낸다.
숫자 표로 시나리오 5개를 나열하는 것과 핸들을 끌면서 손익이 변하는 걸 보는 것은 이해의 깊이가 다르다.
환율 리포트도 정적인 숫자 요약에서 진짜 차트가 됐다.

기간(1M/3M/6M/1Y)을 전환하고
20일·60일 이동평균과 52주 평균을 겹쳐 보고
호버하면 날짜별 상세가 뜬다.
다크 테마는 우측 상단 해/달 토글로 전환된다.
대화창 안에 뜨는 UI라서 Claude의 화면 톤에 맞춰 보이게 하고 싶었다.
🕹️ 도구는 4개에서 6개로
1편에서 “질문 하나를 쪼갠 것만 도구로 만든다”고 썼다.
그 원칙은 유지하되 질문이 하나 늘었다.
“지금 환전해도 될까?”에 더해 “미래의 외화 결제, 환율이 움직이면 어떻게 지키나?”
이 질문에서 도구 2개가 나왔다.
fx_hedge_report는 위의 시뮬레이터,
fx_hedge_guide는 환헤지 자체가 처음인 사람을 위한 가이드다.

수입업자와 수출업자는 거울상이다. 한쪽이 무서워하는 환율 방향을 다른 쪽은 반긴다.
이걸 텍스트 문단으로 쓰면 읽고 지나가지만 카드 두 장을 나란히 놓으면 구조가 한눈에 들어온다.
환헤지는 회사에서 실제로 다루는 도메인이라
방법론(환선물·선물환·분할 환전)의 장단 정리는 실무 감각을 그대로 옮겼다.
물론 1편에서 말한 원칙대로, 내부 스펙이 아니라 전이 가능한 도메인 지식만.
📀 Cloud Run 배포: 이번엔 키를 굽지 않았다
인프라는 GCP Cloud Run을 골랐다.
컨테이너 하나 올리면 HTTPS 엔드포인트가 바로 나오고 안 쓸 때는 0으로 줄어들어 유지비 부담이 작다.
1편에서 “API 키를 빌드 시점에 주입하는 구조를 처음부터 잡아야 한다”고 썼는데 이번엔 그 반성문을 썼다.
키를 이미지에 굽지 않고 런타임에 주입한다.
이미지는 키 없이 빌드되고 배포할 때 환경변수로 꽂는다.
키가 바뀌어도 재빌드가 필요 없고 이미지가 유출돼도 키는 없다.
여기서 하나 밟았던 함정.
# 배포 때 --set-env-vars로 키를 넣었다면
gcloud run deploy foxmate --set-env-vars ECOS_API_KEY=...
# 나중에 키 하나 추가하려고 또 --set-env-vars를 쓰면
# 기존 환경변수가 "전부" 교체돼 날아간다
gcloud run services update foxmate --update-env-vars KRX_API_KEY=...
--set-env-vars는 추가가 아니라 전체 교체다.
기존 값을 유지하며 더하려면 --update-env-vars를 써야 한다.
문서에 쓰여 있지만 한 번 날려 먹기 전에는 눈에 안 들어오는 종류의 문장이다.
🔌 Claude 커넥터 등록: 어려운 건 기술이 아니라 용어였다

서버가 떠 있으면 Claude 쪽 등록은 설정에서 커넥터를 추가하고 엔드포인트 URL을 넣는 게 전부다.
솔직히 기술적으로 어려운 건 없었다.
그런데 두 가지가 걸렸다.
첫째, 커스텀 커넥터 추가 버튼 찾기.
커넥터 설정에 들어가면 잘 만들어진 기성 커넥터 목록이 먼저 보이고
내 서버를 직접 등록하는 입구는 눈에 잘 안 띄는 곳에 있다.
버튼을 찾는 게 등록 과정에서 제일 오래 걸렸다면 말 다 했다.
그 뒤로는 URL 입력하고 도구 권한 허용해주는 정도.
둘째, 용어의 장벽.
나는 MCP를 만들어본 입장이라 쉽게 넘어갔지만
등록 과정 내내 “비개발자가 이 화면을 보면 어떨까”라는 생각이 들었다.
만들 때는 MCP라고 부르던 것이 Claude에 붙이는 순간 커넥터라고 불린다.
같은 걸 가리키는데 이름이 바뀐다.
거기에 “엔드포인트 URL을 입력하세요”가 나온다.
개발자에겐 아무것도 아닌 단어들이 이 기능이 겨냥할 일반 사용자에겐 문 앞의 턱이겠다 싶었다.
MCP 생태계가 정말 넓어지려면 서버 만들기보다 이 등록 경험이 먼저 쉬워져야 할 것 같다.
등록이 끝나면, 대화에서 “환율 리포트 보여줘”라고 하면 Claude가 도구를 고르고 차트가 대화 안에 뜬다.
🎛️ 같은 코어, 두 얼굴
정리하면 이렇다.
1편의 서버와 이번 서버는 어댑터·캐시·계산이라는 코어가 같다.
출처·기준일 강제, TTL 캐시, 엔화 100엔 정규화 -> 1편에서 타협하지 않았던 것들은 그대로 간다.
바뀐 건 그 코어를 세상에 내보내는 방식이다.
- PlayMCP에서는 텍스트로 : 제약 안에서 마크다운을 다듬었다.
- Claude 커넥터에서는 화면으로 : 핸들을 끌고 차트를 호버하는 UI가 됐다.
MCP 서버를 하나 만들었다면 배포처를 하나 늘리는 건 생각보다 가깝다.
코어를 플랫폼과 분리해뒀다면 특히.
두 번의 배포에서 남은 체크리스트로 마무리한다.
- 응답 계약은 플랫폼이 정한다 : 텍스트만인지, UI 리소스를 받는지 먼저 확인하고 시작한다.
- 플랫폼별 차이를 코어에 섞지 않는다 : 코어는 공유, 차이는 경계(브랜치든 어댑터든)에 격리.
- 키는 굽지 말고 꽂는다 : 런타임 주입이면 재빌드 없이 교체되고, 이미지 유출에도 안전하다.
--set-env-vars는 전체 교체다 : 추가는--update-env-vars.- 등록 문서에는 용어 번역을 넣자 : 커넥터=내가 만든 MCP 서버, 엔드포인트=서버 주소. 쓰는 사람이 개발자가 아닐 수 있다.

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