본문 바로가기
AI & LLM

MCP 서버 연동으로 Claude Code 확장하기

by 코드파일럿 2026. 4. 21.

MCP 서버 연동으로 Claude Code 확장하기

이 글에서 다루는 내용

Claude Code에 Model Context Protocol(MCP) 서버를 붙여 외부 도구·데이터 소스를 에이전트의 도구로 노출하는 방법을 정리합니다. MCP 기본 개념, 공식 서버 사용, 간단한 커스텀 MCP 서버 작성 예제, 그리고 접속 상태 디버깅까지 이 글 하나로 정리합니다. MCP는 Claude뿐 아니라 ChatGPT·Cursor 등 점점 더 많은 호스트에서 채택되고 있어, 한 번 익혀두면 다른 도구로도 그대로 옮겨 쓸 수 있습니다.

핵심 가치는 "LLM이 내 도구를 표준 방식으로 부르게 한다"는 점에 있습니다. 회사 내부 데이터에 접근하거나, 깃 저장소를 다루거나, 외부 API를 부르는 일을 매번 프롬프트에 풀어 적어주는 대신, 표준 프로토콜로 노출해 두면 LLM이 필요할 때 직접 호출합니다. 이 방식이 도입 부담을 크게 줄이고, 동시에 보안·감사 측면에서도 더 깔끔합니다.


1. MCP가 해결하는 문제

1-1. 문제 상황

Claude Code는 훌륭한 셸 기반 에이전트지만, 기본 제공 툴만으로는 한계가 있습니다. 사내 위키, 사내 DB, 티켓 시스템, 특정 회사 API에 접근하려면 매번 스크립트를 직접 짜서 붙이는 방식은 비효율적입니다. 또 한 도구는 Cursor에서, 다른 도구는 ChatGPT에서 따로 구현해야 한다면 같은 일을 N번 반복하게 됩니다.

1-2. MCP의 아이디어

MCP는 LLM 에이전트가 외부 도구를 표준화된 방식으로 사용할 수 있도록 만든 프로토콜입니다. "도구를 제공하는 서버"와 "도구를 소비하는 호스트(Claude Code 등)"의 계약을 JSON-RPC 기반으로 맞춥니다. 서버는 자신이 제공하는 도구의 이름·설명·파라미터 스키마를 노출하고, 호스트는 그 정보를 LLM 프롬프트에 포함시켜 모델이 적절한 시점에 호출하도록 유도합니다. 호출 결과는 다시 LLM에게 전달되어 최종 답변을 만드는 재료가 됩니다.

MCP 통신 구조 Host (Claude Code) LLM 추론 tool_call 결정 MCP Client 내장 tool_call tool_result MCP Server JSON-RPC 처리 tool·resource 정의 노출 실제 자원 파일시스템·DB 사내 API 외부 SaaS Host ↔ Server는 stdio·SSE·HTTP 중 하나로 통신, 메시지 포맷은 JSON-RPC 2.0
구성 요소 역할
Host MCP 서버를 소비하는 측 (Claude Code)
Client Host 내부에서 실제 연결을 관리하는 모듈
Server 도구·리소스·프롬프트를 노출하는 프로세스
Transport stdio / SSE / HTTP 등 통신 방식

💡 쉽게 말해 "LLM을 위한 USB-C 같은 표준"이라고 이해하면 됩니다. 구현 언어는 Python, TypeScript 모두 공식 SDK가 제공됩니다.


2. Claude Code에 MCP 서버 등록하기

2-1. 설정 파일 위치

Claude Code는 사용자 단위와 프로젝트 단위의 MCP 설정을 지원합니다. 프로젝트 단위는 루트의 .claude/mcp.json에 작성합니다. 팀 단위로 공유하고 싶다면 이 파일을 깃에 함께 커밋해 두면 됩니다.

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/dev"]
    }
  }
}

2-2. 명령행으로 추가

반복 입력이 번거롭다면 CLI로도 등록할 수 있습니다.

claude mcp add filesystem -- \
  npx -y @modelcontextprotocol/server-filesystem /Users/me/dev

등록 후 Claude Code를 재실행하면 새 도구가 로드됩니다.

2-3. 상태 확인

claude mcp list

등록된 서버 이름과 상태(running / error)가 출력됩니다. 등록은 됐는데 상태가 error라면 다음 트러블슈팅 섹션을 참고합니다.


3. 자주 쓰는 공식 MCP 서버

이름 제공 기능
filesystem 지정한 루트 이하 파일 읽기/쓰기
git 로컬 저장소 상태, 로그, diff
fetch URL fetch (웹 페이지 수집)
memory 에이전트용 영구 메모리
postgres PostgreSQL 스키마·쿼리
brave-search 웹 검색 (Brave API)

