MCP 실전 가이드 — AI 에이전트의 USB-C를 직접 꽂아보자

AI 에이전트가 GitHub에 이슈를 만들고, Slack에 알림을 보내고, 데이터베이스 스키마를 읽으려면 각각 별도의 통합 코드가 필요했다. MCP(Model Context Protocol)는 이 연결 방식을 하나로 통일하는 개방형 프로토콜이다. Anthropic이 2024년 말에 공개한 뒤 채택 속도가 빨랐다. 2026년 3월 기준 누적 설치 9,700만 회, 커뮤니티 서버 12,000개 이상이 GitHub에 등록되어 있다(공식 MCP 문서 참고). Claude, Cursor, Windsurf뿐 아니라 OpenAI, Google, Microsoft, Amazon도 MCP를 지원한다. 이 MCP 실전 가이드에서는 MCP의 아키텍처를 뜯어본 뒤, TypeScript와 Python으로 커스텀 서버를 만들어 Claude Desktop에 직접 연결하는 과정까지 다룬다.

MCP가 해결하는 문제는 정확히 무엇인가

MCP 이전의 세계를 떠올려 보자. AI 모델에 Slack을 붙이려면 Slack용 어댑터, GitHub를 붙이려면 GitHub용 어댑터, DB를 붙이려면 또 별도 커넥터가 필요했다. AI 클라이언트가 M개이고 외부 도구가 N개이면 M×N개의 통합 코드를 작성해야 한다. Language Server Protocol(LSP)이 에디터와 프로그래밍 언어 사이에서 똑같은 문제를 풀었던 것과 같은 구조다.

MCP는 이 M×N을 M+N으로 줄인다. AI 클라이언트는 MCP 클라이언트만 구현하면 되고, 외부 도구는 MCP 서버만 만들면 된다. 실제로 GitHub MCP 서버 하나를 만들어두면 Claude Code, Cursor, Windsurf, Copilot CLI 어디서든 그대로 동작한다.

항목MCP 이전MCP 이후
통합 수M×N (클라이언트 × 도구)M+N (클라이언트 + 도구)
새 도구 추가모든 클라이언트에 개별 어댑터 작성MCP 서버 1개만 구현
새 클라이언트 추가모든 도구에 개별 통합 작성MCP 클라이언트 1개만 구현
프로토콜도구마다 다름 (REST, GraphQL, SDK 등)JSON-RPC 2.0 단일 표준
보안 모델제각각통합 권한 동의·감사 체계

Host, Client, Server — 누가 뭘 하는가

MCP 아키텍처에는 Host, Client, Server라는 역할 구분이 있다. Host는 Claude Desktop이나 Cursor 같은 AI 애플리케이션 자체다. Client는 Host 안에서 MCP 서버와의 연결을 관리하는 커넥터이고, Server는 외부 도구나 데이터를 MCP 규격으로 제공하는 프로세스다.

┌─────────────────────────────────────────┐
│            Host (Claude Desktop)         │
│                                          │
│  ┌──────────┐  ┌──────────┐             │
│  │ MCP      │  │ MCP      │             │
│  │ Client A │  │ Client B │   ...       │
│  └────┬─────┘  └────┬─────┘             │
│       │              │                   │
└───────┼──────────────┼───────────────────┘
        │              │
  ┌─────▼─────┐  ┌─────▼─────┐
  │ MCP       │  │ MCP       │
  │ Server A  │  │ Server B  │
  │ (GitHub)  │  │ (Slack)   │
  └───────────┘  └───────────┘
Plaintext

하나의 Host가 여러 Client를 동시에 유지하고, 각 Client는 Server 하나와 1:1로 연결된다. Claude Desktop에서 GitHub 서버와 Slack 서버를 동시에 쓰는 상황이 전형적인 예다. 통신 포맷은 JSON-RPC 2.0이고, 연결 시작 시 Client와 Server가 서로 지원하는 기능(capability)을 교환하는 핸드셰이크를 거친다.

전송 방식(transport)은 두 가지인데, 실제로는 거의 하나만 쓰게 된다. stdio는 표준 입출력으로 로컬 프로세스끼리 통신하는 방식이고, Streamable HTTP는 원격 서버 연결용이다. 로컬 개발에서는 stdio가 간단하고 빠르다. 이 글의 실습도 전부 stdio를 사용한다.

Tools, Resources, Prompts — 뭘 노출할 것인가

