MCP의 Tools·Resources·Prompts, 언제 무엇으로 노출할까

누가 실행을 결정하는지로 나누는 세 가지 서버 기능과 설계 예시

핵심 요약

  1. Tools는 모델이, Resources는 애플리케이션이, Prompts는 사용자가 사용을 결정한다.
  2. 상태를 바꾸거나 매번 입력이 필요한 동작은 Tool로, 참고 데이터는 Resource로 노출한다.
  3. 사용자가 메뉴에서 고르는 작업 흐름은 Prompt 템플릿이 적합하다.
  4. 세 기능 모두 입력 검증과 요청별 권한 검사가 명세상 요구된다.

MCP 서버를 처음 설계하면 거의 모든 기능을 도구(Tool)로 만들기 쉽다. 하지만 명세는 서버가 노출하는 기능을 Tools, Resources, Prompts 세 가지로 나누고, 각각 "누가 사용을 결정하는가"를 다르게 정의한다. 이 구분을 지키지 않으면 모델이 불필요한 도구를 호출하거나, 사용자가 직접 골라야 할 자료를 모델이 임의로 불러오는 문제가 생긴다. 이 글은 MCP 2026-07-28 명세의 서버 기능 정의를 바탕으로 세 가지를 비교한다. 호스트·클라이언트·서버의 기본 구조는 MCP 개념 정리 글에서 먼저 다뤘다.

사용을 결정하는 주체가 다르다

기능제어 주체(명세 표현)대표 예주요 메서드
Tools모델 제어(model-controlled)DB 조회, API 호출, 계산tools/list, tools/call
Resources애플리케이션 주도(application-driven)파일, DB 스키마, 설정 문서resources/list, resources/read, resources/templates/list
Prompts사용자 제어(user-controlled)슬래시 명령형 템플릿prompts/list, prompts/get

Tools는 모델이 대화 맥락을 보고 스스로 찾아 호출한다. 명세는 그럼에도 사람이 도구 호출을 거부할 수 있도록 항상 사람이 개입하는 구조를 권한다. Resources는 호스트 애플리케이션이 어떤 맥락을 넣을지 결정한다. 트리나 목록 UI로 사용자가 고르게 하거나, 휴리스틱이나 모델 선택에 따라 자동으로 포함할 수도 있다. Prompts는 사용자가 명시적으로 선택해 쓰는 템플릿으로, 명세는 슬래시 명령 형태를 대표 예로 든다. 여기서 "사용자 제어"는 언제 쓸지를 사용자가 정한다는 뜻이고, 프롬프트 내용 자체는 서버가 정의한다.

Tools: 부작용이 있거나 입력이 필요한 동작

도구는 name, description, inputSchema(JSON Schema)를 갖고, 선택적으로 outputSchema와 annotations를 둔다. 결과는 content 배열로 돌려주며, 출력 스키마가 있으면 structuredContent에 스키마에 맞는 JSON을 넣는다.

{
  "name": "create_ticket",
  "title": "장애 티켓 생성",
  "description": "장애 보고 내용을 받아 사내 이슈 트래커에 티켓을 만든다",
  "inputSchema": {
    "type": "object",
    "properties": {
      "summary": { "type": "string", "maxLength": 120 },
      "severity": { "type": "string", "enum": ["low", "medium", "high"] }
    },
    "required": ["summary", "severity"],
    "additionalProperties": false
  }
}

모델이 판단해 실행해야 하는 동작, 즉 상태를 바꾸거나 매번 다른 입력이 필요한 동작이 도구에 맞는다.

Resources: 맥락으로 읽히는 데이터