⚠️ MCP 서버는 LLM이 자동 호출할 수 있는 도구이므로, 쓰기 권한 서버는 화이트리스트 경로만 노출하는 것이 안전합니다. 사용자 전체 홈을 통째로 열지 마세요. filesystem 서버는 루트 인자를 좁게 지정해야 합니다.


4. 커스텀 MCP 서버 예제 (Python)

4-1. 프로젝트 세팅

mkdir my-mcp && cd my-mcp
python -m venv .venv && source .venv/bin/activate
pip install "mcp[cli]>=1.0.0"

4-2. 최소 코드

회사 내 사용자 조회를 가정한 단순 서버입니다. 데코레이터로 도구를 등록하고, docstring이 LLM에게 도구 설명으로 그대로 전달됩니다.

# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("internal-directory")

USERS = {
    "alice": {"team": "platform", "email": "alice@company.com"},
    "bob":   {"team": "data", "email": "bob@company.com"},
}

@mcp.tool()
def find_user(name: str) -> dict:
    """이름으로 사용자 정보를 조회합니다."""
    return USERS.get(name.lower(), {"error": "not found"})

if __name__ == "__main__":
    mcp.run()

4-3. Claude Code에 등록

{
  "mcpServers": {
    "directory": {
      "command": "python",
      "args": ["/Users/me/dev/my-mcp/server.py"],
      "cwd": "/Users/me/dev/my-mcp"
    }
  }
}

Claude Code를 재시작한 뒤 대화창에서 "alice 팀이 어디지?"라고 물으면, LLM이 find_user 도구를 호출해 답을 만듭니다.

동작 흐름
User → LLM → tool_call(find_user, {"name": "alice"})
           ← tool_result({"team":"platform", ...})
LLM → "alice는 platform 팀입니다."

5. 인증과 보안 포인트

  • 민감 정보가 포함된 서버는 stdio 대신 HTTP + 헤더 인증을 쓰고, 로컬 네트워크로 제한합니다.
  • 읽기 전용 서버와 쓰기 가능 서버를 분리하면 사고 반경이 크게 줄어듭니다.
  • LLM이 잘못 도구를 호출해도 복구 가능한 형태(트랜잭션, 드라이런 모드)로 설계하세요.
  • 도구가 어떤 파라미터를 받을 수 있는지 LLM이 명확히 알 수 있도록 docstring과 타입 힌트를 충분히 채워두면, 오용 가능성이 크게 줄어듭니다.

트러블슈팅

문제 1: MCP server failed to start

가장 흔한 원인은 실행 경로 문제입니다. command, args, cwd가 절대경로여야 안정적입니다. 가상환경을 쓰는 서버라면 command/path/to/.venv/bin/python으로 지정하세요.

문제 2: 도구가 호출되지 않음

도구 목록에 노출되었는지 먼저 확인합니다.

claude mcp list
claude mcp status directory

이후 대화창에서 /mcp로 현재 로드된 서버를 다시 점검합니다.

문제 3: 결과에 한글이 깨짐

서버 표준 출력 인코딩이 기본이 아닐 때 발생합니다. Python이라면 PYTHONIOENCODING=utf-8 환경변수를 추가합니다.

{
  "mcpServers": {
    "directory": {
      "command": "python",
      "args": ["server.py"],
      "env": { "PYTHONIOENCODING": "utf-8" }
    }
  }
}

문제 4: LLM이 같은 도구를 반복 호출

도구 응답에 충분한 메타 정보가 없거나, 도구 설명이 모호하면 LLM이 결과를 받고도 다시 호출하는 루프에 빠집니다. docstring에 "성공/실패", "다음 단계 안내" 같은 정보를 명시적으로 넣어주면 안정성이 크게 올라갑니다.


마무리

MCP는 "AI가 내 도구를 어떻게 쓰게 할까"를 표준으로 답한 최초의 프로토콜에 가깝습니다. 이전에는 도구마다 호스트마다 다른 통합 방식을 구현해야 했지만, 표준이 잡히면서 한 번 만든 서버를 여러 호스트에 그대로 재사용할 수 있게 됐습니다. Claude Code의 매력은 이 MCP 생태계를 그대로 활용할 수 있다는 점입니다. 처음에는 공식 서버를 그대로 붙여보고, 필요해지면 사내 API 전용 서버를 추가하는 순서가 가장 효율적입니다. 한 번 익숙해지면, 같은 서버를 Cursor·ChatGPT 같은 다른 호스트에도 그대로 붙여 쓸 수 있어 재사용성이 큽니다. 표준 위에서 도구가 자라기 시작하면, 어떤 호스트가 새로 등장하더라도 그동안의 작업이 그대로 가치를 유지합니다.