Claude Code에서 Notion MCP를 연결하면 페이지 읽기뿐 아니라 생성, 수정, 삭제까지 전부 가능하다는 걸 알고 계셨나요? 저는 /mcp 커맨드로 Notion을 연결한 뒤 도구 목록을 보고서야 write 권한이 포함되어 있다는 걸 깨달았어요. 읽기만 하고 싶었는데 말이죠.
문제: Notion MCP는 기본적으로 read+write
Claude Code에서 Notion MCP를 연결하는 가장 간편한 방법은 공식 HTTP endpoint를 쓰는 거예요.
{ "notion": { "type": "http", "url": "https://mcp.notion.com/mcp" }}이렇게 연결하면 OAuth 인증을 거쳐 Notion workspace에 접근할 수 있어요. 문제는 이 방식이 페이지 조회뿐 아니라 생성(API-post-page), 수정(API-patch-page), 삭제(API-delete-a-block) 도구까지 전부 노출한다는 거예요. 공식 README에서도 이런 경고를 하고 있어요.
“While we limit the scope of Notion API’s exposed (for example, you will not be able to delete databases via MCP), there is a non-zero risk to workspace data by exposing it to LLMs.”
MCP 서버 자체가 database 삭제 같은 일부 위험한 작업은 이미 차단하고 있지만, 페이지 생성이나 수정은 여전히 가능하거든요. 실수로 Claude가 Notion 페이지를 수정하는 상황이 충분히 생길 수 있죠. 공식 문서에서도 보안이 중요한 사용자에게는 Integration의 Capabilities를 제한하라고 권장하고 있어요.
세 가지 선택지
read-only로 제한하는 방법을 세 가지 검토해 봤어요.
1. Claude Code permissions에서 deny 설정
settings.json의 permissions에 write 계열 도구를 하나씩 deny하는 방식이에요.
{ "permissions": { "deny": [ "mcp__notion__API-post-page", "mcp__notion__API-patch-page", "mcp__notion__API-update-a-block", "mcp__notion__API-delete-a-block" ] }}간단하긴 한데, Notion MCP 서버가 도구를 추가하면 deny 목록도 계속 업데이트해야 해요. 새로운 write 도구가 생겨도 모르고 지나칠 수 있거든요.
2. tool-filter-mcp proxy
Perplexity MCP에서 이미 쓰고 있는 @respawn-app/tool-filter-mcp로 write 도구를 필터링하는 방법이에요. 다만 현재 Notion이 HTTP 타입이라 stdio 기반인 tool-filter를 직접 끼울 수 없어요. mcp-remote로 HTTP → stdio bridge를 만들고 그 위에 tool-filter를 씌워야 하는데, proxy가 2중으로 걸려서 좀 무거워요.
3. Notion Integration을 read-only로 생성
Notion Integration 자체의 Capabilities를 Read content만 허용하고, @notionhq/notion-mcp-server (stdio 방식)로 전환하는 방법이에요. 서버 레벨에서 write가 원천 차단되니까 가장 확실하죠.
결론부터 말하면요, 3번이 제일 깔끔했어요.
설정 방법
Notion Internal Integration 생성
- notion.so/profile/integrations에 접속해요.
- New integration을 클릭하고 이름을 지정해요 (예:
Claude Code Read-only). - Configuration 탭에서 Capabilities를 Read content만 체크해요. Insert content, Update content, Delete content는 전부 해제하면 돼요.
- Secrets 탭에서
ntn_****형식의 API token을 복사해요.
여기서 잠깐, 이게 중요한데요. 현재 쓰고 있는 mcp.notion.com (OAuth 방식)에서는 이 Capabilities 설정을 할 수 없어요. 반드시 Internal Integration token 방식으로 전환해야 해요.
페이지에 Integration 연결
읽고 싶은 Notion 페이지에서 ⋯ → Connect to → 방금 만든 integration을 선택해요. 상위 페이지에 연결하면 하위 페이지도 자동으로 접근 권한이 생기거든요.
Claude Code MCP 설정 변경
.claude.json의 프로젝트별 mcpServers 설정을 변경해요.
변경 전 (HTTP, OAuth):
{ "notion": { "type": "http", "url": "https://mcp.notion.com/mcp" }}변경 후 (stdio, API token):
{ "notion": { "command": "npx", "args": ["-yq", "@notionhq/notion-mcp-server"], "env": { "NOTION_TOKEN": "ntn_your_token_here" } }}설정을 바꾼 뒤 Claude Code를 재시작하면 read-only Notion MCP가 적용돼요. /mcp 커맨드로 연결 상태를 확인할 수 있어요.
OAuth vs API token, 뭐가 다를까요?
| 항목 | OAuth (mcp.notion.com) | API token (@notionhq/notion-mcp-server) |
|---|---|---|
| 인증 방식 | 브라우저 OAuth flow | Integration token (ntn_***) |
| 권한 제어 | 불가 (full access) | Integration Capabilities에서 세밀하게 제어 |
| 전송 방식 | HTTP (Streamable HTTP) | stdio (기본) 또는 HTTP |
| 페이지 접근 | OAuth로 승인한 전체 workspace | Integration에 연결한 페이지만 |
API token 방식이 권한 범위도 좁히고, 접근할 수 있는 페이지도 명시적으로 제한할 수 있어서 보안 관점에서 더 나아요.
결과
이제 Claude Code에서 Notion 페이지를 읽을 수는 있지만, 실수로 수정하거나 삭제할 위험은 없어요. Integration Capabilities에서 Read content만 허용했기 때문에 서버 자체에서 write 요청을 거부하거든요. Claude Code의 permission 설정에 의존하지 않아도 되니까 훨씬 안전해요.