MCP 서버가 클라이언트에 노출하는 기능은 Tools, Resources, Prompts로 나뉜다. 커스텀 서버를 설계할 때 이 구분이 중요하다.

Tools는 AI 모델이 직접 호출하는 함수다. “GitHub에 이슈를 만들어줘”라고 하면 AI가 create_issue 도구를 선택하고 파라미터를 채워서 실행한다. 사용자 승인이 필요하고, 이 글의 실습에서 주로 다루는 기능이다.

Resources는 읽기 전용 데이터다. 파일 내용, API 응답, DB 스키마처럼 AI 모델에 컨텍스트를 제공한다. 직접 뭔가를 실행하는 게 아니라 참고 자료로 읽히는 데이터다.

Prompts는 미리 정의된 템플릿이다. “코드 리뷰해줘”라고 하면 서버가 제공한 리뷰 프롬프트 템플릿이 적용되는 식이다. 셋 중에서 실무에서 가장 많이 쓰이는 것은 Tools이고, Prompts는 아직 활용도가 낮은 편이다.

기능호출 주체성격예시
ToolsAI 모델 (사용자 승인 필요)능동적 실행이슈 생성, 파일 쓰기, API 호출
ResourcesAI 모델 또는 클라이언트수동적 읽기파일 내용, DB 스키마, 설정값
Prompts사용자 선택템플릿 제공코드 리뷰 가이드, 커밋 메시지 생성

MCP 실전 가이드: TypeScript로 첫 서버 만들기

공식 튜토리얼에서는 날씨 API를 호출하는 서버를 만드는데, 외부 API 의존성이 생기면 MCP 자체 구조를 이해하기 어렵다. 이 MCP 실전 가이드에서는 외부 의존성 없는 계산기 도구로 서버의 골격에 집중한다.

프로젝트 세팅

mkdir mcp-calculator && cd mcp-calculator
npm init -y
npm install @modelcontextprotocol/sdk zod@3
npm install -D @types/node typescript
mkdir src && touch src/index.ts
ShellScript

프로젝트 디렉토리를 만들고 MCP TypeScript SDK, 입력 검증용 zod, TypeScript 패키지를 설치한다. MCP SDK는 서버와 클라이언트 양쪽 구현체를 모두 포함하고, zod는 도구의 입력 스키마를 정의할 때 쓴다.

package.json에 다음 설정을 추가한다.

{
  "type": "module",
  "bin": {
    "mcp-calculator": "./build/index.js"
  },
  "scripts": {
    "build": "tsc && chmod 755 build/index.js"
  }
}
JSON

chmod 755로 빌드 결과물에 실행 권한을 부여한다. 이게 빠지면 stdio 전송에서 노드가 파일을 실행하지 못해 서버가 안 뜬다.

tsconfig.json을 생성한다.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
JSON

MCP SDK가 ESM 기반이라 target은 ES2022, module과 moduleResolution은 Node16으로 맞춰야 한다. package.json의 "type": "module"과 짝이다.

서버 코드 작성

src/index.ts에 전체 서버 코드를 작성한다.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

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

server.registerTool(
  "calculate",
  {
    description: "두 숫자의 사칙연산을 수행한다",
    inputSchema: {
      a: z.number().describe("첫 번째 숫자"),
      b: z.number().describe("두 번째 숫자"),
      operator: z
        .enum(["+", "-", "*", "/"])
        .describe("연산자 (+, -, *, /)"),
    },
  },
  async ({ a, b, operator }) => {
    let result: number;
    switch (operator) {
      case "+": result = a + b; break;
      case "-": result = a - b; break;
      case "*": result = a * b; break;
      case "/":
        if (b === 0) {
          return {
            content: [{ type: "text", text: "0으로 나눌 수 없다" }],
            isError: true,
          };
        }
        result = a / b;
        break;
    }
    return {
      content: [{ type: "text", text: `${a} ${operator} ${b} = ${result}` }],
    };
  },
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Calculator MCP Server running on stdio");
}

main().catch((error) => {
  console.error("Fatal error in main():", error);
  process.exit(1);
});
TypeScript

McpServer 인스턴스를 만들고 registerTool로 도구를 등록하는 패턴이 MCP 서버의 기본 골격이다. inputSchema에 zod 스키마를 넘기면 SDK가 자동으로 JSON Schema로 변환해서 클라이언트에 노출한다.

