Claude Code
참고 자료

내 시스템을 Claude에 연결하기 | Custom MCP 서버 만들기

MCP Server Development Plugin으로 날씨 API를 감싸는 MCP 서버를 만들고, Tool 정의의 핵심 구조를 이해합니다

마지막 업데이트: 2026. 8. 10.

Overview

공식 MCP가 없는 사내 API나 자체 데이터베이스를 Claude Code에 연결하려면 직접 MCP 서버를 만들어야 합니다. 이 문서는 MCP 연결 Lesson에서 MCP를 사용하는 방법을 익힌 뒤, 자체 시스템까지 연결해야 할 때 선택해서 따라 하는 참고 자료입니다.

Anthropic의 MCP Server Development Plugin으로 MCP 서버 프로젝트를 생성하고, 생성된 Tool 정의를 읽어보며 MCP 서버의 세 가지 핵심 원칙을 익힙니다.

학습 목표

  • MCP Server Development Plugin으로 로컬 stdio MCP 서버 프로젝트를 생성할 수 있습니다
  • Tool 정의의 세 요소 (이름 · description · 입력 스키마) 를 읽고 이해합니다
  • 직접 만든 MCP 서버를 Claude Code에 연결하고 동작을 확인합니다

시작하기 전 확인사항

  • Node.js 20 이상 + Bun 설치 (bun --version)
  • Claude Code 인증 완료 (claude --version)
  • MCP 연결 Lesson의 Server·Client·Host 구조 이해
  • 이 실습은 기존 강의 프로젝트와 무관한 독립 프로젝트로 시작합니다. 새 폴더에서 진행합니다

Step 1: 프로젝트 폴더 준비하기

MCP 서버는 자체 package.json 과 의존성을 갖춘 독립 프로세스입니다. 지금까지 쓰던 강의 프로젝트 (Todo 앱) 와 분리된 새 폴더에서 시작합니다.

  1. 찾기 쉬운 위치에 weather-mcp 폴더 생성
    • macOS: Finder에서 홈 디렉토리 · 바탕화면 등에 ⌘+⇧+N 으로 새 폴더
    • Windows: 탐색기에서 우클릭 → 새 폴더
  2. VS Code에서 폴더 열기: File > Open Folder (단축키: macOS ⌘+O, Windows Ctrl+K Ctrl+O) → 방금 만든 weather-mcp 폴더 선택
  3. VS Code 터미널 열기: ⌃+ (백틱) 또는 메뉴의 Terminal > New Terminal

이제 이 폴더에서 MCP Server Development Plugin 설치와 Claude Code 실행을 이어갑니다.

Step 2: MCP Server Development Plugin 설치하기

mcp-server-dev는 Anthropic 공식 마켓플레이스에서 설치하는 MCP 서버 개발용 Plugin입니다.

/plugin install mcp-server-dev@claude-plugins-official
/reload-plugins

이 Plugin은 원격 HTTP 서버와 로컬 stdio 서버 제작을 모두 안내합니다. 이번 실습에서는 내 컴퓨터에서 실행하는 로컬 stdio 서버를 만듭니다.

Step 3: MCP 서버 프로젝트 생성 요청하기

터미널에서 claude 로 Claude Code를 시작하고 다음과 같이 요청합니다.

/mcp-server-dev:build-mcp-server 도시 이름을 입력하면 현재 날씨 정보 (기온, 풍속, 습도) 를 반환하는 로컬 stdio MCP 서버를 TypeScript 로 만들어줘. 프로젝트 폴더명은 weather-mcp-server 로 해줘. Open-Meteo API 를 사용하고 API 키 없이 동작해야 해.

MCP Server Development Skill이 지침을 따라 프로젝트를 만듭니다. 결과 구조는 대략 이렇습니다.

package.json
index.ts
README.md

src/index.ts가 MCP 서버 메인 파일입니다.

결과가 매번 다를 수 있습니다

AI가 생성하는 코드는 실행마다 세부 사항이 달라질 수 있습니다. 파일 구조나 변수 이름이 아래 예시와 달라도 정상입니다. 핵심 구조(Tool 정의 · 입출력 스키마 · 서버 연결)가 동일한지가 중요합니다.

