Blog
mcpmodel-context-protocolai-agenttool-useclaudeai

MCP(Model Context Protocol) 가이드 - AI 도구 연동의 새로운 표준

Anthropic의 MCP(Model Context Protocol) 개념, 아키텍처, 서버/클라이언트 구현, 주요 MCP 서버 생태계, 보안, 엔터프라이즈 활용을 체계적으로 정리합니다.

Data Dynamics2026년 4월 16일11 min read

MCP(Model Context Protocol)는 Anthropic이 제안한 AI 모델과 외부 도구/데이터 소스를 연결하는 개방형 프로토콜입니다. 이 글에서는 MCP의 개념, 아키텍처, 구현 방법, 생태계를 체계적으로 다룹니다.


1. MCP란 무엇인가

정의와 등장 배경

MCP(Model Context Protocol)는 AI 모델이 외부 도구, 데이터 소스, 서비스에 접근하는 표준화된 프로토콜입니다. USB-C가 다양한 장치를 하나의 규격으로 연결하듯, MCP는 다양한 AI 도구를 하나의 프로토콜로 연결합니다.

[MCP 이전 — 도구마다 커스텀 통합]
Claude ─── 커스텀 코드 ──→ GitHub
Claude ─── 커스텀 코드 ──→ Slack
Claude ─── 커스텀 코드 ──→ Database
Claude ─── 커스텀 코드 ──→ File System

[MCP 이후 — 표준 프로토콜로 통합]
Claude ─── MCP ──→ GitHub MCP Server
                ──→ Slack MCP Server
                ──→ Database MCP Server
                ──→ File System MCP Server

MCP vs 기존 방식 비교

구분Function CallingMCP
표준화모델/플랫폼별 다름통일된 프로토콜
도구 발견수동 등록자동 발견 (서버가 도구 목록 제공)
양방향 통신단방향 (모델→도구)양방향 (도구→모델 알림 가능)
상태 관리없음 (Stateless)세션 기반 (Stateful)
생태계플랫폼 종속오픈 생태계 (서버 공유/재사용)
보안앱별 구현프로토콜 수준 권한 관리

2. MCP 아키텍처

핵심 구성 요소

[MCP 아키텍처]

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  MCP Host    │     │  MCP Client  │     │  MCP Server  │
│  (AI 앱)     │────→│  (프로토콜    │────→│  (도구 제공)  │
│              │     │   클라이언트) │     │              │
│  Claude Code │     │              │     │  GitHub      │
│  Claude.ai   │     │              │     │  Slack       │
│  IDE 확장    │     │              │     │  Database    │
└──────────────┘     └──────────────┘     └──────────────┘
구성 요소역할예시
HostMCP를 사용하는 AI 애플리케이션Claude Desktop, Claude Code, IDE
ClientMCP 프로토콜로 서버와 통신하는 클라이언트Host 내부에 내장
Server도구, 리소스, 프롬프트를 제공하는 서버GitHub, Slack, DB 서버

프로토콜 기능

MCP 서버는 세 가지 핵심 기능을 제공합니다.

기능설명예시
Tools모델이 호출할 수 있는 함수create_issue, query_db, send_message
Resources모델이 읽을 수 있는 데이터파일 내용, DB 스키마, API 문서
Prompts미리 정의된 프롬프트 템플릿코드 리뷰 프롬프트, 분석 프롬프트

통신 프로토콜

[MCP 메시지 흐름]

Client                           Server
  │                                │
  ├─── initialize ────────────→   │  (연결 및 기능 협상)
  │   ←── capabilities ───────   │
  │                                │
  ├─── tools/list ────────────→   │  (사용 가능한 도구 목록)
  │   ←── tool definitions ───   │
  │                                │
  ├─── tools/call ────────────→   │  (도구 호출)
  │   ←── result ─────────────   │
  │                                │
  ├─── resources/read ────────→   │  (리소스 읽기)
  │   ←── content ────────────   │
  │                                │
  │   ←── notification ───────   │  (서버→클라이언트 알림)
  │                                │

3. MCP 서버 구현

Python으로 MCP 서버 만들기

from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio
 
# MCP 서버 생성
server = Server("data-dynamics-tools")
 
# 도구 정의
@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="query_database",
            description="사내 데이터베이스에 SQL 쿼리를 실행합니다. SELECT만 허용.",
            inputSchema={
                "type": "object",
                "properties": {
                    "sql": {"type": "string", "description": "SQL SELECT 쿼리"},
                    "database": {
                        "type": "string",
                        "enum": ["analytics", "production"],
                        "description": "대상 데이터베이스"
                    }
                },
                "required": ["sql", "database"]
            }
        ),
        Tool(
            name="search_docs",
            description="사내 기술 문서를 검색합니다.",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "검색 질의"}
                },
                "required": ["query"]
            }
        )
    ]
 
# 도구 실행
@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "query_database":
        result = execute_sql(arguments["sql"], arguments["database"])
        return [TextContent(type="text", text=str(result))]
    
    elif name == "search_docs":
        results = search_vector_db(arguments["query"])
        return [TextContent(type="text", text=format_results(results))]
    
    raise ValueError(f"Unknown tool: {name}")
 
# 서버 실행
async def main():
    async with mcp.server.stdio.stdio_server() as (read, write):
        await server.run(read, write, server.create_initialization_options())
 
import asyncio
asyncio.run(main())

TypeScript로 MCP 서버 만들기

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: "data-dynamics-tools",
  version: "1.0.0"
});
 
// 도구 등록
server.tool(
  "query_database",
  "사내 데이터베이스에 SQL 쿼리를 실행합니다.",
  {
    sql: z.string().describe("SQL SELECT 쿼리"),
    database: z.enum(["analytics", "production"])
  },
  async ({ sql, database }) => {
    const result = await executeSQL(sql, database);
    return { content: [{ type: "text", text: JSON.stringify(result) }] };
  }
);
 
