패스노트
도메인 2. 툴 설계와 MCP 통합

2.4MCP 서버 통합

예상 학습 시간 45

MCP(Model Context Protocol)는 AI 애플리케이션과 외부 시스템을 잇는 개방형 표준입니다. 이 수업에서는 호스트-클라이언트-서버 아키텍처, 툴·리소스·프롬프트 세 가지 프리미티브, 전송 방식 선택, Claude Code 연결 설정, 그리고 보안 고려사항까지 MCP 통합의 전 과정을 다룹니다.

MCP 아키텍처: 호스트, 클라이언트, 서버

MCP는 세 가지 역할로 구성됩니다.

  • 호스트(host): 사용자가 마주하는 AI 애플리케이션 — Claude Code, Claude Desktop, 여러분이 만든 에이전트
  • 클라이언트(client): 호스트 안에서 서버와의 1:1 연결을 유지하는 프로토콜 구현체. 서버 하나당 클라이언트 하나가 생성됩니다
  • 서버(server): 실제 기능(툴, 리소스, 프롬프트)을 노출하는 프로그램 — GitHub 서버, Postgres 서버, 여러분이 만든 사내 API 서버

통신은 JSON-RPC 2.0 메시지로 이뤄지며, 연결 시작 시 초기화 핸드셰이크로 프로토콜 버전과 서로의 기능(capabilities)을 교환합니다. 이후 클라이언트는 tools/list로 서버의 툴 목록을 받아 모델에게 노출하고, 모델이 호출을 결정하면 tools/call로 실행을 위임합니다.

사용자 ─ 호스트(Claude Code)
           ├─ 클라이언트 A ── stdio ── GitHub MCP 서버
           ├─ 클라이언트 B ── stdio ── Postgres MCP 서버
           └─ 클라이언트 C ── HTTP ─── 사내 API MCP 서버 (원격)

이 구조의 핵심 가치는 M×N 문제의 해소입니다. 표준이 없으면 앱 M개 × 시스템 N개만큼 통합을 새로 만들어야 하지만, MCP를 쓰면 시스템마다 서버 하나만 만들면 모든 호환 호스트에서 재사용됩니다. USB-C 포트에 비유되는 이유입니다.

세 가지 프리미티브: 툴, 리소스, 프롬프트

MCP 서버가 노출하는 기능은 세 종류이며, 누가 사용을 결정하느냐로 구분됩니다.

  • 툴(tools): 모델이 판단해 호출하는 실행 가능한 동작. 부작용이 있을 수 있습니다 (예: 티켓 생성, 쿼리 실행). 모델 제어(model-controlled)
  • 리소스(resources): URI로 식별되는 읽기 전용 데이터. 파일, 스키마, 문서 등 컨텍스트로 제공됩니다. 애플리케이션 제어(application-controlled)
  • 프롬프트(prompts): 사용자가 명시적으로 선택하는 템플릿(슬래시 명령어처럼). 사용자 제어(user-controlled)
# Python SDK (FastMCP) 예시
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("ticket-server")

@mcp.tool()
def create_ticket(title: str, priority: str) -> str:
    """새 지원 티켓을 생성합니다. priority는 low/medium/high 중 하나."""
    ticket_id = db.insert(title=title, priority=priority)
    return f"티켓 {ticket_id} 생성 완료"

@mcp.resource("schema://tickets")
def ticket_schema() -> str:
    """티켓 테이블의 스키마 문서"""
    return open("docs/ticket-schema.md").read()

@mcp.prompt()
def triage_prompt(ticket_id: str) -> str:
    """티켓 분류 절차 템플릿"""
    return f"티켓 {ticket_id}를 심각도 기준으로 분류하세요. 절차: ..."

시험 포인트는 구분 기준입니다. "모델이 필요할 때 스스로 호출"이면 툴, "앱이 컨텍스트로 넣어 주는 읽기 전용 데이터"면 리소스, "사용자가 골라 실행하는 템플릿"이면 프롬프트입니다. 부작용이 있는 동작을 리소스로 만들거나, 읽기 전용 데이터를 툴로만 노출하는 선택지는 오답 패턴입니다.

전송 방식: stdio와 스트리머블 HTTP

MCP의 전송(transport) 계층은 두 가지가 표준입니다.

stdio 전송은 호스트가 서버를 로컬 자식 프로세스로 띄우고 표준 입출력으로 통신합니다. 설치형 로컬 서버의 기본값이며, 네트워크 설정과 원격 인증이 필요 없고 지연이 가장 낮습니다. 파일시스템 서버, 로컬 DB 서버 등에 적합합니다.

스트리머블 HTTP(streamable HTTP) 전송은 서버가 독립된 웹 서비스로 떠 있고 호스트가 HTTP로 접속합니다. 원격·공유 서버의 표준이며, 조직 차원에서 하나의 서버 인스턴스를 여러 사용자가 쓰는 시나리오, SaaS형 MCP 서비스에 적합합니다. 초기 사양의 HTTP+SSE 방식은 스트리머블 HTTP로 대체되었습니다. 원격 서버의 인증은 OAuth 2.1 기반 흐름이 사양에 정의되어 있습니다.

선택 기준
├─ 내 머신의 자원(파일, 로컬 DB)에 접근 → stdio
├─ 팀/조직이 공유하는 중앙 서비스 → 스트리머블 HTTP
└─ 서드파티가 호스팅하는 서비스 → 스트리머블 HTTP (+ OAuth)

