← 목록
AI 2026-07-30 9KB 읽기 10분

크라우니AI 브라우저 MCP — claude-in-chrome 대체 1차 버전

개요

클로드 세션의 브라우저 자동화를 Chrome 확장 MCP(claude-in-chrome) 대신 크라우니 자산(CrownyAI, WKWebView 네이티브 앱) 으로 수행하도록 1차 버전을 완주했다.

기존에는 ~/.claude/scripts/크라우니AI검증.sh(원샷: 로드→dom/text/measure/console/shot 수집→종료)만 있어 click/type 을 계속 주고받는 지속 세션형 루프가 불가능한 갭이 있었다. 이번에 그 갭을 메웠다.

  • 네이티브 로컬 제어서버(127.0.0.1 전용) + MCP 서버(crowny-ai-browser) 2단 구조
  • 기존 한선씨/검증 자산 재사용(스냅샷 로직 공유 함수 승격, console 후킹 재사용)
  • 검증: 컴파일 → 앱 기동 → curl 전 명령 응답 → MCP stdio 종단 → 스크린샷 근거까지 실측

무엇을 했는지

1. 네이티브 로컬 제어서버 (native/crowny-ai-control.m, 신규)

  • 바인딩 127.0.0.1(INADDR_LOOPBACK) 전용 — 외부 노출 0. 접속 주소 이중 판정(bind 제한 + accept 후 재확인).
  • env 게이트: CROWNY_CTL=1 또는 CROWNY_CTL_PORT 없으면 포트조차 열지 않음(일반 사용자 실행 회귀 0).
  • 셸 주입 경로 0: 파일 전체에 system()/NSTask/체계() 호출 없음(크라우니메일·크라우니클라우드에서 반복 지적된 패턴 원천 차단). 토큰 옵션(CROWNY_CTL_TOKENX-Crowny-Token, 불일치=403).
  • 포트: crowny-ports.sh set browserctl 9841로 정식 등록(gateway.yaml SSOT). 점유 시 +1..+9 폴백, 실제 포트를 /tmp/crowny-ai-ctl.port에 기록(MCP가 읽는 계약).
  • 명령(POST JSON): /health /navigate /click /type /key /screenshot /read_page /console /tabs /select_tab
  • accept 루프는 전용 시리얼 큐, 웹뷰 접근은 전부 메인큐 홉(세마포어, 상한 8초) — 서버 스레드 영구 블록 방지.
  • 스크린샷은 검증 표면 로직을 공유 함수 caSnapshotWebViewPNG() 로 승격해 재사용(중복 구현 금지). console 은 window.__crownyVerifyConsole 후킹을 그대로 읽음(게이트만 caVerifyMode() || caCtlEnabled() 로 확장).

2. 주입 경로 정책 — 실측으로 확정

경로결과(실측)
CGEventPostToPid 마우스✗ 페이지 mousedown 리스너 미발화(앱 활성·번들 신원 무관) — 메모리 feedback_appkit_트래킹중_뷰재생성_이벤트단절 의 결론 재확증
CGEventPostToPid 키보드(유니코드)○ 백그라운드에서도 문자 삽입 도달. 단 포커스 선점 전제
CGEventPostToPid 기능키(Enter)△ 백그라운드에서 유실
JS 합성(elementFromPoint→pointer/mouse/click, value+input/change, KeyboardEvent+requestSubmit)✓ 전부 PASS, 포커스 무탈취
기본값(auto) = JS 합성, via:"cgevent" 는 명시 opt-in. 사용자 포커스를 훔치지 않는 헤드리스 루프가 기본이 됐다.

3. MCP 서버 (mcp/mcp-server.js, 신규 — 외부 의존 0)

  • 손수말이 stdio JSON-RPC 2.0(기존 크라우니 MCP 브리지 partner-tools/mcp-server.js 관용구 재사용 — SDK 의존 0).
  • 도구 5종: crowny_navigate · crowny_computer(click|type|key|screenshot) · crowny_read_page · crowny_read_console_messages · crowny_tabs(list|select).
  • 자동 기동: 제어서버 죽어 있으면 CrownyAI.app/Contents/MacOS/CrownyBrowserCROWNY_CTL=1 로 1회 spawn 후 0.5s×24회(12초) 폴링. 번들 실행파일을 쓰는 이유 = 번들 신원이 있어야 창 활성화가 된다.
  • screenshot 은 PNG 를 읽어 MCP image 컨텐츠(base64)로 반환, 나머지는 JSON 텍스트.
  • 등록: ~/.claude.json top-level mcpServers["crowny-ai-browser"] (백업 /tmp/claude.json.bak-mcp-*).

4. 한선씨 동반(정본)

파일자체시험
native/제어서버.한선 — 게이트·포트확정·토큰·경로정리·명령판정·주입경로·좌표변환·키매핑·응답코드·4상 실행판정42/42 티 ALL_PASS
mcp/브라우저MCP.한선 — 도구→경로 매핑·인자충족·기동판정(4상)·실행파일선택·응답종류·JSON-RPC 메서드분류32/32 티 ALL_PASS
학습 등록: crownycode-learn.sh add 브라우저제어서버_MCP_명령라우팅_주입경로4상 / 크라우니AI브라우저MCP_도구경로매핑_기동보증 (둘 다 lookup HIT 확인).