Step 4: 생성된 Tool 정의 읽기

src/index.ts 의 Tool 정의가 MCP 서버의 핵심입니다.

server.registerTool(
  "get-weather",
  {
    title: "Get Weather",
    description: "도시 이름으로 현재 날씨를 조회합니다",
    inputSchema: z.object({
      city: z.string().describe("도시 이름 (예: Seoul, Tokyo, New York)"),
    }),
  },
  async ({ city }) => {
    // 1. 도시 이름 → 좌표 변환 (Geocoding)
    // 2. 좌표 → 날씨 데이터 조회
    // 3. content 배열로 결과 반환
  }
);

Tool 이름

"get-weather"

Claude 가 이 도구를 식별하는 ID

동사 + 명사 형태로 명확하게

설정 객체

{ description, inputSchema }

Tool 선택 기준과 입력 형식

description 이 가장 중요

실행 함수

async ({ city }) => { ... }

실제 API 호출 · 데이터 가공

{ content: [...] } 표준 형식 반환

server.registerTool() 의 세 인자가 Tool 의 품질을 결정합니다

server.registerTool() 은 세 개의 인자를 받습니다.

인자역할
이름Claude가 이 도구를 식별하는 ID (get-weather)
설정 객체title · description · inputSchema 를 담은 메타데이터
실행 함수실제 동작. API 호출, 데이터 가공 후 결과 반환

Tool 정의의 세 요소가 품질을 결정합니다.

  • description: 이 Tool을 언제 호출할지 알려주는 한 줄 설명입니다. "데이터를 가져옵니다" 처럼 모호하면 Claude가 잘못된 Tool을 고릅니다. "도시 이름으로 현재 날씨를 조회합니다" 처럼 구체적이어야 합니다.
  • inputSchema: Tool이 받을 입력 형태를 미리 선언하는 필드입니다. Zod는 TypeScript에서 입력값의 형태를 코드로 정의하고 검사하는 라이브러리입니다. .describe() 에 예시까지 넣으면 Claude가 자연어에서 올바른 값을 더 잘 추출합니다.
  • 실행 함수의 반환: 가장 단순한 예시는 { content: [{ type: "text", text: "..." }] }처럼 텍스트를 반환하는 형태입니다. 필요하면 이미지·오디오·리소스·structuredContent도 함께 반환할 수 있습니다.

Step 5: Claude Code에 MCP 서버 등록하기

MCP 서버 파일을 만들었지만, Claude Code는 아직 이 파일의 존재를 모릅니다. 한 번 등록해두면, Claude Code가 시작될 때마다 .mcp.json 에 적힌 명령어로 이 파일을 백그라운드에서 자동으로 실행해 둡니다. 이후 Tool을 호출할 때 Claude가 이 프로세스에 요청을 보내고, 돌려받은 응답을 사용합니다. Claude in Chrome 같은 공개 MCP와 작동 원리는 같고, 차이는 내 로컬 파일이라는 점 하나입니다.

다음과 같이 등록합니다.

claude mcp add --scope project weather -- bun run '${CLAUDE_PROJECT_DIR:-.}/weather-mcp-server/src/index.ts'

위 명령어로 현재 프로젝트에 MCP 서버를 등록해줘.

명령어가 6 개 부분으로 나뉩니다.

부분의미
claude mcp addClaude Code에 MCP 서버를 등록하는 명령
weather서버 이름. /mcp 에 이 이름으로 표시됨
--scope project스코프. project = 현재 프로젝트 루트의 .mcp.json 에 저장
--구분자. 이 뒤가 서버 실행 명령어
bun runBun 런타임으로 파일 실행. TypeScript를 컴파일 없이 바로 돌림
'${CLAUDE_PROJECT_DIR:-.}/weather-mcp-server/src/index.ts'프로젝트가 다른 위치에 있어도 동작하는 서버 파일 경로

Claude가 명령어를 실행하면 .mcp.json 에 서버 정보가 저장됩니다.

