byteforce

CPN 한국어 자습서 · 러닝패스 2 / 4 — Building with the Claude API

MCP

MCP로 도구 정의하기

Defining tools with MCP

mcp_server.py에 도구 둘을 추가합니다. 예전엔 도구마다 커다란 JSON 스키마를 손으로 써야 했지만, 공식 MCP Python SDK를 쓰면 서버는 한 줄, 도구는 데코레이터 한 줄로 끝납니다. 뒤에서 SDK가 JSON 스키마를 자동 생성합니다. read_doc_contents(읽기)와 edit_document(찾아 치환)를 정의합니다.

전체 내레이션영상 나레이션 한국어 번역 (전체)

Stephen Grider · Anthropic 기술 스태프

CLI 챗봇을 위한 MCP 서버를 만들기 시작합니다. 보다시피 CLI 자체는 이미 동작하고 Claude와 대화도 되지만, 아직 MCP 서버 쪽 기능은 붙어 있지 않습니다. 그래서 지금은 도구 두 개를 가진 MCP 서버를 더합니다 — 하나는 문서를 읽는 도구, 하나는 문서 내용을 수정하는 도구입니다.

서버 구현은 루트 프로젝트 디렉터리의 mcp_server.py 파일에 넣습니다. 여기에는 기본 MCP 서버를 미리 조금 세팅해 두었고, 메모리에만 존재하는 문서 모음(docs)을 정의해 두었습니다. 그리고 우리가 함께 완성할 작업을 TODO 항목으로 적어 두었습니다. 지금은 처음 두 항목, 즉 도구 두 개를 작성하는 것에만 집중합니다.

과거에 도구를 작성해 봤을 때는, 아 문법이 참 많았죠. 그 커다란 JSON 스키마들 말입니다. 그런데 좋은 소식이 있습니다. 이 프로젝트에서는 공식 MCP Python SDK를 씁니다. 우리가 가져다 쓰는 mcp 패키지가 바로 그것입니다. 이 패키지는 단 한 줄의 코드로 MCP 서버를 만들어 줍니다. 그리고 도구 정의도 아주 쉽게 해 줍니다.

도구를 정의하려면 함수 위에 데코레이터만 붙이면 됩니다. 예를 들어 이름이 add_ints이고 설명과 인자 두 개를 받는 도구를 이렇게 만들 수 있습니다. 이런 도구 정의를 한 번 써 두면, 뒤에서 MCP가 우리 대신 도구 JSON 스키마를 생성해 주고, 우리는 그걸 그대로 Claude에 넘기면 됩니다. 보다시피 도구 정의 같은 기본 작업이 한결 쉬워집니다.

우리의 첫 작업은 도구 두 개를 구현하는 것입니다. 먼저 문서를 읽는 도구부터 시작합니다. 목표는 단순합니다 — 문서 이름(ID)을 받아 그 내용을 돌려주는 것. 모든 문서는 이미 docs 딕셔너리 안에 있습니다. 키는 문서의 ID(이름), 값은 문서 내용입니다. 그러니 도구는 정말 단순합니다 — 문자열 하나를 받아 docs에서 알맞은 값을 찾아 돌려줍니다.

구현하려면 첫 TODO 바로 아래에 @mcp.tool로 새 도구를 정의합니다. 이름은 read_doc_contents, 설명은 "Read the contents of a document and return it as a string."로 둡니다. 본래는 Claude가 언제 이 도구를 써야 할지 명확히 알도록 설명을 아주 충실히 적는 게 좋지만, 여기서는 시간을 아끼려고 간단한 설명만 둡니다. 그다음 실제 도구 함수 read_document를 정의합니다.

이 함수는 문자열 doc_id 인자를 받는데, 이를 Field로 지정하고 설명 "Id of the document to read"를 붙입니다. 그러려면 파일 맨 위에서 pydantic의 Field 클래스를 import해야 합니다. 함수 본문에서는 먼저 Claude가 없는 문서를 요청한 경우를 처리합니다 — doc_id가 docs에 없으면, f-string으로 "Doc with id {doc_id} not found" 메시지를 담아 ValueError를 raise합니다. 그 검사를 통과하면 실제 문서 docs[doc_id]를 반환합니다.

이게 도구를 정의하는 전부입니다. 도구 이름, 설명, 기대 인자와 그 타입, 인자 설명까지 명시했습니다. 이 데코레이터와 Field 타입들을 MCP Python SDK가 한데 모아 우리 대신 JSON 스키마를 생성합니다. 첫 도구를 구현했으니 그 TODO를 지우고, 다른 도구 — 문서 수정 도구를 구현합니다.

같은 과정을 반복합니다. @mcp.tool에 이름 edit_document, 설명 "Edit a document by replacing a string in the documents content with a new string"를 줍니다. 함수 edit_document는 인자를 셋 받습니다 — 문서 ID, 찾을 옛 문자열, 그리고 그것을 대체할 새 문자열입니다. doc_id, old_str, new_str을 각각 Field와 설명으로 지정합니다. 문서 수정은 아주 단순한 찾아 치환(find and replace)입니다.

여기서도 Claude가 실제로 존재하는 문서를 요청하는지 확인합니다 — doc_id가 docs에 없으면 같은 식으로 ValueError를 raise합니다. 올바른 문서를 찾으면 docs[doc_id] = docs[doc_id].replace(old_str, new_str)로 치환합니다. 이렇게 도구 구현 두 개를 정말 빠르게 끝냈습니다. 거듭 말하지만, 이 MCP Python SDK로 도구를 정의하는 것이 스키마 정의를 손으로 쓰는 것보다 훨씬 쉽습니다. 좋은 출발입니다 — MCP 서버를 만들고 도구 두 개를 구현했습니다.

이 장에서 배우는 것What you'll learn

약 7분
1

공식 MCP Python SDK — 서버는 FastMCP(...) 한 줄

2

도구 정의 = 함수에 @mcp.tool 데코레이터 한 줄

3

SDK가 뒤에서 도구 JSON 스키마를 자동 생성

4

인자는 pydantic Field로 타입·설명 명시

5

read_doc_contents — docs에서 찾아 반환, 없으면 ValueError

6

edit_documentold_strnew_str 찾아 치환

먼저 짚고 갈 용어
MCP Python SDK
공식 mcp 패키지. 서버 생성과 도구·리소스·프롬프트 정의를 크게 단순화한다.
FastMCP
SDK가 제공하는 서버 클래스. mcp = FastMCP("DocumentMCP") 한 줄로 서버를 만든다.
@mcp.tool
함수를 도구로 등록하는 데코레이터. name·description을 받는다.
pydantic Field
인자의 타입과 설명을 지정. 이 정보로 SDK가 JSON 스키마를 만든다.
자동 JSON 스키마
데코레이터·타입·Field를 모아 SDK가 도구 스키마를 생성 → Claude에 전달.

SDK가 바꾸는 것

One line, one decorator

예전엔 도구마다 커다란 JSON 스키마를 손으로 써야 했습니다. 공식 MCP Python SDK는 서버를 한 줄로 만들고, 도구는 함수 위 데코레이터 한 줄로 정의하게 해 줍니다.

같은 도구, 두 가지 방식 · 전환해 비교해 보세요

데코레이터 방식은 함수·타입·Field를 SDK가 모아 같은 JSON 스키마를 자동 생성합니다 — 결과는 같고, 손으로 쓸 일이 없습니다.

SDK가 보여 주는 도구 정의의 모양은 이렇습니다 — 이름·설명과 인자 두 개를 받는 도구. 한 번 써 두면 뒤에서 MCP가 JSON 스키마를 대신 생성해, 그대로 Claude에 넘길 수 있습니다.

예시 · @mcp.tool 한 줄로 도구 정의
# SDK가 보여 주는 도구 정의의 모양 — 함수 위 데코레이터 하나
@mcp.tool(
    name="add_ints",
    description="Add two integers together",
)
def tool_fn(
    a=Field(description="First number to add"),
    b=Field(description="Second number to add"),
) -> int:
    return a + b

