MCP(Model Context Protocol — Claude 같은 AI가 외부 도구·데이터에 연결하는 공식 표준 규약) 서버를 직접 만들면, 남이 만든 서버를 설치하는 것을 넘어 내가 원하는 기능을 Claude Code에 도구로 붙일 수 있습니다. 이 글에서는 공식 SDK를 이용해 Python과 TypeScript 두 가지 방식으로 아무 외부 의존성 없이 동작하는 최소 MCP 서버를 만들고, claude mcp add 명령으로 Claude Code에 연결해 실제로 도구가 호출되는 것까지 확인합니다. 처음부터 끝까지 따라 하면 대략 30~40분 정도 걸립니다(개인 환경에 따라 다를 수 있습니다).
🟢 현행 모델 라인업 일치 · 모델 안내 · Fable 구독 안내
Fable 5·5.1 구독 안내(2026년 9월 7일 갱신): 2026년 9월 1일 출시된 Claude Fable 5.1이 현행 Fable 모델이고, Fable 5는 레거시로 전환됐습니다. 구독 조건은 두 모델이 같습니다 — Max·Team Premium 플랜은 주간 사용 한도의 50% 범위에서 포함되고, Pro·Team Standard 플랜은 사용량 크레딧(입력 100만 토큰당
MCP 서버는 정확히 무엇을 만드는 걸까요?
MCP 서버는 Claude Code 같은 AI 클라이언트가 호출할 수 있는 "도구(tool)" 함수를 담은 작은 프로그램입니다. 공식 문서에 따르면 MCP 서버는 크게 세 가지를 제공할 수 있습니다: 도구(tool — LLM이 사용자 승인을 받아 호출하는 함수), 리소스(resource — 파일처럼 읽을 수 있는 데이터), 프롬프트(prompt — 미리 만들어둔 작업 템플릿). 이 글은 가장 자주 쓰이는 도구 만들기에 집중합니다. 서버와 Claude Code는 표준입출력(stdio — 터미널의 표준 입력/출력 통로)을 통해 JSON-RPC(구조화된 요청/응답 메시지 형식)로 대화하며, 이 방식 덕분에 Python으로 만든 서버든 TypeScript로 만든 서버든 Claude Code 입장에서는 똑같이 취급됩니다.
시작하기 전에 준비할 것
다음 항목이 갖춰져 있어야 막히지 않고 따라 할 수 있습니다.
- Claude Code CLI가 설치되어 있고 로그인까지 마친 상태(터미널에서
claude명령이 실행되는 상태) - 터미널(명령 프롬프트) 사용에 기초적으로 익숙할 것 — 폴더 이동, 명령어 실행 정도
- Python 트랙을 따라 하려면 Python 3.10 이상, TypeScript 트랙을 따라 하려면 Node.js 20 이상
- 텍스트 에디터(VS Code 등) 하나
두 트랙 모두 만들어볼 필요는 없습니다. 평소 더 익숙한 언어 하나만 골라서 따라 하면 됩니다.
용어 빠른 풀이
- MCP(Model Context Protocol) — AI 애플리케이션이 외부 도구·데이터에 연결하는 공식 개방형 표준 규약
- SDK(Software Development Kit) — 특정 기능을 쉽게 구현하도록 미리 만들어진 코드 도구 모음. 여기서는 MCP 서버를 만들기 위한 공식 라이브러리를 뜻합니다
- stdio(standard input/output) — 프로그램이 터미널과 데이터를 주고받는 표준 통로. MCP에서 가장 기본적인 연결 방식입니다
- 도구(tool) — Claude 같은 AI가 호출할 수 있도록 서버가 등록해 둔 함수 하나하나
- uv — Python 프로젝트 생성·가상환경·패키지 설치를 한 번에 처리하는 공식 문서 권장 도구
Python(mcp 패키지)으로 최소 서버 만들기
먼저 Python 트랙입니다. 공식 문서가 권장하는 uv 도구로 프로젝트를 만듭니다.
-
uv 설치(이미 설치되어 있다면 건너뜁니다). 터미널에서 실행합니다.
curl -LsSf https://astral.sh/uv/install.sh | sh설치 후 터미널을 껐다 다시 켜야
uv명령이 인식됩니다. -
프로젝트 생성과 SDK 설치. 원하는 폴더에서 실행합니다.
uv init hello-mcp cd hello-mcp uv venv source .venv/bin/activate uv add "mcp[cli]" touch hello.py이렇게 보이면 성공: 에러 없이 명령이 끝나고,
hello-mcp폴더 안에hello.py파일이 생깁니다. -
hello.py 작성. 아래 내용을 그대로 붙여 넣습니다. 외부 API 없이도 동작하도록 인사말 도구와 덧셈 도구, 두 개만 넣었습니다.
from mcp.server import MCPServer mcp = MCPServer("hello-server") @mcp.tool() def greet(name: str) -> str: """이름을 받아 인사말을 돌려줍니다. Args: name: 인사할 대상의 이름 """ return f"안녕하세요, {name}님! MCP 서버가 정상적으로 응답하고 있습니다." @mcp.tool() def add_numbers(a: float, b: float) -> str: """두 숫자를 더한 결과를 돌려줍니다. Args: a: 첫 번째 숫자 b: 두 번째 숫자 """ return f"{a} + {b} = {a + b}" if __name__ == "__main__": mcp.run(transport="stdio")주의: stdio 방식 서버에서는
print()를 절대 쓰면 안 됩니다.print()는 표준출력에 글자를 쓰는데, MCP는 그 표준출력 통로로 JSON-RPC 메시지를 주고받기 때문에print()한 줄만 있어도 메시지가 깨져 서버가 먹통이 됩니다. 로그를 남기고 싶다면logging모듈을 쓰세요(표준에러로 나가서 안전합니다). -
로컬에서 실행 확인.
uv run hello.py이렇게 보이면 성공: 에러 없이 실행되고, 터미널이 멈춘 것처럼 조용히 대기합니다. 이는 정상입니다 — 서버가 클라이언트(Claude Code)의 연결을 기다리는 중입니다.
Ctrl+C로 종료하세요.
Claude Code에 연결하고 확인하기 (Python 서버)
Claude Code CLI의 claude mcp add 명령으로 로컬 stdio 서버를 등록합니다. 실행 명령에 절대경로가 필요하므로, 먼저 프로젝트 폴더에서 pwd를 실행해 전체 경로를 복사해 두세요.
-
서버 등록.
/절대/경로/hello-mcp부분을 방금 확인한 실제 경로로 바꿔서 실행합니다.claude mcp add --transport stdio hello-mcp -- uv --directory /절대/경로/hello-mcp run hello.py이렇게 보이면 성공:
Added로 시작하는 줄이 출력됩니다. 이는 설정이 저장됐다는 뜻이지, 연결 성공을 보장하지는 않습니다. -
연결 상태 확인.
claude mcp list이렇게 보이면 성공:
hello-mcp옆에✔ Connected표시가 뜹니다.✘ Failed to connect가 뜨면 아래 "자주 막히는 지점" 항목을 확인하세요. -
Claude Code 안에서 실제로 호출해보기. Claude Code 세션을 시작한 뒤 자연어로 요청합니다.
hello-mcp 서버의 greet 도구로 "우주"에게 인사해줘Claude가
greet도구를 호출하고, 서버가 만든 인사말 문장을 그대로 답변에 반영하면 성공입니다.
TypeScript(공식 SDK)로 최소 서버 만들기
같은 서버를 TypeScript로 만들어 봅니다. 이미 Python 트랙을 완료했다면 이 섹션은 건너뛰어도 됩니다.
-
Node.js 확인. 20 이상인지 확인합니다.
node --version npm --version -
프로젝트 생성과 SDK 설치.
mkdir hello-mcp-ts cd hello-mcp-ts npm init -y npm install @modelcontextprotocol/server zod npm install -D @types/node typescript mkdir src touch src/index.ts -
package.json 수정. 최상위에
"type": "module"과scripts.build를 추가합니다.{ "type": "module", "scripts": { "build": "tsc && chmod 755 build/index.js" } } -
tsconfig.json 생성. 프로젝트 루트에 새 파일로 만듭니다.
{ "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "types": ["node"], "outDir": "./build", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules"] } -
src/index.ts 작성.
import { McpServer } from "@modelcontextprotocol/server"; import { StdioServerTransport } from "@modelcontextprotocol/server/stdio"; import { z } from "zod"; const server = new McpServer({ name: "hello-server", version: "1.0.0", }); server.registerTool( "greet", { description: "이름을 받아 인사말을 돌려줍니다", inputSchema: z.object({ name: z.string().describe("인사할 대상의 이름"), }), }, async ({ name }) => { return { content: [ { type: "text", text: `안녕하세요, ${name}님! MCP 서버가 정상적으로 응답하고 있습니다.`, }, ], }; }, ); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("hello-server MCP 서버가 stdio로 실행 중입니다"); } main().catch((error) => { console.error("서버 실행 중 오류:", error); process.exit(1); });주의: Python과 마찬가지로
console.log()는 절대 쓰지 마세요. 표준출력이 깨져 JSON-RPC 통신이 망가집니다. 로그가 필요하면console.error()(표준에러로 나감)를 쓰세요. -
빌드.
npm run build이렇게 보이면 성공: 에러 없이 끝나고
build/index.js파일이 생성됩니다. 이 빌드 단계를 건너뛰면 다음 단계에서 연결이 실패합니다.
Claude Code에 연결하고 확인하기 (TypeScript 서버)
Python 때와 마찬가지로 절대경로가 필요합니다. hello-mcp-ts 폴더에서 pwd로 경로를 확인하세요.
-
서버 등록.
claude mcp add --transport stdio hello-mcp-ts -- node /절대/경로/hello-mcp-ts/build/index.js -
연결 상태 확인.
claude mcp list이렇게 보이면 성공:
hello-mcp-ts옆에✔ Connected가 뜹니다. Claude Code 세션 안에서는/mcp를 입력해도 같은 상태를 확인할 수 있습니다. -
실제로 호출해보기. Python 트랙과 같은 방식으로 자연어 요청을 해봅니다.
hello-mcp-ts 서버의 greet 도구로 "우주"에게 인사해줘
| 구분 | Python | TypeScript |
|---|---|---|
| 필요 버전 | Python 3.10 이상 | Node.js 20 이상 |
| 패키지 관리 | uv | npm |
| 핵심 SDK 설치 | uv add "mcp[cli]" | npm install @modelcontextprotocol/server zod |
| 서버 클래스 | MCPServer | McpServer |
| 로컬 실행 명령 | uv run hello.py | 빌드 후 node build/index.js |
자주 막히는 지점과 해결
- claude mcp list에서 ✘ Failed to connect가 뜬다:
claude mcp add에 넣었던 실행 명령(uv --directory ... run hello.py또는node .../build/index.js)을 터미널에서 그대로 직접 실행해 보세요. 그 자리에서 나는 에러 메시지가 원인을 정확히 알려줍니다. - 서버가 아예 응답하지 않거나 연결이 끊긴다: Python의
print(), TypeScript의console.log()가 코드 어딘가에 남아 있지 않은지 확인하세요. stdio 서버에서는 이 둘이 JSON-RPC 메시지를 깨뜨리는 가장 흔한 원인입니다. - 경로 문제로 연결이 안 된다:
claude mcp add에는 반드시 절대경로를 넣어야 합니다. 상대경로는 실행 위치에 따라 달라져 실패하기 쉽습니다. 프로젝트 폴더에서pwd로 정확한 경로를 확인하세요. - 서버 자체 옵션이 Claude CLI 옵션으로 오인된다:
claude mcp add명령에서 서버 실행 명령 앞에--(더블 대시)를 반드시 넣으세요. 이게 없으면 서버에 전달하려던 인자를 Claude CLI가 자기 옵션으로 잘못 해석합니다. - TypeScript 서버 연결이 안 된다:
npm run build를 건너뛰지 않았는지,build/index.js파일이 실제로 생성됐는지 확인하세요.
응용 및 다음 단계
동작 확인이 끝났다면 같은 파일에 @mcp.tool()(Python) 또는 server.registerTool(...)(TypeScript) 블록을 추가해 원하는 기능(파일 읽기, 사내 API 호출 등)을 도구로 늘려갈 수 있습니다. 팀원과 함께 쓰고 싶다면 claude mcp add에 --scope project를 붙여보세요. 이 경우 설정이 프로젝트 루트의 .mcp.json 파일에 저장되어 버전 관리 시스템으로 팀 전체와 공유할 수 있습니다. 반대로 이미 만들어진 서버를 찾아 쓰고 싶을 때는 완성된 서버를 고르는 관점의 글을 참고하는 편이 더 빠릅니다.
자주 묻는 질문
Q. MCP 서버는 Python이나 TypeScript로만 만들 수 있나요?
아니요. 공식 SDK는 Python, TypeScript 외에도 Java, Kotlin, C#, Ruby 등 여러 언어로 제공됩니다. 이 글은 가장 널리 쓰이는 Python과 TypeScript를 다뤘습니다.
Q. 만든 서버를 팀원과 함께 쓰려면 어떻게 하나요?claude mcp add에 --scope project 옵션을 붙이면 설정이 프로젝트 루트의 .mcp.json에 저장되어 버전 관리로 공유할 수 있습니다. 다만 팀원마다 서버를 최초 1회 승인하는 절차가 필요합니다.
Q. 도구를 더 추가하고 싶으면 어떻게 하나요?
같은 파일 안에 Python이면 @mcp.tool() 데코레이터가 붙은 함수를, TypeScript면 server.registerTool(...) 호출을 하나 더 작성하면 됩니다. 서버를 다시 등록할 필요 없이 재시작만 하면 새 도구가 반영됩니다.
Q. 서버가 계속 연결 실패로 뜨는데 원인을 못 찾겠어요.claude mcp add 명령에 넣었던 실행 명령을 터미널에서 그대로 직접 실행해 보세요. 그때 나오는 에러 메시지가 가장 정확한 단서입니다.