Chrome DevTools MCP, 오류 조사와 폼 입력의 권한을 나누는 법
AI에게 주문 저장 오류를 조사시키려는데, 재현하다가 실제 주문이 한 번 더 들어갈까 걱정이다. 콘솔 기록은 읽게 하고 폼 입력은 막으려면 무엇을 꺼야 할까?

- Console 오류와 네트워크 요청은 입력 도구를 꺼도 조회할 수 있으며, 직접 코드 평가도 따로 제한할 수 있다.
- 폼 입력과 제출 재현에는 입력 도구가 필요하다. 클릭을 허용하면 연결된 계정으로 저장 요청이 나갈 수 있다.
- 도구 제한·브라우저 프로필·접속 URL은 각각 따로 설정한다. 어느 한 옵션도 브라우저 전체를 읽기 전용으로 만들지는 않는다.
오류를 읽는 일과 오류를 다시 일으키는 일
Chrome DevTools MCP에 이미 발생한 오류를 읽게 한다면 버튼을 누를 권한까지 줄 필요는 없다. Console 메시지와 네트워크 요청을 조회하는 도구가 따로 있기 때문이다. 반면 가입 양식을 채우고 제출했을 때 생기는 오류를 재현하려면 입력·클릭이 필요하다. 두 작업은 같은 브라우저에서 진행돼도 필요한 조작 범위가 다르다.
공식 도구 목록은 입력, 이동, 네트워크, 디버깅 등을 나눠 제공한다. 설정 문서의 도구 분류 옵션은 이 묶음을 서버에서 제외한다. 자연어로 “누르지 마”라고 요청하는 데서 그치지 않고, 사용하지 않을 입력 도구를 제공 목록에서 뺄 수 있다.
| 맡길 작업 | 필요한 기능 | 실제로 생기는 차이 |
|---|---|---|
| 이미 발생한 오류 조사 | 화면·텍스트, Console, 네트워크 기록 조회 | 입력 도구를 끈 상태에서 기록을 읽는다. 제출을 다시 누르지는 못한다. |
| 폼 오류 재현 | 위 조회 기능과 입력·클릭 | 값을 넣고 제출해 새 요청을 만든다. 테스트 계정의 데이터가 바뀔 수 있다. |
| 로그인한 업무 서비스 조사 | 그 계정이 열린 브라우저 연결 | 기존 로그인 상태를 이어받는다. 계정이 볼 수 있는 화면·응답도 조사 대상이 된다. |
예를 들어 주문 화면에서 저장 실패가 발생했다면, 먼저 실패 요청의 응답과 같은 시각의 오류를 읽는 작업을 맡길 수 있다. 기록만으로 원인을 좁히지 못했을 때 재현 단계로 넘어가면 된다. 첫 단계부터 “주문 화면을 고쳐줘”라고 넓게 맡기면 조사와 재제출이 한 작업에 섞인다.
입력 도구와 직접 코드 평가를 함께 줄인다
--no-javascript-evaluation은 AI가 제공한 JavaScript를 직접 실행하는 경로를 막는다. 일반 모드의 evaluate_script와 slim 모드의 evaluate가 비활성화되고, navigate_page에 초기화 코드를 넣는 initScript도 사용할 수 없게 된다. javascript:·data:·vbscript: URL로 직접 이동하는 경로도 제한한다.
페이지 제목을 읽기 위해 짧은 코드를 실행하는 경우에도 평가 도구는 막힌다. 서버가 코드의 의도를 읽어 조회는 허용하고 수정만 금지하는 방식이 아니기 때문이다. 화면의 텍스트는 take_snapshot, 화면 모습은 take_screenshot으로 가져올 수 있다. 스냅샷은 접근성 트리를 바탕으로 만든 텍스트이므로 페이지의 모든 JavaScript 변수나 내부 상태를 대신 보여 주지는 않는다.
클릭과 입력까지 제외하려면 --category-input=false를 추가한다. 이 분류에는 click, fill, fill_form, press_key, type_text, 파일 업로드 등이 들어 있다. 클릭만 금지하고 Enter 키로 제출하는 길을 남기는 대신, 입력 도구 묶음을 제외하는 설정이다.
사이트 자체의 JavaScript는 계속 실행된다. 공식 저장소 이슈 #2726에서 ITSMERNB는 1.8.0의 직접 평가를 껐어도 페이지에 있는 JavaScript 링크를 클릭하면 코드가 실행됐다고 보고했다. 현재 설정 문서도 허용된 클릭·타이핑이 일으키는 페이지 코드는 계속 동작한다고 명시한다.
DevTools 화면 자체를 조작하는 --experimental-devtools도 직접 평가 제한과 별도로 작동한다. 이를 켜면 Console UI에 코드를 입력하는 경로가 열리고, 직접 평가 제한은 그 경로를 막지 않는다. 기본값은 꺼짐이며, 오류 메시지를 읽는 작업에는 이 실험 기능을 켤 필요가 없다.
오류 조회에 쓸 설정과 실제 조사 순서
다음은 일반적인 MCP 클라이언트의 서버 등록 예제다. 공식 시작 안내에 맞춰 Node.js LTS, npm, 지원되는 Chrome이 있는 환경에서 실행한다. 이미 서버를 등록했다면 중복 서버를 더 만들기보다 해당 항목의 실행 인수를 바꾼다.
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y", "chrome-devtools-mcp@latest",
"--no-javascript-evaluation",
"--category-input=false",
"--category-emulation=false",
"--category-performance=false",
"--category-memory=false",
"--experimental-devtools=false"
]
}
}
} 이 예제는 입력과 직접 평가뿐 아니라 화면·네트워크 조건 변경, 성능 측정, 메모리 도구도 제외한다. Console과 네트워크 조회가 속한 분류는 남긴다. 일반 도구 목록을 사용하는 예제이므로 도구 세트를 크게 줄이는 --slim을 함께 넣지 않는다.
페이지 이동 분류는 남겨 두었다. 여기에는 새 URL 열기뿐 아니라 list_pages와 select_page도 포함돼 있어, 분류 전체를 끄면 열린 탭을 나열하고 고르는 기능까지 빠진다. 또한 디버깅 분류에는 다시 로드할 수 있는 lighthouse_audit도 있다. 따라서 이 설정은 완성된 읽기 전용 프리셋이 아니다. 조회만 허용하려면 클라이언트가 지원하는 도구 승인 기능으로 개별 호출과 인수를 제한하는 단계가 남는다.
- 연결된 Chrome에서 오류가 발생한 페이지를 그대로 둔다. 아직 기록이 없다면 테스트 데이터로 오류를 재현한 뒤 조회를 맡긴다.
list_pages에서 대상 탭의 ID를 찾는다. 그 값을pageId로 지정해take_snapshot과list_console_messages를 호출한다. 뒤의 메시지·요청 상세 조회에도 같은 페이지 ID를 전달한다.list_console_messages의 메시지 ID를get_console_message에 넘겨 상세 오류를 읽는다.list_network_requests에서 실패한 요청을 찾고, 그 요청 ID로get_network_request를 호출해 응답을 읽는다.
목록 조회 도구는 기본적으로 마지막 페이지 이동 이후의 기록을 반환한다. 이전 이동에서 보존된 기록이 필요하면 list_console_messages의 includePreservedMessages 또는 list_network_requests의 includePreservedRequests를 켠다. 문서상 보존 범위는 최근 세 번의 이동이다. 목록에 없는 과거 요청은 이 절차만으로 되살릴 수 없으므로, 기록이 부족할 때는 연결을 유지한 채 테스트 데이터로 다시 재현한다.
폼 재현에는 무엇을 다시 허용해야 하나
가입 오류가 특정 입력값에서만 발생한다면 조회 기록만으로는 재현할 수 없다. 그때는 실행 인수를 --category-input=true로 바꿔 입력 분류를 다시 켠다. 새 스냅샷에서 입력란의 UID를 받아 fill_form으로 값을 넣고, 화면이 바뀌면 새 스냅샷에서 제출 버튼의 UID를 얻는다. UID는 페이지 요소 식별자이므로 이전 화면의 값을 바뀐 화면에 그대로 적용하지 않는다.
직접 코드 평가는 계속 꺼 둬도 된다. 입력·클릭 도구만으로 재현 가능한 화면이라면 페이지에 별도 스크립트를 넣을 이유가 없다. 예를 들어 테스트용 가입 폼에 이미 등록된 이메일을 넣고 제출하면, 웹앱의 원래 이벤트 처리 코드가 요청을 보낸다. 이어서 네트워크 응답과 화면의 오류 표시를 읽어 “서버가 거절했는가, 화면이 거절 이유를 보여 줬는가”를 연결할 수 있다.
입력만 허용하고 저장은 막고 싶은 상황은 더 까다롭다. 입력 중 자동 저장하는 앱이라면 제출 버튼을 누르기 전에 서버 데이터가 바뀐다. 이 경우 “Submit을 누르지 말라”는 조건으로 저장을 막을 수 없다. 테스트 계정·테스트 데이터에서 재현하거나, 서비스 자체에서 변경 권한이 없는 계정을 사용해야 한다. 후자는 서버에서 변경 요청을 거절하는 방식이므로 일반 사용자의 저장 흐름을 끝까지 재현하는 작업에는 맞지 않는다.
로그인 상태는 연결한 프로필에서 따라온다
고급 사용 문서에 따르면 기본 실행은 MCP 전용 Chrome 프로필을 사용하며, 이 프로필은 실행 사이에 지워지지 않는다. 처음 별도 창이 떴다는 사실만으로 다음 실행도 로그인 정보가 없는 새 세션이라고 볼 수 없다. 해당 프로필에서 로그인했다면 후속 실행에도 그 상태가 남을 수 있다.
--isolated는 브라우저를 닫을 때 정리되는 임시 프로필을 쓰는 옵션이다. 이전 로그인 상태가 필요 없는 공개 화면 재현에 적합하다. 다만 임시 프로필 안에서 운영 계정으로 로그인해 저장 버튼을 누르면 서버의 데이터는 바뀐다. 프로필을 나중에 지우는 것은 서버에 전송한 변경을 되돌리는 기능이 아니다.
반대로 이미 로그인한 Chrome을 그대로 조사하려면 Chrome 144 이상에서 chrome://inspect/#remote-debugging으로 원격 디버깅을 켜고 --autoConnect로 연결하는 경로가 있다. 브라우저의 연결 허용 창에서 승인하며, 공식 문서상 서버는 선택된 프로필의 열린 창 전체에 접근한다. 사용자가 보고 있던 탭 하나만 연결되는 방식이 아니다.
로그인 오류처럼 계정 상태가 핵심일 때는 이 연결 방식이 유용하다. 주문·관리자 작업처럼 계정의 변경 권한이 큰 경우에는 조사할 계정을 분리하는 편이 작업 범위를 명확하게 만든다. 프롬프트의 “조회만”과 서비스가 부여한 계정 권한은 서로 다른 곳에서 적용된다.
URL 제한은 요청 목적지에 적용된다
조사 대상 사이트 밖으로 이동하지 않게 하려면 --allowed-url-pattern으로 목적지를 제한할 수 있다. 이 허용 목록은 Chrome 149 이상에서 제공되며, 페이지 이동뿐 아니라 하위 리소스 요청에도 적용된다. 예컨대 --allowed-url-pattern=https://staging.example.com/*은 예시 호스트의 HTTPS 기본 포트에 맞춘 패턴이다. 실제 서비스의 호스트로 바꿔야 한다.
화면과 API의 호스트가 다르면 화면 주소만 허용해도 API 호출이 막힐 수 있다. 별도 인증 서버나 CDN을 쓰는 서비스도 마찬가지다. 이 상태에서 생긴 로그인 실패나 빈 화면을 원래 앱의 장애로 판정하면 원인이 뒤바뀐다. 필요한 API·인증·리소스 주소를 네트워크 기록에서 찾아 조사 범위에 포함하는 순서가 필요하다.
허용된 호스트 안의 저장 요청은 URL 허용 목록만으로 조회 요청과 구별되지 않는다. 따라서 목적지 제한은 폼 제출 권한이나 계정의 쓰기 권한을 대신하지 않는다. 운영 주소와 테스트 주소를 분리할 때는 유용하지만, 같은 주소로 읽기·쓰기를 처리하는 앱에 자동으로 읽기 전용 동작을 만들어 주지는 않는다.
설정 변경 뒤에는 제공 도구와 연결 대상을 확인한다
일반적인 실행 인수를 바꾼 뒤에는 클라이언트에서 해당 MCP 서버를 다시 시작해 새 인수로 연결한다. 입력 분류를 껐다면 클릭·폼 입력 도구가 제공되지 않아야 하고, 직접 평가를 껐다면 평가 도구도 빠져야 한다. 목록이 그대로라면 다른 이름으로 등록된 서버나 이전 프로세스를 보고 있는지부터 확인할 수 있다.
별도 JSON 설정 파일에는 categoryInput 같은 camelCase 키를 사용한다. 명령행 인수는 설정 파일보다 우선한다. --watchConfig를 켜면 지원되는 도구 설정은 재시작 없이 갱신되지만, 잘못된 JSON은 오류를 기록하고 이전 설정을 유지한다. 브라우저 실행·접속에 쓰는 옵션은 재시작이 필요하다.
실시간으로 URL 허용 목록을 좁혀도 이미 연결된 탭이 자동으로 모두 분리되는 것은 아니다. 공식 문서는 이후 요청과 이동에 새 제한을 적용하되, 이미 열린 대상은 연결된 채 남는다고 설명한다. 연결 범위를 바꾼 작업에서는 남아 있는 탭과 프로필도 다시 맞춰야 한다. 설정 파일과 상위 디렉터리를 에이전트가 수정할 수 없게 두라는 공식 지침도 같은 이유다. 실행 중인 에이전트가 제한 자체를 고칠 수 있다면 파일에 적힌 권한은 고정된 제한이 되지 못한다.