AI 코딩 도구

Claude Code로 MCP 서버 만드는 방법: 단계별 가이드 (2026)

2026년 8월 20일11분 읽기

Claude Code로 MCP 서버를 만든다는 것은, Model Context Protocol을 통해 도구/리소스를 노출하는 작은 서비스를 작성하고, 그것을 claude mcp add로 Claude Code에 곧바로 연결하는 것을 뜻해요. 과정은 세 단계예요. (1) Python 또는 TypeScript로 도구를 설계하고 작성하기, (2) 트랜스포트 고르기(로컬에서는 stdio가 기본), (3) Claude Code에 연결하고 테스트하기. 방법은 두 가지예요. 실제로 무슨 일이 일어나는지 이해하려고 직접 손으로 작성하는 방법과, Claude Code에게 스캐폴딩을 맡기는 방법이에요. 이 가이드에서는 둘 다 살펴봐요.

· 작성: Jasmine — Claude Code를 매일 사용하고, 팀을 위해 사내 MCP 서버 몇 개를 직접 손으로 작성해 배포해 온 개발자예요.

MCP 서버란? (간단 정리)

MCP 서버란, 세 가지 종류의 기능——도구(에이전트가 호출할 수 있는 함수), 리소스(읽을 수 있는 데이터), 프롬프트(재사용 가능한 프롬프트 템플릿)——를 Model Context Protocol을 통해 LLM에 노출하는 작은 프로세스예요. 달리 말하면, Claude Code와 바깥 세계——사내 API, 데이터베이스, 파일 시스템, 또는 Claude가 통제된 방식으로 접근하게 하고 싶은 모든 서비스——사이의 표준화된 '어댑터'예요.

MCP의 좋은 점은 오픈 표준이라는 거예요. 서버를 한 번 작성하면 여러 호스트(Claude Code, Claude Desktop, 그리고 다른 클라이언트)에서 사용할 수 있어요. 이 가이드에서는 개념을 깊이 파고들지 않아요——그건 MCP란 무엇인가 글에서 다뤄요. 여기서는 공식 문서가 보통 따로 떼어 놓는 부분, 즉 직접 서버를 작성하고 그것을 곧바로 Claude Code에 연결하는 부분에 집중해요.

직접 MCP 서버를 작성해야 할 때는 언제일까요?

코드를 한 줄 쓰기 전에 이렇게 물어보세요. 이 서버를 이미 누군가 만들지 않았을까? 흔한 요구의 상당수는 이미 공식 또는 커뮤니티 서버가 있어요——GitHub, Playwright, Sentry, 파일 시스템 등이요. 기존 것을 연결하는 편이 새로 만드는 것보다 항상 빨라요.

상황할 일
GitHub를 다루기, 브라우저 조작하기, Sentry 오류 읽기기존 서버 사용——claude mcp add만 하면 돼요
아직 아무도 감싸지 않은 우리 회사의 사내 API직접 MCP 서버를 작성하기
특정 스키마를 가진 비공개 데이터베이스직접 작성하기(쿼리와 권한을 제어)
여러 시스템에 걸친 다단계 워크플로워크플로로 패키징해서 직접 작성하기
로컬 파일 몇 개만 읽으면 되는 경우기존 파일 시스템 서버 사용하기

제 경험칙은 이래요. 데이터나 로직이 내 것이고 아직 표준 어댑터가 없을 때 직접 MCP 서버를 작성하세요. 다른 사람들이 이미 잘 해 놓은 것을 다시 만들지 마세요.

시작하기 전에

중간에 걸려 넘어지지 않도록 하는 짧은 체크리스트예요.

  • Claude Code가 설치되어 있고 로그인되어 있을 것(Pro/Max 요금제나 API 키 둘 다 됩니다).
  • 런타임: Node.js 18+(TypeScript용) 또는 Python 3.10+(Python용).
  • SDK 고르기: Python이 편하다면 FastMCP / Python SDK, Node에서 산다면 TypeScript SDK(@modelcontextprotocol/sdk).
  • 구체적인 목표: 예를 들어 "사내 API에서 주문을 조회하는 도구". 무엇이든 다 하는 범용 서버로 시작하지 마세요.

Claude Code가 처음이라면, 먼저 Claude Code란 무엇인가를 읽고 세션을 실행하는 방법과 권한을 부여하는 방법을 이해하세요.

