안녕하세요. まさきん입니다.
가족용 챗봇에서 장보기 목록에 글을 쓰지 못하는 문제가 있었습니다. 뒤에서 돌리고 있는 claude -p 가 MCP 도구를 매번 거부하고 있었거든요. 원인과 고친 방법을 공식 문서로 확인하면서 메모해 둡니다.
※ 글을 공개한 시점의 정보입니다. 최신 조건은 공식 사이트에서 확인해 주세요.
claude -p의 무인 실행에서는 확인이 필요한 작업이 거부됩니다--permission-mode acceptEdits가 통과시키는 것은 파일 편집과 일부 파일 조작 명령입니다- MCP 도구는
--allowedTools나permissions.allow에 명시하면 통과합니다 - 형식은
mcp__<서버 이름>__<도구 이름>이고, 서버 단위로도 지정할 수 있습니다 - 저는 Notion 의 검색·가져오기·쿼리·생성·업데이트, 이 5가지 작업만 허용했습니다
장보기 목록에 쓸 수 없었다
우리 집에는 가족이 함께 쓰는 메신저 앱의 봇이 있습니다. 직접 만든 것이고, 뒤에서는 claude -p 를 호출합니다. Claude Code 를 헤드리스로 돌리는 방식이죠.
이 봇에게 장보기 목록을 읽고 쓰게 하려고 했습니다. 장보기 목록은 Notion 데이터베이스입니다. 가족이 “이거 사다 줘” 하고 보내면 봇이 목록에 추가한다. 그런 쓰임새를 생각하고 있었습니다.
그런데 몇 번을 해도 쓸 수가 없었습니다. Notion 도구를 호출할 때마다 반드시 거부됩니다. 제 컴퓨터의 대화형 세션에서는 되는데, 봇을 거칠 때만 통과하지 않았습니다.
원인은 허용이 없었던 것
결론은 단순했습니다. 봇이 호출하는 claude -p 에 Notion 커넥터에 대한 허용이 없었던 겁니다.
봇은 --permission-mode acceptEdits 로 돌아갑니다. 파일 편집은 자동으로 통과하는 설정입니다. 그래서 “어느 정도는 맡기고 있다”고 생각하고 있었습니다. 다만 MCP 도구는 그 범위에 들어 있지 않았습니다.
제 환경에서는 무인 실행의 MCP 도구가 반드시 거부됐습니다. --allowedTools 로 명시할 때까지 계속요. 여기가 이번 이야기의 출발점입니다.
무인 실행에서는 대답할 사람이 없다
구조를 정리해 둡니다. Claude Code 는 작업 전에 허용 여부를 확인할 때가 있습니다. 대화형 세션이라면 화면에 확인이 뜨고 사람이 대답합니다.
-p 를 붙인 실행은 비대화 모드입니다. 공식 문서에서는 “Run Claude Code programmatically” 라는 페이지에서 설명합니다. 확인에 대답할 상대를 마련하지 않은 -p 실행에서는 확인이 필요한 작업이 거부된다고 적혀 있습니다.
즉 “물어보고 멈추는” 것이 아니라 “묻지도 않고 거절당하는” 셈이죠. 봇의 뒤편에서는 이 차이가 그대로 “반드시 거부”로 보이게 됩니다. 구조를 알고 나니 과연 그렇구나 싶었습니다.
권한 모드 비교
다음은 권한 모드입니다. 공식 “Choose a permission mode” 에는 확인 없이 실행할 수 있는 범위가 모드별로 실려 있습니다.
| 모드 | 확인 없이 실행할 수 있는 것 | 공식이 꼽는 용도 |
|---|---|---|
| default | 읽기만 | 모든 작업을 직접 확인하는 일 |
| acceptEdits | 읽기·파일 편집·일부 파일 조작 명령 | 코드를 확인하면서 진행하는 일 |
| plan | 읽기 중심(편집은 승인 필요) | 변경 전 조사 |
| auto | 분류기가 작업을 심사해 판단 | 긴 작업 |
| dontAsk | 읽기와 미리 허용한 도구만 | 범위를 좁힌 CI 나 스크립트 |
| bypassPermissions | 거의 전부 | 격리된 컨테이너나 VM 에서만 |
default 는 화면에서는 Manual 이라는 이름으로 표시됩니다. 설정값으로는 default 그대로입니다.
모드는 바탕입니다. 그 위에 허용 규칙과 거부 규칙을 겹치는 구조입니다. 공식 문서에는 거부 규칙이 bypassPermissions 를 포함한 어떤 모드에서도 적용된다고 적혀 있습니다.
acceptEdits 가 통과시키는 범위
acceptEdits 가 자동으로 통과시키는 것은 작업 디렉터리 안의 파일 편집입니다. 여기에 mkdir 나 mv 같은 파일 조작 명령도 통과합니다.
반면 그 밖의 셸 명령이나 네트워크 접근은 대상이 아닙니다. 공식 문서에는 --allowedTools 나 permissions.allow 규칙이 필요하다고 적혀 있습니다. 자동 승인 목록에 MCP 도구는 들어 있지 않습니다.
acceptEdits 는 “편집을 맡기는 모드”이지 “외부 서비스 조작을 맡기는 모드”가 아니다. 그렇게 읽는 것이 자연스럽다고 생각합니다.
bypassPermissions 가 먹히지 않았다
사실 설정 파일에는 bypassPermissions 를 적어 두었습니다. 위치는 ~/.claude/settings.json 입니다. 그래서 “전부 통과하겠지” 하고 믿고 있었습니다. 하지만 봇에서는 먹히지 않았습니다.
이유는 공식 문서에 적혀 있었습니다. 시작할 때의 모드는 먼저 해당하는 것이 쓰입니다.
--permission-mode플래그(또는--dangerously-skip-permissions)- 설정 파일의
permissions.defaultMode
CLI 레퍼런스에도 같은 내용이 있습니다. --permission-mode 는 설정 파일의 defaultMode 를 덮어씁니다. 봇은 --permission-mode acceptEdits 를 붙여서 시작합니다. 그래서 설정 파일의 bypassPermissions 는 쓰이지 않았던 것입니다.
플래그와 설정 파일의 관계는 모드 말고는 자세히 확인하지 않았습니다. 이 부분은 제 환경에서 일어난 사실까지만 적어 둡니다.
MCP 도구 이름 쓰는 법
허용 규칙에 적는 MCP 도구 이름에는 정해진 형태가 있습니다. 공식 “Configure permissions” 에 실린 형식은 다음과 같습니다.
| 쓰는 법 | 대상 |
|---|---|
mcp__puppeteer | puppeteer 서버의 모든 도구 |
mcp__puppeteer__* | 마찬가지로 서버의 모든 도구(와일드카드) |
mcp__puppeteer__puppeteer_navigate | puppeteer 서버의 puppeteer_navigate 만 |
mcp__github__get_* | github 서버에서 get_ 로 시작하는 도구 |
서버 단위로도, 도구 단위로도 지정할 수 있습니다. 다만 허용 규칙의 와일드카드에는 조건이 있습니다. mcp__<서버 이름>__ 뒤에만 쓸 수 있습니다. mcp__* 처럼 서버 이름까지 흐리게 한 허용은 경고와 함께 무시된다고 적혀 있습니다.
또 하나 주의할 점은 커넥터의 이름입니다. Claude Code 가 스스로 가져오는 커넥터의 도구는 형태가 조금 다릅니다. mcp__claude_ai_<서버 이름>__<도구 이름> 이 된다고 합니다. 실제 이름을 확인한 다음 적는 것이 안전합니다.
—allowedTools 로 명시하기
고치는 방법은 쓸 도구를 --allowedTools 에 나열하는 것뿐이었습니다. 공식 문서에서는 “확인 없이 실행할 도구”를 지정하는 플래그라고 설명합니다.
형태는 이렇습니다. 서버 이름과 도구 이름은 예시입니다. 실제 이름은 환경마다 다르니 바꿔서 쓰세요.
claude -p "장보기 목록에 우유를 추가해 줘" \
--permission-mode acceptEdits \
--allowedTools \
"mcp__notion__search" \
"mcp__notion__fetch" \
"mcp__notion__query" \
"mcp__notion__create_pages" \
"mcp__notion__update_page"
저는 이 허용 목록을 봇의 코드 안에 넣어 두었습니다. 봇이 claude -p 를 호출할 때마다 같은 목록을 넘기는 방식입니다.
설정 파일에 적는 방법도 있습니다. settings.json 의 permissions.allow 에 같은 형식으로 나열합니다.
{
"permissions": {
"allow": ["mcp__notion__search", "mcp__notion__fetch"],
"deny": ["mcp__notion__delete_page"]
}
}
이쪽도 도구 이름은 예시입니다. 어디에 둘지는 취향일지도 모르겠습니다. 저는 “이 봇이 무엇을 할 수 있는지”를 코드에서 읽을 수 있는 편이 마음이 놓여서 코드 쪽에 두었습니다.
허용한 5가지 작업
서버째로 허용하면 설정은 한 줄로 끝납니다. 하지만 저는 그렇게 하지 않았습니다. 허용한 것은 5가지 작업 뿐입니다.
| 작업 | 허용 | 장보기 목록에서의 용도 |
|---|---|---|
| 검색 | 했다 | 목록이나 품목을 찾는다 |
| 가져오기 | 했다 | 페이지 내용을 읽는다 |
| 쿼리 | 했다 | 데이터베이스를 조건으로 거른다 |
| 생성 | 했다 | 새 품목을 추가한다 |
| 업데이트 | 했다 | ”다음에 살 것” 같은 상태를 바꾼다 |
| 삭제 | 하지 않았다 | 쓰지 않는다 |
| 위 5가지 외의 작업 | 하지 않았다 | 쓰지 않는다 |
장보기 목록을 읽고 쓰는 일은 이 5가지로 충분합니다. 삭제는 넣지 않았습니다. 품목을 지우고 싶을 때는 상태를 업데이트하면 되기 때문입니다.
허용을 넣은 뒤로 봇은 움직이게 됐습니다. 가족이 요청한 물건을 장보기 목록의 “다음에 살 것”에 넣고 보고해 주고 있습니다.
도구에 넘기는 권한을 쓰는 만큼만으로 좁히는 감각은 고정비 점검과 비슷하다고 느낍니다. 휴대폰 요금도 쓰는 만큼에 맞추면 낭비가 잘 보이죠.
허용을 최소한으로 좁히는 생각
왜 좁히는가. 이유는 봇에 들어오는 입력이 저만의 것이 아니기 때문입니다.
가족이 자유롭게 글을 보내옵니다. 말실수도 있고, 의도와 다르게 해석될 때도 있습니다. 그때 삭제까지 허용해 두면 되돌릴 수가 없습니다. 생성과 업데이트뿐이라면 틀려도 고칠 수 있습니다.
생각을 늘어놓으면 다음과 같습니다.
- 먼저 “읽는 작업”과 “쓰는 작업”으로 나눈다
- 쓰는 작업은 “추가·변경”과 “삭제”로 나눈다
- 삭제하는 작업은 필요해질 때까지 넣지 않는다
- 서버 단위 허용은 도구가 늘어나면 범위도 넓어진다는 점을 의식한다
공식 문서에는 규칙의 평가 순서도 적혀 있습니다. 순서는 deny(거부), ask(확인), allow(허용)입니다. 가장 먼저 걸린 것이 결과가 됩니다. 그래서 절대로 쓰게 하고 싶지 않은 도구는 deny 에 적는 것이 확실합니다. --disallowedTools 에 도구 이름을 그대로 적는 방법도 있습니다. 그 도구는 Claude 에게 보이지 않게 된다고 합니다.
비밀 정보를 다룰 때도 똑같이 “형식만 보고 안심하지 않는” 감각이 중요했습니다. 그 이야기는 gitleaks 가 놓친 2건에 대한 글에 적었습니다.
dontAsk 라는 선택지
공식 문서를 읽다가 하나 더 눈에 들어온 모드가 있었습니다. dontAsk 입니다.
dontAsk 는 확인이 필요한 작업을 모두 거부하는 모드입니다. 통과하는 것은 읽기와 미리 허용한 것뿐입니다. 공식 문서에도 허용 목록을 엄격하게 정한 CI 용으로 예시가 실려 있습니다.
claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"
제 봇은 지금으로서는 acceptEdits 그대로입니다. 파일 편집도 맡기고 싶은 상황이 있기 때문입니다. 다만 외부 서비스 조작만 한다면 dontAsk 쪽이 더 맞을지도 모르겠습니다.
덧붙여 권한 모드를 지정하지 않은 -p 실행은 주의가 필요합니다. 시작 모드가 환경이나 버전에 따라 달라집니다. 공식 문서에도 쓰고 싶은 모드를 명시하라고 적혀 있습니다.
설정 순서
앞으로 같은 일을 할 때의 흐름입니다.
- 봇에게 시키고 싶은 작업을 말로 적어 본다
- 그 작업에 필요한 MCP 도구를 고른다
- 실제 도구 이름을
mcp__<서버 이름>__<도구 이름>형태로 확인한다 --allowedTools나permissions.allow에 나열한다- 쓰게 하고 싶지 않은 도구가 있으면 deny 에 적는다
claude -p로 실제로 호출해 거부가 나오지 않는지 본다- 허용 목록은 작업이 늘어났을 때만 추가한다
도구 이름과 거부를 확인하는 법
도구 이름은 짐작으로 적으면 맞지 않습니다. 공식 문서에는 system/init 이라는 이벤트가 소개돼 있습니다. --output-format stream-json 의 맨 처음에 나오는 것입니다. 여기에 모델과 도구, MCP 서버 정보가 들어갑니다.
거부도 같은 출력에서 추적할 수 있습니다. 거부는 permission_denied 라는 시스템 메시지로 나옵니다. 마지막 결과 메시지에도 permission_denials 로 목록이 실린다고 합니다. 봇의 로그에 이것을 남겨 두면 원인 찾기가 빨라질 것 같습니다.
흔한 실수
- acceptEdits 로 하면 MCP 도구도 통과한다고 믿어 버린다
- 설정 파일의 bypassPermissions 가 플래그보다 강하다고 믿어 버린다
- 도구 이름을 짐작으로 적어서 실제 이름과 맞지 않는다
mcp__*같은 넓은 허용을 적어 놓고 무시되고 있다는 것을 알아차리지 못한다- 귀찮아져서 서버째로 전부 허용한다
- 무인 실행에서 bypassPermissions 를 써서 무엇이든 통과하는 상태로 만든다
위의 두 가지는 바로 제가 한 일입니다. 모드 이름에서 받는 인상과 실제로 통과하는 범위는 조금 달랐습니다.
bypassPermissions 에 대해서는 공식 문서가 강하게 주의를 줍니다. 격리된 컨테이너나 VM 에서 쓰는 것이 전제라고 합니다. 가족의 입력이 그대로 닿는 봇에는 좀 맞지 않는다고 생각합니다.
시작하기 전에 확인할 것
- 봇이 어떤 권한 모드로 시작되는가
- 시작 플래그와 설정 파일 중 어느 쪽에서 모드가 정해지는가
- 쓰게 하고 싶은 작업을 말로 적어 보았는가
- MCP 도구의 실제 이름을 확인했는가
- 삭제처럼 되돌릴 수 없는 작업을 뺐는가
- 거부된 도구를 로그에서 추적할 수 있는가
- 허용 목록을 둘 곳을 한 군데로 정했는가
자주 묻는 질문
Q. claude -p 에서 MCP 도구가 거부되는 이유는 무엇인가요?
-p 는 비대화 실행입니다. 확인에 대답할 상대를 마련하지 않은 경우, 확인이 필요한 작업은 거부된다고 공식 문서에 적혀 있습니다. 제 환경에서는 MCP 도구를 명시해서 허용할 때까지 반드시 거부됐습니다.
Q. acceptEdits 로 하면 MCP 도구도 통과하나요?
통과하지 않았습니다. 공식 설명으로는 acceptEdits 가 자동으로 통과시키는 것은 파일 편집과 일부 파일 조작 명령입니다. 그 밖에는 --allowedTools 나 permissions.allow 가 필요하다고 합니다.
Q. settings.json 에 bypassPermissions 를 적었는데 먹히지 않습니다.
시작할 때 --permission-mode 를 붙이고 있지 않은지 확인해 보세요. 공식 문서에는 이 플래그가 설정 파일의 defaultMode 를 덮어쓴다고 적혀 있습니다. 제 봇도 여기서 걸렸습니다.
Q. 서버 단위로 한꺼번에 허용할 수 있나요?
할 수 있습니다. mcp__<서버 이름> 이나 mcp__<서버 이름>__* 로 적으면 그 서버의 모든 도구가 대상입니다. 다만 삭제 같은 것도 포함됩니다. 저는 필요한 작업만 하나씩 적었습니다.
Q. —allowedTools 와 —tools 는 무엇이 다른가요?
--allowedTools 는 확인 없이 실행할 도구를 지정하는 것입니다. --tools 는 쓸 수 있는 내장 도구를 좁히는 플래그입니다. 공식 문서에는 --tools 가 MCP 도구에는 영향을 주지 않는다고 적혀 있습니다.
Q. 허용 규칙을 적어도 통과하지 않는 경우가 있나요?
있는 모양입니다. 조직이 ask 로 설정한 커넥터의 도구에는 허용 규칙이 먹히지 않는다고 공식 문서에 적혀 있습니다. 사용자의 조작이 필수로 지정된 MCP 도구도 마찬가지입니다. dontAsk 모드에서는 이것들이 거부됩니다.
Q. —bare 를 붙이면 어떻게 되나요?
--bare 는 MCP 서버 등의 자동 로드를 생략하는 모드입니다. 공식 문서에는 MCP 서버는 --mcp-config 로 넘긴 것만 연결된다고 나와 있습니다. 인증도 API 키 등이 전제가 되므로, 붙이기 전에 확인해 두는 편이 좋을 것 같습니다.
Q. 확인에 대답할 사람이 없다고 명시하는 방법이 있나요?
공식 문서에는 --permission-prompts none 이라는 플래그가 실려 있습니다. 확인이 필요한 작업을 거부하고, Claude 에게 다시 시도하지 말라고 전하는 것입니다. v2.1.259 이상이 필요하다고 합니다. 저는 아직 써 보지 않았습니다.
참고한 공식 정보
- Run Claude Code programmatically(Claude Code Docs)
- Choose a permission mode(Claude Code Docs)
- Configure permissions(Claude Code Docs)
- CLI reference(Claude Code Docs)
- All settings(Claude Code Docs)
- Configure permissions - Agent SDK(Claude Code Docs)
정리
claude -p 에서 MCP 도구가 거부된 것은 허용이 없었기 때문이었습니다. acceptEdits 는 파일 편집을 위한 모드입니다. 외부 서비스 조작은 따로 명시해야 했습니다.
허용은 쓰는 작업만으로 좁히는 것이 좋을 것 같습니다. 저는 5가지 작업에서 시작했습니다. 직접 만든 봇을 계속할지 말지 따져 본 내용은 Claude Max 사용률에 대한 글에 정리했습니다. 알림에서 AI 에게 상담하는 구조는 Claude 에 넘기는 버튼에 대한 글에도 적었습니다. 봇이 움직이지 않을 때는 먼저 시작 플래그를 들여다보세요.
이 글에는 제휴 광고가 포함되어 있습니다. 이 사이트의 링크를 통해 상품·서비스에 신청하시면 제휴사로부터 보상을 받을 수 있습니다. 또한 운영자는 라쿠텐 그룹 소속 직원으로, 사원 추천 프로그램을 통해 보상을 받는 경우가 있습니다. 기사 내용과 평가는 광고 유무와 관계없이 운영자의 실제 경험과 조사를 바탕으로 작성했지만, 위 관계를 이해하신 후 읽어 주시기 바랍니다. 자세한 내용은 면책조항·제휴 링크 안내를 참고해 주세요. 면책조항·제휴 링크 안내
이 글에는 기계 번역이 포함되어 있습니다. 정확한 조건은 라쿠텐 모바일 공식 사이트의 다국어 페이지에서 확인해 주세요.
라쿠텐 모바일의 통신 지역·전파 상황이 궁금하신 분은, 공식 전파 개선·조사 요청 양식 을 통해 문의하실 수 있습니다.