전송 방식은 서버의 기능과 무관하게 교체 가능하도록 설계되어 있습니다. SDK로 서버를 작성하면 같은 툴 코드를 stdio로도, HTTP로도 서비스할 수 있습니다. 시험에서는 "로컬 파일에 접근해야 하는 서버는 어떤 전송이 적절한가"(stdio), "전사 공용 서버는?"(HTTP) 형태로 출제됩니다.

Claude Code 연결 설정과 스코프

Claude Code에 MCP 서버를 연결하는 기본 도구는 claude mcp add 명령과 .mcp.json 파일입니다.

# stdio 서버 추가 (로컬 스코프)
claude mcp add my-tickets -- python ticket_server.py

# 원격 HTTP 서버 추가
claude mcp add --transport http central-api https://mcp.example.com/api

# 프로젝트 스코프로 추가 (.mcp.json에 기록되어 팀과 공유)
claude mcp add --scope project github -- npx -y @modelcontextprotocol/server-github

연결 설정에는 세 가지 스코프(scope) 가 있습니다.

  • local(기본): 현재 프로젝트에서 나만 사용. 개인 실험용
  • project: 프로젝트 루트의 .mcp.json에 기록되어 저장소로 커밋·공유. 팀 표준 서버용
  • user: 내 모든 프로젝트에서 사용. 개인 공용 도구용
// .mcp.json (project 스코프)
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}

보안 유의점을 반드시 챙겨야 합니다. 첫째, 토큰 등 비밀 값은 .mcp.json에 하드코딩하지 말고 환경 변수 확장으로 주입합니다. 둘째, 프로젝트 스코프 서버는 저장소를 여는 모든 팀원의 환경에서 실행되므로, 검증되지 않은 서버를 커밋하는 것은 공급망 위험입니다. Claude Code가 프로젝트 스코프 서버 사용 전 승인을 요구하는 이유입니다. 셋째, 서버에 주는 자격증명은 최소 권한으로 — 조회용 서버라면 읽기 전용 계정을 사용합니다. 넷째, 외부 데이터를 읽어오는 서버는 프롬프트 인젝션 경로가 될 수 있으므로, 신뢰할 수 없는 콘텐츠를 다루는 서버와 강한 권한을 가진 서버를 한 세션에 함께 쓰는 조합을 경계해야 합니다.

시험 함정

  • 클라이언트는 서버당 하나씩 생성되는 1:1 연결이다. '하나의 클라이언트가 모든 서버를 관리한다'는 선택지는 오답.
  • 툴=모델 제어, 리소스=애플리케이션 제어, 프롬프트=사용자 제어. 이 구분을 뒤섞은 선택지가 단골 오답이다.
  • 부작용 있는 동작은 리소스가 아니라 툴로 노출해야 한다.
  • 로컬 자원 접근은 stdio, 원격·공유 서비스는 스트리머블 HTTP. HTTP+SSE는 구식 표기다.
  • .mcp.json의 project 스코프는 팀과 공유된다. 개인 토큰을 하드코딩해 커밋하는 선택지는 보안 오답.
  • MCP의 가치는 M×N 통합 문제를 M+N으로 줄이는 표준화다. '지연 감소'나 '비용 절감'을 1차 가치로 내세운 선택지를 주의하라.

실습 시나리오

실제 시험과 같은 형식의 시나리오 문제입니다.

팀 전체가 사용할 사내 위키 검색 MCP 서버를 만들었습니다. 팀원 모두의 Claude Code에서 자동으로 이 서버가 연결되게 하되, 각자의 위키 API 토큰은 노출되지 않아야 합니다. 올바른 설정 방법은 무엇입니까?

빌드 연습 · 사내 데이터용 MCP 서버 구축과 연결

60
  1. 1.서버 뼈대 만들기

    Python 또는 TypeScript MCP SDK로 JSON 파일을 검색하는 툴 1개를 가진 서버를 작성한다

    기대 결과 · MCP Inspector에서 tools/list와 tools/call이 동작한다

  2. 2.리소스와 프롬프트 추가

    데이터 스키마 문서를 리소스로, 자주 쓰는 분석 절차를 프롬프트로 추가한다

    기대 결과 · 세 가지 프리미티브의 용도 차이를 실제 코드로 구분할 수 있다

  3. 3.Claude Code 연결 (stdio)

    claude mcp add로 로컬 연결 후 /mcp 명령으로 상태를 확인하고 툴을 호출해 본다

    기대 결과 · Claude Code 세션에서 서버 툴이 호출되고 결과가 대화에 반영된다

  4. 4.프로젝트 스코프 공유

    --scope project로 .mcp.json을 생성하고 토큰을 환경 변수 확장으로 분리한다

    기대 결과 · 저장소에 비밀 값 없이 팀 공유 가능한 설정 파일이 만들어진다

  5. 5.오류 응답 다듬기

    존재하지 않는 검색어, 권한 오류 상황에 2.2 수업의 행동 가능한 오류 메시지를 적용한다

    기대 결과 · 실패 시에도 모델이 다음 행동을 결정할 수 있는 응답이 반환된다

  6. 6.최소 권한 점검

    서버가 사용하는 자격증명을 읽기 전용으로 교체하고 쓰기 시도가 거부되는지 확인한다

    기대 결과 · 서버 침해를 가정해도 데이터 변경이 불가능한 권한 구조가 된다

출처 및 더 읽기