옵션 1 — MCP 서버를 직접 손으로 작성하기

한 번 수동으로 해 보면 Claude가 도구를 호출할 때 실제로 무슨 일이 일어나는지 이해하게 돼요. 그다음에는 마음껏 자동화할 수 있어요. 아래 다섯 단계로 설계에서 동작하는 테스트까지 진행해요.

1단계 — 엔드포인트가 아니라 워크플로를 중심으로 도구를 설계하기

가장 흔한 실수는 각 REST 엔드포인트를 도구에 1:1로 대응시키는 거예요. 그 결과 한 가지 일을 하려고 다섯 개의 도구를 호출해야 하는 에이전트가 되고, 쉽게 흐름을 놓쳐요. 대신 에이전트 중심으로 설계하세요.

  • 의도별로 작업을 통합하기: 에이전트에게 get_order + get_customer + get_items를 이어 붙이게 하는 대신, 하나의 get_order_summary 도구가 한 번에 모든 것을 반환해요.
  • 사람이나 에이전트가 읽을 수 있는 출력을 반환하기: 내부 코드가 아니라 명확한 필드 이름을 쓰세요.
  • 에이전트를 '가르치는' 오류 메시지를 작성하기: 스택 트레이스만이 아니라 고칠 힌트를 곁들여 오류를 알려요.

이 원칙들은 ak-mcp-builder 스킬에 녹아 있는 모범 사례에서 나온 거예요——많은 범용 튜토리얼이 건너뛰는 부분이죠.

2단계 — 프로젝트를 스캐폴딩하고 SDK 설치하기

나중에 알아보기 쉽도록 이름을 명확하게 지으세요. Python은 {service}_mcp, TypeScript는 {service}-mcp-server를 써요.

Python(FastMCP):

python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install "mcp[cli]" # or: pip install fastmcp
# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("orders_mcp")

if __name__ == "__main__":
 mcp.run() # defaults to the stdio transport

TypeScript(MCP SDK):

npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new McpServer({ name: "orders-mcp-server", version: "1.0.0" });

const transport = new StdioServerTransport();
await server.connect(transport);

3단계 — 첫 번째 도구 작성하기(실행 가능한 예제와 함께)

좋은 도구에는 세 부분이 있어요. 촘촘한 입력 스키마, 명확한 설명(에이전트는 이것을 읽고 언제 도구를 호출할지 알아요), 그리고 동작을 기술하는 도구 어노테이션이에요. 다음은 주문 조회 도구예요.

Python:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("orders_mcp")

@mcp.tool(
 annotations={
 "readOnlyHint": True, # read-only, does not change data
 "idempotentHint": True, # same result when called again
 "openWorldHint": True, # calls an external system
 }
)
def get_order_summary(order_id: str) -> str:
 """Look up a summary of one order by its order ID.
 Use when the user asks about the status/total/customer of a specific order."""
 order = fetch_order(order_id) # calls your internal API
 if order is None:
 return f"Order '{order_id}' not found. Double-check the ID (format ORD-xxxxx)."
 return (
 f"Order {order['id']} | Customer: {order['customer']} | "
 f"Status: {order['status']} | Total: ${order['total']:,}"
 )

TypeScript(입력 스키마에 Zod 사용):

import { z } from "zod";

server.registerTool(
 "get_order_summary",
 {
 description: "Look up a summary of one order by its order ID.",
 inputSchema: { order_id: z.string().describe("Order ID, format ORD-xxxxx") },
 annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
 },
 async ({ order_id }) => {
 const order = await fetchOrder(order_id);
 const text = order
 ? `Order ${order.id} | Customer: ${order.customer} | Status: ${order.status}`
 : `Order '${order_id}' not found.`;
 return { content: [{ type: "text", text }] };
 }
);

Claude가 도구를 호출했을 때의 샘플 출력: Order ORD-10231 | Customer: Alex Nguyen | Status: In transit | Total: $540. 한 가지 주의할 점이 있어요. 어노테이션은 호스트에게 힌트일 뿐 보안 장치가 아니에요——쓰기를 막으려고 readOnlyHint에 의존하지 마세요.

4단계 — 트랜스포트 고르기(stdio / HTTP / SSE)