리소스는 URI로 식별되는 데이터다. 파일(file://), 웹 자원(https://), git 같은 표준 스킴과 사용자 정의 스킴을 쓸 수 있고, 명세는 URI 템플릿으로 매개변수가 있는 리소스도 정의할 수 있게 한다. 읽기 결과는 contents 배열에 텍스트나 base64 바이너리로 담긴다.

{
  "uriTemplate": "schema://orders/{table}",
  "name": "주문 DB 테이블 스키마",
  "description": "주문 데이터베이스 테이블의 컬럼 정의",
  "mimeType": "application/json"
}

리소스에는 audience(user, assistant), priority(0.0~1.0), lastModified 주석을 달 수 있어 클라이언트가 어떤 자료를 우선 넣을지 판단하는 데 쓴다. 존재하지 않는 리소스는 빈 배열이 아니라 -32602 오류로 응답해야 한다.

Prompts: 사용자가 고르는 작업 템플릿

프롬프트는 이름, 설명, 인자 목록을 갖고, prompts/get을 호출하면 인자를 채운 메시지 배열을 돌려준다. 메시지에는 텍스트뿐 아니라 리소스 링크나 내장 리소스도 넣을 수 있다.

{
  "name": "incident_review",
  "title": "장애 회고 초안",
  "description": "티켓 번호를 받아 회고 문서 초안을 요청하는 프롬프트",
  "arguments": [
    { "name": "ticket_id", "description": "장애 티켓 번호", "required": true }
  ]
}

같은 기능을 어디에 둘지 판단하는 기준

  1. 상태를 바꾸는가? 바꾼다면 Tool이다. 리소스 읽기와 프롬프트 조회는 부작용이 없어야 한다.
  2. 모델이 스스로 불러야 하는가? 대화 흐름에 따라 필요할 때마다 조회해야 하면 Tool, 사용자나 앱이 미리 골라 넣는 참고 자료라면 Resource다.
  3. 사용자가 의도적으로 시작하는 작업인가? "회고 초안 작성"처럼 사용자가 메뉴에서 고르는 작업 흐름이면 Prompt다.
  4. 클라이언트가 지원하는가? 호스트마다 리소스·프롬프트 지원 수준이 다르므로, 대상 클라이언트가 지원하지 않는 기능만으로 핵심 기능을 만들지 않는다.

예를 들어 사내 주문 시스템 서버라면 get_order·cancel_order는 Tool, 테이블 스키마와 운영 정책 문서는 Resource, "주간 주문 이상 징후 리포트"는 Prompt로 나눌 수 있다. 리소스와 도구가 같은 데이터를 다룰 때는 도구가 resource_link를 결과에 포함해 관련 리소스를 가리키게 하는 방식도 명세에 정의돼 있다.

보안 관점에서 달라지는 점

기능명세의 보안 요구
Tools서버는 모든 입력 검증, 접근 제어, 호출 빈도 제한, 출력 정제를 해야 한다. 클라이언트는 민감 작업 전 확인을 받아야 한다.
Resources서버는 모든 리소스 URI를 검증하고, file:// 리소스는 디렉터리 이탈(경로 조작)을 막도록 경로를 정제해야 한다.
Prompts구현체는 프롬프트 입력과 출력을 검증해 인젝션 공격과 무단 리소스 접근을 막아야 한다.

세 기능 모두 권한 검사는 요청마다 이뤄져야 한다. 명세는 목록 결과가 연결별로 달라지면 안 되지만, 요청에 담긴 인가 정보에 따라 달라질 수는 있다고 설명한다. 인가 구현은 MCP 서버 OAuth 글에서, 무상태 전환에 따른 변경은 2026-07-28 스펙 마이그레이션 글에서 다뤘다.

초보자가 자주 실수하는 포인트

  • 단순한 문서 조회까지 모두 Tool로 만들어 모델이 불필요하게 호출하는 경우
  • 리소스 읽기에 부작용(로그 외 상태 변경)을 넣는 경우
  • 존재하지 않는 리소스에 빈 contents 배열로 응답하는 경우
  • 대상 클라이언트가 지원하지 않는 Prompts만으로 핵심 기능을 제공하는 경우

체크리스트

  • 상태를 바꾸는 기능이 모두 Tool로 노출되는가
  • Resource URI 검증과 경로 정제가 구현됐는가
  • Prompt 인자에 필수 여부와 설명이 있는가
  • 대상 클라이언트의 기능 지원 범위를 확인했는가
  • 요청마다 인가 정보로 권한을 검사하는가

자주 묻는 질문

리소스만 있고 도구가 없는 서버도 의미가 있나요?

있다. 문서나 스키마를 맥락으로 제공하는 읽기 전용 서버는 리소스만으로 구성할 수 있다. 다만 호스트가 리소스를 어떻게 노출하는지는 클라이언트마다 다르다.

도구 주석(annotations)을 믿고 승인 절차를 생략해도 되나요?

명세는 신뢰하는 서버가 아니면 도구 주석을 신뢰하지 말라고 경고한다. 읽기 전용 표시만 보고 확인 절차를 빼지 않는다.

프롬프트 내용은 누가 정하나요?

서버가 정의한다. 사용자 제어라는 표현은 언제 사용할지를 사용자가 고른다는 의미다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 위 참고 자료를 바탕으로 정리했으며, 내용은 운영 과정에서 순차적으로 보완될 수 있습니다.