// 리소스 등록
server.resource(
  "schema://analytics",
  "analytics 데이터베이스의 스키마 정보",
  async () => ({
    contents: [{
      uri: "schema://analytics",
      text: await getSchemaInfo("analytics"),
      mimeType: "text/plain"
    }]
  })
);
 
// 서버 시작
const transport = new StdioServerTransport();
await server.connect(transport);

4. MCP 클라이언트 설정

Claude Desktop 설정

// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
// %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
  "mcpServers": {
    "data-dynamics-db": {
      "command": "python",
      "args": ["./mcp_servers/db_server.py"],
      "env": {
        "DB_HOST": "localhost",
        "DB_PORT": "5432"
      }
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxx"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
    }
  }
}

Claude Code 설정

// .claude/settings.json 또는 프로젝트 루트
{
  "mcpServers": {
    "database": {
      "command": "python",
      "args": ["./tools/db_mcp_server.py"]
    }
  }
}

5. 주요 MCP 서버 생태계

공식 MCP 서버

서버제공 도구용도
filesystem파일 읽기/쓰기/검색로컬 파일 시스템 접근
github이슈, PR, 리포 관리GitHub 연동
slack메시지 전송/검색Slack 연동
postgresSQL 쿼리 실행PostgreSQL 연동
sqliteSQL 쿼리 실행SQLite 연동
puppeteer웹 스크래핑/자동화브라우저 제어
memory지식 그래프 관리장기 기억
brave-search웹 검색Brave 검색 엔진
google-maps지도/장소 검색Google Maps API

커뮤니티 MCP 서버

서버제공 도구용도
jira이슈 관리Jira 연동
confluence문서 검색/편집Confluence 연동
docker컨테이너 관리Docker 연동
kubernetes클러스터 관리K8s 연동
grafana대시보드/메트릭모니터링
elasticsearch로그/데이터 검색ELK 스택 연동

6. 실전 활용 사례

데이터 엔지니어링 MCP 서버

# Spark 작업 관리 MCP 서버
@server.list_tools()
async def list_tools():
    return [
        Tool(name="spark_submit", description="Spark 작업을 제출합니다.", ...),
        Tool(name="spark_status", description="실행 중인 Spark 작업 상태를 조회합니다.", ...),
        Tool(name="spark_logs", description="Spark 작업 로그를 가져옵니다.", ...),
        Tool(name="hdfs_ls", description="HDFS 디렉토리를 조회합니다.", ...),
        Tool(name="hive_query", description="Hive 쿼리를 실행합니다.", ...),
    ]

활용 시나리오:

사용자: "어제 실행한 야간 배치 작업이 실패했어. 로그를 확인하고 원인을 분석해줘."

Claude (MCP 사용):
1. spark_status() → 실패한 작업 ID 확인
2. spark_logs(job_id) → 에러 로그 수집
3. 로그 분석 → OOM 에러 진단
4. 해결 방안 제시 (설정 변경 추천)

DevOps MCP 서버

사용자: "프로덕션 서버의 CPU가 90% 이상이야. 원인을 찾아줘."

Claude (MCP 사용):
1. grafana.query_metrics("cpu_usage", "prod-*") → 메트릭 수집
2. kubernetes.get_pods("production") → 파드 상태 확인
3. elasticsearch.search_logs("error", "last_1h") → 최근 에러 로그
4. 종합 분석 → 특정 파드의 메모리 누수 진단
5. slack.send_message("#ops", "장애 분석 보고서") → 팀에 공유

7. 보안 고려사항

MCP 보안 원칙

원칙설명구현
최소 권한필요한 권한만 부여도구별 세밀한 권한 설정
입력 검증도구 입력값 검증스키마 검증 + 비즈니스 규칙
감사 로깅모든 도구 호출 기록호출자, 입력, 결과 로깅
네트워크 격리서버 접근 범위 제한로컬/VPN만 허용
비밀 관리인증 정보 안전 관리환경 변수, 비밀 관리자

안전한 MCP 서버 구현

# 보안이 강화된 MCP 서버
@server.call_tool()
async def call_tool(name: str, arguments: dict):
    # 1. 입력 검증
    if name == "query_database":
        sql = arguments["sql"].strip().upper()
        if not sql.startswith("SELECT"):
            raise ValueError("SELECT 쿼리만 허용됩니다.")
        
        dangerous_keywords = ["DROP", "DELETE", "UPDATE", "INSERT", "ALTER", "TRUNCATE"]
        for keyword in dangerous_keywords:
            if keyword in sql:
                raise ValueError(f"위험한 키워드 감지: {keyword}")
    
    # 2. 실행
    result = await execute_tool(name, arguments)
    
    # 3. 감사 로그
    audit_log.info(f"Tool: {name}, Args: {arguments}, Result: {len(str(result))} chars")
    
    return result

참고: MCP 서버는 AI 모델에 실제 시스템 접근 권한을 부여하므로, 보안 설계가 매우 중요합니다. 프로덕션 배포 전에 반드시 보안 검토를 수행하세요.


8. MCP의 미래

발전 방향

방향설명현재 상태
원격 MCP 서버HTTP/SSE 기반 원격 서버 지원지원 (Streamable HTTP)
인증 표준화OAuth 2.0 기반 인증 흐름진행 중
서버 마켓플레이스MCP 서버 검색/설치 허브초기 단계
멀티 모델 지원Claude 외 다른 모델도 MCP 지원확대 중
엔터프라이즈 관리중앙 집중식 서버 관리/모니터링개발 중

References


— Data Dynamics 엔지니어링 팀