MCP 서버 만들어보기: LLM이 외부 세계와 연결되는 표준 프로토콜

AI

MCPModel Context ProtocolLLMAI 에이전트API 연동

이 글은 누구를 위한 것인가

  • Claude Desktop, Cursor 등 AI 도구를 쓰는데 "MCP"라는 용어가 자꾸 등장해 궁금한 분
  • AI가 회사 내부 시스템(DB, 문서, API)에 접근하도록 연결하고 싶은 개발자
  • AI 에이전트 개발에 관심 있는 기획자·개발자

들어가며

AI를 쓰다 보면 이런 상황이 생긴다. "AI야, 우리 회사 고객 DB에서 이번 달 가입자 수 알려줘." AI는 당연히 모른다. 회사 내부 데이터에 접근할 방법이 없으니까.

이 문제를 해결하는 가장 오래된 방법은 Function Calling이었다. AI가 특정 함수를 호출하면 개발자가 그 결과를 다시 AI에게 넘겨주는 방식이다. 작동하긴 하지만, OpenAI, Anthropic, Google 각각 방식이 달라서 개발자가 모델마다 다른 코드를 작성해야 했다.

2024년 11월 Anthropic이 **MCP(Model Context Protocol)**를 오픈소스로 공개했다. AI가 외부 도구와 연결하는 표준 규격이다. USB-C가 충전기 포트를 표준화한 것처럼, MCP는 AI와 외부 도구 연결을 표준화한다.


1. Function Calling과 MCP의 차이

Function Calling (기존)

개발자가 OpenAI용 코드 작성 → OpenAI에서만 동작
개발자가 Anthropic용 코드 작성 → Claude에서만 동작
개발자가 Gemini용 코드 작성 → Gemini에서만 동작

→ 같은 기능인데 3번 구현

MCP (새로운 표준)

개발자가 MCP 서버 한 번 구현
→ Claude, Cursor, Copilot, Zed 등 MCP를 지원하는 모든 AI에서 동작

한 번 만들면 여러 AI 도구에서 쓸 수 있다. 생태계 전체가 이 표준으로 움직이기 시작했다.


2. MCP 생태계 현황

MCP 출시 후 1년이 지난 2025년 말 기준, 주요 플랫폼들이 공식 MCP 서버를 출시했다.

서비스MCP 서버 제공기능
Figma✅ 공식디자인 파일 읽기, 컴포넌트 정보 조회
GitHub✅ 공식코드 검색, PR 관리, 이슈 조회
Notion✅ 공식문서 읽기/쓰기, 데이터베이스 조회
Slack✅ 공식메시지 발송, 채널 조회
Postgres✅ 공식DB 쿼리 실행
Google Drive✅ 공식파일 검색, 문서 읽기
Brave Search✅ 공식웹 검색

이미 수백 개의 MCP 서버가 오픈소스로 공개되어 있다. mcp.run, smithery.ai 같은 MCP 서버 디렉토리 사이트도 생겼다.


3. MCP의 3가지 구성요소

MCP 서버는 AI에게 세 가지 유형의 기능을 제공한다.

Tool (도구)

AI가 실행할 수 있는 함수다. AI가 자율적으로 호출 여부를 결정한다.

예시:
- search_database(query) → DB 검색
- send_email(to, subject, body) → 이메일 발송
- create_issue(title, description) → GitHub 이슈 생성

Resource (리소스)

AI가 읽을 수 있는 데이터다. 파일, DB 레코드, API 응답 등.

예시:
- file://project/README.md → 파일 내용
- db://customers/recent → 최근 고객 목록
- api://weather/seoul → 서울 날씨 데이터

Prompt (프롬프트 템플릿)

미리 만들어둔 유용한 프롬프트 패턴이다.

예시:
- "코드 리뷰를 해줘" 프롬프트 → 자동으로 코드 파일과 리뷰 지시사항 조합

4. 간단한 MCP 서버 만들어보기

Python으로 기본 MCP 서버를 만드는 예시다. 사내 직원 정보를 조회하는 MCP 서버를 상상해보자.

from mcp.server import Server
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types

