MCP 서버 보안 체크리스트: AI 에이전트에 도구 권한을 줄 때 반드시 나눠야 할 경계
요약: MCP(Model Context Protocol)는 AI 애플리케이션이 파일, 데이터베이스, 검색, 업무 도구에 연결되는 표준 인터페이스입니다. 공식 문서도 MCP를 “AI 애플리케이션을 외부 시스템에 연결하는 오픈 표준”으로 설명합니다. 문제는 연결이 쉬워질수록 권한 사고도 쉬워진다는 점입니다. MCP 서버를 만들 때는 기능보다 권한 경계를 먼저 설계해야 합니다.
MCP가 편한 이유가 곧 위험한 이유다
MCP는 개발자에게 매력적입니다. 한 번 서버를 만들어두면 Claude, ChatGPT, VS Code, Cursor 같은 여러 클라이언트에서 같은 도구를 쓸 수 있습니다. 파일 검색, DB 조회, 사내 문서 검색, 배포 상태 확인, 티켓 생성 같은 기능을 표준 방식으로 노출할 수 있습니다. 팀 입장에서는 “AI 에이전트가 우리 시스템을 이해하고 직접 도와준다”는 장점이 큽니다.
하지만 보안 관점에서는 상황이 달라집니다. MCP 서버는 모델에게 단순 정보를 주는 레이어가 아니라 실제 행동을 가능하게 하는 레이어입니다. 도구가 read_customer_table이면 개인정보가 나갈 수 있고, run_sql이면 데이터가 바뀔 수 있으며, create_ticket이면 외부 시스템에 기록이 남습니다. send_slack_message, deploy_service, delete_file 같은 도구는 더 직접적인 영향을 줍니다.
따라서 MCP 서버 설계의 첫 질문은 “어떤 도구를 만들까”가 아닙니다. “이 도구가 실패하거나 악용되면 무엇이 망가지는가”여야 합니다.
도구는 read, suggest, write, execute로 나눠라
가장 쉬운 실수는 모든 MCP 도구를 같은 권한으로 취급하는 것입니다. 이름만 다를 뿐 모두 “AI가 호출할 수 있는 함수”로 보면 안 됩니다. 최소한 네 단계로 나눠야 합니다.
첫째, read 도구입니다. 파일 읽기, 문서 검색, 이슈 조회, 로그 조회처럼 상태를 바꾸지 않는 도구입니다. 그래도 안전하다고 단정하면 안 됩니다. 로그에는 토큰, 이메일, 고객 데이터가 들어 있을 수 있습니다. read 도구도 마스킹과 범위 제한이 필요합니다.
둘째, suggest 도구입니다. SQL을 실행하지 않고 SQL 초안을 만들거나, PR을 생성하지 않고 diff 제안을 반환하는 도구입니다. 모델이 틀려도 실제 시스템은 바뀌지 않습니다. 개발 초기에는 write 도구보다 suggest 도구를 먼저 만드는 편이 안전합니다.
셋째, write 도구입니다. 티켓 생성, 문서 수정, 설정 변경처럼 상태를 바꾸는 도구입니다. 이 단계부터는 승인, 감사 로그, rollback 정보가 필요합니다.
넷째, execute 도구입니다. 배포, 마이그레이션, 결제 취소, 계정 비활성화처럼 외부 영향이 크거나 되돌리기 어려운 작업입니다. execute 도구는 기본적으로 자동 호출을 금지하고 사람 승인을 요구하는 것이 맞습니다.
이 네 단계가 분리되어 있으면 정책도 명확해집니다. read는 제한된 범위에서 자동 허용, suggest는 자동 허용, write는 조건부 승인, execute는 명시 승인처럼 운영할 수 있습니다.
입력 검증은 프롬프트가 아니라 스키마에서 해야 한다
MCP 도구 설명에 “위험한 명령은 실행하지 마세요”라고 적는 것만으로는 부족합니다. 모델은 자연어를 해석하고, 사용자는 모호하게 요청하며, 외부 문서에는 prompt injection이 숨어 있을 수 있습니다. 권한 검사는 프롬프트가 아니라 서버 코드와 스키마에서 해야 합니다.
예를 들어 run_sql 도구를 제공한다면 아래 조건이 필요합니다.
- SELECT만 허용할지, INSERT/UPDATE/DELETE도 허용할지 분리.
- 접근 가능한 테이블 allowlist.
- 최대 row limit.
- 실행 timeout.
- 개인정보 컬럼 마스킹.
- 트랜잭션 read-only 설정.
- 쿼리 plan 검사 또는 금지 키워드 검사.
파일 도구라면 path traversal을 막아야 합니다. ../../ 같은 경로, symlink, 숨김 디렉터리, 홈 디렉터리 전체 접근을 제한해야 합니다. HTTP fetch 도구라면 내부망 주소, metadata endpoint, localhost 접근을 막아야 합니다. 메시지 발송 도구라면 대상 채널 allowlist와 rate limit이 필요합니다.
핵심은 “모델을 믿지 않는 구조”입니다. 모델이 좋은 의도로 잘못된 인자를 넣어도 서버가 거절해야 합니다.
감사 로그는 디버깅용이 아니라 책임 경계다
MCP 서버가 실제 업무 시스템에 연결되면 “누가 무엇을 했는가”를 남겨야 합니다. 여기서 누군가는 모델이 아니라 사용자와 세션입니다. 나중에 사고가 났을 때 “AI가 그랬다”는 말은 책임 경계가 아닙니다. 어떤 사용자의 어떤 요청에서 어떤 도구가 어떤 인자로 호출됐고, 서버가 어떤 결과를 반환했는지 남아야 합니다.
권장 로그 필드는 다음과 같습니다.
- user_id 또는 workspace_id.
- session_id.
- tool_name.
- risk_level: read, suggest, write, execute.
- input_hash와 주요 파라미터.
- approval_id 또는 approver.
- result_status.
- affected_resource.
- timestamp와 latency.
단, 로그에 원문 prompt나 개인정보를 그대로 저장하면 또 다른 위험이 됩니다. 민감 데이터는 hash, redaction, 샘플링을 적용해야 합니다. 디버깅에 필요한 정보와 보관하면 안 되는 정보를 분리해야 합니다.
OAuth와 토큰 범위는 “나중에”가 아니라 MVP부터 넣어라
초기 MCP 서버를 만들 때 가장 흔한 편법은 하나의 관리자 토큰으로 모든 사용자 요청을 처리하는 것입니다. 빠르게 데모를 만들 수는 있지만, 운영으로 가면 바로 막힙니다. 사용자별 권한 차이를 반영할 수 없고, 퇴사자 접근 차단도 어렵고, 감사 로그도 부정확해집니다.
가능하면 사용자 또는 워크스페이스 단위 인증을 MVP부터 넣어야 합니다. OAuth를 쓰든 사내 토큰을 쓰든 원칙은 같습니다.
- 토큰은 필요한 scope만 가진다.
- refresh와 revoke 경로가 있다.
- 사용자 권한이 바뀌면 MCP 서버에도 반영된다.
- 관리자 권한 도구는 별도 승인 흐름을 탄다.
- 토큰은 로그에 남지 않는다.
MCP가 여러 클라이언트에서 쓰이는 표준이 될수록 인증과 권한 설계는 더 중요해집니다. 서버 하나를 잘못 열면 여러 AI 클라이언트에서 동시에 위험이 퍼질 수 있습니다.
오늘 적용할 체크리스트
- MCP 도구를 read, suggest, write, execute 네 단계로 분류합니다.
- write와 execute 도구는 기본 자동 호출을 금지합니다.
- SQL, 파일, HTTP, 메시지 도구에 allowlist와 timeout을 둡니다.
- path traversal, localhost/internal network fetch, 대량 데이터 조회를 차단합니다.
- 도구 호출마다 user_id, session_id, tool_name, risk_level, approval_id를 기록합니다.
- 로그에는 민감 원문을 저장하지 않고 hash 또는 redaction을 적용합니다.
- 관리자 토큰 하나로 모든 요청을 처리하지 않습니다.
- OAuth 또는 사용자별 scope를 MVP부터 고려합니다.
- prompt instruction이 아니라 서버 코드에서 최종 권한 검사를 수행합니다.
MCP의 장점은 연결성을 표준화하는 것입니다. 하지만 표준 연결은 표준 사고 경로가 될 수도 있습니다. 기능을 빨리 붙이기 전에 도구 위험도를 나누고, 서버가 거절할 수 있는 구조를 먼저 만드는 것이 안전한 MCP 운영의 출발점입니다.