Skip to main content
Glama
README.md
# stay-search MCP

Airbnb(한국)와 야놀자 NOL의 숙소 검색 결과를 수집해 가격·시장 데이터를 분석하는 MCP 서버.
Claude가 직접 호출할 수 있는 툴 4개를 제공하고, 수집한 결과를 SQLite에 스냅샷으로 쌓아 추이를 본다.

## 사용

Claude Code / Desktop에 등록한 뒤 자연어로 물으면 된다.

```
9월 10~12일 서울 2인, Airbnb랑 야놀자 가격대 비교해줘
```

### 툴

| 툴 | 역할 |
|---|---|
| `search_stays` | 지역·날짜·인원으로 숙소 목록 수집 (+ 자동 스냅샷 저장) |
| `compare_prices` | 소스별 1박 가격 분포(중앙값·사분위·유형별) 비교 |
| `price_history` | 저장된 스냅샷에서 일자별 가격 중앙값 추이 조회 |
| `list_snapshots` | 어떤 지역·기간이 수집돼 있는지 목록 |

### 지역 지정

`region`에 `서울`·`제주`·`강릉` 같은 한글 지명을 그대로 넣으면 된다 — 주요 국내 지역은
Airbnb용 영문 슬러그로 자동 변환된다 (`src/sources/airbnb.ts`의 `KOREAN_SLUGS`).

변환 목록에 없는 지역은 `airbnbRegion`에 슬러그를 직접 지정한다:

```
airbnbRegion: "Sokcho--South-Korea"
```

> **왜 필요한가**: Airbnb는 URL 경로의 지역을 `City--Country` 슬러그로만 해석한다.
> 한글이나 자유 텍스트를 넘기면 **오류 없이** 전 세계 숙소를 섞어서 반환한다.
> 이걸 그대로 통계에 넣으면 조용히 틀린 시세가 나오므로, 결과 좌표가 5도 이상
> 흩어지면 에러를 던진다.

## 개발

```bash
npm install
npm run build

# 소스 어댑터만 단독 검증 (파서가 깨졌는지 가르는 첫 도구)
npx tsx scripts/probe-airbnb.ts "Seoul--South-Korea" 2026-09-10 2026-09-12 2
SOURCE=yanolja npx tsx scripts/probe-airbnb.ts 서울 2026-09-10 2026-09-12 2

# MCP 툴 수동 호출
npm run inspect
```

`scripts/probe-yanolja.ts`와 `probe-yanolja-api.ts`는 야놀자의 내부 검색 엔드포인트를
찾아낼 때 쓴 Playwright 진단 스크립트다. 야놀자가 API를 바꾸면 다시 돌려서 새 형태를 확인한다.
평상시 수집에는 브라우저가 필요 없다.

## 구조

```
src/index.ts          MCP 서버 · 툴 4개 등록
src/types.ts          두 소스를 맞춘 정규화 Listing 타입
src/sources/airbnb.ts 검색 페이지 HTML의 내장 JSON 파싱
src/sources/yanolja.ts universal-search API POST
src/store.ts          node:sqlite 스냅샷 저장/조회
src/stats.ts          1박 기준 가격 분포 집계
src/throttle.ts       호스트별 직렬 요청 + 최소 간격 + TTL 캐시
```

### 데이터 해석 시 주의

- **가격 기준**: Airbnb는 총액, 야놀자는 1박가로 표시된다. 모든 통계는 1박 기준으로 정규화한 값.
- **야놀자 광고 표기**: 검색 결과가 사실상 전량 `광고`로 표시된다. 제외하면 표본이 거의 남지
  않으므로 기본 포함이고, 필요하면 `excludeAds: true`로 걷어낸다.
- **Airbnb 가격 누락**: 일부 숙소는 가격이 비어 온다(해당 날짜 예약 불가 등). 통계에서 제외되며
  건수를 경고로 알린다.
- **야놀자 좌표 없음**: 검색 응답에 위경도가 없어 `lat`/`lng`는 null이다.

## 수집 정책

두 사이트 모두 이용약관상 자동 수집을 허용하지 않으며, 야놀자는 robots.txt로 `/discovery/`
경로를 차단하고 있다. 개인 분석 범위를 넘지 않도록 코드 레벨에서 강제한다:

- 호스트당 **직렬 요청** + 최소 간격 (Airbnb 1.5초, 야놀자 3초)
- 같은 조건 재조회는 **6시간 캐시**로 받아 중복 요청을 내지 않음
- 안티봇 우회 로직 없음 — 차단되면 그대로 에러를 올린다

상업적 재배포로 용도가 확장되면 야놀자는 [제휴 문의](https://start.yanolja.com),
Airbnb는 파트너 API 경로를 별도로 검토해야 한다.

TDQS

A4.1/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: search_stays fetches current listings, compare_prices compares price distributions between platforms, price_history reads historical trends, and list_snapshots shows available data. There is no overlap or ambiguity between them.

Naming Consistency4/5

Three tools follow the verb_noun pattern (search_stays, compare_prices, list_snapshots), but price_history is a noun phrase and breaks the pattern. While the names are still readable and clear, the inconsistency prevents a perfect score.

Tool Count5/5

With only 4 tools, the server is well-scoped for its purpose of stay search, price comparison, and historical trend analysis. Each tool earns its place and there is no bloat or redundancy.

Completeness4/5

The server covers the core workflow of searching, comparing, and tracking price history, with list_snapshots providing metadata. However, there is no way to retrieve the raw saved snapshot listings themselves, only the price history medians, which is a minor gap for users who want to inspect past search results in detail.

Maintenance

ActivityStale
ResponsivenessNo issues