MCP 서버 설계 방법 — Tools·Resources·권한·호출 흐름 정리

MCP 서버 설계 방법을 Tools·Resources·Prompts의 역할부터 입력 스키마, 오류 처리, 호출 흐름, 권한 제한과 자동화 연결 시 주의점까지 쉽게 정리합니다. 무엇이든 Tool로 만들면 호출 대상이 늘어납니다.

목차

이 글은 MCP(Model Context Protocol)의 기본 개념을 이해하고, 기존 API나 자동화 시스템에 연결할 MCP 서버를 설계한다고 가정합니다. 특정 인프라나 구현 프레임워크가 아니라, 서버에 무엇을 공개하고 어떻게 제한할지에 초점을 둡니다.

MCP 서버에서 노출할 기능 구분

MCP 서버에서는 Tools, Resources, Prompts를 서로 다른 역할로 구분할 수 있습니다. 이 글에서는 그중 Tools와 Resources를 중심으로 서버에 공개할 기능을 설명합니다.

무엇이든 Tool로 만들면 호출 대상이 늘어납니다. 정적인 데이터나 애플리케이션이 제공할 컨텍스트는 Resource로, 모델이 호출해 작업을 수행해야 하는 기능은 Tool로 분리하면 AI 클라이언트가 사용할 기능을 명확하게 구성할 수 있습니다. 조회 기능이라도 모델이 능동적으로 호출해야 한다면 Tool로 설계할 수 있습니다.

Tool 설계와 호출 흐름

Tool의 입력 스키마는 필수 인자, 허용되는 값, 문자열 형식과 작업 범위를 명확히 담아야 합니다. 반환 데이터도 AI가 해석하기 쉬운 구조로 구성하고, 성공 결과와 오류 결과의 형식을 구분하면 후속 자동화가 안정적으로 이어집니다.

Tool을 사용하는 기본 흐름은 연결, 사용 가능한 Tool 확인, Tool 호출, 결과 반환 순서로 진행됩니다. AI 클라이언트는 먼저 사용할 수 있는 기능을 확인한 뒤 인자를 전달하고, MCP 서버는 기존 API나 도구를 실행해 결과 또는 오류를 돌려줍니다. 인자가 잘못되면 실행 전에 검증하고, 외부 API가 실패하면 원인과 재시도 가능 여부를 구분해 결과에 담습니다.

작업 범위는 작게 유지하는 편이 안전합니다. 한 Tool이 여러 시스템을 한꺼번에 수정하지 않도록 나누고, 되돌릴 수 있는 작업과 삭제처럼 되돌리기 어려운 작업은 별도로 설계합니다.

실전 코드 예시

FastMCP(Python)로 위 원칙을 실제 코드에 적용하면 다음과 같습니다. 아래 예시는 파일을 조회하는 Tool 하나를 구현합니다 — 입력 스키마를 명확히 하고, 성공과 오류 결과를 구분해서 돌려줍니다.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("file-tools")

@mcp.tool()
def read_file_summary(path: str, max_lines: int = 50) -> dict:
    """지정한 경로의 텍스트 파일에서 앞부분 일부를 읽어 반환합니다."""
    if not isinstance(path, str) or not path:
        return {"ok": False, "error": "path는 비어 있지 않은 문자열이어야 합니다."}
    if max_lines <= 0 or max_lines > 500:
        return {"ok": False, "error": "max_lines는 1~500 사이여야 합니다."}

    try:
        with open(path, "r", encoding="utf-8") as f:
            lines = []
            for _ in range(max_lines):
                line = f.readline()
                if not line:
                    break
                lines.append(line)
    except FileNotFoundError:
        return {"ok": False, "error": f"파일을 찾을 수 없습니다: {path}"}

    return {"ok": True, "path": path, "lines": lines}

이 예시는 앞서 설명한 세 가지를 그대로 반영합니다. 입력 스키마는 path(문자열, 필수)와 max_lines(정수, 기본값 50)로 명확히 제한했고, 잘못된 인자는 실행 전에 걸러 ok: False로 돌려줍니다. 파일이 없는 경우처럼 실행 중 실패도 예외를 그대로 노출하지 않고 같은 형식(ok, error)으로 감싸 AI 클라이언트가 성공과 실패를 일관되게 해석할 수 있게 했습니다. 이 Tool은 읽기 전용이라 별도 승인 없이 노출해도 되지만, 파일을 쓰거나 지우는 Tool이라면 앞서 설명한 대로 권한과 승인 절차를 먼저 설계해야 합니다.

권한·안전성·자동화 연결

권한은 MCP 서버가 접근할 파일, 데이터베이스, API 범위를 기준으로 제한합니다. 읽기 전용 작업과 수정 작업을 분리하고, 삭제·결제·대량 변경처럼 민감한 작업은 별도 승인이나 추가 제한의 대상으로 둡니다. MCP 서버 자체가 권한을 자동으로 안전하게 만들어 주는 것은 아니므로, 인증·인가와 감사 기록은 연결된 시스템에서도 확인해야 합니다.

자동화 시스템과 연결할 때는 Tool이 너무 많아 선택 오류가 생기거나, 같은 작업이 중복 호출될 수 있습니다. 긴 작업은 상태 조회용 Tool을 따로 두고, 요청 식별자나 중복 방지 키를 사용하면 동일 작업의 반복 실행을 막을 수 있습니다.

구조는 MCP 서버, AI 클라이언트, 기존 API·도구, 자동화 시스템의 네 계층으로 나눌 수 있습니다. 먼저 읽기 전용 Tool로 흐름을 검증한 뒤 수정 기능을 추가하면, 잘못된 인자나 외부 API 실패가 실제 데이터 변경으로 이어지는 범위를 줄일 수 있습니다.

결론

MCP 서버 설계의 핵심은 기능을 많이 공개하는 것이 아니라, Resource와 Tool을 구분하고 작은 작업 단위·명확한 스키마·제한된 권한으로 호출 흐름을 통제하는 것입니다.

관련 글