Naver Real Estate MCP
by hyunsuleedev
README.md
# naverestate-mcp
네이버 부동산 수집을 위한 **Playwright + MCP** 프로젝트.
## 목표
- 네이버 부동산 페이지를 실제 브라우저로 열고 public 흐름으로 접근
- UI 상호작용(필터, 스크롤, 중복매물 펼치기)을 Playwright로 수행
- 그 과정에서 발생한 내부 네트워크 응답을 **passive capture**
- 수집 결과를 정규화하고 MCP tool로 노출
## 설계 원칙
- 기본 모드는 **passive network capture**
- 브라우저가 실제로 발생시킨 요청/응답만 캡처
- 도구가 내부 API를 새로 직접 때리는 active harvester를 기본으로 두지 않음
- 브라우저 조작과 도메인 로직을 분리
- `jipxl`의 확장프로그램 구조는 버리고, 재사용 가능한 타입/정규화 로직만 선별 이관
- 로그인 없는 public 흐름을 기본으로 한다
- 캐시는 **아파트 이름 전체**를 key로 사용하고, 구/동은 metadata로만 저장한다
- 네이버 부동산이 새 Playwright 컨텍스트를 차단할 수 있으므로, 필요하면 **기존 Chrome에 CDP attach** 하는 경로를 지원한다
## 패키지 구조
- `packages/collector-core`
- 타입, 정규화, 그룹핑, 결과 모델
- `packages/playwright-driver`
- persistent context, response capture registry, collector driver
- `packages/mcp-server`
- MCP tool spec, server entry skeleton
## 현재 상태
현재 기본 수집은 실제 동작 확인 완료:
- TypeScript workspace 구조
- collector-core 타입/그룹핑/정규화
- playwright-driver 수집 동작 확인
- mcp-server tool 호출 가능
- 고덕그라시움(`complexNo=113907`) 기준 검증 완료
- 대표매물 수집 성공
- 중복매물 수집 성공
- JSON 저장 성공
### 최근 반영 사항
- 새 Playwright Chrome에서 네이버 부동산이 `404`로 튕기던 문제 수정
- `--disable-blink-features=AutomationControlled`
- `navigator.webdriver = false`
- `navigator.languages` 보정
- overview 응답 패턴 수정
- `/api/complexes/overview/{complexNo}` 캡처 지원
- `동일매물 묶기` 체크 로직 수정
- checkbox 직접 클릭 대신 label click / force setChecked fallback
- 중복매물 응답 파싱 수정
- `/api/articles?representativeArticleNo=...` 응답의 array payload 지원
## 현재 기본 수집 전제
- `collectDuplicates`는 옵션으로 둔다
- `true`: 중복매물까지 수집
- `false`: 대표매물 목록까지만 수집
- 검색/수집 기본 정렬은 **항상 최신순(`dateDesc`)** 으로 고정한다
- 캐시는 아파트 이름 전체 기준으로 저장한다
## 실행 방법
### 1) 기본 실행 (권장 시작점)
새 Playwright persistent Chrome 프로필로 실행한다.
```bash
cd /Users/hyunsu/.openclaw/workspace/naverestate-mcp
npm run build
node packages/mcp-server/dist/index.js
```
현재는 anti-detection 보정이 들어가 있어서, 기본 persistent 실행만으로도 네이버 부동산 상세 진입이 가능하다.
### 2) CDP attach 모드
환경변수로 기존 Chrome 디버깅 엔드포인트를 넘기면, 새 Playwright 프로필 대신 기존 브라우저에 붙을 수 있다.
```bash
export NAVER_CDP_ENDPOINT_URL=http://127.0.0.1:9222
node packages/mcp-server/dist/index.js
```
권장 용도:
- 이미 사람이 열어둔 실제 Chrome 세션을 재사용하고 싶을 때
- Playwright 프로필과 실제 사용자 브라우저 동작 차이를 비교할 때
## MCP 도구
현재 stdio MCP 서버에서 제공하는 도구는 아래 4개다.
| Tool | 설명 |
|------|------|
| `naver_search_complex` | 키워드로 단지 자동완성 후보 검색 |
| `naver_resolve_complex` | 후보를 `complexNo`로 resolve하고 cache 저장 |
| `naver_collect_complex` | 단지 상세에서 대표매물 + 중복매물 수집 |
| `naver_get_last_result` | 마지막 수집 JSON 다시 가져오기 |
## 호출 예시
### Search
```json
{
"name": "naver_search_complex",
"arguments": {
"keyword": "고덕그라시움"
}
}
```
### Resolve
```json
{
"name": "naver_resolve_complex",
"arguments": {
"apartmentName": "고덕그라시움",
"fullLabel": "고덕동 고덕그라시움"
}
}
```
### Collect
```json
{
"name": "naver_collect_complex",
"arguments": {
"filter": {
"complexNo": "113907",
"tradeTypes": ["A1"]
},
"collectDuplicates": true
}
}
```
### Get last result
```json
{
"name": "naver_get_last_result",
"arguments": {}
}
```
## 현재 결과 모델 요약
수집 결과 JSON은 아래 필드를 포함한다.
- `complex`: 단지 개요
- `articlePages`: 대표매물 목록 원본 응답들
- `duplicateResponses`: 중복매물 원본 응답들
- `articles`: 대표매물 정규화 목록
- `duplicateGroups`: `representativeArticleNo` 기준 중복매물 묶음
- `listingGroups`: 대표매물 + duplicates 합친 최종 구조
## 검증된 샘플
고덕그라시움(`complexNo=113907`) 기준 최근 검증 결과:
- 대표매물 `212`
- 중복 묶음 `89`
- JSON 저장 성공
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessSyncing