첫 번째 MCP 서버 만들기: 실전 가이드
MCP(Model Context Protocol)는 컨텍스트 윈도우를 채우지 않고도 데이터베이스, 파일, API 등 외부 툴과 데이터에 대한 구조화된 접근 권한을 Claude에 부여하는 방법입니다. 서버는 생각보다 간단합니다: SDK 설치, 툴을 JSON 스키마로 정의, 핸들러 구현, stdio로 연결. 30분 이내에 Claude가 커스텀 툴을 호출할 수 있습니다.
매주 수요일. 28,400명+ 구독자. 핵심만.
✓ 받은편지함을 확인하세요 — 확인 링크를 클릭해 가입을 완료하세요.
✓ 구독이 완료되었습니다!
✓ 이미 목록에 있습니다.
목차
2026년 6월 업데이트.
TL;DR: MCP(Model Context Protocol)는 컨텍스트 윈도우를 채우지 않고도 데이터베이스, 파일, API 등 외부 툴과 데이터에 대한 구조화된 접근 권한을 Claude에 부여하는 방법입니다. 서버는 생각보다 간단합니다: SDK 설치, 툴을 JSON 스키마로 정의, 핸들러 구현, stdio로 연결. 30분 이내에 Claude가 커스텀 툴을 호출할 수 있습니다.
[운영자 관점] 저는 정기적으로 에이전트에 새 툴을 연결하는데, MCP는 이제 그것을 깔끔하게 하는 표준 방법입니다. 서버가 한 번 구축되면 MCP를 지원하는 모든 클라이언트 — Claude Desktop, Claude Code, Anthropic SDK를 사용하는 모든 앱 — 가 호출 코드 변경 없이 사용할 수 있습니다. 이게 바로 가치입니다: 한 번 만들고, 어디서나 재사용.
MCP가 실제로 무엇인가
Model Context Protocol은 AI 모델이 외부 컨텍스트와 툴에 연결하는 방법을 표준화하는 오픈 프로토콜입니다. AI 통합을 위한 USB-C 표준이라고 생각하세요: 이전에는 Claude가 데이터베이스를 읽거나 API를 호출하게 하려는 모든 앱이 자체 솔루션을 발명해야 했습니다. 이후에는 MCP 서버 하나를 만들면 호환되는 모든 호스트가 사용할 수 있습니다.
MCP는 서버가 제공할 수 있는 세 가지를 정의합니다:
- 툴 — Claude가 호출할 수 있는 함수 (파일 읽기, DB 쿼리, Slack 메시지 보내기)
- 리소스 — Claude가 읽을 수 있는 데이터 (문서, 데이터베이스 행, 파일 트리)
- 프롬프트 — 호스트가 주입할 수 있는 재사용 가능한 프롬프트 템플릿
대부분의 운영자 사용 사례에서는 툴 서버를 구축합니다. 리소스와 프롬프트는 기본이 작동한 후에 옵니다.
아키텍처는 클라이언트-서버이며, 클라이언트 (Claude Desktop, Claude Code, 커스텀 앱)가 모든 것을 제어합니다. 서버는 수동적 — 툴 호출 요청을 기다리고 결과를 반환하기만 합니다.
모든 MCP 서버의 세 가지 구성 요소
구축하는 모든 MCP 서버는 동일한 구조를 갖습니다:
- 서버 객체 — 서버의 이름, 버전, 제공하는 기능 (툴, 리소스, 프롬프트)을 선언
- 툴 정의 — 입력을 위한 이름, 설명, JSON 스키마가 있는 툴 목록
- 요청 핸들러 — Claude가 툴을 호출할 때 실행되는 함수
그게 전부입니다. 시작하는 데 데이터베이스, HTTP 스택, auth 레이어가 필요 없습니다. 최소 서버는 TypeScript 30줄 미만입니다.
사전 요구 사항 (2분)
- Node.js 18+ —
node --version으로 확인 - TypeScript 5+ (아래에 dev 의존성으로 포함)
- 테스트용 MCP 클라이언트 — Claude Desktop은 무료이고 서버가 작동하는 것을 볼 수 있는 가장 쉬운 방법
MCP 서버 자체를 실행하는 데 Anthropic API 키가 필요하지 않습니다. API 키는 클라이언트 (Claude Desktop)에 있으며, 서버에는 없습니다.
1단계: 프로젝트 설정 (3분)
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript tsx @types/nodepackage.json에 추가:
{
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsx src/index.ts"
}
}tsconfig.json 생성:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"strict": true
},
"include": ["src/**/*"]
}2단계: 최소 서버 작성 (5분)
src/index.ts 생성:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-mcp-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// 이 서버가 제공하는 툴 선언
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "get_word_count",
description: "텍스트 블록의 단어 수를 셉니다.",
inputSchema: {
type: "object",
properties: {
text: {
type: "string",
description: "단어를 세는 텍스트",
},
},
required: ["text"],
},
},
],
}));
// 클라이언트의 툴 호출 처리
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "get_word_count") {
const { text } = args as { text: string };
const count = text.trim().split(/\s+/).filter(Boolean).length;
return {
content: [{ type: "text", text: `단어 수: ${count}` }],
};
}
throw new Error(`알 수 없는 툴: ${name}`);
});
// stdio를 통해 연결 — Claude Desktop이 서버와 통신하는 방법
const transport = new StdioServerTransport();
await server.connect(transport);이것이 전체 서버입니다. 하나의 툴 (get_word_count)을 등록하고 구현합니다. 구조가 중요합니다.
3단계: 빌드하고 Claude Desktop에 등록 (5분)
TypeScript 빌드:
npm run buildClaude Desktop 설정 파일에 등록합니다.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
파일이 없으면 생성:
{
"mcpServers": {
"my-mcp-server": {
"command": "node",
"args": ["/absolute/path/to/my-mcp-server/build/index.js"]
}
}
}절대 경로를 사용합니다. 저장 후 Claude Desktop을 재시작합니다. 메시지 입력에 망치 아이콘 (🔨)이 보이면 Claude가 툴을 발견했다는 의미입니다.
4단계: 유용한 툴 만들기
단어 세기는 설명을 위한 것입니다. 더 유용한 툴은 프로젝트 디렉토리에서 파일 읽기 — 코드베이스, changelog, 설정 파일을 요약하는 컨텍스트 주입 에이전트에 사용합니다.
import { readFileSync, readdirSync } from "fs";
import { join, extname } from "path";
const ALLOWED_EXTENSIONS = [".md", ".txt", ".ts", ".json", ".yaml"];
const PROJECT_DIR = process.env.PROJECT_DIR ?? process.cwd();로직은 동일합니다: 정확한 JSON 스키마로 툴 정의, 핸들러 구현, path traversal 방지 위한 입력 검증, 클라이언트에 텍스트 반환.
내가 겪은 문제들 (당신이 겪지 않도록)
경로는 절대 경로여야 합니다. Claude Desktop 설정의 상대 경로는 예상대로 해석되지 않습니다. 항상 전체 경로 /home/user/...를 사용하세요.
stdio는 서버에서 console.log를 사용할 수 없다는 의미입니다. Claude Desktop은 stdin/stdout을 통해 서버와 통신합니다. 디버그 console.log는 JSON-RPC 스트림을 손상시킵니다. 대신 stderr에 로그하세요:
process.stderr.write(`디버그: ${message}\n`);설정 변경 후마다 Claude Desktop을 재시작하세요. MCP 서버는 시작 시 로드됩니다. 편집된 설정 파일은 앱을 닫고 다시 열기 전까지 아무것도 하지 않습니다.
툴 설명이 제품입니다. Claude는 description 필드를 기반으로 툴을 호출할지 결정합니다. 모호한 설명은 Claude가 언제 사용해야 하는지 모른다는 의미입니다. 정확한 설명은 Claude가 적절한 순간에 사용한다는 의미입니다. 구현보다 설명에 더 많은 시간을 투자하세요.
프로덕션에서 MCP 서버 사용 방법
stdio 패턴은 Claude Desktop과 Claude Code (로컬)에 잘 작동합니다. 프로덕션 에이전트 — Cloudflare Workers에서 실행하는 30개 이상 — 에는 단계별로 Haiku vs Sonnet으로 라우팅하는 유연성이 필요하기 때문에 Anthropic SDK의 tool-use API를 직접 사용합니다.
실제로 사용하는 패턴:
- 로컬 개발 툴링 — 프로젝트별 툴을 노출하는 Claude Code용 MCP 서버
- 컨텍스트 주입 — 수동 복사 없이 관련 문서를 미리 로드하는 MCP 서버
- 프로토타입-to-API 브리지 — MCP를 먼저 구축하고 (반복이 빠름), 프로덕션을 위해 SDK tool-use로 로직 포팅
다음에 만들 것
서버 구조가 이해되면, 유용한 툴은 Claude의 외부 컨텍스트에 접근하는 것들입니다:
- 데이터베이스 리더 — 읽기 전용 SQL 쿼리를 실행하고 JSON으로 결과 반환
- Slack 리더 — 채널에서 마지막 N개 메시지 가져오기
- GitHub 리더 — 오픈 PR 목록, 특정 커밋의 파일 읽기
- 내부 API 래퍼 — auth 헤더가 포함된 REST API 호출
자주 묻는 질문
MCP 서버를 만들려면 Anthropic API 키가 필요한가요?
아니요. MCP 서버는 Anthropic API를 호출하지 않습니다. 클라이언트의 툴 호출 요청에 응답하기만 합니다. API 키는 클라이언트에 있으며, 서버에는 없습니다.
MCP 서버가 외부 API를 호출할 수 있나요?
예 — 핸들러는 단순히 비동기 TypeScript 코드입니다. 날씨 API를 가져오고, 데이터베이스를 쿼리하고, 파일에 작성합니다. 서버는 핸들러가 내부적으로 무엇을 하는지 신경 쓰지 않습니다.
stdio와 HTTP 전송의 차이는 무엇인가요?
stdio는 로컬 서버용 — Claude Desktop 또는 Claude Code와 동일한 기기. HTTP with SSE는 웹 서비스로 배포할 수 있는 원격 서버용. stdio로 시작하세요; 디버그가 더 간단합니다.
Claude는 내 툴을 언제 호출해야 하는지 어떻게 알까요?
Claude는 툴의 description 필드와 대화 컨텍스트를 기반으로 결정합니다. Claude가 계속 툴을 무시하면, 설명을 더 정밀하게 만드세요.
매주 수요일. 28,400명+ 구독자. 핵심만.
✓ 받은편지함을 확인하세요 — 확인 링크를 클릭해 가입을 완료하세요.
✓ 구독이 완료되었습니다!
✓ 이미 목록에 있습니다.
AI 플레이북을 받아보세요
매주 수요일. 28,400명+ 구독자. 핵심만.
받은편지함을 확인하세요.
확인 이메일을 보냈습니다 — 링크를 클릭해 구독을 완료하세요. 1분 안에 보이지 않으면 스팸함을 확인하세요.
구독이 완료되었습니다.
환영합니다 — 다음 호가 곧 받은편지함에 도착합니다.
이미 목록에 있습니다 — 매주 수요일에 확인하세요.