Skip to main content
Glama
jcyeom

pubdata-mcp

by jcyeom
README.md
# pubdata-mcp

한국 공공데이터를 수집·정규화해 DuckDB 데이터마트에 적재하고, 이를 MCP 서버로 노출한 뒤
Ollama 로컬 LLM 에이전트가 자연어 질문에 답하는 end-to-end 파이프라인입니다.

데이터 엔지니어링(수집·정규화·안전한 쿼리 서빙)과 AI 오케스트레이션(MCP + LLM 툴콜)을
하나의 프로젝트로 보여주는 백엔드 포트폴리오입니다.

## 아키텍처

```
data.go.kr ──ingest──> DuckDB 데이터마트 ──> MCP Server ──stdio──> Ollama Agent Host
 (실거래가/기상/대기질)   (정규화 테이블)      (툴/리소스)          (자연어 → 툴콜 → 답변)
```

- ingest: 커넥터 인터페이스 + 3개 커넥터 (아파트 실거래가, 일별 기상, 일별 대기질). API 키 없으면 mock 폴백
- store: DuckDB 적재 및 read-only 쿼리 (지역 partition 기반 idempotent 적재)
- server: MCP 서버 (`list_datasets`, `describe_schema`, `query_sql`, `price_stats`, `correlate` + `pubdata://catalog` 리소스)
- host: MCP 서버를 subprocess로 띄우고 Ollama 툴콜 루프로 질의에 답하는 에이전트

### 데이터셋

- `apt_trade` — 아파트 매매 실거래가 (지역/월)
- `weather` — 일별 기온·강수·풍속 (지역/일)
- `air_quality` — 일별 PM10·PM2.5·오존 (지역/일)

`weather`와 `air_quality`는 `(obs_date, region_code)`를 공유해 `correlate` 툴로 크로스 도메인
상관분석이 가능합니다 (예: 풍속 vs 미세먼지 → corr ≈ -0.95, 바람이 강한 날 미세먼지가 낮음).

핵심 백엔드 포인트는 `server/safe_sql.py`의 **read-only SQL 가드**(단일문 강제, DDL/DML 차단,
LIMIT 강제)와 DuckDB read-only 커넥션 이중 방어입니다.

## 빠른 시작

```bash
# 1. 의존성 설치 (uv)
uv sync

# 2. 데이터 적재 (키 없으면 mock 데이터로 동작)
for r in 11680 11650 11440; do
  uv run pubdata-ingest apt_trade   --region $r --ym 202406
  uv run pubdata-ingest weather     --region $r --ym 202406
  uv run pubdata-ingest air_quality --region $r --ym 202406
done

# 3. MCP 서버 단독 실행 (Claude Desktop / MCP Inspector에 연결 가능)
uv run pubdata-server

# 4. 에이전트로 자연어 질의 (CLI)
uv run pubdata-agent "강남구와 서초구 아파트 평균 거래가를 비교해줘"

# 5. 웹 UI (질문 + 답변 + 툴 호출 트레이스 표시) — http://localhost:8000
uv run pubdata-web
```

## 웹 UI / API

`pubdata-web`은 FastAPI 앱을 띄웁니다.

- `GET /` — 질문 입력 → 답변과 함께 에이전트가 호출한 MCP 툴 트레이스(인자·결과·소요시간)를 표시
- `POST /api/ask` `{"question": "..."}` → `{answer, model, steps, elapsed_ms, trace[]}`
- `GET /api/health` — 상태 및 설정된 모델

## Docker

Ollama는 호스트에서 실행 중이라고 가정합니다. compose는 host networking으로 호스트의
`localhost:11434` Ollama에 바로 접근합니다 (Linux 기준).

```bash
docker compose up --build
# http://localhost:8000
```

첫 기동 시 마트가 비어 있으면 mock 데이터로 3개 지역을 자동 적재합니다.
호스트에 tool-calling 모델(`ollama pull qwen2.5:7b`)이 있어야 합니다.
Docker Desktop(mac/Windows)에서는 `docker-compose.yml` 주석의 대안 설정을 참고하세요.

## 실제 API 사용

`.env.example`를 `.env`로 복사하고 `PUBDATA_DATA_GO_KR_KEY`에 data.go.kr 서비스 키를 넣으면
mock 대신 실데이터를 수집합니다.

## Claude Desktop 연결 예시

```json
{
  "mcpServers": {
    "pubdata": {
      "command": "uv",
      "args": ["run", "pubdata-server"],
      "cwd": "/home/jcyeom/dlwlr/pubdata-mcp"
    }
  }
}
```

## 관측성 (Observability)

모든 에이전트 실행은 `data/traces.jsonl`에 append됩니다 (질문·모델·툴 궤적·소요시간·에러·답변).

- `GET /api/traces?limit=20` — 최근 실행 조회 (최신순)
- best-effort 로깅이라 실패해도 요청에 영향 없음

## 평가 (Eval)

골든 케이스로 에이전트 품질을 회귀 검증합니다.

```bash
uv run pubdata-eval
```

각 케이스는 3가지를 채점합니다:
- answer-correctness: 답변에 기대값(실데이터 숫자)이 포함되는가 (콤마 무시 비교)
- tool-trajectory: 기대한 MCP 툴이 호출됐는가
- error-free: 툴 에러가 없었는가

결과는 표로 출력되고 `data/eval_report.json`에 저장됩니다. 하나라도 실패하면 exit code 1 (CI 연동 가능).
로컬 LLM 재현성을 위해 에이전트는 `temperature=0`으로 호출합니다.

## 테스트

```bash
uv run pytest   # 23 tests: SQL 가드, 파이프라인, 관측성, eval 스코어링
```

## 로드맵

- [x] end-to-end 파이프라인 (ingest → DuckDB → MCP → Ollama 에이전트)
- [x] read-only SQL 가드 + idempotent 적재
- [x] Docker 배포 + 웹 UI (툴 트레이스 표시)
- [x] 툴콜 정확도 eval 셋 + 요청 트레이싱/관측성
- [x] 기상/대기질 커넥터 추가 → 크로스 도메인 상관분석 (correlate 툴)
- [ ] 기상/대기질 실 API 연동 (현재 mock, apt_trade는 실 API 지원)
- [ ] 수집 스케줄러(APScheduler) + 증분 적재

TDQS

A4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: listing datasets, describing schemas, running SQL queries, computing price statistics, and calculating correlations. No overlap or ambiguity.

Naming Consistency5/5

All tools use consistent snake_case naming with verb-first patterns (list_datasets, describe_schema, query_sql, price_stats, correlate). The single verb 'correlate' fits the pattern.

Tool Count5/5

Five tools cover the core functionality of data discovery, schema exploration, custom queries, and common analytics. This is a well-scoped set for a data mart server.

Completeness4/5

The tool set covers essential workflows: discover (list_datasets), understand (describe_schema), query (query_sql), and two analytics helpers. Minor gaps like missing aggregation functions, but overall complete for the intended domain.

Maintenance

ActivityStale
ResponsivenessNo issues