트랜스포트는 호스트가 서버와 어떻게 통신할지를 결정해요. 무작정 기본값으로 두지 말고 상황에 맞게 고르세요.

트랜스포트사용 시점장점 / 단점
stdio서버가 로컬에서 실행되고, 클라이언트가 하나(내 컴퓨터의 Claude Code)가장 단순하고 네트워크 불필요 · 클라이언트는 하나만
HTTP(streamable)원격 서버, 여러 클라이언트, 자체 인프라에 배포공유·확장 가능 · 인증/OAuth를 직접 처리해야 함
SSE실시간 이벤트를 푸시해야 함(점차 streamable HTTP로 대체되는 중)스트리밍에 적합 · 더 오래된 방식

로컬 + Claude Code의 기본값: stdio를 쓰세요. 서버를 여러 사람과 공유하거나 원격에 배포해야 할 때만 HTTP로 넘어가세요.

5단계 — 올바른 방법으로 실행하고 테스트하기

여기서 많은 사람이 걸려 넘어져요——그리고 이를 경고하는 튜토리얼은 드물어요.

  • 서버는 오래 실행되는 프로세스예요. python server.py를 직접 실행하면 stdio로 입력을 기다리기 때문에 터미널이 '멈춘' 것처럼 보여요——이건 정상이지 버그가 아니에요. 막히지 않고 빠르게 확인하려면 timeout 5s python server.py를 쓰거나, tmux / 별도 창에서 실행하거나, 평가 하네스를 사용하세요.
  • stdio에서는 절대 stdout에 로그를 남기지 마세요. stdout은 프로토콜 채널이에요——거기에 끼어든 print() 하나가 JSON-RPC 스트림을 깨뜨리고, 서버는 헷갈리는 방식으로 '죽어요'. 대신 stderr에 로그를 남기세요(Python: print(..., file=sys.stderr) 또는 logging 모듈).
  • 먼저 컴파일되는지 확인하세요: Python은 python -m py_compile server.py, TypeScript는 npm run build.

가장 믿을 만한 테스트 방법은 평가 기반(eval-driven)이에요. 각 도구를 샘플 입력으로 호출하고 출력을 검증하는 스크립트를 작성해, timeout을 건 자식 프로세스에서 실행하세요. 그러면 Claude Code에 연결하고 나서야 아무것도 반환하지 않는 도구를 발견하는 대신, 스키마와 프로토콜 버그를 즉시 잡아낼 수 있어요.

옵션 2 — Claude Code에게 MCP 서버를 대신 작성하게 하기

옵션 1에서 구조를 이해했다면, 매번 보일러플레이트를 다시 타이핑할 필요가 없어요. 이게 재미있는 '메타 관점'이에요. Claude Code 자신을 이용해 Claude Code용 MCP 서버를 작성하는 거죠.

에이전트가 작업에서 벗어나지 않도록 조각으로 나눈, 제가 좋아하는 프롬프트 패턴이에요.

Write a Python MCP server named orders_mcp using FastMCP.
- Tool get_order_summary(order_id) calls our internal API at BASE_URL (read from env).
- Tight input schema, clear description, readOnlyHint/idempotentHint annotations.
- Log to stderr, NOT stdout. Transport stdio.
Then write a test script that uses timeout so it does not hang, and explain how to wire it into Claude Code.

Claude Code는 프로젝트를 스캐폴딩하고, 도구와 스키마를 작성하고, 요청하면 테스트 단계까지 작성해 줘요. 당신의 주된 일은 그것을 검토하는 거예요——반복적인 부분은 에이전트가 처리해요. 팁: 작성하기 전에 에이전트에게 가정(경로, 환경 변수 이름)을 밝히게 하고, 그 세션 안에서 py_compile / npm run build를 직접 실행해 코드가 제대로 컴파일되는지 확인하게 하세요. 그러면 테스트되지 않은 코드 더미 대신, 이미 기본 점검을 통과한 서버를 얻게 돼요.

서버를 많이 만든다면, 모든 모범 사례를 직접 외우는 대신 이미 만들어진 스킬을 쓰는 게 좋아요. AgentKit(ak-mcp-builder 스킬)의 Engineer Kit은 다단계 MCP 서버 구축 과정(research -> implement -> review -> eval)을 제공하며, 도구 설계 모범 사례와 테스트용 평가 하네스를 함께 패키징해요——그래서 위의 보일러플레이트와 stdio / 오래 실행되는 프로세스의 함정을 전부 머릿속에 담아 둘 필요가 없어요. 자세한 내용은 AgentKit Engineer Kit 안에 무엇이 있는지를 보세요.

