MCP 도구 어노테이션: readOnlyHint와 클라이언트 활용법

MCP 도구 어노테이션은 readOnlyHint 같은 선택적 힌트입니다. 각 힌트의 의미와 기본값, 그리고 ChatGPT·VS Code·Copilot이 이를 쓰는 방식을 정리합니다.

읽는 시간 6분Sume
전체 글

MCP 도구 어노테이션(tool annotations)은 서버가 도구마다 붙여 그 도구의 동작을 설명하는 선택적 힌트로, readOnlyHint, destructiveHint, idempotentHint, openWorldHint, 그리고 표시용 title이 있습니다. 클라이언트는 이를 읽고 어떤 호출에 사람의 승인이 필요한지 같은 것을 정하지만, 어노테이션은 보장이 아니라 힌트입니다. 명세는 신뢰할 수 있는 서버에서 온 것이 아니면 어노테이션을 신뢰하지 말라고 합니다.

정의는 MCP 명세 2025-11-25 버전의 스키마 레퍼런스와 Tools 페이지에서 가져왔습니다. 클라이언트 동작은 각 클라이언트의 자체 문서에서, 예시로 든 Sume 호스팅 MCP 서버 내용은 그 코드와 MCP 도구와 게이트에서 가져왔습니다. 모두 2026-09-27에 확인했습니다.

각 어노테이션은 무엇을 뜻하나요?

네 힌트는 모두 불리언이며, 서버가 생략했을 때 적용되는 기본값이 각각 있습니다.

  • 이 기본값대로 읽으면, 어노테이션을 보내지 않는 도구는 파괴적일 수 있고 외부 개체에 닿을 수 있는 쓰기 도구입니다.
  • title은 사람이 읽기 좋은 이름입니다. 표시할 때 명세가 정한 순서는 도구의 title, 그다음 annotations.title, 그다음 name입니다.
MCP 스키마 레퍼런스 2025-11-25 버전 기준, 2026-09-27 확인.
어노테이션true일 때 의미기본값
readOnlyHint도구가 환경을 수정하지 않음false
destructiveHint도구가 파괴적 업데이트를 할 수 있음. false는 추가만 하는 업데이트를 뜻함. readOnlyHint가 false일 때만 의미가 있음true
idempotentHint같은 인수로 반복 호출해도 추가 효과가 없음. readOnlyHint가 false일 때만 의미가 있음false
openWorldHint도구가 웹 검색처럼 외부 개체로 이뤄진 열린 세계와 상호작용할 수 있음. 메모리 도구의 세계는 닫혀 있음true

어노테이션은 도구 정의의 어디에 들어가나요?

서버가 tools/list에서 반환하는 각 도구의 annotations 객체에 들어가며, name, description, inputSchema와 나란히 놓입니다. 아래는 명세의 날씨 예시를 줄이고 어노테이션을 더한 것입니다. 아무것도 바꾸지 않고 외부 서비스를 호출하는 조회 도구입니다.

{
  "name": "get_weather",
  "title": "Weather Information Provider",
  "description": "Get current weather information for a location",
  "inputSchema": {
    "type": "object",
    "properties": {
      "location": { "type": "string", "description": "City name or zip code" }
    },
    "required": ["location"]
  },
  "annotations": {
    "readOnlyHint": true,
    "openWorldHint": true
  }
}

MCP 도구 어노테이션은 강제되나요?

강제되지 않습니다. 명세는 ToolAnnotations의 모든 속성을 도구를 충실하게 설명한다는 보장이 없는 힌트라고 부릅니다. 클라이언트는 신뢰할 수 없는 서버의 어노테이션을 근거로 도구 사용을 결정해서는 절대 안 되며, 신뢰할 수 있는 서버에서 온 것이 아니면 어노테이션을 신뢰할 수 없는 것으로 간주해야 합니다. Mastra 문서는 그 위험을 분명하게 설명합니다. 악의적이거나 버그가 있는 서버는 읽기 전용이 아닌 도구를 읽기 전용이라고 주장할 수 있습니다.

MCP 클라이언트는 readOnlyHint를 어떻게 쓰나요?

클라이언트마다 다릅니다. 읽기 전용으로 표시되지 않은 호출은 모두 먼저 묻는 클라이언트가 있고, 그런 도구를 아예 빼는 클라이언트가 하나 있으며, 정책을 여러분의 코드에 맡기는 클라이언트도 있습니다.

ChatGPT 개발자 모드, VS Code MCP 가이드, GitHub Docs, AI SDK, Mastra 기준, 2026-09-27 확인.
클라이언트문서 내용
ChatGPT 개발자 모드쓰기 작업은 기본적으로 확인 필요. readOnlyHint를 따르며, 이 힌트가 없는 도구는 쓰기 작업으로 취급
VS CodereadOnlyHint로 표시되지 않은 모든 도구에 확인 대화상자를 띄움. 읽기 전용 도구는 확인 없이 실행
GitHub Copilot 코드 리뷰annotations.readOnlyHint가 true일 때만 도구를 사용. 없거나 false면 제외
AI SDK도구 메타데이터에 어노테이션을 노출하지만, 이를 자동으로 승인 정책으로 바꾸지는 않음
Mastra어노테이션을 requireToolApproval 함수에 넘김. 어노테이션을 근거로 한 승인 완화는 신뢰하는 서버에만 적용

Sume MCP 서버는 어떤 값을 설정하나요?

현재 코드에서 https://mcp.sume.com/mcp의 Sume 호스팅 서버는 모든 도구에 네 가지 힌트를 모두 붙입니다. 그 위에 Sume 자체 게이트가 더해집니다. OAuth 세션에 mcp:write가 생기기 전까지 쓰기·유료 도구는 숨겨지고, 모든 쓰기·유료 호출에는 idempotency_key가 필요합니다. 현재 코드가 설정하는 값은 다음과 같습니다.

  • tools_list, jobs_status, jobs_wait 같은 읽기 도구에는 readOnlyHint: true, idempotentHint: true, destructiveHint: false가 설정됩니다.
  • generate_video, video_trim 같은 쓰기·유료 도구에는 readOnlyHint: false와 idempotentHint: false가 설정됩니다.
  • destructiveHint: true인 도구는 jobs_cancel 하나뿐입니다. 모든 도구는 openWorldHint: false를 설정합니다.
  • tools_list는 프로토콜 어노테이션과 별도로 도구마다 Sume safety 블록도 반환하며, 여기에는 read_only, paid_generation, requires_idempotency_key 같은 필드가 있습니다. 자세한 내용은 Sume MCP 도구 목록에서 다룹니다.
  • 그래서 ChatGPT는 유료 Sume 도구를 호출하기 전에는 확인을 요청하지만, 상태 읽기는 읽기 전용으로 취급합니다. 이 흐름은 ChatGPT에 MCP 서버를 추가하는 방법에서 볼 수 있습니다.

출처

관련 글

개발자 카테고리의 다른 글

개발자 글 전체 보기

작성자 Sume