Skip to main content
Glama
yongkyu4803

govtpress-mcp

by yongkyu4803
README.md
# govtpress-mcp

대한민국 12개 정부기관 보도자료를 조회하는 **읽기 전용 MCP 서버**입니다.
Next.js App Router + [mcp-handler](https://www.npmjs.com/package/mcp-handler) 로 구현하고 Vercel에 배포합니다.

- 기획: [PRD.md](./PRD.md) · 설계/구현 계획: [PLAN.md](./PLAN.md)

---

## 이 서버가 하는 일

**"어떤 기관이 언제 무엇을 발표했는지" 찾아주는 색인입니다.**
제목·기관·발행일·원문 URL을 제공하며, **본문과 요약은 제공하지 않습니다.**
내용 확인은 각 결과의 원문 URL로 이어집니다.

| | |
|---|---|
| 수집 기간 | 2025-01-01 ~ 현재 (일 단위 갱신) |
| 총 건수 | 약 17,500건 |
| 기관 | 12개 (2025-01 첫 주부터 12개 전부) |
| 수집 방식 | 2026-08-25 까지 기관 게시판과 전수 대조 완료, 이후는 일 단위 수집 |
| 날짜 기준 | KST (Asia/Seoul), `YYYY-MM-DD` |

### 대상 기관

`ftc` 공정거래위원회 · `kca` 한국소비자원 · `fsc` 금융위원회 · `fss` 금융감독원 ·
`moef` 기획재정부 · `msit` 과학기술정보통신부 · `molit` 국토교통부 · `motie` 산업통상자원부 ·
`mois` 행정안전부 · `mohw` 보건복지부 · `mss` 중소벤처기업부 · `mcst` 문화체육관광부

---

## 툴

| 툴 | 용도 |
|---|---|
| `press_search` | 제목 키워드·기관·기간·부서로 검색 (주력) |
| `press_latest` | 최근 N일 발행분 + 수집 신선도 경고 |
| `press_get` | id 또는 원문 URL로 단건 메타데이터 조회 |
| `press_daily_briefing` | 특정 날짜 발행분을 기관별로 묶어 반환 |
| `press_list_agencies` | 기관별 코드·누적 건수·수집 시작일 |
| `press_stats` | 기간·기관·시간단위별 발행량 집계 |
| `press_coverage` | 미수집일과 기관별 수집 실패 이력 |

### 예시

```
"최근 3개월 금융위·금감원의 가계부채 관련 발표 찾아줘"   → press_search
"어제 정부 보도자료 브리핑 만들어줘"                      → press_daily_briefing
"올해 부처별 보도자료 발행 추이 비교해줘"                 → press_stats
"데이터 어디까지 수집돼 있어?"                            → press_coverage
```

---

## 데이터의 한계 — 읽기 전에 알아야 할 것

1. **본문·요약이 없습니다.** 제목만으로 내용을 추측하지 말고 원문 URL을 확인하세요.
2. **검색은 제목만 대상입니다.** 제목에 없는 단어로는 찾을 수 없습니다.
3. **2026-04-21에 수집 체계가 바뀌었습니다.** 이 날 전후로 하루 수집량이 약 25건 → 55건으로
   뜁니다. 정부 발표량 변화가 아니라 수집 범위 확대입니다. 이 시점을 걸친 시계열 비교는
   유효하지 않으며, `press_stats` 가 자동으로 경고합니다.
4. **최근 구간의 발행 건수는 하한입니다.** 2026-08-25 까지는 게시판과 전수 대조해 메웠지만,
   이후 일 단위 수집분에는 누락이 섞입니다 (메우기 전 실측 월 3~5%).
5. **담당부서는 2026-07-02 이전 자료에만** 있습니다 (구 수집 파이프라인 전용 필드).
6. **주말 발행은 희소합니다.** 토요일 하루 평균 1.8건, 일요일 8.4건 (평일 31~44건).

---

## 아키텍처

```
MCP 클라이언트 ──Streamable HTTP──> Vercel Function (Fluid Compute, icn1)
                                     app/[transport]/route.ts
                                     └ mcp-handler (stateless, Redis 불필요)
                                          │ supabase-js, anon key, 읽기 전용
                                          ▼
                                   Supabase Postgres
                                   └ VIEW press_releases_unified
                                        ├ govt_press_releases (현행 파이프라인)
                                        └ press_releases      (구 파이프라인, 이력)
```

두 세대의 수집 파이프라인을 **라이브 VIEW**로 통합합니다. 기관 + 정규화 제목을 키로 발행일
±1일 허용 범위에서 중복을 제거하며, 어느 쪽 파이프라인이 갱신되든 자동 반영됩니다.

### 보안

`anon`(publishable) 키만 사용합니다. 대상 테이블과 뷰의 RLS 정책이 `SELECT` 만 허용하므로
**`service_role` 키를 배포 환경에 두지 않습니다.**

---

## 개발

```bash
npm install
cp .env.example .env.local   # SUPABASE_URL / SUPABASE_ANON_KEY 채우기
npm run dev                  # http://localhost:3000/mcp
```

### 검증

```bash
node scripts/smoke.mjs http://localhost:3000/mcp
```

initialize → tools/list → 툴 13개 케이스 호출을 수행하고, 응답 줄 수와 대략적 토큰량을 출력합니다.
정상 종료 시 `전 케이스 통과` 를 마지막 줄에 찍습니다.

MCP Inspector로 대화형 점검도 가능합니다.

```bash
npx @modelcontextprotocol/inspector
```

### 배포

```bash
vercel link
vercel env add SUPABASE_URL production
vercel env add SUPABASE_ANON_KEY production
vercel --prod
```

배포 후 엔드포인트는 `https://<project>.vercel.app/mcp` 입니다.

### 클라이언트 등록

```bash
claude mcp add --transport http govtpress https://<project>.vercel.app/mcp
```

---

## 데이터베이스 객체

이 서버가 의존하는 Supabase 객체입니다 (마이그레이션으로 생성).

| 객체 | 역할 |
|---|---|
| `press_releases_unified` (view) | 두 파이프라인 통합 + 중복 제거. 앱은 이것만 읽습니다 |
| `press_stats(from,to,group_by,agencies)` | 발행량 집계 (PostgREST로 GROUP BY 불가) |
| `press_missing_days(from,to)` | 미수집일 산출 |
| `press_agency_summary()` | 기관별 누적/시작일/최신일 |

> **성능 참고**: 데이터베이스 collation 이 `en_US.UTF-8` 이라 한글 문자열 정렬이 매우 느립니다.
> 뷰의 중복 제거 키(`title_key`)는 `COLLATE "C"` 로 고정되어 있습니다 — 정규화된 그룹핑
> 전용 키라 언어적 정렬 순서가 불필요하고, 이 한 줄이 조회 시간을 10.3초에서 0.2초로 줄입니다.
> **이 지정을 제거하지 마세요.** PostgREST의 3초 statement timeout에 즉시 걸립니다.