
2주 동안 Claude Code로 홈랩 인프라와 콘텐츠 파이프라인을 만들면서 MCP 서버를 3개 구축했다. PayloadCMS MCP, GPU 상태 API, 그리고 ComfyUI 제어 파이프라인. 처음엔 각각 독립된 문제를 풀려고 만든 건데, 돌이켜 보니 세 서버가 하나의 패턴을 공유하고 있었다.
AI 에이전트가 외부 시스템을 안전하게 조작하려면 어떤 인터페이스가 필요한가. 이 글에서 3가지 서버를 비교하면서 그 답을 정리해 본다.
먼저 큰 그림부터 보자. Claude Code 에이전트가 블로그 글을 쓰려면 세 가지 외부 시스템과 대화해야 한다.

각각 다른 프로토콜(MCP, HTTP API, REST)을 쓰지만 결국 하는 일은 같다. 에이전트에게 "이 시스템으로 뭘 할 수 있는지"를 알려주고, 안전한 범위 안에서 조작을 허용하는 것.
PayloadCMS에는 공식 MCP 플러그인이 있다. payload.config.ts에 몇 줄 추가하면 CMS의 컬렉션을 MCP 도구로 노출할 수 있다.
plugins: [
mcpPlugin({
collections: {
posts: {
enabled: true,
description: '기술 블로그 게시글. Lexical richText 포맷.',
},
media: {
enabled: { find: true, create: true, update: false, delete: false },
description: '블로그 이미지. alt 텍스트 필수.',
},
},
}),
]여기서 핵심은 media 컬렉션의 권한 설정이다. find와 create만 열어두고 update와 delete는 막았다. AI 에이전트가 실수로 기존 이미지를 덮어쓰거나 삭제하는 걸 원천 차단한 셈이다.
MCP의 가장 큰 장점은 에이전트가 스키마를 자동으로 이해한다는 점이다. REST API를 쓰면 에이전트에게 "title은 string이고 content는 Lexical JSON이고..." 하나하나 알려줘야 한다. MCP는 스키마 자체를 프로토콜로 전달하니 에이전트가 필드 타입에 맞는 데이터를 스스로 생성한다.
실제로 블로그 작성 에이전트가 Lexical richText JSON을 직접 만들어서 posts에 저장하는데, MCP 연동 후에는 JSON 구조를 잘못 만드는 실수가 확 줄었다.
두 번째 서버는 GPU 상태를 관리하는 REST API다. 원래 nvidia-smi를 파싱해서 GPU 메모리 사용량만 보고 판단했는데, 문제가 생겼다.
vLLM이 모델을 로딩하는 동안 GPU 메모리가 점진적으로 증가한다. 로딩 초기에는 메모리를 거의 안 쓰니까 "유휴"로 오판해서 vLLM을 중복 시작하는 사고가 발생했다.
그래서 GPU API를 별도 서버로 분리하고, 프로세스 수준의 상태 머신을 만들었다.
async def _check_gpu_and_decide(self) -> GPUDecision:
status = await self._query_gpu_status()
if status is None:
return GPUDecision.UNKNOWN
if status.get("is_idle", False):
return GPUDecision.IDLE
processes = status.get("processes", [])
vllm_keywords = ("vllm", "translategemma")
for proc in processes:
command = proc.get("command", "")
if any(kw in command.lower() for kw in vllm_keywords):
return GPUDecision.VLLM_LOADING
return GPUDecision.BUSY4가지 상태(IDLE, VLLM_LOADING, BUSY, UNKNOWN)로 분기하니 엣지 케이스를 체계적으로 처리할 수 있게 됐다. VLLM_LOADING이면 대기만 하고, BUSY면 아예 시작을 안 하고, UNKNOWN이면 안전하게 스킵한다.
이 API는 MCP가 아니라 단순 REST로 구현했다. 이유가 있다. GPU 상태 조회는 읽기 전용이고 스키마가 단순해서 MCP의 자동 스키마 전달이 큰 이점을 주지 않기 때문이다.
세 번째는 ComfyUI다. ComfyUI는 자체 HTTP API(/prompt 엔드포인트)를 제공하는데 워크플로우 JSON을 통째로 POST하는 방식이다.
# 워크플로우 실행
curl -X POST http://localhost:8188/prompt \
-H "Content-Type: application/json" \
-d '{"prompt": {WORKFLOW_JSON}}'
# 큐 상태 확인
curl -s http://localhost:8188/queue
# 결과 확인
curl -s http://localhost:8188/historyComfyUI API의 특이한 점은 워크플로우 자체가 곧 API 스키마라는 것이다. 노드 ID, 연결 관계, 파라미터를 JSON으로 기술하면 ComfyUI가 실행한다. 에이전트 입장에서는 워크플로우 템플릿만 알고 있으면 프롬프트와 시드만 바꿔서 반복 실행할 수 있다.
여기에 comfyui_ctl.py라는 제어 스크립트를 덧붙였다. GPU 상태 확인 후 ComfyUI를 시작하고 health check까지 기다려주는 래퍼다. GPU가 busy면 시작을 거부해서 충돌을 방지한다.
3가지 서버를 나란히 놓고 보면 각각의 선택 이유가 보인다.
PayloadCMS MCP는 스키마가 복잡하고 CRUD가 필요한 경우에 적합하다. 에이전트가 posts 컬렉션의 모든 필드(title, slug, content, featuredImage, category, tags, series, seriesOrder 등)를 정확히 채워야 하는 상황에서 MCP의 자동 스키마 이해가 결정적이었다.
GPU API는 읽기 위주에 상태 판단이 핵심인 경우다. 엔드포인트가 GET /status 하나뿐이고 응답도 is_idle, processes 정도라 단순 REST면 충분하다.
ComfyUI HTTP API는 이미 잘 만들어진 자체 API가 있어서 그걸 그대로 쓴 경우다. 워크플로우 JSON 자체가 곧 인터페이스 명세이니 별도 추상화 없이 그대로 호출하면 된다.
이 세 서버가 합쳐지면 글감 하나로 블로그 발행까지 자동화할 수 있다.

