{
  "markdown": "# @keumbang/goldpopcon-openapi-mcp\n\n[![npm](https://img.shields.io/npm/v/@keumbang/goldpopcon-openapi-mcp)](https://www.npmjs.com/package/@keumbang/goldpopcon-openapi-mcp)\n[![CI](https://github.com/keumbang/goldpopcon-openapi-mcp/actions/workflows/publish.yml/badge.svg)](https://github.com/keumbang/goldpopcon-openapi-mcp/actions/workflows/publish.yml)\n[![node](https://img.shields.io/node/v/@keumbang/goldpopcon-openapi-mcp)](https://nodejs.org)\n[![license](https://img.shields.io/npm/l/@keumbang/goldpopcon-openapi-mcp)](./LICENSE)\n[![goldpopcon-openapi-mcp MCP server](https://glama.ai/mcp/servers/keumbang/goldpopcon-openapi-mcp/badges/score.svg)](https://glama.ai/mcp/servers/keumbang/goldpopcon-openapi-mcp)\n\n[![VS Code 설치](https://img.shields.io/badge/VS_Code-설치-0098FF?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=goldpopcon-openapi&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40keumbang%2Fgoldpopcon-openapi-mcp%22%5D%7D)\n[![Cursor 설치](https://img.shields.io/badge/Cursor-설치-000000?logo=cursor&logoColor=white)](https://cursor.com/install-mcp?name=goldpopcon-openapi&config=eyJjb21tYW5kIjoibnB4IC15IEBrZXVtYmFuZy9nb2xkcG9wY29uLW9wZW5hcGktbWNwIn0%3D)\n\n골드팝콘(금방) Open API **코딩 어시스턴트 MCP 서버**. Claude Code · Claude Desktop · Codex CLI · Gemini CLI · Cursor 등 MCP 클라이언트에 붙여, 금·은 거래 API 연동 코드를 정확히 짜도록 돕는다.\n\n> ### 📘 골드팝콘 Open API 문서 → **[https://keumbang.github.io/goldpopcon-openapi-mcp/](https://keumbang.github.io/goldpopcon-openapi-mcp/)**\n>\n> 엔드포인트 표 · 빠른 시작 · JWT 서명 규격 · 권한/한도 · 멱등성 · 에러 코드. 스펙에서 생성되는 공식 문서다.\n> 요청·응답 스키마는 [Redoc](https://keumbang.github.io/goldpopcon-openapi-mcp/redoc.html) 에서 본다. MCP 없이 직접 연동할 사람도 여기부터 읽으면 된다.\n> (repo 안에서 바로 보려면 [docs/index.md](./docs/index.md))\n\n## API 키 발급\n\nOpen API 키(`gpk_` 액세스 키 + `sk_` 시크릿 키)는 **골드팝콘 앱에서만 발급**된다. 웹 발급 경로는 없다.\n\n1. 골드팝콘 앱 설치 — [App Store](https://apps.apple.com/kr/app/id6747214612) · [Google Play](https://play.google.com/store/apps/details?id=com.keumbang.goldpopcorn)\n2. 회원가입 후 앱 내 Open API 메뉴에서 키 발급\n3. `sk_` 시크릿 키는 **발급 화면에서만 노출**된다 — 그 자리에서 안전한 곳에 보관\n\n이 API에서 개발자가 막히는 지점은 필드명이 아니라 **요청 서명**이다 — `query_hash` 입력이 메서드에 따라 갈리고(POST=raw body, GET=정규화 querystring) 업비트 예제를 그대로 옮기면 전부 401이 난다. 이 MCP는 그 절차를 코드로 생성하고 로컬에서 서명/검증까지 해준다.\n\n## 도구\n\n| 도구 | 용도 |\n|---|---|\n| `list_endpoints` | 엔드포인트 목록 — 권한 스코프·멱등성·rate 버킷 포함 |\n| `get_endpoint` | 단일 엔드포인트 상세 — 파라미터·본문 스키마·요청/성공 응답 예제·응답 코드 |\n| `list_error_codes` | 에러 코드 표 + 상태 코드별 재시도 판단 + 함정(잔액 부족=400 P0001, 인증 실패=401 error:null) |\n| `signing_guide` | JWT 서명 절차 — `query_hash` 분기·시각 클레임·nonce·멱등성 |\n| `generate_signed_request` | 언어별(python/javascript/go/curl) 완결형 서명 요청 코드 생성 |\n| `sign_request` | 실제 키로 JWT를 **로컬 계산**(디버깅) — JWT·query_hash·바로 쓸 curl 반환 |\n| `verify_signature` | 이미 만든 JWT를 서버와 같은 순서로 검증 — 401 원인 진단 |\n| `call_api` *(opt-in)* | 실제 호출 — **조회 전용·production 고정**. env 로 켤 때만 등록 |\n\n리소스: `goldpopcon://openapi.yaml`(전체 스펙), `goldpopcon://overview`(서명·한도·에러 산문).\n\n> **보안**: `sign_request`/`verify_signature`/`call_api`에 넘긴 `secret_key`는 로컬 서명에만 쓰이고 서명 결과(JWT)만 전송된다 — secret 자체는 네트워크를 타지 않는다.\n\n### call_api — 조회 전용 라이브 호출\n\n기본 **비활성**. `GOLDPOPCON_MCP_ALLOW_LIVE=true` 일 때만 등록된다. 4중 안전장치로 자금 이동을 원천 차단:\n\n1. **env 게이트** — 변수 없으면 도구 자체가 없다\n2. **화이트리스트** — `getPrices` / `getBalances` / `getPriceHistory` / `getOrderPreview` / `getTradeHistory` 만. `buy`·`sell`·`payout`·`virtual-accounts` 는 라이브 불가(코드 생성만)\n3. **production 고정** — 인자로 서버를 바꿀 수 없다. 조회 전용이라 production 을 읽어도 자금은 움직이지 않는다\n4. **GET 강제** — 쓰기 메서드 차단\n\n자금 이동 엔드포인트를 실제로 호출하려면 `generate_signed_request` 로 코드를 받아 개발자 본인 환경에서 실행한다.\n\n#### 읽기 자동화 — 키는 env 로\n\nLLM 이 시세·잔고를 반복 조회하는 자동화라면 `accessKey`/`secretKey` **인자를 생략**하고 env 로 준다. 인자로 넘긴 `sk_` 는 호출마다 모델 컨텍스트·트랜스크립트·클라이언트 로그에 평문으로 남는다.\n\n```json\n{\n  \"mcpServers\": {\n    \"goldpopcon-openapi\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@keumbang/goldpopcon-openapi-mcp\"],\n      \"env\": {\n        \"GOLDPOPCON_MCP_ALLOW_LIVE\": \"true\",\n        \"GOLDPOPCON_ACCESS_KEY\": \"gpk_...\",\n        \"GOLDPOPCON_SECRET_KEY\": \"sk_...\"\n      }\n    }\n  }\n}\n```\n\nenv fallback 은 `call_api`(조회 전용)에만 있다. `sign_request` 는 `buyAsset` 서명까지 만들 수 있어 열지 않았다 — 열면 에이전트가 사람 개입 없이 유효한 자금 이동 서명을 찍어낸다.\n\n`call_api` 는 `structuredContent` 로도 응답한다 — 마크다운 파싱 없이 값을 바로 쓴다.\n\n```json\n{\n  \"operationId\": \"getPrices\",\n  \"url\": \"https://api.goldpopcon.com/api/open/v1/prices\",\n  \"status\": 200,\n  \"ok\": true,\n  \"data\": { \"...\": \"응답 본문 JSON 그대로\" },\n  \"rateLimit\": { \"limit\": 600, \"remaining\": 599, \"reset\": 1730000000, \"retryAfter\": null }\n}\n```\n\n- `data` 형태는 엔드포인트마다 다르다 — `get_endpoint` 의 성공 응답 예제가 스펙이다.\n- 4xx/5xx 도 도구 에러가 아니라 `status`/`ok` 로 온다. 루프가 분기해서 처리한다.\n- JSON 이 아닌 본문(게이트웨이 HTML 오류 등)은 `data` 대신 `raw` 로 온다.\n- 429 면 `rateLimit.retryAfter` 에 대기 초. quote 600/분, trade 60/분.\n\n## 설치 · 빌드\n\n```bash\ngit clone https://github.com/keumbang/goldpopcon-openapi-mcp.git\ncd goldpopcon-openapi-mcp\nnpm install\nnpm run build       # dist/ 생성\nnpm test            # 서명 회귀 테스트\n```\n\n## MCP 클라이언트 등록\n\nCLI 한 줄로 붙는 클라이언트:\n\n```bash\n# Claude Code\nclaude mcp add goldpopcon-openapi -- npx -y @keumbang/goldpopcon-openapi-mcp\n\n# Codex CLI  (~/.codex/config.toml 에 기록된다. 세션에서 /mcp 로 연결 확인)\ncodex mcp add goldpopcon-openapi -- npx -y @keumbang/goldpopcon-openapi-mcp\n```\n\n설정 파일 직접 편집(Claude Desktop `claude_desktop_config.json`, Cursor `~/.cursor/mcp.json`, Gemini CLI `~/.gemini/settings.json`):\n\n```json\n{ \"mcpServers\": { \"goldpopcon-openapi\": { \"command\": \"npx\", \"args\": [\"-y\", \"@keumbang/goldpopcon-openapi-mcp\"] } } }\n```\n\nGemini CLI 는 `PATH` 해석이 불안정하다 — 서버가 안 뜨면 `command` 를 `which npx` 로 얻은 절대경로로 바꾼다.\n\n로컬 클론 실행:\n\n```json\n{\n  \"mcpServers\": {\n    \"goldpopcon-openapi\": {\n      \"command\": \"node\",\n      \"args\": [\"/절대경로/goldpopcon-openapi-mcp/dist/index.js\"]\n    }\n  }\n}\n```\n\n개발 중엔 `command: \"npx\", args: [\"tsx\", \"/절대경로/.../src/index.ts\"]`.\n\n## 환경변수\n\n| 변수 | 기본 | 의미 |\n|---|---|---|\n| `GOLDPOPCON_OPENAPI_SPEC` | 번들 `spec/openapi.yaml` | 스펙 파일 경로 재지정 |\n| `GOLDPOPCON_MCP_ALLOW_LIVE` | (없음) | `true` 면 `call_api`(조회 전용·production) 활성화 |\n| `GOLDPOPCON_ACCESS_KEY` | (없음) | `call_api` 액세스 키 기본값 — 인자 생략 시 사용 |\n| `GOLDPOPCON_SECRET_KEY` | (없음) | `call_api` 시크릿 키 기본값 — 반복 호출 자동화에서 권장 |\n\n## 예시 대화\n\n- \"sellAsset 을 파이썬으로 호출하는 코드 줘, 금 0.5g\" → `generate_signed_request(operationId=sellAsset, language=python, pathParams={asset:gold}, body={quantity:0.5})`\n- \"보유한 금 전부 팔려면?\" → `generate_signed_request(operationId=sellAsset, language=python, pathParams={asset:gold}, body={quantity:0.001, sell_all:true})` — `sell_all` 이 요청 수량을 무시하고 가용 잔량 전량을 체결한다\n- \"이 JWT 가 왜 401 나?\" → `verify_signature(token=..., secretKey=..., method=POST, rawBody=...)`\n- \"가격 이력 엔드포인트 파라미터 뭐야?\" → `get_endpoint(operationId=getPriceHistory)`\n- \"잔액 부족이면 몇 번 에러야?\" → `list_error_codes` — `400 P0001`(500 아님). 상태 코드별 재시도 판단표도 같이 나온다\n\n## 스펙 동기화\n\n스펙 원본은 **백엔드 repo 의 `docs/openapi.yaml`**(이 repo 밖)이고, 이 repo 는 `spec/openapi.yaml` 사본을 번들한다. 원본이 바뀌면 `SPEC_SRC` 로 경로를 지정해 갱신한다:\n\n```bash\nSPEC_SRC=/path/to/<backend-repo>/docs/openapi.yaml npm run sync-spec\n```\n`SPEC_SRC` 는 **필수**다. 생략하면 원본을 못 찾고 실패한다 — 백엔드 repo 명을 이 repo 에 남기지 않기 위해 기본 경로를 두지 않았다.\n\n`dist/` 가 있으면 sync-spec 이 문서 사이트(`docs/index.md` · `docs/openapi.yaml`)도 같이 다시 만든다. 스펙만 따로 갱신했다면 `npm run docs` 로 맞춘다 — 둘 다 생성물이라 직접 고치지 않는다. 문서 내용을 바꾸려면 백엔드 스펙의 `info.description` 을 고친다. 손으로 쓰는 파일은 `docs/_config.yml` 과 `docs/redoc.html` 둘뿐이다.\n\n갱신 후 `spec/openapi.yaml` 과 `docs/` 를 커밋한다. main 에 푸시되면 GitHub Pages 가 사이트를 다시 배포한다. 서명 규칙이 서버와 어긋나면 `npm test`(서버 검증 규칙 미러)가 잡는다.\n```\n<backend-repo>/docs/openapi.yaml  ──sync-spec──▶  spec/openapi.yaml  ──gen-docs──▶  docs/  ──Pages──▶  keumbang.github.io\n```\n",
  "bytes": 7584,
  "sha": "f0a7415a0c5bac8e3d5f7650a94adc31170ee4e50ee41af6dd48bd999c8400f4",
  "repo_slug": "keumbang/goldpopcon-openapi-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_goldpopcon_openapi_mcp_7893d5e3/readme"
}