혼동을 피하기 위한 한 가지 설명: 여기서 'AgentKit'은 Claude Code를 위한 스킬 모음(agentkit.best, ak CLI)을 가리키며, OpenAI의 'AgentKit' 제품과는 다른 거예요. 제 접근법: 이해를 위해 한 번은 직접 손으로 해 보고, 그다음에는 속도를 위해 스킬을 쓰는 거예요.

MCP 서버를 Claude Code에 연결하기

이제 서버가 생겼으니 Claude Code에 연결하세요. 핵심 명령은 claude mcp add예요.

로컬 stdio 서버——-- 구분자 뒤에 명령을 전달하세요.

claude mcp add orders -- python /path/to/server.py
# or a built TypeScript server:
claude mcp add orders -- node /path/to/dist/index.js

원격 서버(HTTP):

claude mcp add orders --transport http https://mcp.company.com/orders

연결을 확인하세요.

claude mcp list # shows: orders ✔ Connected
claude mcp get orders # view a server's full configuration

스코프는 서버가 어디서 사용 가능한지를 결정해요. local(나만, 이 프로젝트에서만), project(팀 전체를 위해 커밋), user(내 모든 프로젝트). 팀이 공유하는 서버라면, 저장소 루트에 .mcp.json을 직접 작성해 커밋하세요.

{
 "mcpServers": {
 "orders": {
 "command": "python",
 "args": ["server.py"],
 "env": { "BASE_URL": "https://api.internal.company.com" }
 }
 }
}

.mcp.json을 편집한 뒤에는, 다시 로드되도록 Claude Code 세션을 재시작하는 것을 잊지 마세요.

흔한 문제와 해결 방법

증상흔한 원인해결
Failed to connect명령/경로/URL이 잘못됨claude mcp get <name>을 실행해 살펴보고, 명령을 단독으로 테스트하세요
시작하자마자 서버가 '죽음'stdout에 로그를 남겨 stdio 프로토콜을 깨뜨림모든 로그를 stderr로 옮기세요
도구가 Claude에 나타나지 않음환경 변수 / API 키 누락--env KEY=value로 전달하거나 .mcp.json에 선언하세요
첫 실행 시 타임아웃(npx가 패키지를 내려받는 중)의존성 다운로드가 기본 타임아웃보다 오래 걸림시작 시 MCP_TIMEOUT=60000을 설정하세요
.mcp.json을 편집했는데 아무것도 바뀌지 않음세션이 설정을 다시 로드하지 않음Claude Code 세션을 재시작하세요

MCP 서버 작성 모범 사례

기억할 만한 것들을 정리했어요(상당수는 ak-mcp-builder에서 가져왔어요).

  • 도구 이름{service}_{action}_{resource} 패턴(snake_case)으로 짓고, 여러 서버를 연결했을 때 충돌을 피하도록 서비스 접두사를 붙이세요.
  • 출력에 JSON과 Markdown을 모두 지원하세요——에이전트는 구조화된 데이터를 잘 읽고, 사람은 Markdown 버전을 더 쉽게 읽어요.
  • 많은 데이터를 반환하는 도구는 페이지네이션하세요: 수천 행을 반환하는 대신 limit, has_more, next_offset을 쓰세요.
  • 출력 길이에 상한을 두세요(경험칙으로 약 25,000자), 그리고 안내와 함께 잘라내세요("N개 더 있음, offset을 사용하세요...").
  • 오류 메시지를 실행 가능하게 만드세요: 무엇이 잘못됐고 어떻게 고치는지 정확히 말하세요.
  • 보안: 입력을 검증하고, API 키는 환경 변수에 두고(절대 하드코딩 금지), 내부 오류 / 스택 트레이스를 에이전트에 흘리지 마세요. 어노테이션은 힌트일 뿐 진짜 접근 제어를 대신하지 못한다는 걸 기억하세요.

개발 워크플로를 더 자동화하고 싶으세요? Claude Code용 커스텀 스킬을 만드는 방법과, Claude Code의 서브에이전트를 사용해 빌드/테스트 작업을 나누는 방법을 보세요.