실제 동작 순서를 보면, 에이전트가 먼저 글감을 분석해서 Lexical JSON으로 블로그 글을 작성하고 PayloadCMS MCP로 draft를 저장한다. 그다음 GPU API로 상태를 확인한 뒤 ComfyUI로 이미지를 생성하고 media에 업로드한다. draft에 이미지를 연결하면 끝. 사용자가 확인 후 published로 바꾸면 afterChange 훅이 n8n 웹훅을 트리거해서 SNS 배포까지 이어진다.
이걸 5개 에이전트 팀으로 확장하면 더 재미있다. museck-agent가 블로그를 쓰고, comfy-agent가 이미지를 만들고, postiz-agent가 SNS 텍스트로 가공하는 식으로 역할을 분리하면 하나의 대화에서 전체 파이프라인을 제어할 수 있다.
MCP는 만능이 아니다. 스키마가 복잡하고 에이전트가 다양한 필드를 채워야 할 때 빛나지만, 단순 읽기 API에는 REST가 더 가볍다. 도구 선택 기준은 "에이전트가 스키마를 얼마나 이해해야 하는가"였다.
권한 제한은 선택이 아니라 필수다. media 컬렉션에서 update/delete를 막은 게 단순한 안전장치가 아니었다. 에이전트가 수백 번 반복 실행되면서 예상 못한 사이드 이펙트를 만들어내는 걸 여러 번 봤다. "이 정도면 안전하겠지"보다 "이것만 허용"이 맞다.
GPU 같은 공유 자원은 상태 머신으로 관리해야 한다. 메모리 사용량 같은 단순 지표 대신 프로세스 유형을 보는 게 핵심이었다. nvidia-smi 파싱으로 삽질하던 걸 상태 머신 4개로 정리하니 엣지 케이스가 사라졌다.
에이전트 팀의 핵심은 경계 설계다. 각 에이전트가 어떤 시스템에 접근할 수 있고 어떤 권한을 가지는지 명확히 나누는 게 중요했다. museck-agent는 PayloadCMS만, comfy-agent는 ComfyUI만. 경계가 불분명하면 에이전트끼리 충돌한다.
MCP 서버 3종을 만들면서 느낀 건, AI 에이전트와 외부 시스템을 연결하는 데 정답은 하나가 아니라는 것이다. 스키마가 복잡하면 MCP, 단순 조회면 REST, 기존 API가 있으면 그대로 쓰면 된다. 중요한 건 에이전트에게 딱 필요한 만큼만 권한을 열어주는 것.
2주간 이 시스템을 돌려본 결과, 글감 하나 던지면 블로그 글 작성부터 이미지 생성, CMS 저장, SNS 배포까지 자동으로 돌아간다. 물론 사람이 중간에 확인하는 단계는 남겨뒀다. 자동화는 결국 "어디까지 기계에게 맡기고 어디서 사람이 판단할 것인가"의 설계 문제다.