에이전트 보안의 다음 경계는 도구 노출이다

에이전트에 도구를 붙이는 일이 점점 쉬워지고 있다. MCP 서버를 연결하고, function calling을 열고, 사내 API를 플러그인처럼 감싸면 모델은 단순히 답변하는 프로그램이 아니라 실제 시스템을 움직이는 실행자가 된다.
Cloudflare가 2026-07-22 Agents SDK changelog에서 낸 업데이트도 이 흐름 안에 있다. 반복적인 MCP schema conversion을 줄였고, @cloudflare/think에서 자동 MCP tool exposure를 끌 수 있는 옵션을 추가했다. 옵션 이름은 includeMcpTools = false다.
이 글은 Cloudflare 사용법을 정리하려는 글이 아니다. Cloudflare가 보안 사고를 냈다는 이야기도 아니다. 핵심은 Cloudflare가 아니라, 에이전트에게 어떤 도구를 보이느냐가 권한 경계가 된다는 점이다.
MCP 서버에 연결돼 있다는 것과, LLM에게 지금 그 도구를 호출 가능한 선택지로 보여준다는 것은 분리돼야 한다.
즉, 에이전트 보안에서 봐야 할 것은 “도구가 연결돼 있느냐”만이 아니다. “그 도구가 지금 모델의 선택지 안에 들어와 있느냐”도 독립적인 점검 항목이다.
Cloudflare 업데이트가 보여준 신호
Cloudflare changelog에 따르면 includeMcpTools = false는 Code Mode나 다른 메커니즘으로 MCP tools를 노출할 때 쓰는 옵션이다. 이 값을 끄면 Think가 자동으로 getAITools()를 호출해 MCP tools를 모델에게 노출하는 경로를 건너뛴다.
import { Think } from "@cloudflare/think";
export class MyAgent extends Think<Env> {
includeMcpTools = false;
waitForMcpConnections = true;
}중요한 점은 이것이 MCP 자체를 꺼버리는 옵션이 아니라는 것이다. MCP 등록, 탐색, raw catalog 접근, 직접 호출, Code Mode connector는 계속 작동할 수 있다. 달라지는 것은 Think의 자동 tool set에 MCP tools를 넣는 경로다.
여기서 네 가지 축이 갈라진다.
| 축 | 의미 |
|---|---|
| 연결 | 시스템이 어떤 도구를 사용할 수 있도록 붙어 있는 상태 |
| 탐색 | 런타임이나 개발자가 도구 목록을 조회할 수 있는 상태 |
| 노출 | LLM이 응답 생성 중 “이 도구를 호출할 수 있다”고 보는 상태 |
| 실행 | 실제 API 호출·코드 실행·상태 변경이 일어나는 상태 |
이 네 가지를 한 덩어리로 다루면 권한 경계가 흐려진다. 연결된 도구가 곧 모델에게 보이는 도구라고 가정하는 순간, 에이전트 하네스는 너무 많은 권한을 기본값으로 열어두기 쉽다.
도구는 컨텍스트가 아니라 실행 권한이다
Cloudflare MCP tools 문서는 MCP tool을 MCP 서버가 클라이언트에게 호출 가능하게 노출하는 서버 쪽 기능으로 설명한다. MCP 자체도 AI 애플리케이션을 데이터 소스·도구·워크플로에 연결하는 표준으로 정의된다.
이 말은 단순히 “플러그인 목록이 늘어난다”는 뜻이 아니다. 도구는 호출될 수 있다.
- DB 조회: 내부 데이터나 고객 정보에 닿을 수 있다.
- GitHub 이슈 생성: 외부 협업 시스템에 상태를 남길 수 있다.
- 내부 API 호출: 사내 시스템의 읽기·쓰기 경로를 열 수 있다.
- 파일 검색: 모델이 보지 말아야 할 범위까지 탐색할 수 있다.
- 코드 실행: 단순 답변을 넘어 런타임 자체를 움직일 수 있다.
- 외부 서비스 액션: 이메일, 슬랙, 결제, 배포 같은 실제 행동으로 이어질 수 있다.
즉, 도구는 컨텍스트가 아니다. 문서 조각이나 참고 정보처럼 “읽히는 것”이 아니라, 호출되면 외부 세계를 바꾸는 실행 권한이다.
많이 보이는 만큼 실패의 크기도 커진다
LLM은 도구 설명을 읽고 호출 여부를 판단한다. 운영자가 버튼을 보고 “이건 지금 누르면 안 된다”고 멈추는 구조와 다르다. 모델은 프롬프트·문맥·도구 설명·시스템 지시를 함께 보고 다음 행동을 고른다.
그래서 도구 목록이 넓어질수록 실패의 모양이 바뀐다.
| 위험 | 문제가 되는 이유 |
|---|---|
| 프롬프트 인젝션 | 외부 문서나 웹페이지가 모델에게 특정 도구 호출을 유도할 수 있다 |
| 오판 | 읽기 작업처럼 보였지만 실제로는 쓰기·삭제·전송이 포함될 수 있다 |
| 권한 우회 | 원래 사람 승인이 필요했던 작업이 자동 호출 경로로 지나갈 수 있다 |
| 상태 변경 | 답변 오류가 DB 수정, 티켓 생성, 코드 실행 같은 행동으로 번질 수 있다 |
모델의 답변 오류는 텍스트에서 끝날 수 있다. 하지만 도구 호출 오류는 실제 시스템 액션으로 이어질 수 있다. 에이전트가 볼 수 있는 도구 목록은 곧 행동 가능성의 경계다.
연결된 도구와 보이는 도구를 나눠야 한다
내가 이 업데이트를 보며 가장 크게 잡은 원칙은 단순하다.
⇒ 연결된 도구 ≠ 모델에게 보이는 도구
MCP든, OpenAI function calling이든, LangChain tool이든, 자체 플러그인이든 구조는 비슷하다. “등록돼 있다”와 “지금 호출 가능하다” 사이에 한 번 더 문을 둬야 한다.
기본 설계는 이렇게 잡는 편이 안전하다.
- 기본값은 최소 노출: 모든 도구를 한 번에 보여주지 않는다.
- 작업 단위 허용: 현재 태스크에 필요한 도구만 allowlist로 노출한다.
- 쓰기 권한 분리: 읽기 도구와 상태 변경 도구를 같은 등급으로 다루지 않는다.
- 위험 호출 승인: 돈·권한·삭제·배포처럼 되돌리기 어려운 작업은 사람 승인이나 별도 정책을 둔다.
- 로그 기준 통일: 어떤 경로로 호출됐든 누가, 왜, 무엇을 실행했는지 남긴다.
- 도구 설명 검토: 설명이 너무 넓거나 모호하면 모델의 판단도 넓고 모호해진다.
에이전트 플랫폼은 이제 도구 연결 기능만 제공해서는 부족하다. 어떤 도구를 언제 모델에게 보여줄지 제어하는 계층이 필요하다.
중복 경로가 권한 모델을 흐린다
도구 노출에서 까다로운 지점은 같은 기능이 여러 경로로 열릴 때다. Cloudflare 사례에서도 Think 자동 도구, Code Mode connector, raw MCP catalog, 직접 호출 API 같은 경로가 구분된다. 각각은 합리적인 기능일 수 있다. 문제는 조직이 그것들을 하나의 권한 모델로 묶어 보지 않을 때 생긴다.
점검 질문은 이렇다.
- 이 호출은 어떤 승인 정책을 탔나?
- 같은 작업이 다른 경로로도 가능한가?
- 로그는 한곳에 모이나?
- 모델에게는 안 보이지만 코드에서는 호출 가능한가?
- 운영자는 이 차이를 알고 있나?
에이전트를 조직 안의 직원처럼 본다면, 도구 노출은 사번을 발급하는 일이 아니라 출입증 권한을 배정하는 일에 가깝다. 회사 시스템에 계정이 있다는 것과, 지금 이 직원이 결제 시스템·고객 DB·배포 콘솔에 들어갈 수 있다는 것은 다르다.
지금 점검할 목록
에이전트에 도구를 붙이는 팀이라면 전체 연결도를 그리는 것에서 멈추면 안 된다. “모델에게 실제로 보이는 목록”을 따로 확인해야 한다.
- 현재 visible tool set: 지금 LLM 프롬프트에 호출 가능한 도구로 들어가는 목록은 무엇인가.
- 쓰기 권한 도구: 생성·수정·삭제·전송·배포를 수행하는 도구는 무엇인가.
- 외부 호출 도구: 이메일, 슬랙, 결제, 티켓, 고객 연락처럼 외부로 나가는 도구는 무엇인가.
- 코드 실행 도구: 셸, 스크립트, 노트북, 브라우저 자동화처럼 임의 실행에 가까운 도구는 무엇인가.
- 내부 데이터 접근 도구: 고객 정보, 로그, 문서, 재무 데이터, 운영 DB에 닿는 도구는 무엇인가.
- 중복 노출 경로: 같은 기능이 function calling, MCP, 플러그인, 직접 API로 동시에 열려 있지는 않은가.
- 승인·로그 차이: 경로가 달라도 승인 기준과 감사 로그가 동일하게 적용되는가.
결론은 단순하다. 연결은 인프라의 문제이고, 노출은 권한 설계의 문제다.
Cloudflare의 includeMcpTools = false는 모든 MCP 보안 문제를 해결하는 만능 장치가 아니다. 다만 “연결된 도구”와 “LLM-visible tool set”을 분리하는 문제가 실제 SDK 설계 항목으로 올라왔다는 신호로 읽을 수 있다.
즉, 앞으로 에이전트 보안 리뷰에서 물어야 할 질문은 하나 더 늘었다.
이 에이전트는 무엇에 연결돼 있는가?
에서 멈추면 부족하다.
이 모델은 지금 무엇을 호출할 수 있는가?
여기까지 물어야 한다.