한 가지 주의할 점이 있다. console.error로 로그를 출력하는 이유는 stdio 전송 방식에서 stdout이 JSON-RPC 메시지 전용이기 때문이다. console.log를 쓰면 JSON-RPC 메시지와 섞여서 서버가 오동작한다. MCP 서버 개발에서 가장 흔한 실수이고, 필자도 처음에 이것 때문에 30분을 날렸다.

빌드와 테스트

npm run build
ShellScript

빌드가 성공하면 build/index.js가 생성된다. 이 파일을 Claude Desktop에 연결하기 전에, MCP Inspector로 먼저 동작을 확인하는 것이 좋다. Inspector 사용법은 뒤에서 다룬다.

Python이라면 코드가 절반으로 줄어든다

Python SDK에는 FastMCP라는 고수준 API가 있다. 데코레이터 하나로 도구를 등록할 수 있어서, 같은 기능을 적은 코드로 만들 수 있다.

프로젝트 세팅

uv init mcp-calculator-py && cd mcp-calculator-py
uv venv && source .venv/bin/activate
uv add "mcp[cli]"
touch calculator.py
ShellScript

uv는 Astral 사의 Python 패키지 매니저로, pip보다 10~100배 빠르다. 가상 환경 생성과 패키지 설치를 한 번에 처리한다. mcp[cli]는 MCP Python SDK에 CLI 도구까지 포함하는 옵션이다.

서버 코드 작성

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("calculator")


@mcp.tool()
async def calculate(a: float, b: float, operator: str) -> str:
    """두 숫자의 사칙연산을 수행한다.

    Args:
        a: 첫 번째 숫자
        b: 두 번째 숫자
        operator: 연산자 (+, -, *, /)
    """
    match operator:
        case "+": result = a + b
        case "-": result = a - b
        case "*": result = a * b
        case "/":
            if b == 0:
                return "0으로 나눌 수 없다"
            result = a / b
        case _:
            return f"지원하지 않는 연산자: {operator}"
    return f"{a} {operator} {b} = {result}"
Python

FastMCP는 함수의 타입 힌트와 docstring을 파싱해서 MCP 도구 정의를 자동 생성한다. TypeScript에서 zod 스키마를 별도로 작성하던 부분이 Python에서는 타입 힌트로 끝난다. @mcp.tool() 데코레이터만 붙이면 함수가 곧바로 MCP 도구가 된다. TypeScript 40줄이 Python 20줄로 줄어든다. Python 쪽이 프로토타이핑에 확실히 유리하고, 프로덕션에서는 타입 안정성 때문에 TypeScript를 선호하는 팀도 있다.

Claude Desktop에 서버 연결하기

만든 서버를 Claude Desktop에 연결한다. 설정 파일 하나를 수정하면 된다.

설정 파일 위치

# macOS
code ~/Library/Application\ Support/Claude/claude_desktop_config.json

# Windows
code %AppData%\Claude\claude_desktop_config.json
ShellScript

이 파일이 없으면 직접 생성한다. Claude Desktop은 시작할 때 이 파일을 읽어서 MCP 서버 목록을 로드한다.

TypeScript 서버 연결

{
  "mcpServers": {
    "calculator": {
      "command": "node",
      "args": ["/Users/your-name/mcp-calculator/build/index.js"]
    }
  }
}
JSON

command에 실행할 바이너리, args에 빌드된 서버 파일의 절대 경로를 지정한다. 상대 경로를 사용하면 Claude Desktop의 작업 디렉토리가 예측 불가능하기 때문에 서버가 시작되지 않을 수 있다. 설정을 저장한 뒤 Claude Desktop을 재시작하면, 채팅 입력창 옆에 도구 아이콘이 나타나면서 calculator 서버가 연결된 것을 확인할 수 있다.

Python 서버 연결

{
  "mcpServers": {
    "calculator-py": {
      "command": "uv",
      "args": [
        "--directory", "/Users/your-name/mcp-calculator-py",
        "run", "calculator.py"
      ]
    }
  }
}
JSON

Python 서버는 uv run을 통해 가상 환경 활성화와 스크립트 실행을 한 번에 처리한다. --directory 플래그로 프로젝트 경로를 지정하면 uv가 해당 디렉토리의 가상 환경을 자동으로 찾아 사용한다.

Claude Code에서 MCP 서버 추가

