MCP 도구가 읽기 전용인지 헷갈릴 때: annotations 네 가지 힌트 해석

MCP 도구에 readOnlyHint: true가 있어도 호출 승인이 자동으로 생기지는 않는다. 이 값은 서버가 설명하는 도구의 성격이다. 실행할 계정의 권한, 사용자가 허용한 대상, 클라이언트의 승인 정책은 따로 확인해야 한다. 반대로 읽기 전용 도구에 확인 창이 떴다는 이유만으로 서버가 쓰기 작업을 했다고 단정할 수도 없다.

읽기·쓰기 표시가 예상과 다르거나 자동 재시도 여부가 헷갈릴 때는 도구 정의 → 실제 동작 → 클라이언트 정책을 차례로 대조한다. 이 글은 MCP 2026-07-28 규격의 ToolAnnotations를 기준으로 한다. 아래 예제와 점검표는 설명을 위한 가상 설계이며 특정 제품에서 재현한 장애 기록은 아니다.

네 가지 힌트가 답하는 질문

공식 ToolAnnotations 스키마의 정의를 줄이면 다음과 같다. 생략한 값의 기본값까지 함께 읽어야 한다. 네 항목을 전부 false로 간주하면 뜻이 달라진다.

항목과 기본값값이 뜻하는 것
readOnlyHint · falsetrue면 환경을 수정하지 않는다고 설명한다.
destructiveHint · truetrue면 파괴적 변경 가능성, false면 추가형 변경만 한다는 뜻이다. readOnlyHint가 false일 때만 의미가 있다.
idempotentHint · falsetrue면 같은 인자로 반복 호출해도 환경에 추가 효과가 없다는 뜻이다. readOnlyHint가 false일 때만 의미가 있다.
openWorldHint · truetrue면 외부 개체와 상호작용할 수 있다. false면 상호작용 범위가 닫혀 있다는 뜻이다.

이들은 모두 힌트이며 실제 동작의 보증서가 아니다. MCP의 도구 정의 규칙은 신뢰하는 서버에서 온 경우가 아니라면 annotations를 신뢰하지 말도록 요구한다. 따라서 이름에 read나 safe가 들어간다는 이유로 권한 검사를 생략하는 방식은 피한다.

먼저 확인할 것은 어떤 서버의 어떤 도구인가

가상의 문서 검색 도구를 살펴보자. 아래 JSON은 tools/list 응답의 tools 배열에 들어갈 도구 정의 한 개다. 전체 요청이나 전체 응답은 아니므로 이대로 전송하는 예제가 아니다.

{
  "name": "search_public_guides",
  "description": "Search published guides without modifying documents.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string"
      }
    },
    "required": [
      "query"
    ],
    "additionalProperties": false
  },
  "annotations": {
    "readOnlyHint": true,
    "openWorldHint": true
  }
}

이 예제는 공개 문서를 검색하고 원문을 수정하지 않는다고 설명한다. 하지만 검색어가 외부 서비스로 전달될 수 있으므로, 읽기 전용이라는 표시만 보고 비밀값이나 고객 원문을 인자에 넣어서는 안 된다. openWorldHint는 구체적인 수신자 목록을 제공하지 않는다. 실제 전송처와 전송 필드는 서버 구현·운영 문서에서 별도로 확인한다.

같은 이름의 도구가 여러 연결에 있을 수도 있다. 화면의 표시 이름만 적지 말고 연결 대상과 도구 식별자를 함께 남긴다. MCP는 도구 이름의 유일성을 서버 안에서 다루며, 여러 서버를 묶는 클라이언트에는 충돌을 구별할 전략을 권고한다. Tool Names 규칙

표시와 동작이 다를 때 좁혀 볼 위치

다음은 규격의 의무 사항을 추가한 표가 아니라, 문제 위치를 찾기 위한 진단 제안이다. 표시가 이상하다는 한 문장을 더 작은 관측으로 나눈다.

관측한 증상우선 대조할 것바로 결론내리지 않을 것
읽기 도구인데 확인 창이 뜬다받은 readOnlyHint 원문, 서버 신뢰 판단, 클라이언트의 승인 정책확인 창이 있으니 쓰기 도구라는 판단
추가만 하는 도구인데 위험 경고가 뜬다destructiveHint 생략 여부와 실제 추가 동작의 영향삭제가 없으니 모든 호출이 무해하다는 판단
같은 인자로 두 번 불렀더니 중복 결과물이 생겼다idempotentHint 선언과 실제 저장·발송 경로힌트가 true였으니 두 번째 효과가 없었을 것이라는 판단
닫힌 범위라고 표시되는데 외부 서비스에 접속한다openWorldHint, 외부 호출 경로, 정의를 받은 시점false만 보고 네트워크 접근이 차단됐다는 판단
서버 정의를 고쳤는데 화면 표시가 그대로다서버 원문과 클라이언트가 보유한 정의의 차이서버 코드만 바뀌면 현재 화면도 바뀌었다는 판단

