
약 15분이면 Claude가 실제로 호출하는 MCP 서버를 만들 수 있습니다. Node 20과 Python 3.11에서 측정해본 결과, 정상 작동하는 add 도구를 stdio를 통해 실행하고 Claude Desktop에서 인식시키는 데 처음에는 14분, 한번 패턴을 이해하면 5분 미만이 걸렸습니다. 이 튜토리얼은 동일한 서버를 두 가지 방법으로 만들어 봅니다. Python에서는 FastMCP 2.x를 사용하고, TypeScript에서는 @modelcontextprotocol/sdk 1.x를 사용합니다. 따라서 여러분의 스택을 선택하고 실제 코드를 복사할 수 있습니다. 아키텍처와 프로토콜 이론을 먼저 알고 싶다면 Model Context Protocol 개념 가이드에서 찾을 수 있습니다. 여기서는 그냥 구축해봅시다.
MCP 서버 빠른 시작: 무엇을 만들 것인가
MCP 서버는 Claude, Cursor, VS Code 같은 AI 클라이언트에 Model Context Protocol을 통해 도구, 데이터, 프롬프트 템플릿을 노출하는 작은 프로그램입니다. 서버를 한 번 작성하면 MCP 호환 클라이언트가 호출할 수 있습니다. 이 튜토리얼에서는 두 개의 도구(add 계산기와 fetch_url 헬퍼)가 있는 서버를 만들고, 로컬에서 stdio를 통해 실행한 다음, 실제 클라이언트에 연결합니다.
시작하기 전에 필요한 모든 것이 있습니다.
두 경로 모두 동일하게 작동하는 서버를 생성합니다. 팀이 이미 사용하는 언어를 선택하세요. 선호도가 없다면 FastMCP가 첫 번째 서버를 더 짧게 만들어주므로 Python부터 시작하세요.
MCP 서버가 실제로 노출하는 것은 무엇인가?
코드를 작성하기 전에 서버가 제공할 수 있는 세 가지를 알면 도움이 됩니다. MCP 서버는 도구(모델이 호출할 수 있는 함수, 예: "데이터베이스 검색"), 리소스(모델이 로드할 수 있는 읽기 전용 데이터, 예: 파일이나 레코드), 프롬프트(재사용 가능한 프롬프트 템플릿)를 노출합니다. 대부분의 서버는 도구 중심이 되며, 리소스와 프롬프트는 선택 사항입니다.
클라이언트(예: Claude Desktop)는 호스트 역할을 합니다. 서버를 시작하거나 연결하고, "어떤 도구를 가지고 있나?"를 묻고, 모델이 도구가 유용하다고 판단할 때 호출합니다. 서버 내부에서 절대 모델을 호출하지 않습니다. 흐름은 반대 방향으로 실행됩니다.
그 방향이 중요합니다. 서버는 수동적인 제공자입니다. 클라이언트가 연결될 때까지 대기하고, 검색 요청에 답하고, 호출되는 모든 도구를 실행합니다. 이 정신적 모델을 유지하면 이 튜토리얼의 나머지 부분이 명확해집니다.
Python에서 MCP 서버를 구축하는 방법 (단계별)
Python은 FastMCP가 프로토콜 복잡성을 처리하고 일반 함수를 데코레이터로 도구로 변환하기 때문에 실행 중인 서버의 가장 빠른 경로입니다. 아래의 모든 것은 공식 Python SDK를 사용합니다. 네 가지 단계는 다음과 같습니다.
단계 1: 프로젝트 설정. 이제 MCP Python 프로젝트의 표준인 uv를 사용하세요:
pip를 선호한다면: python -m venv .venv && source .venv/bin/activate && pip install "mcp[cli]"
단계 2: 서버 작성. server.py를 만드세요:
주목할 두 가지가 있습니다. 문서 문자열은 모델이 읽는 도구 설명이 되므로 지시문처럼 작성하세요. 그리고 타입 힌트(a: int)는 자동으로 입력 스키마가 되므로 FastMCP가 JSON 스키마를 생성해줍니다.
단계 3: 실행. mcp.run()은 stdio에서 서버를 시작하고, 클라이언트는 로컬에서 시작합니다. 개발 중에는 직접 실행하지 않으며, 클라이언트가 시작합니다. 빠른 동작 확인을 위해 dev 런너를 사용하세요:
단계 4: 깔끔한 출력 반환. 지금 플래그할 가치가 있는 주의 사항: 문자열이나 타입 값을 반환하고, 렌더링되기를 바라는 단순한 중첩된 딕셔너리는 반환하지 않으세요. 생산 섹션에서 다시 다루겠지만, 간단히 말하면 모호한 반환 타입은 일부 클라이언트에서 자동으로 잘릴 수 있습니다.
이것이 완전한 Python MCP 서버입니다. 두 개의 도구, 실제 네트워크 호출, 자동 스키마입니다. 다음으로 TypeScript에서 동일한 것을 만들어봅시다.
TypeScript에서 MCP 서버를 구축하는 방법 (단계별)
TypeScript 경로는 공식 TypeScript SDK와 입력 검증을 위한 zod를 직접 사용합니다. FastMCP보다 약간 더 장황하지만 타입이 훌륭하고 Node 호스트에 깔끔하게 배포됩니다.
단계 1: 프로젝트 설정.
단계 2: 서버 작성. server.ts를 만드세요:
단계 3: 실행. 개발 중: npx tsx server.ts. 프로덕션의 경우 tsc로 컴파일하고 빌드된 .js를 Node로 실행하세요. 반환 형태에 주목하세요: 모든 도구는 { content: [{ type: "text", text: ... }] }를 반환합니다. 이 명시적 content 배열은 Python의 "깔끔한 문자열 반환" 규칙과 동등합니다. SDK는 원시 객체가 아닌 타입 콘텐츠 블록을 원합니다.
단계 4: zod로 입력 검증. z.string().url() 스키마는 핸들러가 실행되기 전에 나쁜 입력을 거부하는데, 이는 모델이 인수를 생성할 때 정확히 원하는 것입니다.
동일한 두 도구, 동일한 동작, 관용적인 TypeScript입니다. 이제 클라이언트가 서버에 접근하는 방법을 결정해봅시다.
stdio vs Streamable HTTP: 어떤 전송을 사용해야 할까?
MCP 서버는 두 가지 전송 중 하나를 통해 통신합니다. stdio는 클라이언트가 시작하고 표준 입출력을 통해 통신하는 로컬 하위 프로세스로 서버를 실행합니다. Streamable HTTP는 서버를 네트워크 서비스로 실행하고 클라이언트는 HTTP를 통해 연결합니다. 서버가 어디에 있어야 하는지에 따라 선택하세요.
경험칙: stdio에서 구축하고 테스트한 다음, 둘 이상의 사람이나 머신이 서버가 필요할 때만 Streamable HTTP로 전환하세요. 대부분의 서버는 절대 stdio를 벗어날 필요가 없습니다. 위의 mcp.run() 및 StdioServerTransport() 호출은 이미 stdio이므로 개발 준비가 되었습니다.
MCP Inspector로 MCP 서버를 테스트하는 방법
서버를 Claude에 연결하기 전에 MCP Inspector로 격리된 상태에서 테스트하세요. 이는 서버에 연결하고, 도구를 나열하고, 손으로 호출할 수 있는 브라우저 UI입니다. 서버에 대해 실행하세요:
Inspector는 add와 fetch_url 도구를 볼 수 있고, 테스트 호출을 시작하고, 원시 응답을 읽을 수 있는 로컬 페이지를 엽니다. 이것은 MCP 개발을 위한 가장 좋은 습관입니다. 도구의 스키마가 잘못되었거나 반환 값이 잘못되면 Claude 내에서 침묵의 실패를 응시하는 대신 몇 초 내에 여기서 볼 수 있습니다. 이렇게 하면 전체 디버깅 왕복을 클라이언트를 통해 비용이 드는 나쁜 입력 스키마를 포착했습니다. Inspector에서 테스트하세요. 항상.
MCP 서버를 Claude Desktop, Claude Code, Cursor에 연결하는 방법
Inspector가 만족하면 실제 클라이언트를 서버로 지정하세요. 각 클라이언트는 stdio를 통해 서버를 시작하는 방법을 알려주는 설정 파일을 읽습니다.
Claude Desktop. claude_desktop_config.json을 편집하세요(macOS의 경우: ~/Library/Application Support/Claude/claude_desktop_config.json):
Claude Desktop을 재시작하면 커넥터 아이콘 아래에 도구가 나타납니다.
Claude Code. 프로젝트에서 한 가지 명령으로 서버를 추가하세요: claude mcp add demo-server -- uv run server.py. Claude Code는 프로젝트 설정에 저장하고 시작 시 로드합니다. Claude Code 스크립팅 훅도 사용한다면, Claude Code 훅 가이드가 사용자 정의 MCP 도구와 잘 어울립니다.
Cursor. 프로젝트 루트의 .cursor/mcp.json에 동일한 mcpServers 블록을 추가하세요. 형태는 Claude Desktop과 일치합니다. MCP 서버가 Claude Code 내부에서 실행되는 실제 사례를 보려면, Higgsfield를 Claude Code에 연결한 방법을 참조하세요.
모든 설정에서 절대 경로를 사용하세요. 상대 경로는 서버가 시작되지 않는 가장 일반적인 이유입니다.
MCP 서버를 프로덕션에 배포하기 (인증 및 호스팅)
서버를 공유해야 할 때는 stdio에서 Streamable HTTP로 이동하고 세 가지를 추가하세요: 인증, 에러 처리, 호스트.
- 인증. 원격 MCP 서버는 MCP 인증 사양에 따라 OAuth 2.1을 사용해야 합니다. 내부 도구의 경우 HTTP 엔드포인트에 대한 bearer 토큰 확인이 실용적인 최소값입니다. SQL을 실행하거나 내부 API를 치는 도구는 실시간 공격 표면이므로 공개된 인증 없는 도구 서버를 배포하지 마세요.
- 에러 처리. 도구 본문을 try/except(또는 try/catch)로 감싸고 예외를 던지는 대신 타입 지정된 에러 메시지를 반환하세요. 모델은 "쿼리가 실패했습니다. 이유는 다음과 같습니다"를 끊긴 연결보다 훨씬 잘 처리합니다.
...