opinet-mcp
# opinet-mcp
한국석유공사 **오피넷(Opinet)** 유가정보 무료 API를 Claude / Claude Code 등 MCP 클라이언트에서 사용할 수 있게 해주는 MCP 서버입니다.
- 언어: TypeScript (ESM)
- SDK: `@modelcontextprotocol/sdk`
- 전송: stdio
- 호출 제한: **1,500 call/일** (오피넷 정책)
---
## 사전 준비
1. [오피넷 무료 API](https://www.opinet.co.kr/) 에서 API Key 발급
2. Node.js **18 이상** (글로벌 `fetch` 사용)
---
## 설치 & 실행 — 3가지 방법
### 방법 1. npx로 즉시 실행 (권장 · 별도 설치 불필요)
> npm 레지스트리에 publish 후 사용 가능. publish는 아래 "배포" 섹션 참고.
```bash
OPINET_API_KEY=발급키 npx -y opinet-mcp
```
### 방법 2. 글로벌 설치
```bash
npm install -g opinet-mcp
OPINET_API_KEY=발급키 opinet-mcp
```
### 방법 3. 소스 클론 (개발 / private 사용)
```bash
git clone https://github.com/KimJintak/opinet-mcp.git
cd opinet-mcp
npm install
npm run build
OPINET_API_KEY=발급키 node dist/index.js
```
---
## MCP 클라이언트 등록
### Claude Desktop / Claude Code
설정 파일 위치:
| OS | 경로 |
| --- | --- |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
| Linux | `~/.config/Claude/claude_desktop_config.json` |
#### A. npx 방식 (가장 간편 — publish 후 사용)
```json
{
"mcpServers": {
"opinet": {
"command": "npx",
"args": ["-y", "opinet-mcp"],
"env": {
"OPINET_API_KEY": "발급받은_키"
}
}
}
}
```
#### B. 글로벌 설치 방식
```json
{
"mcpServers": {
"opinet": {
"command": "opinet-mcp",
"env": {
"OPINET_API_KEY": "발급받은_키"
}
}
}
}
```
#### C. 로컬 빌드 방식 (소스 클론한 경우)
```json
{
"mcpServers": {
"opinet": {
"command": "node",
"args": ["/절대/경로/opinet-mcp/dist/index.js"],
"env": {
"OPINET_API_KEY": "발급받은_키"
}
}
}
}
```
> ⚠️ Claude Desktop은 PATH를 제한적으로 상속받습니다. `command: "node"` 또는 `"npx"`로 실행 시 못 찾는다면 절대경로(`/opt/homebrew/bin/node`, `/usr/local/bin/npx` 등)로 지정하세요. 터미널에서 `which node` / `which npx`로 확인.
설정 후 **Claude Desktop 완전 종료(Cmd+Q) → 재실행**하면 도구 아이콘에서 6개 툴을 확인할 수 있습니다.
### 다른 MCP 클라이언트 (Cursor, Cline, Continue 등)
위 JSON 구조와 동일하게 각 클라이언트의 MCP 서버 설정 파일에 추가하면 됩니다.
---
## 제공 툴 (6종)
| Tool name | 오피넷 엔드포인트 | 설명 |
| --- | --- | --- |
| `get_national_average_price` | `avgAllPrice.do` | 전국 주유소 평균가격 (현재) |
| `get_sido_average_price` | `avgSidoPrice.do` | 시도별 주유소 평균가격 (현재) |
| `get_recent_7days_price` | `avgRecentPrice.do` | 최근 7일간 전국 일일 평균가격 (추세) |
| `get_lowest_price_top20` | `lowTop10.do` | 전국/지역별 최저가 주유소 TOP20 |
| `search_stations_around` | `aroundAll.do` | KATEC 좌표 기준 반경 내 주유소 검색 |
| `get_station_detail` | `detailById.do` | 주유소 ID(UNI_ID)로 상세정보 조회 |
### 공통 코드
**제품코드 (`prodcd`)**
| 코드 | 제품 |
| --- | --- |
| `B027` | 보통휘발유 |
| `D047` | 자동차경유 |
| `B034` | 고급휘발유 |
| `C004` | 실내등유 |
| `K015` | 자동차부탄 |
**시도코드 (`sido` / `area` 2자리)**
| 코드 | 지역 | 코드 | 지역 |
| --- | --- | --- | --- |
| 01 | 서울 | 10 | 부산 |
| 02 | 경기 | 11 | 제주 |
| 03 | 강원 | 12 | 대구 |
| 04 | 충북 | 13 | 인천 |
| 05 | 충남 | 14 | 광주 |
| 06 | 전북 | 15 | 대전 |
| 07 | 전남 | 16 | 울산 |
| 08 | 경북 | 17 | 세종 |
| 09 | 경남 | | |
> 시군구 단위는 4자리 코드입니다 (예: `0207` = 경기 광명시). 오피넷 `areaCode.do` 엔드포인트로 별도 조회 가능.
### 좌표계 주의사항
`search_stations_around`의 입력 좌표(`x`, `y`)와 모든 응답의 `GIS_X_COOR / GIS_Y_COOR`는 **KATEC 좌표계**입니다. WGS84(위경도)와 다르므로, 위경도를 입력으로 받으려면 클라이언트에서 KATEC으로 변환 후 호출하세요.
---
## 사용 예시 (자연어)
- "오늘 전국 휘발유 평균가 알려줘" → `get_national_average_price`
- "서울 시도 평균 경유 가격" → `get_sido_average_price` (`sido=01`, `prodcd=D047`)
- "최근 7일간 휘발유 추세" → `get_recent_7days_price` (`prodcd=B027`)
- "광명시에서 가장 싼 휘발유 주유소 5곳" → `get_lowest_price_top20` (`prodcd=B027`, `area=0207`, `cnt=5`)
- "주유소 ID A0008322 상세정보" → `get_station_detail`
---
## 동작 확인 (스모크 테스트)
API 키 없이 실행 → 환경변수 안내 후 종료되면 빌드 OK:
```bash
node dist/index.js
```
API 키가 있을 때, stdio로 직접 호출:
```bash
export OPINET_API_KEY=발급키
# 등록된 툴 목록 확인
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js
# 전국 평균가격 호출
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_national_average_price","arguments":{}}}' | node dist/index.js
```
---
## 개발
```bash
npm install
npm run dev # tsc --watch
npm run build # 한 번 빌드
npm start # dist/index.js 실행
npm run clean # dist 삭제
```
프로젝트 구조:
```
opinet-mcp/
├── src/
│ └── index.ts # MCP 서버 본체
├── dist/ # 빌드 결과물 (배포 대상)
├── package.json
├── tsconfig.json
├── README.md
└── LICENSE
```
---
## 배포 (npm publish)
처음 publish할 때:
```bash
# 1) npm 로그인
npm login
# 2) package.json의 author / repository / name 확인 (필요하면 scoped: @yourname/opinet-mcp)
# 3) 빌드 + publish (prepublishOnly에서 자동 빌드됨)
npm publish
# scoped 패키지면
npm publish --access public
```
이후 버전 업:
```bash
npm version patch # 0.1.0 -> 0.1.1
npm publish
```
publish 후에는 누구나 `npx -y opinet-mcp` 로 즉시 사용 가능합니다.
> `prepare` 스크립트가 있어서 `npm install` 시 자동 빌드됩니다. 즉, GitHub에서 직접 설치 (`npm i github:KimJintak/opinet-mcp`) 해도 동작합니다.
---
## 라이선스
MIT.
데이터 출처는 한국석유공사 오피넷이며, 데이터 사용 시 [오피넷 이용 약관](https://www.opinet.co.kr/)을 따르시기 바랍니다.
TDQS
Scored across 5 tools
Each tool targets a distinct data view (cheapest stations, national average, historical trends, regional averages, single station details). While all relate to fuel prices, the scope filters (top20, 7-day history, sido codes) create clear boundaries.
All tools use consistent snake_case with a 'get_' verb prefix followed by descriptive noun phrases (lowest_price_top20, national_average_price, etc.). The pattern is predictable throughout.
Five tools cover the essential read-only queries for a fuel price information service without bloat. The scope is well-contained, though an additional search-by-radius or brand filter could round it out.
Core price discovery workflows are covered: finding cheap stations, checking averages at national/regional levels, viewing trends, and drilling into station details. Minor gaps include no brand-specific queries or historical data beyond 7 days.