자주 묻는 질문(FAQ)

MCP 서버는 어떤 언어로 작성해야 하나요?

가장 흔한 선택지는 Python(FastMCP / Python SDK)과 TypeScript(@modelcontextprotocol/sdk)예요. MCP에는 다른 언어용 SDK도 있지만, Claude Code에는 Python이나 TS가 가장 빠르고 예제도 가장 많은 선택지예요.

기존 서버에 연결하는 것과는 어떻게 다른가요?

기존 서버에 연결하는 건 누군가 이미 작성한 것에 claude mcp add를 가리키기만 하면 돼요. 직접 서버를 작성하는 건 아직 아무도 어댑터를 만들지 않은 나만의 로직/데이터(사내 API, DB)를 노출해야 할 때예요.

Claude Code가 MCP 서버를 스스로 작성할 수 있나요?

네. 원하는 도구, 스키마, 트랜스포트를 설명하면 Claude Code가 프로젝트를 스캐폴딩하고, 도구를 작성하고, 테스트 스크립트까지 작성해 줘요. 당신은 검토만 하면 돼요. ak-mcp-builder 스킬은 이 과정을 모범 사례와 함께 패키징해요.

원격(HTTP) 서버는 어떻게 배포하나요?

자체 인프라에서 streamable HTTP 트랜스포트로 서버를 실행한 다음 claude mcp add <name> --transport http <url>을 하세요. 원격 서버는 인증(OAuth/토큰)도 처리해야 해요——내 컴퓨터를 신뢰하는 로컬 stdio 서버와 달리요.

Claude Code Pro가 필요한가요?

특정 요금제가 필요하지는 않아요. 로그인하면 MCP는 Claude Code에서 동작해요——Pro/Max 요금제나 API 키 둘 다 됩니다. 서버를 작성하는 것 자체는 이미 지불하고 있는 모델 사용료 외에 비용이 들지 않아요.

ak-mcp-builder는 무엇이고, 꼭 필요한가요?

ak-mcp-builder는 평가 하네스를 갖춘 다단계 과정으로 MCP 서버를 구축하는, AgentKit Engineer Kit의 스킬이에요. 꼭 필요하지는 않아요——옵션 1처럼 전부 직접 손으로 작성할 수 있어요. 서버를 많이 만들 때 작업을 더 빠르게 하고 모범 사례의 함정을 피하도록 도와줄 뿐이에요.

결론과 다음 단계

정리하면, Claude Code로 MCP 서버를 만드는 방법은 두 가지예요. 깊이 이해하기 위해 직접 손으로 작성하는(워크플로를 중심으로 도구 설계 -> SDK 설치 -> 도구 작성 -> 트랜스포트 선택 -> timeout/stderr로 테스트) 방법과, 속도가 필요할 때 Claude Code에게 대신 작성하게 하는 방법이에요. 어느 쪽이든 핵심은 claude mcp add.mcp.json으로 Claude Code에 연결하고 ✔ Connected를 확인하는 거예요. 제 조언: 이해를 위해 한 번은 직접 손으로 해 보고, 그다음에는 자동화하세요.

다음 단계로, 이 구축 과정을 당신만의 커스텀 스킬로 바꿔 보세요. 그리고 표준화되고 평가 준비가 된 MCP 서버 구축 과정을 곧바로 쓰고 싶다면, AgentKit Engineer Kit — 20% 할인, 지금 $79.20(ak-mcp-builder 스킬)을 살펴보세요.

출처: Model Context Protocol - 명세 및 서버 구축 가이드(버전 2026-07-28); Claude Code 문서 - MCP 및 claude mcp add(v2.1.219). CLI는 빠르게 업데이트되므로, 사용하기 전에 정확한 명령을 확인하세요.

J

Jasmine

작성자 · Jasmine Daily

Jasmine Daily를 써 내려가는 사람 - 생각과 경험, 그리고 하루하루의 순간을 적어 두어요. 솔직하고, 서두르지 않고, 완벽하지 않게.

Jasmine Daily

아직 읽을 이야기가 더 있어요.

이 글이 마음에 닿았다면, 일기의 다른 페이지들도 몇 장 넘겨 보세요.

다음 읽을거리

관련 글