Claude Desktop이 아닌 Claude Code(CLI)에서도 MCP 서버를 사용할 수 있다. Claude Code의 기본 설정과 활용법은 Claude Code 실전 활용법 가이드를 참고하자. 터미널에서 다음 명령으로 등록한다.

# 프로젝트 범위 (기본값)
claude mcp add calculator -- node /path/to/mcp-calculator/build/index.js

# 전역 범위 (모든 프로젝트에서 사용)
claude mcp add --scope user calculator -- node /path/to/mcp-calculator/build/index.js
ShellScript

이 명령은 기본적으로 프로젝트 단위 설정(.claude/settings.local.json)에 MCP 서버를 등록한다. -- 구분자는 서버명과 실행 명령어를 분리하는 필수 문법이다. --scope user 플래그는 서버명 앞에 위치해야 하며, 전역 설정(~/.claude.json)에 등록되어 모든 프로젝트에서 사용할 수 있다.

MCP Inspector로 디버깅하기

서버를 만들었는데 Claude Desktop에서 안 잡힐 때가 있다. 설정 파일 경로가 틀렸는지, 서버 코드에 문제가 있는지 구분이 안 된다. MCP Inspector는 이럴 때 쓰는 브라우저 기반 디버깅 도구다. MCP 세계의 Postman이라고 생각하면 된다(MCP Inspector 공식 패키지).

실행 방법

npx @modelcontextprotocol/inspector node build/index.js
ShellScript

별도 설치 없이 npx로 바로 실행된다. 브라우저에서 http://localhost:6274로 Inspector UI가 열리면, 서버가 노출하는 도구·리소스·프롬프트 목록이 왼쪽에 나타난다. 도구를 선택해서 파라미터를 넣고 호출하면 응답이 JSON으로 표시된다.

도구 목록 조회(tools/list)로 서버가 뭘 제공하는지 확인하고, 도구 호출(tools/call)로 실제 파라미터를 넣어 테스트하고, JSON-RPC 트래픽을 실시간으로 관찰할 수 있다. 특히 JSON-RPC 트래픽 뷰가 유용한데, Client와 Server 사이에 오가는 메시지 전체를 볼 수 있어서 어디서 에러가 나는지 바로 파악된다.

CLI 모드

Inspector는 GUI 없이 CLI에서도 사용할 수 있다.

npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
ShellScript

CI/CD에서 MCP 서버의 도구 정의가 바뀌지 않았는지 검증하거나, 스모크 테스트를 자동화할 때 유용하다.

어떤 MCP 서버를 조합하면 좋을까

이 MCP 실전 가이드를 따라 서버를 만들었다면 다음 단계는 조합이다. MCP 서버가 12,000개 넘게 있다고 해서 많이 연결하는 게 좋은 건 아니다. 서버마다 도구 정의가 AI 모델의 컨텍스트를 소비하기 때문에, 너무 많으면 도구 선택 정확도가 떨어진다. 실무에서 잘 동작하는 구성은 3~8개 정도다.

GitHub MCP Server가 가장 많이 쓰인다. 2025년 4월 GitHub이 Go 기반 공식 서버(github/github-mcp-server)를 출시하면서 기존 npm 패키지(@modelcontextprotocol/server-github)는 deprecated 되었다. 리포 관리, 이슈, PR, CI/CD까지 51개 도구를 제공하며, Docker로 실행한다.

서버주요 기능추천 시나리오
GitHub리포, 이슈, PR, Actions (51개 도구, Docker 필요)코드 리뷰, 이슈 관리 자동화
PostgreSQL읽기 전용 쿼리, 스키마 탐색DB 구조 파악, 쿼리 작성 보조
Slack채널 관리, 메시지 전송알림 자동화, 팀 커뮤니케이션
Filesystem로컬 파일 읽기/쓰기프로젝트 파일 탐색, 설정 파일 수정
Brave Search웹 검색최신 문서·라이브러리 검색
Sentry에러 그룹핑, 근본 원인 분석버그 트래킹, 에러 모니터링

실전 조합 예시: 백엔드 개발자

{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "<토큰>" }
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost:5432/mydb"]
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/your-name/projects"]
    }
  }
}
JSON

