Claude Code에서 Notion MCP를 연결하면 페이지 읽기뿐 아니라 생성, 수정, 삭제까지 전부 가능합니다. 저는 /mcp 커맨드로 Notion을 연결한 뒤 도구 목록을 보고서야 write 권한이 포함되어 있다는 걸 알았습니다. 읽기만 필요했는데 말이죠. 이 글에서는 Notion MCP를 read-only로 제한하기 위해 검토한 선택지들과 최종 설정 과정을 정리합니다.
문제: 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번을 선택했습니다. 클라이언트 쪽 설정에 의존하는 1번이나 proxy를 겹겹이 쌓는 2번과 달리, 권한 자체를 서버에서 제한하는 방식이라 관리할 것이 없었기 때문입니다.
설정 방법
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 방식과 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 설정에 의존하지 않아도 되니 구성도 한결 단순해졌습니다.