# MCP 서버 인스턴스 생성
app = Server("employee-directory")

# 가짜 직원 데이터 (실제로는 DB 조회)
EMPLOYEES = {
    "kim.minsu": {"name": "김민수", "department": "개발팀", "email": "kim@company.com"},
    "lee.jiyeon": {"name": "이지연", "department": "마케팅팀", "email": "lee@company.com"},
}

# Tool 정의: 직원 정보 검색
@app.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="find_employee",
            description="사번 또는 이름으로 직원 정보를 검색합니다",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "검색할 이름 또는 사번"}
                },
                "required": ["query"]
            }
        )
    ]

# Tool 실행 로직
@app.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
    if name == "find_employee":
        query = arguments["query"].lower()
        results = []
        for emp_id, info in EMPLOYEES.items():
            if query in emp_id or query in info["name"]:
                results.append(f"{info['name']} | {info['department']} | {info['email']}")

        if results:
            return [types.TextContent(type="text", text="\n".join(results))]
        else:
            return [types.TextContent(type="text", text="해당하는 직원을 찾을 수 없습니다.")]

# 서버 실행
async def main():
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await app.run(read_stream, write_stream, InitializationOptions())

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

이 서버를 Claude Desktop 설정에 추가하면, Claude에게 "마케팅팀 직원 알려줘"라고 물어볼 수 있게 된다.


5. Claude Desktop에서 MCP 서버 연결하기

Claude Desktop의 설정 파일(claude_desktop_config.json)에 MCP 서버 정보를 추가한다.

{
  "mcpServers": {
    "employee-directory": {
      "command": "python",
      "args": ["/path/to/employee_mcp_server.py"]
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/username/Documents"]
    }
  }
}

설정 후 Claude Desktop을 재시작하면 AI가 지정된 도구에 접근할 수 있다.


6. MCP 보안 고려사항

MCP 서버는 AI에게 실제 권한을 부여한다. 신중하게 설계해야 한다.

핵심 원칙: 최소 권한 AI가 반드시 필요한 작업만 할 수 있도록 권한을 최소화한다.

  • 읽기만 필요하면 쓰기 권한 부여 금지
  • 특정 DB 테이블만 필요하면 전체 DB 접근 금지
  • 운영 환경보다 개발/스테이징 환경에서 먼저 테스트

인증과 감사 로그

  • MCP 서버 요청마다 인증 토큰 확인
  • 모든 도구 실행을 로그로 기록
  • 비정상 패턴 감지 시 자동 차단
# MCP 서버에 감사 로그 추가 예시
import logging

@app.call_tool()
async def handle_call_tool(name: str, arguments: dict):
    logging.info(f"Tool called: {name}, args: {arguments}, timestamp: {datetime.now()}")

    # 민감한 데이터에는 추가 검증
    if name == "delete_record":
        if not arguments.get("confirmed", False):
            return [types.TextContent(type="text", text="삭제 확인이 필요합니다.")]

7. 국내 기업 MCP 활용 사례

개발팀 사용 사례

  • Cursor에 사내 Jira MCP 서버 연결 → AI가 티켓을 직접 조회하며 코드 작성
  • GitHub MCP로 PR 리뷰 자동화 → AI가 코드 변경사항을 직접 읽고 코멘트 생성

비개발팀 사용 사례

  • Notion MCP + Claude → 회의록에서 액션 아이템 자동 추출, Slack으로 발송
  • Google Sheets MCP → 스프레드시트 데이터를 AI가 분석해 주간 리포트 생성

맺으며

MCP는 "AI에게 도구를 주는" 방법이다. 처음에는 AI가 대화만 할 수 있었지만, MCP를 통해 AI가 파일을 읽고, DB를 조회하고, 이메일을 보내고, 코드를 커밋할 수 있게 된다.

중요한 건 표준화다. 한 번 MCP 서버를 만들면 어떤 AI 도구에서든 쓸 수 있다. 회사 내부 시스템을 MCP 서버로 만들면, 새로운 AI 도구가 나와도 다시 연동 코드를 짤 필요가 없다. AI 생태계의 USB-C, MCP가 가져오는 가치가 바로 이것이다.