서버와 문서 준비

FastMCP & the docs dict

구현은 루트의 mcp_server.py에 들어갑니다. 기본 서버는 FastMCP(...) 한 줄로 만들어져 있고, 메모리에만 존재하는 docs 딕셔너리가 정의돼 있습니다 — 키는 문서 ID(이름), 값은 내용입니다.

mcp_server.py · 서버 한 줄 + docs + TODO
from mcp.server.fastmcp import FastMCP
from pydantic import Field

mcp = FastMCP("DocumentMCP", log_level="ERROR")   # 서버를 한 줄로 생성

docs = {
    "deposition.md": "This deposition covers the testimony of Angela Smith, P.E.",
    "report.pdf": "The report details the state of a 20m condenser tower.",
    "financials.docx": "These financials outline the project's budget and expenditures.",
    "outlook.pdf": "This document presents the projected future performance of the system.",
    "plan.md": "The plan outlines the steps for the project's implementation.",
    "spec.txt": "These specifications define the technical requirements for the equipment.",
}

# TODO: Write a tool to read a doc
# TODO: Write a tool to edit a doc
지금 할 일

적어 둔 TODO 중 처음 두 개 — 문서를 읽는 도구와 수정하는 도구 — 에만 집중합니다.

도구 두 개 구현

read & edit

첫 TODO 아래에 @mcp.tool로 읽기 도구를 정의합니다. 이름 read_doc_contents, 인자 doc_id를 pydantic Field로 지정합니다. 없는 문서를 요청하면 ValueError를 던지고, 아니면 docs[doc_id]를 반환합니다.

mcp_server.py · 읽기 도구
@mcp.tool(
    name="read_doc_contents",
    description="Read the contents of a document and return it as a string.",
)
def read_document(
    doc_id: str = Field(description="Id of the document to read"),
):
    if doc_id not in docs:
        raise ValueError(f"Doc with id {doc_id} not found")

    return docs[doc_id]

같은 방식을 반복해 수정 도구를 만듭니다. edit_document는 인자를 셋 — doc_id, old_str, new_str — 받고, 문서에서 옛 문자열을 새 문자열로 찾아 치환합니다. (Field 설명까지 모아 SDK가 JSON 스키마를 자동 생성합니다.)

mcp_server.py · 수정 도구 (찾아 치환)
@mcp.tool(
    name="edit_document",
    description="Edit a document by replacing a string in the documents content with a new string",
)
def edit_document(
    doc_id: str = Field(description="Id of the document that will be edited"),
    old_str: str = Field(
        description="The text to replace. Must match exactly, including whitespace"
    ),
    new_str: str = Field(
        description="The new text to insert in place of the old text"
    ),
):
    if doc_id not in docs:
        raise ValueError(f"Doc with id {doc_id} not found")

    docs[doc_id] = docs[doc_id].replace(old_str, new_str)
도구 정의가 명시하는 것
  • 도구 이름설명 — Claude가 언제 쓸지 판단하는 근거.
  • 각 인자의 타입Field 설명.
  • 없는 문서 요청은 ValueError로 안전하게 처리.

정리 & 점검

Recap & check
핵심 정리
  • 공식 MCP Python SDK — 서버는 FastMCP(...) 한 줄, 도구는 @mcp.tool 한 줄.
  • 인자는 pydantic Field로 타입·설명을 명시 → SDK가 JSON 스키마를 자동 생성.
  • read_doc_contents — docs에서 찾아 반환, 없으면 ValueError.
  • edit_documentold_strnew_str로 찾아 치환.

Q1Python SDK로 도구를 가장 쉽게 정의하는 방법은?

Q2도구 인자의 타입과 설명은 무엇으로 지정하나요?

Q3read_document가 없는 문서 ID를 받으면?

MEMBER SESSION REQUIRED · REGISTRATION IS FREE

여기부터는 등록한 분에게 열립니다.

전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 76개 레슨을 끝까지 읽을 수 있습니다.

등록하고 이어서 읽기

이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.