safemap-uv-index-mcp
행정안전부 생활안전지도(safemap.go.kr)에서 제공하는 자외선지수 정보조회 서비스(기상청 생활기상지수 중 자외선지수를 시군구 단위로 정리한 자료)를 조회하는 MCP 서버.
제공 데이터
단일 데이터셋 구성이며, 별도의 Dataset Registry 표는 필요하지 않다.
- 데이터셋명(화면 표시): 자외선지수
- 제공기관: 기상청 (관리부서: 기상융합서비스과)
- 제공 플랫폼: 행정안전부 생활안전지도(safemap.go.kr)
- 원 API: 자외선지수 정보조회 서비스 (IF_0113)
툴
get_uv_index
시도/시군구 기준으로 자외선지수를 조회한다.
파라미터| 이름 | 타입 | 필수 | 설명 ||---|---|---|---|| sido | string | 선택 | 시도명으로 필터링 (예: "서울", "경기"). 클라이언트 사이드 부분 일치 || sigungu | string | 선택 | 시군구명으로 필터링 (예: "강남구"). 클라이언트 사이드 부분 일치 || page_no | int | 선택 (기본 1) | 지역 필터 없이 전체 페이징 조회 시 사용 || num_of_rows | int | 선택 (기본 300) | 한 번에 가져올 결과 수 (전국 총 269건이므로 300이면 1페이지에 전체 포함) |
반환 필드| 필드 | 설명 ||---|---|| ctprvn_nm | 시도명 (예: "서울", "경남", "강원특별자치도") || signgu_nm | 시군구명. 시도 전체를 대표하는 항목은 빈 문자열("")로 옴 || emd_nm | 읍면동명. 실측 결과 항상 빈 문자열로 확인됨 || ulvry_index | 자외선지수 값. 정수(int)로 반환 (실측 결과 0~9 범위의 순수 숫자로 확인됨, 등급 문자열 아님) || occrrnc_dt | 발생일시. 실측 포맷: YYYYMMDDHH (10자리, 예: "2026072106" = 2026-07-21 06시) |
알려진 제약사항 (실측 완료)
원 명세서가 엑셀/XML 샘플이 아닌 화면 캡처 2장 + 자바 샘플코드로만 제공되어 실측이필요했던 항목들의 실제 확인 결과는 다음과 같다 (2026-08-22 실측):
- returnType 기본값:
returnType을 생략해도 실제로 JSON이 반환됨(안내 문구"Default: JSON"이 맞음). 다만 안전하게 매 요청에returnType=json을 명시적으로 포함한다. - 지역 필터 파라미터:
sidoNm등 지역 필터 파라미터를 시도해봤으나 서버가 무시하고전체 데이터를 그대로 반환함 — API 자체 지역 필터는 지원하지 않음. 이 서버는전국 데이터를 전체 조회한 뒤sido/sigungu파라미터로 클라이언트 사이드필터링을 수행한다. - 자외선지수(ulvry_index): 실측 결과
"0","1","2","7","9"등 순수숫자 문자열로 확인됨 ("낮음/보통/높음" 같은 등급 문자열 아님). 서버는 이를 정수로안전 변환하여 반환한다. - 발생일시(occrrnc_dt) 포맷:
YYYYMMDDHH(시(hour) 단위까지, 분 없음). 예:"2026072106". - totalCount / 전국 시군구 수:
numOfRows=1000, pageNo=1로 호출 시totalCount=269,실제 반환 건수도 269건으로 일치. 시도 17개 전체가 포함되며, 각 시도별로 "시군구 전체"를대표하는 항목(signgu_nm="")과 개별 시군구 항목이 함께 옴. - 에러코드: 정상 응답은
resultCode="00",resultMsg="NORMAL_SERVICE". 잘못된서비스키로 호출 시resultCode="30",resultMsg="SERVICE_KEY_IS_NOT_REGISTERED_ERROR"(HTTP 상태코드는 500으로 확인됨). - 읍면동명(emd_nm): 실측 범위 내에서는 항상 빈 문자열로 확인됨.
- 엔드포인트:
http://safemap.go.kr/openapi2/IF_0113으로 호출 시https://www.safemap.go.kr/...로리다이렉트됨(자동 https 전환, httpxfollow_redirects=True로 처리).
설치 및 실행
pip install -r requirements.txt
cp .env.example .env # SAFEMAP_API_KEY 값 입력
python server.py
환경변수
| 변수명 | 설명 |
|---|---|
| SAFEMAP_API_KEY | 행정안전부 생활안전지도(safemap.go.kr)에서 발급받은 인증키 |
| PORT | 서버 포트 (기본 8080) |
배포 (fly.io)
fly launch --no-deploy
fly secrets set SAFEMAP_API_KEY=발급받은키
flyctl deploy
배포 후 Claude.ai 커넥터 연결 시 반드시 /mcp 경로를 붙인다:
https://safemap-uv-index-mcp.fly.dev/mcp
Rate Limit
API 키 인증 없이 URL만으로 커넥터 연결이 가능한 공개 서버이므로, IP 기준슬라이딩 윈도우 방식의 rate limit이 적용된다:
- 60초 이내 30회 초과 시 429 (
Fly-Client-IP헤더 우선, 없으면X-Forwarded-For첫 값 사용) - CORS preflight(OPTIONS) 요청은 카운트에서 제외
라이선스
MIT License. 데이터 자체의 저작권은 공공누리(행정안전부 생활안전지도) 이용조건을 따른다.
출처
행정안전부 생활안전지도(safemap.go.kr), 기상청(기상융합서비스과) 제공「자외선지수 정보조회 서비스(IF_0113)」