5. 세션 배선

  • ~/.claude/commands/크라우니코드.md — "🌐 브라우저 자동화 = crowny-ai-browser MCP(claude-in-chrome 대신)" 절 추가(도구표 + 주입경로 주의 + 원샷 검증.sh 와의 분기 기준).
  • ~/.claude/scripts/크라우니갑옷.shB2 브라우저 자동화 감지층 추가(UserPromptSubmit 훅 경유). "웹페이지 …클릭/스크린샷/자동화", claude-in-chrome, "크롬 확장/헤드리스" 패턴에 결정형 매칭 → 이 MCP 사용 지시 주입. 오탐 시험: "브라우저 좋아하는 색깔"=미발동 확인.

검증 결과 (실측 근거)

항목근거
컴파일make ai 에러 0(신규 경고 0, 기존 경고만)
앱 기동 + 리슨로그 [CrownyAI-CTL] 제어서버 리슨 127.0.0.1:9841 (pid=…, token=on/off)
curl 전 명령/health /navigate /read_page /screenshot /tabs /console /select_tab 전부 200 + 정상 JSON. 미지원 경로=400, 토큰 불일치=403
실제 네비게이션JS 클릭으로 example.com "Learn more" → https://www.iana.org/help/example-domains 이동 확증(health url 변화)
실제 입력 루프click→type→Enter → 폼 submit 핸들러 발화, 스크린샷 /tmp/mcp-final.pngSUBMITTED:MCP최종시험 육안 확인
MCP 종단stdio JSON-RPC 로 initialize/tools/list/5도구 호출 전부 성공, 앱 미기동 상태에서 자동 기동 후 동작(pid 신규)
번들 반영install-ai-app.sh + 심볼가드 strings … | grep -cE "crowny-ai-ctl.port|org.crowny.ai.ctl" = 2
포트 등록crowny-ports.sh get browserctl → 9841

관련 파일 경로

  • /Users/ef/CrownyBrowser/native/crowny-ai-control.m (신규 — 제어서버)
  • /Users/ef/CrownyBrowser/native/제어서버.한선 (신규 — 로직 정본, 42/42)
  • /Users/ef/CrownyBrowser/native/crowny-ai.h (§8 제어 표면 계약 추가 + caSnapshotWebViewPNG 선언)
  • /Users/ef/CrownyBrowser/native/crowny-ai-verify.m (스냅샷 공유 함수 승격, console 후킹 게이트 확장)
  • /Users/ef/CrownyBrowser/native/crowny-ai-content.m (console 후킹 호출 게이트 1줄)
  • /Users/ef/CrownyBrowser/native/crowny-ai-main.m (didFinishLaunching 말미 caCtlRegister+caCtlStart)
  • /Users/ef/CrownyBrowser/native/Makefile (AI_SRC 에 control.m 추가)
  • /Users/ef/CrownyBrowser/mcp/mcp-server.js (신규 — MCP 글루)
  • /Users/ef/CrownyBrowser/mcp/브라우저MCP.한선 (신규 — 로직 정본, 32/32)
  • /Users/ef/.claude.json (mcpServers crowny-ai-browser 등록)
  • /Users/ef/.claude/commands/크라우니코드.md · /Users/ef/.claude/scripts/크라우니갑옷.sh (세션 배선)
  • 검증 산출: /tmp/mcp-final.png(폼 submit 육안), /tmp/mcp-clean.png(AI홈), /tmp/ctl-shot1.png

잔여 이슈

  1. MCP 도구 노출은 세션 재시작 필요~/.claude.json 등록은 완료됐지만 현재 실행 중인 클로드 세션에는 mcp__crowny-ai-browser__* 도구가 로드되지 않는다. 새 세션에서 확인 필요.
  2. read_page 품질 1차 수준 — 선택자 기반 상호작용 요소만(a/button/input/select/textarea/role/onclick/contenteditable), 접근성 트리 미사용, iframe·shadow DOM 미탐색, 스크롤 밖 요소 좌표 보정 없음.
  3. 멀티탭/멀티윈도우 최소/tabs·/select_tab 는 첫 창만 등록(단일 창 기준). 새 탭 생성·닫기·창 선택 API 없음. CrownyAI 는 이미 멀티윈도우라 caCtlRegister 를 창 목록 전체로 확장하면 열림.
  4. CGEvent 마우스 미도달 — 진짜 네이티브 마우스 이벤트가 필요한 케이스(드래그, 네이티브 크롬 UI 조작)는 아직 불가. via:"cgevent" 는 좌표 변환까지만 검증됨(전역좌표 계산은 창이 화면 밖일 때 음수/화면초과 값이 나오는 미검증 구간 있음).
  5. 스크롤·대기(wait) 명령 없음 — 페이지 스크롤, "요소 나타날 때까지 대기"가 없어 긴 페이지는 read_page 좌표가 뷰포트 밖일 수 있다.
  6. 정리 사고(정직 기록): 검증 중 pkill사용자가 쓰던 CrownyAI 인스턴스를 함께 종료했다(세션 복원은 정상 종료 시에만 저장되므로 그 창의 탭 목록은 유실 가능). 다음부터 pid 지정 종료로 좁혀야 한다.
  7. crowny.org 네비게이션 미확인https://crowny.org 는 로드되지 않고 AI홈에 머물렀다(example.com·iana.org·file:// 은 정상). 기존 메모리 feedback_공개https000_헤어핀NAT_오진 과 같은 범주로 보이며 이번 트랙 코드 문제는 아니나 별도 확인 필요.
  8. RPN 정본(제어서버.한선·브라우저MCP.한선의 clike_to_rpn 변환) 미착수.