키움증권 MCP 서버 — 주문은 이중 게이트로 잠긴다
kiwoom-spec-mcp는 자격증명을 아예 받지 않고 API 검색·예제 조회만 합니다.
kiwoom-exec-mcp는 App Key로 시세·계좌를 조회하고, 주문은 게이트 두 개를 통과해야 나갑니다 —
① 환경변수 KIWOOM_MCP_ALLOW_ORDERS가 정확히 문자열 "1"일 때만 주문 도구 2개가 등록되고
(true·yes는 전부 꺼짐으로 처리됩니다),
② 그다음 kiwoom_order_submit에 최상위 confirm=true를 넘겨야 실제로 전송됩니다.
다만 confirm은 AI도 설정할 수 있는 값이라, 최종 안전장치는 MCP 클라이언트의 실행 승인 화면입니다.
이 글에서 확인할 것
- 서버 두 개의 권한 분리
kiwoom-spec-mcp도구 4개kiwoom-exec-mcp도구 6개- 주문 게이트 —
"1"과confirm=true - 설치 두 갈래 —
.mcpb와mcpServersJSON - 원격(HTTP) 전송과 헤더 인증
- 이걸로 자동매매가 되나
1. 서버 두 개의 권한 분리
MCP는 Model Context Protocol의 약자로, AI 에이전트가 외부 도구를 호출하는 규약입니다.
키움증권은 공식 저장소 Kiwoom-Securities/Kiwoom-REST-API에
이 규약을 따르는 서버를 두 개 넣어 두었습니다.
이름이 비슷해서 한 덩어리처럼 보이지만, 자격증명을 받느냐 마느냐로 성격이 갈립니다.
| 서버 | 역할 | App Key | 대표 도구 |
|---|---|---|---|
kiwoom-spec-mcp |
API 검색 · 명세 · 예제 코드 조회 | 불필요 | spec_search |
kiwoom-exec-mcp |
시세 · 계좌 조회, (게이트 뒤) 주문 | 필요 | kiwoom_query |
공식 문서가 권장하는 조합은 spec으로 API를 찾고 예제를 확인한 뒤, 실제 조회·주문은 exec로 실행하는 구성입니다.
두 서버가 같은 명령 어휘(command_path)를 공유하기 때문에 가능한 분업입니다 —
spec_search가 돌려준 command_path를 kiwoom_query의 인자로 그대로 넣을 수 있습니다.
2. kiwoom-spec-mcp — 자격증명 없는 검색 서버
이 서버는 키움 API를 직접 호출하지 않습니다.
네트워크 요청은 예제 코드를 가져오는 raw.githubusercontent.com 요청뿐이고,
자격증명을 받지도, 요구하지도 않습니다.
| 도구 | 하는 일 |
|---|---|
spec_search(query, market, group, limit) | 키워드로 API 검색. market은 domestic·overseas·auth, group은 그룹명으로 선필터. 스펙 인덱스가 한글이라 한글 검색이 기본이고, API ID(ka10081)나 필드 코드(stk_cd)로도 찾습니다 |
spec_show(api_id) | 특정 API의 요청·응답 필드 계약 상세 |
spec_groups() | market × group별 API 수 목록 — 필터에 쓸 값 확인용 |
get_example(api_id) | 실행 가능한 예제 코드 반환. 주문·환전·토큰 등 쓰기성 API 19개는 응답에 safety 경고 필드가 붙습니다 |
설계에서 눈여겨볼 지점은 get_example의 출처가 서버 코드에 고정돼 있고 환경변수로 바꿀 수 없다는 것입니다.
공식 문서는 그 이유를 "다른 저장소의 코드가 공식 예제로 서빙되는 경로를 원천 차단하기 위한 설계"라고 적어 두었습니다.
아직 저장소에 게시되지 않은 API의 예제를 요청하면 404 안내가 돌아옵니다.
{
"mcpServers": {
"kiwoom-spec": {
"command": "uv",
"args": ["run", "--frozen", "--directory", "/path/to/mcp_spec", "kiwoom-spec-mcp"]
}
}
}
env가 없습니다. 자격증명이 필요 없으니 넣을 것도 없습니다.
--frozen은 uv.lock에 고정된 버전만 쓰게 해 기동을 빠르고 재현 가능하게 만드는 옵션입니다.
3. kiwoom-exec-mcp — 도구 6개와 마스킹
| 도구 | 정책 | 하는 일 |
|---|---|---|
kiwoom_commands(market, group) | — | 실행 가능한 command_path 목록 |
kiwoom_help(command_path) | — | 명령 옵션 계약 확인 |
kiwoom_query(command_path, options) | 조회만 | 조회 실행, JSON 고정. 계좌번호는 정책에 따라 자동 마스킹 |
kiwoom_order_preview(...) | 주문(env 게이트) | 미전송 주문 확인 |
kiwoom_order_submit(..., confirm) | 주문(env 게이트) | 최상위 confirm=true일 때만 실제 전송 |
kiwoom_debug_headers() | 진단(env 게이트) | 도착 헤더의 이름·길이만 반환(값은 반환하지 않음). KIWOOM_MCP_DEBUG_HEADERS=1일 때만 등록 |
options dict는 CLI 플래그로 그대로 변환되므로,
confirm·profile·mode를 options 안에 넣으면 안 됩니다.
이 서버는 내부적으로 kiwoomcli를 그대로 호출하는 구조라,
키움 REST API 자체의 제약이 그대로 따라옵니다.
4. 인증 — 키는 env로만
로컬 stdio 방식에서는 자격증명을 MCP 클라이언트 설정의 env로만 주입합니다.
공식 문서는 "도구 인자로 키를 받는 방식은 쓰지 않는다 — 도구 인자는 대화 트랜스크립트에 평문으로 남기 때문"이라고 이유까지 적어 두었고,
앞으로도 추가되지 않을 것이라고 못 박았습니다.
{
"mcpServers": {
"kiwoom-exec": {
"command": "uv",
"args": ["run", "--frozen", "--directory", "/path/to/mcp_exec", "kiwoom-exec-mcp"],
"env": {
"KIWOOM_MODE": "demo",
"APP_KEY": "<모의투자 앱키>",
"APP_SECRET": "<모의투자 시크릿>",
"KIWOOM_MCP_ALLOW_ORDERS": "0"
}
}
}
}
키 이름은 모드와 무관하게 항상 APP_KEY·APP_SECRET이고,
모의투자(demo)와 실전(real)은 KIWOOM_MODE 한 줄로 구분합니다.
서버가 내부에서 _MOCK 이름으로 매핑해 줍니다.
kiwoomcli setup을 마친 머신이라면
키 대신 KIWOOM_PROFILE에 별칭을 넣어 대체할 수 있습니다.
env를 비워 두지 마십시오.
공식 문서는 env가 비면 로컬 환경에 이미 설정된 자격증명으로 폴백할 수 있고, 그게 실전 계좌일 수 있다고 경고합니다.
항상 위 예시처럼 KIWOOM_MODE와 키를 명시적으로 지정하십시오.
API 키를 넘길 때의 일반 원칙과 같은 맥락입니다.
5. 주문 게이트 — "1"과 confirm=true
여기가 이 서버 설계의 핵심입니다. 게이트가 두 겹입니다.
게이트 ① — 도구가 존재하지 않는다
KIWOOM_MCP_ALLOW_ORDERS가 정확히 "1"일 때만 주문 도구 2개가 등록됩니다.
이 값을 주지 않은 설정에는 주문 표면 자체가 없습니다.
AI가 주문을 내려고 해도 호출할 도구가 목록에 없습니다.
"true"·"TRUE"·"yes"는 참으로 해석되지 않습니다.
전부 꺼짐으로 처리되며, 값을 지운 ""나 키 자체를 뺀 것과 동일합니다.
오타로 주문이 열리지 않게 만든 설계입니다.
공식 예시가 "0"을 미리 넣어 두라고 권하는 이유도 같습니다 — 안전하게 꺼진 상태로 토글이 눈에 보이게 하려는 것입니다.
같은 규칙이 KIWOOM_MCP_DEBUG_HEADERS에도 적용됩니다.
게이트 ② — confirm=true
게이트 ①을 열어도 kiwoom_order_submit은 최상위 confirm=true를 명시적으로 받아야 실제로 전송합니다.
넘기지 않으면 미전송 안내만 돌아옵니다. 국내·해외 주문 쓰기 모두 동일합니다.
그런데 confirm은 AI가 채울 수 있는 값입니다.
공식 문서의 표현을 그대로 옮기면 "confirm은 호출자(AI 포함)가 설정할 수 있는 값"이고,
"사람의 실제 승인은 MCP 클라이언트의 도구 실행 승인 UI에 의존"합니다.
그래서 문서가 곧바로 덧붙이는 문장이 "주문을 자동 승인하도록 클라이언트를 설정하지 마세요"입니다.
게이트 ②는 실수를 막는 장치이지, AI의 판단을 막는 장치가 아닙니다.
실제 안전선은 사람이 눌러야 하는 승인 쪽에 있습니다.
6. 설치 두 갈래
A. Claude Desktop — .mcpb 번들
저장소 mcpb/ 폴더에 사전 빌드된 번들 두 개가 올라와 있습니다 —
kiwoom-spec-mcp-1.0.0.mcpb와 kiwoom-exec-mcp-1.0.0.mcpb.
설정 JSON을 손으로 쓰지 않아도 됩니다.
파일을 더블클릭하거나, 실행 중인 Claude Desktop 창에 드래그 앤 드롭하거나,
설정 → 확장 프로그램 → 고급 설정 → 확장 프로그램 설치에서 고르면 됩니다.
설치 화면에서 kiwoom-exec-mcp는 세 가지를 묻습니다 —
App Key / App Secret(보안 입력란), 계좌 종류(기본 demo),
주문 도구 활성화 여부(기본 0 = 꺼짐, 조회만).
kiwoom-spec-mcp는 입력할 필드가 없습니다.
조용히 실패하는 지점.
Claude Desktop은 Node.js 런타임은 내장하지만 Python과 uv는 내장하지 않습니다.
시스템에 Python 3.13 이상과 uv가 없으면 설치가 막히거나,
설치는 되어도 도구 목록이 비어 보이는 식으로 조용히 실패합니다.
최초 실행 때는 uv가 나머지 의존성을 내려받는데, kwcli가 pandas·numpy를 물고 있어
약 140MB, 수십 초가 걸립니다. Linux는 지원하지 않습니다.
B. CLI 클라이언트 — 설치 스크립트
Claude Code나 Codex 같은 CLI 클라이언트를 쓴다면 mcpb/의
setup-mcp-cli.sh(macOS·Linux) 또는 setup-mcp-cli.ps1(Windows)을 쓰거나,
앞의 mcpServers JSON을 직접 넣습니다.
저장소 루트의 SETUP-MCP.md는 아예 AI 에이전트가 읽고 설치를 수행하도록 쓰인 문서라,
REPOSITORY_URL·REPO_DIR·EXPECTED_TOOL 같은 설치 메타데이터가 텍스트 블록으로 박혀 있습니다.
로컬에서 직접 띄워 볼 수도 있습니다.
cd mcp_spec
uv sync --frozen
uv run kiwoom-spec-mcp # 기본 전송: stdio
cd ../mcp_exec
uv sync --frozen
uv run kiwoom-exec-mcp
7. 원격(HTTP) 전송과 헤더 인증
기본 전송은 stdio지만, KIWOOM_MCP_TRANSPORT=http로 streamable HTTP를 켤 수 있습니다.
포트는 KIWOOM_MCP_PORT > PORT > 기본 8000 순으로 결정되고,
바인드 주소 기본값은 127.0.0.1입니다.
이 경로에서는 자격증명을 요청 헤더로 받습니다 —
x-kiwoom-app-key · x-kiwoom-app-secret · x-kiwoom-mode.
| 환경변수 | 기본값 | 역할 |
|---|---|---|
KIWOOM_MCP_MAX_CONCURRENCY | 8 | 동시 kiwoomcli subprocess 상한 |
KIWOOM_MCP_TOKEN_TTL | 900 | HTTP 경로에서 서버 RAM에 두는 접근 토큰 상한(초). 0이면 요청마다 발급. 디스크에 쓰지 않습니다 |
KIWOOM_MCP_RATELIMIT | 0(off) | 윈도우당 최대 요청 / IP |
KIWOOM_MCP_RATELIMIT_APPKEY | 0(off) | 윈도우당 최대 요청 / AppKey 지문 |
KIWOOM_MCP_RATELIMIT_WINDOW | 60 | rate limit 윈도우(초) — 두 축이 공유 |
문서가 명시한 함정이 하나 있습니다 — HTTP rate limit 두 축은 함께 켜야 의미가 있고, 한쪽만 켜면 우회됩니다. IP만 제한하면 AppKey를 그대로 둔 채 IP를 바꾸면 되고, 그 반대도 마찬가지이기 때문입니다. 키움 서버 자체의 429 제한과는 별개의 층이라는 점도 기억해 두십시오.
8. 이걸로 자동매매가 되나
안 됩니다. 정확히는 용도가 다릅니다. MCP 서버는 사람이 AI와 대화하는 동안 조회·확인·코드 찾기를 대신하게 하는 도구이고, 호출 하나하나가 클라이언트의 승인 흐름을 거칩니다. 반면 자동매매 봇은 사람 없이 장중 내내 돌아야 하므로 스케줄링, 토큰 재발급, 유량 제한 재시도, 부분 체결 처리, 장애 복구, 그리고 손실이 커졌을 때 멈추는 판단이 따로 필요합니다.
공식 문서가 밝혀 둔 제약도 봇 관점에서는 그대로 걸립니다.
- 너무 짧은 간격으로
kiwoom_query를 반복 호출하면 유량 제한(429) 오류가 납니다. - 모의투자(
demo) 모드에서는 환율 조회와 주문가능금액 조회가 거절됩니다. - 현재가 조회(
domestic quotes price) 응답에는 전일대비 값이 들어 있지 않아 현재가와 전일 종가의 차이로 직접 계산해야 합니다. overseas orders cancel은 전량만 취소되고,overseas orders modify는 수량을 바꿀 수 없고 가격만 바꿉니다(원주문이 STOP이면stop_price필수). 국내 취소는qty로 부분 취소가 됩니다.- 프로필·계좌마다 거래 가능한 시장이 달라, 결과가 빈 목록이면 먼저
KIWOOM_PROFILE·KIWOOM_MODE로 고른 계좌를 확인해야 합니다.
그래서 언제 유용한가.
337개 API 중 내가 원하는 기능이 어느 command_path에 있는지 찾는 단계,
필드 이름과 응답 형태를 확인하는 단계, 예제 코드를 꺼내 오는 단계 —
즉 만들기 전의 탐색에서 시간을 크게 줄여 줍니다.
kiwoom-spec-mcp는 자격증명조차 필요 없으니 여기부터 붙이는 것이 안전합니다.
자주 묻는 질문
키움증권 MCP 서버는 어디에 있나요?
공식 공개 저장소 Kiwoom-Securities/Kiwoom-REST-API의 mcp_spec/·mcp_exec/ 폴더입니다.
Claude Desktop용 사전 빌드 번들은 mcpb/에 kiwoom-spec-mcp-1.0.0.mcpb·kiwoom-exec-mcp-1.0.0.mcpb로 올라와 있습니다.
MCP를 붙이면 AI가 마음대로 주문을 낼 수 있나요?
기본 설정에서는 주문 도구가 등록조차 되지 않습니다.
KIWOOM_MCP_ALLOW_ORDERS가 정확히 "1"일 때만 등록되고,
그 뒤에도 confirm=true가 있어야 전송됩니다.
다만 confirm은 AI도 넣을 수 있는 값이므로,
실질적인 마지막 방어선은 MCP 클라이언트의 도구 실행 승인 화면입니다.
주문을 자동 승인하도록 설정하지 마십시오.
앱키는 어디에 넣나요?
로컬 stdio에서는 클라이언트 설정의 env로만 넣습니다.
도구 인자로 키를 받는 방식은 지원하지 않습니다(대화 기록에 평문으로 남기 때문).
Claude Desktop .mcpb 설치라면 설치 화면의 보안 입력란에만 넣고
대화창에 붙여넣지 마십시오. 원격 HTTP 배포라면 x-kiwoom-app-key 헤더를 씁니다.
이 내용을 그대로 믿어도 되나요?
이 글의 도구 이름·환경변수·기본값·제약은
2026-09-10 시점 Kiwoom-Securities/Kiwoom-REST-API 저장소 main 브랜치의
mcp_exec/README.md·mcp_spec/README.md·mcpb/README.md·SETUP-MCP.md를 직접 확인한 것입니다.
저장소와 지원 명령 범위는 서버 업데이트에 따라 바뀌므로
실제 작업 시점의 저장소 문서와 키움증권 OpenAPI 개발자센터 안내로 대조하십시오.
이 글은 개발 실무 안내이며 투자 권유나 수익 보장이 아닙니다.