Step 6: 연결 확인하고 날씨 조회 테스트하기

/mcp를 열어 weather 서버를 선택하고 Reconnect를 실행합니다. 그래도 새 설정이 보이지 않을 때만 Claude Code를 다시 시작합니다.

/mcp

weather 서버가 "Connected" 상태면 성공입니다.

이제 Claude에게 날씨를 물어봅니다.

서울 날씨 어때?

Claude가 get-weather Tool을 호출해서 Open-Meteo API에서 실시간 데이터를 가져옵니다. 응답에 기온·풍속·습도가 포함되면 성공입니다.

한 단계 더 나아가 여러 도시를 비교합니다.

도쿄랑 뉴욕 날씨 비교해줘

Claude가 get-weather 를 두 번 호출해 두 도시 결과를 가져오고 비교합니다. MCP 서버는 데이터만 가져오고, 비교·판단·표현은 Claude가 담당합니다. 이것이 MCP 서버의 역할 경계입니다.

좋은 MCP 서버의 세 가지 원칙

description이 Tool 선택을 결정하기

사용자 질문: "서울 날씨 어때?"
Claude 가 쓸 수 있는 Tool (내장 + MCP)
Read"파일 읽기"
Bash"셸 명령 실행"
WebSearch"웹 검색"
screenshot"현재 탭 스크린샷 (Claude in Chrome)"
get-weather"도시 이름으로 현재 날씨를 조회합니다"← 매칭
get-weather({ city: "Seoul" })
Tool 은 이름이 아니라 description 으로 매칭됩니다 — 내가 만든 Tool 도 같은 목록에서 함께 경쟁합니다

Claude는 사용자 질문과 여러 Tool의 description 을 비교해서 무엇을 호출할지 판단합니다. 내가 만든 get-weather 도 내장 Tool · 다른 MCP의 Tool과 같은 목록에서 함께 경쟁합니다. description에 "날씨" 라는 단어가 있어야 "서울 날씨 어때?" 에 이 Tool이 선택됩니다. 그래서 설명을 구체적으로 적을수록 올바른 Tool이 선택됩니다.

입력 스키마: Claude 와의 계약

z.string().describe("도시 이름") 이라고 정의하면, Claude는 사용자의 자연어에서 도시 이름을 추출해 문자열로 전달합니다. 스키마가 명확할수록 추출 정확도가 올라갑니다. .describe("도시 이름 (예: Seoul, Tokyo)") 처럼 예시까지 넣으면 추출 정확도가 더 올라갑니다.

복잡성은 서버 안에 숨기기

날씨 MCP는 내부적으로 API를 두 번 호출합니다 (Geocoding → Weather). 그러나 Claude가 보는 인터페이스는 city 하나뿐입니다. 좋은 MCP 서버는 외부 시스템의 복잡성(좌표 변환 · 호출 순서 · 에러 처리)을 감추고 Claude에게 단순한 인터페이스만 노출합니다.

핵심 포인트 정리

  1. MCP Server Development Plugin으로 생성: 만들고 싶은 서버와 전송 방식(stdio 또는 HTTP)을 설명하면 Claude가 프로젝트 구조 · SDK 설정 · Tool 정의를 만듭니다.
  2. Tool 정의의 세 요소: description(Claude 선택 근거) · inputSchema(Claude와의 계약) · 실행 함수의 결과가 명확할수록 Claude가 Tool을 안정적으로 사용합니다.
  3. 프로젝트 스코프로 연결: 프로젝트 상대 경로로 .mcp.json에 등록하면 서버 정의를 팀과 공유할 수 있습니다. 각 팀원은 연결 승인과 의존성·환경 변수·인증을 따로 준비합니다.

FAQ

함께 읽을 내용

직접 만든 MCP 서버를 실제 업무 절차에 일관되게 사용하려면 도구는 가능성, Skill은 일관성을 참고합니다. MCP는 외부 시스템에 접근할 Tool을 제공하고, Skill은 그 Tool을 언제 어떤 순서와 기준으로 사용할지 정합니다.

On this page