GitHub으로 코드와 이슈를 관리하고, PostgreSQL로 DB 스키마를 탐색하고, Filesystem으로 로컬 파일에 접근하는 조합이다. Spring 백엔드와 MCP를 함께 쓰는 방법이 궁금하다면 Spring AI 2.0과 MCP 연동 가이드도 함께 읽어보자. 이 상태에서 AI 에이전트에게 “users 테이블 스키마 확인해서 새 마이그레이션 이슈를 GitHub에 만들어줘”라고 말하면, 세 서버가 연계되어 한 번에 처리된다. 이게 MCP의 진짜 가치가 느껴지는 순간이다.

2026 로드맵 — 아직 안 된 것들

이 MCP 실전 가이드에서 다룬 기능 이후로 어떤 것들이 추가될까. 현재 MCP 스펙은 2025년 11월 버전이 최신이다. 쓰다 보면 불편한 부분이 있는데, 로드맵에서 정확히 그 지점을 짚고 있다.

전송 계층이 가장 시급하다. Streamable HTTP가 실험적으로 나와 있긴 한데, 상태 기반 세션이 로드 밸런서와 충돌하는 문제가 있다. 무상태 세션 모델로 전환하는 작업이 진행 중이다. 이게 해결되면 MCP 서버를 AWS Lambda 같은 서버리스 환경에서 운영하는 게 훨씬 쉬워진다.

서버 디스커버리도 준비 중이다. 지금은 설정 파일에 서버를 수동으로 등록해야 하는데, .well-known 엔드포인트를 통해 URL 하나로 서버를 자동 발견하고 연결하는 메커니즘이 올해 안에 나올 예정이다.

에이전트 간 통신을 위한 Tasks 프리미티브(SEP-1686)가 실험적으로 출시되었다. AI 에이전트가 다른 에이전트에게 작업을 위임하고 결과를 받아오는 구조인데, 아직 재시도 로직과 만료 정책이 미정이라 프로덕션에서 쓰기엔 이르다.

엔터프라이즈 기능(감사 로그, SSO 통합 인증, 게이트웨이)은 아직 스펙이 확정되지 않았다. 기업에서 MCP를 본격적으로 도입하려면 이 부분이 나와야 한다.

마무리

작년까지 MCP를 “API 래퍼를 하나 더 감싸는 거 아닌가”라고 생각했다. 근데 올해 프로젝트에서 Claude Code에 GitHub MCP 서버를 연결했더니, 이슈 확인하고 PR 만드는 일이 터미널 하나에서 끝나기 시작했다. 사내 API용 MCP 서버를 직접 만들어 연결했을 때 체감이 확 왔다. 코드 한 줄 안 고치고 클라이언트를 Claude에서 Cursor로 바꿔도 그대로 동작한다.

아직 원격 서버 지원이나 엔터프라이즈 기능이 부족한 건 사실이다. 그래도 로컬 개발 환경에서 MCP를 쓰는 건 이미 충분히 실용적이다. 이 MCP 실전 가이드를 따라 서버 하나만 만들어보면, 왜 다들 USB-C에 비유하는지 바로 알게 될 거다.

FAQ

MCP와 기존 REST API의 차이점은 무엇인가?

REST API는 특정 서비스의 기능을 HTTP 엔드포인트로 노출하는 인터페이스다. MCP는 여러 서비스의 도구와 데이터를 AI 에이전트가 일관된 방식으로 쓸 수 있게 표준화한 프로토콜이다. 기존 REST API를 대체하는 게 아니라, REST API 위에 MCP 서버를 올려서 AI 에이전트용 인터페이스 계층을 추가하는 구조다.

MCP 서버를 프로덕션에 배포해도 안전한가?

stdio 전송 방식은 로컬 전용이라 보안 위험이 낮다. 원격 서버(Streamable HTTP)를 쓸 경우 OAuth 2.1 인증이 로드맵에 포함되어 있고, 모든 도구 호출에는 사용자 명시적 승인이 필요하다. MCP 서버가 접근하는 외부 API의 권한을 최소한으로 설정하는 게 기본 원칙이다.

어떤 AI 클라이언트에서 MCP를 지원하는가?

2026년 5월 기준으로 Claude Desktop, Claude Code, Cursor, Windsurf, GitHub Copilot CLI, Gemini CLI, OpenAI의 Apps SDK 등 주요 AI 코딩 도구가 모두 MCP를 지원한다. 지원 클라이언트 전체 목록은 공식 사이트(modelcontextprotocol.io/clients)에서 확인할 수 있다.