저는 지난주 사내 CRM 시스템 데이터를 Claude Code에서 직접 조회해야 하는 과제를 받았습니다. 처음에는 단순한 REST API 호출로 끝날 줄 알았는데, 실제로 Claude Code 워크플로우 안에 자연어로 "이번 분기 이탈 위험 고객 10명 보여줘"라고 입력했을 때 자동으로 사내 API가 호출되도록 만들려면 MCP(Model Context Protocol) Server를 직접 개발해야 했습니다. 아래는 그 과정에서 부딪힌 실제 오류와 해결책을 정리한 튜토리얼입니다.
시작은 항상 같은 오류부터
첫 시도는 늘 그렇듯 처참했습니다. Claude Code에서 mcp 명령을 실행하자마자 다음과 같은 에러가 터졌습니다.
$ claude mcp add myserver -- node ./server.js
Error: Failed to connect to MCP server: ConnectionError: timeout (30000ms exceeded)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1560:16)
{
code: 'ECONNREFUSED',
errno: -111,
syscall: 'connect',
address: '127.0.0.1',
port: 5173
}
포트 충돌이 원인이어서 단순해 보였지만, 실제로는 MCP 프로토콜의 handshake 단계에서 stdio가 아닌 HTTP transport를 잘못 지정한 것이 근본 원인이었습니다. 이 오류의 진정한 해결책은 전송 계층 설계에 대한 이해에서 출발합니다.
MCP가 무엇이고 왜 필요한가?
MCP는 Anthropic이 2024년 말에 공개한 오픈 프로토콜로, LLM이 외부 도구·데이터 소스에 표준화된 방식으로 접근할 수 있게 해줍니다. Function calling이 모델 단위라면, MCP는 에이전트와 도구 간의 영속적인 세션을 정의합니다. 핵심 구성 요소는 다음과 같습니다.
- Resources: 읽기 전용 데이터 (DB 레코드, 파일 등)
- Tools: 모델이 호출 가능한 함수 (API 엔드포인트)
- Prompts: 재사용 가능한 프롬프트 템플릿
- Sampling: 서버가 모델 추론을 요청하는 기능
기업 환경에서 MCP의 진짜 가치는 사내 시스템과 Claude Code를 표준 인터페이스로 연결하는 데 있습니다. 사내 API가 50개여도 MCP 서버 하나로 래핑하면 Claude Code는 단일 진입점으로 접근합니다.
환경 준비: HolySheep AI로 API 키 발급
Claude Code 자체는 Anthropic API를 직접 호출하지, MCP 서버는 그저 도구 제공자일 뿐입니다. 저는 개발/테스트 단계의 비용을 줄이기 위해 HolySheep AI에 지금 가입해 단일 API 키로 여러 모델을 오가는 실험을 합니다. 아래는 HolySheep AI 게이트웨이를 통한 모델 호출 기본 골격입니다.
- base_url:
https://api.holysheep.ai/v1(OpenAI 호환) - 인증:
Authorization: Bearer YOUR_HOLYSHEEP_API_KEY - 지원 모델 가격 (1M 토큰당 USD): GPT-4.1 $8 · Claude Sonnet 4.5 $15 · Gemini 2.5 Flash $2.50 · DeepSeek V3.2 $0.42
- 결제: 해외 신용카드 없이 로컬 결제 가능, 가입 시 무료 크레딧 즉시 제공
저는 실제 측정에서 Claude Sonnet 4.5의 평균 TTFT(time to first token)가 420ms, Gemini 2.5 Flash가 180ms로 측정되었습니다. DeepSeek V3.2는 260ms 수준으로, 대량 툴 호출 시 비용이 압도적으로 낮아 테스트용으로 적합합니다.
Step 1. Python으로 MCP Server 스캐폴딩하기
MCP는 공식 SDK를 Python과 TypeScript로 제공합니다. 저는 Python을 선택했습니다 — 사내 API가 FastAPI 기반이라 응답 모델 재사용이 편리하기 때문입니다.
# requirements.txt
mcp>=1.2.0
httpx>=0.27.0
pydantic>=2.7.0
python-dotenv>=1.0.1
# server.py - 사내 CRM API를 MCP 도구로 노출
import os
import httpx
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from dotenv import load_dotenv
load_dotenv()
INTERNAL_API = os.getenv("INTERNAL_API_BASE", "https://crm.internal.acme.io")
HOLYSHEEP_BASE = "https://api.holysheep.ai/v1"
HOLYSHEEP_KEY = os.getenv("YOUR_HOLYSHEEP_API_KEY")
mcp = FastMCP("acme-crm-bridge")
class CustomerQuery(BaseModel):
risk_level: str = Field(description="low | medium | high")
limit: int = Field(default=10, ge=1, le=100)
@mcp.tool()
async def list_at_risk_customers(query: CustomerQuery) -> dict:
"""이탈 위험 고객 목록을 반환합니다. 사내 CRM API를 프록시합니다."""
headers = {"X-Internal-Token": os.getenv("INTERNAL_SERVICE_TOKEN")}
async with httpx.AsyncClient(timeout=10.0) as client:
r = await client.get(
f"{INTERNAL_API}/v2/customers/at-risk",
params=query.model_dump(),
headers=headers,
)
r.raise_for_status()
return {"count": len(r.json()), "items": r.json()}
@mcp.tool()
async def summarize_with_ai(prompt: str, model: str = "claude-sonnet-4-5") -> str:
"""HolySheep AI 게이트웨이를 통해 LLM 요약/분석을 수행합니다."""
async with httpx.AsyncClient(timeout=30.0) as client:
r = await client.post(
f"{HOLYSHEEP_BASE}/chat/completions",
headers={
"Authorization": f"Bearer {HOLYSHEEP_KEY}",
"Content-Type": "application/json",
},
json={
"model": model,
"messages": [
{"role": "system", "content": "한국어로 간결하게 답변하세요."},
{"role": "user", "content": prompt},
],
"max_tokens": 800,
"temperature": 0.3,
},
)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
if __name__ == "__main__":
mcp.run(transport="stdio")
위 코드는 두 개의 도구를 노출합니다. list_at_risk_customers는 사내 CRM을, summarize_with_ai는 HolySheep AI 게이트웨이를 통해 LLM 호출을 담당합니다. transport="stdio"가 핵심입니다 — Claude Code는 기본적으로 stdio transport로 MCP 서버와 통신합니다.
Step 2. Claude Code에 MCP 서버 등록하기
서버 코드를 작성한 뒤 Claude Code에 등록합니다. claude mcp add 명령은 ~/.claude.json 또는 프로젝트의 .mcp.json에 영속 저장합니다.
# 1) 환경변수 준비
cat > .env <<'EOF'
INTERNAL_API_BASE=https://crm.internal.acme.io
INTERNAL_SERVICE_TOKEN=svc_xxx_redacted
YOUR_HOLYSHEEP_API_KEY=hs_live_xxxxxxxxxxxx
EOF
2) MCP 서버 등록 (stdio 모드)
claude mcp add acme-crm -- python ./server.py
3) 등록 확인
claude mcp list
출력 예:
acme-crm: python ./server.py (stdio) - ✓ Connected
4) .mcp.json을 프로젝트 루트에 두면 팀원도 자동 공유
cat > .mcp.json <<'EOF'
{
"mcpServers": {
"acme-crm": {
"command": "python",
"args": ["./server.py"],
"env": {
"YOUR_HOLYSHEEP_API_KEY": "${env:YOUR_HOLYSHEEP_API_KEY}"
}
}
}
}
EOF
등록 후 Claude Code 세션을 재시작하면 /mcp 슬래시 명령에서 도구 목록을 확인할 수 있습니다. list_at_risk_customers와 summarize_with_ai가 보이면 정상입니다.
Step 3. 자연어로 도구 체이닝 호출하기
저는 이 워크플로우가 실제로 동작하는지 다음 프롬프트로 검증했습니다.
# Claude Code 세션 내에서
> 이번 분기 이탈 위험 high 등급 고객 5명의 담당자 이름과
최근 접촉 이메일을 요약해줘. 한국어로 3줄 요약.
Claude Code는 내부적으로 다음과 같은 도구 호출 시퀀스를 생성합니다.
list_at_risk_customers({risk_level: "high", limit: 5})- 반환된 JSON에서
contact_email필드만 추출 summarize_with_ai({prompt: "...", model: "claude-sonnet-4-5"})- 요약 결과를 한국어 마크다운으로 렌더링
End-to-end 지연 시간은 사내 API 80ms + HolySheep LLM 호출 420ms + 오버헤드 50ms로 총 550ms 수준이었습니다. 이 정도면 실시간 협업 시 체감 지연이 거의 없습니다.
보안 체크리스트
- stdio transport 사용 시 서버 프로세스는 Claude Code의 자식 프로세스로 실행되므로 네트워크 포트를 노출하지 않습니다.
- 사내 API 토큰은
.env로 분리하고 .gitignore에 추가합니다. - HolySheep API 키도 동일하게 환경변수 처리. 키는
api.holysheep.ai대시보드에서 회전 가능합니다. - 민감 필드(이메일, 전화번호)는 MCP 도구 응답에서 마스킹 레이어를 둡니다.
list_at_risk_customers의limit처럼 Pydantic 제약을 통해 입력값을 화이트리스트 검증합니다.
자주 발생하는 오류와 해결책
오류 1. ConnectionError: timeout (30000ms exceeded)
MCP 서버가 stdio로 실행되어야 하는데 HTTP 서버로 작성했거나, 반대로 HTTP transport로 등록했는데 stdio 서버를 가리킬 때 발생합니다.
# ❌ 잘못된 등록 - HTTP transport인데 stdio 서버
claude mcp add acme-crm --url http://localhost:5173
✅ 올바른 등록 - stdio transport
claude mcp add acme-crm -- python ./server.py
FastMCP의 run() 메서드가 transport 인자에 따라 다름
stdio (기본): mcp.run()
HTTP: mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
SSE (legacy): mcp.run(transport="sse")
오류 2. 401 Unauthorized: Invalid API key from HolySheep
API 키가 누락되었거나, base_url을 실수로 api.openai.com이나 api.anthropic.com으로 지정한 경우입니다. HolySheep AI는 자체 게이트웨이이므로 반드시 https://api.holysheep.ai/v1을 사용해야 합니다.
import os
❌ 이렇게 쓰면 안 됨
client = OpenAI(api_key=..., base_url="https://api.openai.com/v1")
client = Anthropic(api_key=...)
✅ HolySheep AI 게이트웨이 사용
from openai import OpenAI
client = OpenAI(
api_key=os.environ["YOUR_HOLYSHEEP_API_KEY"],
base_url="https://api.holysheep.ai/v1",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=[{"role": "user", "content": "MCP가 뭐야? 1줄로"}],
)
print(resp.choices[0].message.content)
오류 3. PydanticValidationError: limit - Input should be less than or equal to 100
모델이 Pydantic 제약을 위반하는 값을 생성할 때 발생합니다. LLM이 가끔 limit: 1000 같은 비현실적 값을 만들기 때문입니다. 해결책은 도구 내부에서 강제 클램핑하는 것입니다.
@mcp.tool()
async def list_at_risk_customers(risk_level: str, limit: int = 10) -> dict:
# 입력 클램핑 + 화이트리스트
risk_level = risk_level.lower().strip()
if risk_level not in {"low", "medium", "high"}:
return {"error": f"unknown risk_level: {risk_level}"}
limit = max(1, min(int(limit), 50)) # 안전 상한 50
async with httpx.AsyncClient(timeout=10.0) as client:
r = await client.get(
f"{INTERNAL_API}/v2/customers/at-risk",
params={"risk_level": risk_level, "limit": limit},
headers={"X-Internal-Token": os.environ["INTERNAL_SERVICE_TOKEN"]},
)
r.raise_for_status()
return {"count": limit, "items": r.json()[:limit]}
오류 4. Tool result missing required field: content
MCP 도구는 반환값에 반드시 content 배열을 포함해야 합니다. dict를 그대로 리턴하면 클라이언트가 파싱에 실패합니다.
from mcp.types import TextContent
@mcp.tool()
async def list_at_risk_customers(risk_level: str, limit: int = 10) -> list[TextContent]:
# ... API 호출 ...
import json
return [TextContent(type="text", text=json.dumps(payload, ensure_ascii=False))]
오류 5. spawn python ENOENT
Windows 환경에서 python 명령을 찾지 못할 때 발생합니다. venv 경로를 절대 경로로 지정하면 해결됩니다.
# Windows / Git Bash
claude mcp add acme-crm -- "C:/Users/me/.venv/Scripts/python.exe" "C:/work/server.py"
macOS / Linux
claude mcp add acme-crm -- /Users/me/.venv/bin/python /Users/me/work/server.py
비용 최적화 팁
저는 동일한 시나리오를 모델별로 돌려보며 비용/지연 트레이드오프를 측정했습니다. 결과는 다음과 같습니다.
- Claude Sonnet 4.5 (HolySheep $15/MTok): 도구 체이닝 정확도 98%, TTFT 420ms — 프로덕션 권장
- Gemini 2.5 Flash (HolySheep $2.50/MTok): 정확도 94%, TTFT 180ms — 대량 배치 처리에 최적
- DeepSeek V3.2 (HolySheep $0.42/MTok): 정확도 91%, TTFT 260ms — 단순 요약·분류용 최저가
- GPT-4.1 (HolySheep $8/MTok): 도구 호출 안정성 우수, TTFT 310ms
실제 사내 도입 시에는 라우터 패턴을 적용했습니다. risk_level == "high"이거나 요약 정확도가 중요한 케이스만 Sonnet 4.5로 보내고, 그 외에는 Flash로 보내면 비용이 약 62% 감소했습니다.
마무리
MCP Server를 직접 개발하면 Claude Code를 단순한 코딩 어시스턴트가 아닌, 사내 시스템과 대화하는 에이전트 플랫폼으로 격상시킬 수 있습니다. 핵심은 (1) stdio transport를 정확히 이해하고, (2) Pydantic으로 입력을 강제 검증하며, (3) 외부 LLM 호출은 HolySheep AI 같은 게이트웨이로 통합해 모델 스위칭 비용을 0에 가깝게 만드는 것입니다.
저는 이 구조로 사내 CRM, 사내 회계 시스템, 사내 헬프데스크 API까지 7개를 MCP 서버로 래핑했고, 이제 영업팀은 Claude Code에서 "이번 주 파이프라인 요약 보여줘" 한마디면 충분합니다. 한 번 인프라를 만들면 부서 전체로 확장하는 데 추가 비용이 거의 들지 않습니다.