예를 들어 문서 제목을 바꾸는 도구의 실제 구현은 그대로 둔 채 readOnlyHint만 true로 수정하는 것은 해결이 아니다. 설명과 동작의 불일치를 더 키운다. 반대로 구현은 읽기만 하는데 정의가 빠져 있다면 정의를 보완하고, 클라이언트가 새 정의를 받았는지까지 확인한다. 승인 정책 자체가 별도로 확인을 요구한다면 그 정책은 여전히 적용될 수 있다.

추가형 변경과 멱등성을 섞지 않는다

가상의 메모 추가 기능을 생각해 보자. 기존 메모를 지우지 않고 새 메모만 붙이므로 추가형 변경으로 설명할 수 있다. 그렇지만 같은 문장을 두 번 보내 메모가 두 개 만들어진다면 반복 호출의 추가 효과는 존재한다. 이 설계에는 readOnlyHint: false, destructiveHint: false, idempotentHint: false가 어울린다.

반면 가상의 설정 도구가 특정 옵션을 같은 값으로 맞추는 기능이라면 두 번째 호출 이후 최종 설정은 같을 수 있다. 그래도 호출 때마다 별도 알림을 보내거나 과금을 발생시키는 경로가 있다면 그 효과도 함께 살펴야 한다. 최종 데이터 한 칸이 같다는 것만으로 전체 도구의 멱등성을 판단하지 않는 편이 안전하다.

응답이 끊겼을 때 힌트 하나로 쓰기 작업을 다시 실행하지 않는다. 실제 서비스가 제공하는 중복 방지 계약과 결과 조회 경로를 확인한다. 구체적인 재시도 설계는 재시도 전에 결과부터 확인하기에서 다뤘다. 이번 점검의 초점은 그 계약과 서버의 힌트가 서로 맞는지다.

운영 데이터를 건드리지 않고 대조하는 방법

먼저 허용된 조회로 현재 도구 정의를 확보하고, 관련 구현이나 운영 명세의 실행 효과를 읽는다. 실제 호출 시험이 필요하면 생산 데이터 대신 승인된 테스트 데이터와 격리된 대상에서 진행한다. 삭제·발송·결제 기능을 “힌트가 맞는지 확인”한다는 이유로 실환경에서 실행하지 않는다.

다음은 팀에서 복사해 사용할 수 있는 점검 양식이다. MCP 표준 메시지가 아니며, 아직 관측하지 않은 칸은 추정으로 채우지 않는다. 계정명·인증값·개인 데이터는 기록하지 않고 식별자를 가린다.

대상: 연결 식별자 / 도구 name / 서버 구현 버전
정의: 확인 시각 / 네 가지 힌트의 명시값 또는 생략
실행 효과: 읽기 / 추가 / 수정·삭제 / 외부 전송
반복 호출: 같은 인자의 추가 효과 / 근거 / 미확인 범위
클라이언트: 제품·버전 / 표시 / 승인 정책
차이: 서버 정의와 구현 / 정의와 화면 중 어디인가
수정 후: 새 정의 수신 / 동일 조건의 표시·동작 재확인

검사 순서를 작게 잡으면 원인을 덜 섞을 수 있다. 같은 클라이언트 버전과 같은 테스트 도구를 두고 먼저 정의 원문을 비교한다. 그다음 정의를 새로 받아 표시가 달라지는지 본다. 마지막으로 허용된 테스트 호출의 효과를 대조한다. 여러 설정과 구현을 동시에 바꾸면 어느 변경이 영향을 줬는지 남기기 어렵다.

화면이 낡은 정의를 계속 쓰는 문제라면 변경 알림과 캐시 진단의 목록 변경 경로를 참고할 수 있다. 다만 해당 글의 리소스 본문 구독을 도구 목록에 그대로 적용하지 말고 toolsListChanged와 도구 목록 갱신을 대조한다.

힌트를 고친 뒤에도 남는 확인

힌트가 정확해지면 사람이 도구를 이해하는 데 도움이 된다. 실행 허용 여부는 여전히 현재 대상과 권한에 달려 있다. 읽기 권한이 없는 문서를 읽기 전용 도구로 조회하는 것도 허용된 작업은 아니며, 추가형 변경도 알림 발송처럼 외부 영향을 만들 수 있다.

정의와 실행 사이의 검사를 더 구체화하려면 도구 계약의 사전·사후 조건을 함께 확인한다. 다음 오류 보고에는 “안전한 도구인데 막혔다” 대신 어느 연결의 어떤 정의를 받았고, 어떤 정책 또는 실제 효과와 달랐는지를 남기자. 그 차이가 서버 설명을 고칠지, 구현을 고칠지, 클라이언트 표시를 고칠지 결정할 근거가 된다.

자료 확인: 2026년 10월 10일 KST. MCP 2026-07-28의 ToolAnnotations와 Tools를 대조했다. 특정 SDK 버전의 구현이나 제품별 승인 화면을 시험한 글은 아니므로, 실제 적용 시 서버·클라이언트 버전과 동작을 별도로 확인해야 한다.


다른 글 보기 · 주제 탐색 · 작성자와 편집 기준 · 문의·정정 요청

RUDA DIRECTOR에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기