Korean stocks: median price path after each DART filing type, T+1 closes, earnings. 12 tools, no key
com.aikstockdata/mcp (Model Context Protocol) Server
This MCP server provides Korean stock market and disclosure data as free JSON for AI consumption. It covers KOSPI, KOSDAQ, and KONEX, including confirmed closes and DART filings, and publishes 1-year daily per-stock price series plus KOSPI/KOSDAQ index data.
🛠️ Key Features
Publishes “confirmed 종가” for KOSPI, KOSDAQ, and KONEX stocks
Includes DART disclosures (“공시”) by filing type
Provides median price path after each DART filing type
Adds T+1 close data
Publishes per-stock, 1-year daily time series
Tool count: 12
Topics include model context protocol, MCP, and Korean stock market data
🚀 Use Cases
Analyze how price movements change after DART filing types
Correlate disclosure events with subsequent trading outcomes (T+1 closes)
Build workflows using KOSPI/KOSDAQ index and stock daily series
⚡ Developer Benefits
MCP endpoint: https://mcp.aikstockdata.com/mcp
No signup, API key, or request limits indicated
Public JSON is hosted via the site (index at index.json with coverage)
⚠️ Limitations
Included stock universe changes daily; counts can become outdated
Stock coverage varies over time via coverage (universe_n, published_n, excluded_n)
Start here for "how was the Korean market today?" — index levels, breadth, 52-week high/low counts, top-3 disclosures, growth top-3, movers and disclosure-type counts in one call. Then drill down with get_stock / list_stocks / get_disclosures. Coverage: every KOSPI, KOSDAQ and KONEX stock in the FSC price feed (no ETFs/ETNs); counts are in index.json coverage. | "오늘 시장 어땠어?"의 출발점 — 지수·등락 폭·주요 공시·성장 랭킹·등락률 상하위를 한 번에. 이어서 get_stock / list_stocks / get_disclosures 로 파고들면 됩니다.
Parameters
No parameters.
Raw schema
{
"type": "object",
"properties": {}
}
search_stock
Find a ticker from part of the name — Korean or Latin, case-insensitive — or a 6-digit code, across every listed stock we publish (KOSPI, KOSDAQ, KONEX; no ETFs). Korean readings of Latin names also match ('네이버' finds NAVER, '케이티' finds KT/KTis). Romanised Korean does not ('samsung' returns nothing; '삼성' works). Up to 10 matches, market-cap sorted. | 이름 일부(한글·영문 모두, 대소문자 무시)나 6자리 코드로 찾습니다. 영문 이름의 한글 읽기도 매치됩니다('네이버'→NAVER, '케이티'→KT·KTis). 다만 한국어의 로마자 표기는 안 됩니다('samsung' 0건, '삼성'은 여러 건). 수록 전 종목 · 시총순 최대 10건.
Parameters1
query
string
required
Stock name or code fragment, e.g. '삼성' or '005930'. | 종목명 또는 6자리 코드의 일부
Raw schema
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Stock name or code fragment, e.g. '삼성' or '005930'. | 종목명 또는 6자리 코드의 일부"
}
},
"required": [
"query"
]
}
get_stock
One Korean stock by 6-digit code: T+1 confirmed close & change, market cap, latest financials from the latest periodic report (revenue / operating income / net income, with YoY; Korean reports are cumulative year-to-date, so H1 = Jan-Jun, not Q2 alone), and ranking signals. Two as-of dates move independently — price (quote_as_of) and filings (disclosure_through); the response header carries both, do not merge them into one "today". null means not provided, never 0. Name → code: search_stock. 250 trading days of prices: get_history. Filings with receipt times: get_disclosures. Screening a list: list_stocks. | 6자리 코드로 한 종목 — 확정 종가·등락·시총·최근 정기보고서 실적(전년비 · 반기는 1~6월 누적)·랭킹 신호. 기준일이 둘이고 따로 움직입니다(시세·공시) — 응답 머리말에 둘 다 실리니 하나로 합치지 마세요. null 은 '미제공'이며 0이 아닙니다. 이름으로 찾기는 search_stock, 1년 시세는 get_history, 접수 시각이 있는 공시는 get_disclosures, 조건 목록은 list_stocks.
Parameters1
code
string
required
6-digit ticker as a STRING with leading zeros kept — '000020', not 20. e.g. '005930' (삼성전자). Unknown but well-formed code returns a short note (not an error); a malformed one tells you to use search_stock. | 6자리 종목코드 **문자열**(앞자리 0 유지 — '000020'을 20으로 읽으면 안 맞습니다). 형식이 맞는데 없는 코드면 오류가 아니라 안내를 돌려주고, 형식이 틀리면 search_stock 을 안내합니다.
Raw schema
{
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "6-digit ticker as a STRING with leading zeros kept — '000020', not 20. e.g. '005930' (삼성전자). Unknown but well-formed code returns a short note (not an error); a malformed one tells you to use search_stock. | 6자리 종목코드 **문자열**(앞자리 0 유지 — '000020'을 20으로 읽으면 안 맞습니다). 형식이 맞는데 없는 코드면 오류가 아니라 안내를 돌려주고, 형식이 틀리면 search_stock 을 안내합니다."
}
},
"required": [
"code"
]
}
get_rankings
Answers "which stocks scored highest on measured DART financials?" — kind='growth' is 성장 TOP8 (max 8 rows), kind='quiet' is 조용한 실적주. Scores come from a published formula over ACTUAL filed financials only — no prices, no analyst estimates. Mechanical, not stock picks. For 52-week high/low or turnaround LISTS use list_stocks(). | "실측 재무로 점수가 높은 종목"에 답합니다 — growth 는 최대 8건, quiet 는 조용한 실적주. 시세·전망치를 쓰지 않고 DART 실측 재무만 씁니다. 52주 신고저·흑자전환 목록은 list_stocks().
Index levels (KOSPI/KOSDAQ close, change, %) and up/down breadth — nothing else. Prices are the previous session's T+1 settled close, never real-time. Index and breadth routinely disagree — the index is cap-weighted, breadth is one vote per stock — which is why both are returned; do not infer one from the other. For the full daily digest (disclosures, rankings, movers) use get_today(). | 지수와 등락 폭만 봅니다. 하루 전체 요약은 get_today(), 조건별 종목 목록은 list_stocks().
Parameters
No parameters.
Raw schema
{
"type": "object",
"properties": {}
}
get_data_urls
Direct URLs for every public dataset (JSON/CSV) — no signup, no API key. Call this BEFORE concluding something is unavailable: the tool list is not the extent of the data. Returns the endpoint catalog (quotes, disclosures, rankings, per-stock JSON, search index) plus the 30-trading-day dated archive with the exact dates held per pattern. Most AI fetch tools cut responses near 150 KB and a truncated JSON is unparseable — the catalog names a smaller alternative for every large file, so read that instead of guessing. | 전체 공개 데이터(JSON·CSV) 직링크 카탈로그 — 무가입·무키. **없다고 결론내기 전에 먼저 부르세요**: 도구 목록이 데이터의 전부가 아닙니다. 최근 30영업일 날짜별 아카이브(패턴별 보유 날짜 포함)도 함께 냅니다. 대부분의 AI 가 응답을 150KB 안팎에서 자르고 잘린 JSON 은 파싱되지 않습니다 — 큰 파일마다 소형 대체본이 카탈로그에 적혀 있으니 그쪽을 쓰세요.
Parameters
No parameters.
Raw schema
{
"type": "object",
"properties": {}
}
get_earnings
Earnings from DART, INCLUDING preliminary (잠정) results filed ~2 weeks before the regular report. Each row says whether the figure is year-to-date cumulative or a single quarter. Pass a code for one stock's history, or omit it for the largest caps. get_stock returns the REGULAR report only — use this for the newest numbers. | DART 실적 — 정기보고서보다 2주 빠른 잠정실적 포함. 행마다 누적인지 단독 분기인지 적습니다. code 를 주면 그 종목 이력, 생략하면 시총 상위. get_stock 은 정기보고서만 주므로 최신 수치는 이 도구로 보세요.
Answers "is this stock near its high or deep in a drawdown, and is volume unusual?" — 250 trading days of daily CLOSES, plus period high/low, drawdown from the high, and volume vs the 60-day average. Close-based (this 250-day history file carries daily closes only; the latest day's high/low is in the stock file), so it will differ from an HTS 52-week range. | "고점 대비 얼마나 빠졌나·거래량이 평소보다 많나"에 답합니다 — 250거래일 **종가 기준** 고저·낙폭·거래량 배수. 장중 고저가 아니라 HTS 52주 범위와 다를 수 있습니다.
Parameters2
code
string
required
6-digit ticker | 6자리 종목코드
days
number
optional
recent N days to list, default 20, max 60 — for all 250 rows read /data/public/s/{code}_history.json | 나열할 최근 일수(기본 20, **최대 60**. 250행 전체는 s/{code}_history.json)
Raw schema
{
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "6-digit ticker | 6자리 종목코드"
},
"days": {
"type": "number",
"description": "recent N days to list, default 20, max 60 — for all 250 rows read /data/public/s/{code}_history.json | 나열할 최근 일수(기본 20, **최대 60**. 250행 전체는 s/{code}_history.json)"
}
},
"required": [
"code"
]
}
get_disclosure_impact
Answers "what usually happened after this kind of filing?" — median MARKET-ADJUSTED return at +1/+5/+20 trading days per DART filing type (+20 only where that type has enough samples — see h20_status), with 95% intervals, sample window and n. A historical record, not a forecast. Coverage: every KOSPI, KOSDAQ and KONEX stock in the FSC price feed (no ETFs/ETNs); counts are in index.json coverage. | "이 공시 나오면 보통 어땠나"에 답합니다 — 공시 유형별로 접수 이후 1·5·20거래일 뒤까지(20거래일은 표본이 찬 유형만) 시장 등락을 뺀 수익률 중앙값·95% 구간·표본기간. 과거 기록이며 예측·추천이 아닙니다.
Parameters1
label
string
optional
filing type in Korean, e.g. 배당 결정 | 공시 유형(선택)
Raw schema
{
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "filing type in Korean, e.g. 배당 결정 | 공시 유형(선택)"
}
}
}
get_earnings_calendar
Answers "who has filed this quarter's results, who hasn't, and what came in since last time?" — filed / not-yet lists against the statutory deadline, plus a diff of filings new since the previous publish. Built for stateless agents: polling this replaces a webhook. | "누가 냈고 누가 아직인가 · 지난번 이후 새로 뜬 건 뭔가"에 답합니다. 법정 마감 D-day 와 직전 발행 대비 신규 목록까지. 상태를 못 들고 다니는 에이전트를 위한 도구입니다.
Parameters2
view
string
optional
summary(기본) | not_yet(미접수 목록) | filed(접수 목록) | new(직전 발행 이후 신규)
limit
number
optional
목록 최대 건수(기본 20, 최대 100)
Raw schema
{
"type": "object",
"properties": {
"view": {
"type": "string",
"description": "summary(기본) | not_yet(미접수 목록) | filed(접수 목록) | new(직전 발행 이후 신규)"
},
"limit": {
"type": "number",
"description": "목록 최대 건수(기본 20, 최대 100)"
}
}
}
get_disclosures
Answers "what was filed, and when exactly?" — DART filings with RECEIPT TIME (HH:MM) and session (pre-open / intraday / after-close), filterable by date, type and importance. OpenDART's filing-list API returns the receipt date only; we add the HH:MM. About half of tracked filings arrive AFTER the close (daily counts: /data/public/press_owl_filings.csv), so that day's price move is not a reaction to them. date=today serves the 15:00 intraday collection (no importance scores yet); any other date serves the ranked list of the last 7 days. | "무슨 공시가 몇 시에 났나"에 답합니다 — 접수 시각(HH:MM)과 장 구분까지. 공개 공시 목록 API(OpenDART)는 접수 날짜까지만 줍니다 — 시:분은 저희가 모읍니다. 날짜·유형·중요도로 거를 수 있습니다. 추적 유형 기준 **절반 안팎이 장 마감 후** 접수라(날짜별은 press_owl_filings.csv) 그날 등락은 그 공시의 반응이 아닙니다. date=오늘이면 15:00 장중 수집본(아직 중요도 점수 없음), 다른 날짜면 최근 7일 상위 목록입니다.
Parameters5
date
string
optional
YYYYMMDD (예: 20260910). "today" 도 받습니다 — 오늘(KST)로 풀어 장중 수집본을 줍니다. 생략하면 최근 7일 중요도 상위 목록입니다. | YYYYMMDD, or "today" for the intraday snapshot; omit for the last 7 days by importance.
session
string
optional
pre_open | intraday | after_close
label
string
optional
공시 유형 부분일치(예: 배당, 자사주)
min_score
number
optional
중요도 점수 하한(장중 수집본에는 점수가 없습니다)
limit
number
optional
최대 건수(기본 20, 최대 100)
Raw schema
{
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "YYYYMMDD (예: 20260910). \"today\" 도 받습니다 — 오늘(KST)로 풀어 장중 수집본을 줍니다. 생략하면 최근 7일 중요도 상위 목록입니다. | YYYYMMDD, or \"today\" for the intraday snapshot; omit for the last 7 days by importance."
},
"session": {
"type": "string",
"description": "pre_open | intraday | after_close"
},
"label": {
"type": "string",
"description": "공시 유형 부분일치(예: 배당, 자사주)"
},
"min_score": {
"type": "number",
"description": "중요도 점수 하한(장중 수집본에는 점수가 없습니다)"
},
"limit": {
"type": "number",
"description": "최대 건수(기본 20, 최대 100)"
}
}
}
list_stocks
Return the LIST of stocks matching a condition — turnaround to profit, 52-week high/low, growth or quiet-performer rankings — with optional market-cap range and a cap-to-operating-income multiple ceiling. Other tools give counts; this one gives the names. | 조건에 맞는 종목 목록을 돌려줍니다 — 흑자전환·52주 신고저·성장/조용한 실적주. 시총 범위와 시총÷연환산영업이익 배수 상한도 걸 수 있습니다. 다른 도구가 개수를 준다면 이건 목록을 줍니다.
무슨 공시가 몇 시에 났나 — 접수 시각(HH:MM)과 장 구분(장전·장중·장마감후). 공개 API 어디에도 없는 값입니다
list_stocks
조건에 맞는 종목 목록 — 흑자전환·52주 신고저에 시총÷연환산영업이익 배수 상한까지
get_earnings
잠정 실적 포함 — 정기보고서보다 2주 빠릅니다
get_earnings_calendar
누가 냈고 누가 아직인가 — 법정 마감 D-day, 직전 발행 대비 신규 목록. 상태를 못 들고 다니는 에이전트에겐 이게 웹훅을 대신합니다
get_history
종목별 일별 시세(쌓인 전 구간) + 52주 고저·고점 대비 낙폭·거래량 배수
get_disclosure_impact
공시 유형별로 그 뒤 1·5거래일 주가(시장 등락을 뺀 값). 20거래일은 그 유형의 표본이 차면 나옵니다 — 응답의 h20_status 를 보세요
get_data_urls
원자료 주소 카탈로그 — 도구에 없는 것도 JSON 으로 다 있습니다
그다음엔 그냥 물어보면 됩니다: "오늘 한국 시장 어땠어?" · "삼성전자 최근 공시 정리해줘" ·
"흑자전환한 종목 중에 시총이 영업이익의 10배 안 되는 것만"
MCP 없이 — 주소만 붙여넣기
code
https://aikstockdata.com/data/public/today.json 을 읽고 오늘 한국 시장을 요약해줘.
Python
python
import urllib.request, json
defget(path):
url = "https://aikstockdata.com/data/public/" + path
# User-Agent 를 반드시 준다. CDN 봇 필터가 파이썬 기본 UA 를 403 한다.
req = urllib.request.Request(url, headers={"User-Agent": "my-app"})
return json.load(urllib.request.urlopen(req))
today = get("today.json") # 오늘 하루 요약 (7KB)
samsung = get("s/005930.json") # 한 종목 (5KB)
hist = get("s/005930_history.json") # 전 구간 [날짜, 종가, 거래량] · 길이는 count·period 에
★종목코드는 여섯 자리 문자열입니다. 정수로 읽으면 000020이 20이 됩니다.
pandas 를 쓴다면 dtype={"code": str} 를 반드시 주세요.
MCP 를 붙였거나 주소를 붙여넣었다면, 아래는 그대로 복사해 쓰는 질문입니다.
전부 우리 데이터로 답할 수 있는 것만 골랐습니다.
오늘 무슨 일이 있었나
code
오늘 한국 시장 어땠어? 지수랑 오른 종목 수를 같이 알려줘.
지수와 상승 종목 수는 자주 반대를 가리킵니다. 둘 다 봐야 합니다.
code
오늘 접수된 공시 중 중요도 높은 것 10건만 쉬운 말로 풀어줘.
code
오늘 장 마감 후에 나온 공시만 골라줘. 아직 종가에 반영되지 않은 것들이야.
공개 API(OpenDART)에는 접수 날짜만 있어서, 이 질문에는 따로 모은 접수 시각이 필요합니다.
한 종목을 파고들 때
code
삼성전자 최근 공시랑 분기 실적 정리해줘. 전년 동기 대비도.
code
005930 의 종가 흐름에서 최고가 대비 지금 몇 % 지점인지 계산해줘.
s/005930_history.json 한 파일로 끝납니다.
code
SK하이닉스가 최근에 낸 공시 중에 자기주식 관련된 게 있어?
여러 종목을 훑을 때
code
시가총액 상위 20개 종목의 오늘 등락률을 표로 만들어줘.
code
최근 120일 안에 실적을 발표한 종목 중 영업이익이 전년 대비 늘어난 곳을 찾아줘.
code
52주 신고가를 찍은 종목이 오늘 몇 개야?
공시가 나온 뒤에 무슨 일이 있었는지
code
배당 결정 공시 뒤 5거래일 동안 시장 대비 수익률이 어땠는지 알려줘.
신뢰구간도 같이 보여주고, 0을 포함하는지 판단해줘.
숫자만 받아 오지 말고 구간을 같이 물어보세요. 현재 숫자가 있는 56칸 중
41칸의 95% 구간이 0을 포함합니다. 그 사실을 감추지 않는 것이 이 표의 요점입니다.
code
공시 접수 시각이 장 시작 전인 건과 장 마감 후인 건을 나눠서,
공시 당일 수익률 중앙값을 각각 계산해줘.
접수 시각이 없으면 이 질문 자체가 불가능합니다.
데이터를 검증하고 싶을 때
code
https://aikstockdata.com/data/public/index.json 을 읽고
지금 데이터가 며칠 전 것인지, 신선도 상태가 뭔지 알려줘.
신선도는 저희 주장이 아니라 계산값입니다. 오래되면 스스로 stale 이라고 밝힙니다.
code
disclosure_impact.json 의 per_event 를 받아서 배당 결정 유형의 +5일
중앙값을 직접 다시 계산해줘. cluster 로 중복을 먼저 제거하고.
집계를 반박하라고 개별 값을 싣습니다. 같은 cluster 는 한 번만 세야 합니다
— 안 그러면 저희가 저질렀던 중복 계산이 재현됩니다.
왜 만들었나
한국 시장 데이터는 AI가 쓰기 어렵습니다. 공식 출처(금융위원회 공공데이터포털,
금융감독원 DART)는 API 키를 먼저 받아야 하고, 한글 필드명이 그대로인 XML·JSON을 주며,
값이 없는 것인지 0인 것인지 구분할 방법을 주지 않습니다.
이 프로젝트는 그것을 LLM이 그대로 읽는 자기설명형 JSON으로 정규화하고, 주소 하나만
붙여넣으면 되는 MCP 서버를 얹었습니다.
실질적인 차이는 자격증명입니다. 한국 주식 MCP 서버 대부분은 DART·증권사 API를 실시간으로
중계하기 때문에 첫 호출 전에 키 발급이 필요합니다. 이 서버는 미리 만들어 둔 공개 파일을
내보내므로 주소를 붙여넣는 순간부터 동작합니다.
공개 API 로는 바로 안 나오는 것
1. ★공시 접수 시각 (HH:MM) — 공개 API 어디에도 없습니다
DART 공시검색 API가 주는 접수 정보는 날짜(YYYYMMDD)뿐입니다. 개별 공시 뷰어에도,
공시검색 화면에도 시:분이 없습니다. 그런데 같은 날짜의 공시라도 장중에 나온 것과
장 마감 후에 나온 것은 그날 종가에 대해 정반대를 뜻합니다 — 앞의 것은 이미 주가에
반영됐고, 뒤의 것은 아직 반영되지 않았습니다.
저희는 시:분이 나오는 DART 최근공시 목록에서 이 값을 따로 모아 붙입니다.
code
https://aikstockdata.com/data/public/disclosures.json # 저녁 발행(18:30 전후) · events[].receipt_time · session
https://aikstockdata.com/data/public/disclosures_intraday.json # 15:00 발행 · 그날 접수분 중 우리가 분류하는 유형(label)
https://aikstockdata.com/data/public/dart_receipt_times.json # 접수번호 ↔ 시각 대조표
session 은 정규장(09:00~15:30) 기준 세 갈래입니다.
값
뜻
그날 종가 움직임은
pre_open
~09:00 접수
전체가 공시 뒤 — 반응으로 읽을 수 있는 유일한 경우
intraday
09:00~15:30
앞부분은 공시 이전 — 섞여 있습니다
after_close
15:30~
전체가 공시 앞 — 공시 반응이 아닙니다
python
d = get("disclosures.json")
late = [e for e in d["events"] if e["session"] == "after_close"]
# 오늘 장 마감 뒤에 나온 공시 — 아직 종가에 반영되지 않았다
실측으로 접수 건의 40% 안팎이 장 마감 후입니다. 시각이 없으면 그 40%를 그날 종가의
반응으로 잘못 읽게 됩니다.
2. 공시 유형별로 그 뒤에 실제로 무슨 일이 있었나
공시마다 그 종목의 일별 종가와 소속 지수를 붙여 두었습니다. "이런 종류의 공시 뒤에
시장은 어떻게 움직였나" 를 기록으로서 물을 수 있습니다 — 예측이 아닙니다.
유형별로 +1 / +5거래일 뒤의 시장조정 수익률 중앙값(종목 수익률 − 같은 기간
소속 지수 수익률)과 시장을 이긴 비율을 함께 냅니다. +20거래일은 그 유형의 표본이
차면 유형별로 나옵니다 — 응답의 h20_status 를 보세요(없다고 결론내지 말 것).
개별 값은 DART 접수번호를 열쇠로 싣기 때문에 원문과 대조할 수 있습니다.
표본이 20건 미만인 유형에는 숫자를 넣지 않습니다. 몇 건짜리 중앙값은 우연을 통계로
둔갑시킵니다. 95% 구간도 함께 싣는데, 현재 숫자가 있는 56칸 중 41칸의 구간이 0을 포함합니다.
그 사실을 감추지 않는 것이 이 표의 요점입니다.
3. 종목당 일별 시세가 한 파일
s/{종목코드}_history.json — 쌓인 전 구간의 [날짜, 종가, 거래량](2026-09-14 발행부터 250거래일에서 자르지 않고 매 거래일 한 행씩 늘어난다 — count·period·max_days(null)·retention 이 그 사실을 말한다).
행을 객체가 아니라 배열로 둡니다. 여섯 개 키 이름을 250번 반복하면 정보 없이 파일만
두 배가 됩니다(실측 14.3KB → 6.8KB).
4. 지수와 상승 종목 수를 따로 줍니다 — 둘이 어긋나기 때문에
today.json 은 KOSPI·KOSDAQ 종가와 상승·하락 종목 수를 둘 다 싣습니다. 이 둘은
자주 반대를 가리킵니다. 2026-08-03 에는 코스피가 5.12% 내렸는데 855종목이 오르고
518종목이 내렸습니다 — 지수는 시총 가중이고 종목 수는 한 종목 한 표이기 때문입니다.
대부분의 출처는 둘 중 하나만 주고 나머지는 같으려니 하게 만듭니다.
5. 거래일마다 날짜별 주소가 남습니다
https://aikstockdata.com/market/{YYYY-MM-DD} — 주소의 날짜는 발행일이 아니라
종가 기준일입니다. (한 번 틀린 적이 있습니다. 폭락한 날 페이지가 몇 시간 동안
+17.9% 머리기사를 달고 있었습니다. 지금은 날짜와 데이터가 어긋날 수 없습니다.)
인용용 월간 동결본은 허깅페이스의 korea-equity-daily-YYYY-MM 에 따로 있습니다 —
한 번 올리고 다시 고치지 않으므로 이름만 적으면 됩니다(리비전 해시 불필요).
main 은 갱신될 때마다 통째로 덮어쓰이는 자리라 인용에 쓸 수 없습니다.
그 스냅샷이 언제 것인지는 데이터셋 카드 첫 줄이 날짜로 밝힙니다 —
매 거래일 갱신되는 것은 미러가 아니라 사이트의 원본입니다.
파일로 직접 받기 — 무엇이 얼마나 큰가
MCP 없이 주소만 쓸 때 필요한 표입니다. 크기는 정확한 수가 아니라 띠입니다 —
파일은 매 거래일 커지므로 여기 수를 박아 두면 그날 저녁부터 거짓이 됩니다.
2026-09-21 18:10 KST 기준이고, 현재 값은 언제나
index.json 의 file_bytes 에 있습니다.
⚠️ 대부분의 AI fetch 도구는 응답을 150 KB 안팎에서 자릅니다. 잘린 JSON 은
파싱되지 않습니다. 지금 35개 중 12개가 그 문턱을 넘습니다 —
표에서 ★큼 으로 표시된 것은 소형 대체본을 쓰세요. 대체본 목록은 카탈로그의
fetch_guide.small_alternatives 에 있습니다.
기자용 — 올빼미 공시 통계(CSV) — 날짜별 DART 접수 건수를 장전·장중·장후·시각미확보로 나눈 표와 장후 비율(%). 범위는 dart_receipt_times.json 과 같다(전건 아님).
작음 (~2 KB)
이 표 34행은 카탈로그에서 생성됩니다 — 사이트에 파일이 늘면
여기 자동으로 실립니다. 폴더 단위(종목별 s/, 날짜별 daily/)의 파일 수와 총량은
index.json 의 subtrees 에 있습니다.
필드가 무슨 뜻인지 — 사람 말고 기계에게 물어보세요
각 파일의 필드 이름·자료형·단위는 JSON Schema 9개로 따로 나갑니다.
여기 표로 옮겨 적지 않은 이유가 있습니다 — 표는 낡고 스키마는 파일과 함께 갱신됩니다.
code
https://aikstockdata.com/data/public/schemas/ ← 스키마가 있는 곳
https://aikstockdata.com/data/public/index.json ← `schemas` 배열이 전 목록
그래서 index.json 하나만 읽으면 무슨 파일이 있고 · 얼마나 크고 · 언제 것이고 ·
각 필드가 무슨 뜻인지까지 기계가 스스로 알아냅니다. 사람에게 물어볼 것이 없습니다.
설계 원칙
null 은 0이 아닙니다. 결측은 null, 0 은 실제로 측정된 0입니다(거래 없음 등,
has_trade: false 로 표시).
'기준일'이 두 개입니다.quote_as_of(시세 기준일, T+1 확정 종가)와
disclosure_through(공시 수록일)는 따로 움직입니다. 하나의 "오늘"로 합치지 마세요.
신선도는 주장이 아니라 계산값입니다.index.json → freshness.status 는 실제 경과일에서
나옵니다(fresh 4일 이내 / delayed 5~7일 / stale 8일 이상). quote_as_of_age_days 를
같이 실어 직접 검산할 수 있게 했습니다.
회계 항등식을 어기는 수치는 게시하지 않고 철회합니다. 순이익이 매출액을 넘는 등의
파싱 결과는 숫자를 지우고 공시 제목과 DART 원문 링크만 남깁니다
(value_status: "withdrawn_inconsistent").
랭킹 산식은 전부 공개돼 있습니다 — rankings.json 안에 성분별 점수까지 들어 있어
누구나 재계산할 수 있습니다.
실패도 공개합니다.notices.json 에 파이프라인 실패와 정정을 기록합니다. 실행이
실패하면 반쯤 만든 것을 내보내지 않고 마지막 정상 스냅샷을 유지합니다.
투자 권유가 아닙니다. 공개 공시에 대한 기계적 집계이며 목표주가·투자의견·매수매도
추천은 제공하지 않습니다. 설계상 그렇습니다.
없는 것
실시간·분봉 시세가 없습니다(전 영업일 확정 종가, T+1). 증권사 유래의 컨센서스·목표주가·
선행 PER 이 없습니다 — PER(TTM)·PBR 은 공공 원천만으로(DART 정기보고서 + 확정 종가) 계산해 싣고,
못 내는 자리는 null 과 이유(pe_note·pb_note)를 적습니다. 주문 실행 기능이 없습니다.
의도된 것입니다.
출처와 라이선스
금융감독원 전자공시시스템(DART) — 공시
금융위원회 공공데이터포털 — 일별 확정 종가
발행 파일(/data/public/*)의 이용 조건은 aiksd-public-1.1 입니다.
출처를 표기하면 비영리 목적으로 인용·이용할 수 있고, 상업적 재배포는 허용하지 않습니다.
본 사이트가 공개하는 데이터(/data/public/*)는 출처를 표기하면 비영리 목적으로 인용·이용할 수 있습니다. 상업적(영리) 목적의 재배포는 어떤 경우에도 허용하지 않습니다. 시세(종가·거래량·시가총액 등)는 금융위원회 공공데이터포털이 원천이며 원천의 이용허락범위(공공누리 제4유형: 출처표시·상업적 이용금지·변경금지)와 제공기관 안내도 함께 따라야 하고, 공시 내용은 금융감독원 전자공시시스템(DART)의 이용 조건을 따릅니다. 다만 증권사 실시간 시세 등 원천의 실시간 정보를 그대로 재배포하는 것은 허용되지 않습니다.
이 저장소의 코드는 MIT 라이선스입니다(LICENSE 참조). 위 데이터 라이선스는 발행되는
JSON·CSV 파일에 적용되며 이 저장소의 코드에는 적용되지 않습니다.
발행 데이터는 정보 제공 목적이며 투자 조언이 아닙니다. 기계가 집계한 과거 기록이고
어떤 종목의 매수·매도를 권하지 않습니다.
저장소 구성
code
mcp/worker.js MCP 서버 (Cloudflare Worker · 상태 없는 JSON-RPC over HTTP)
examples/ 바로 돌아가는 Python · JavaScript · 셸 예제
발행 파일을 만드는 데이터 파이프라인은 별도로 관리합니다.
English
The Korean documentation above is the primary reference. This section mirrors it.
Why this exists
Korean market data is hard for AI to use. The official sources (금융위원회 public data portal,
금융감독원 DART) require API keys, return raw XML/JSON with untranslated Korean field names, and
give you no way to tell whether a number is missing or actually zero.
This project normalizes them into self‑describing JSON that an LLM can read directly — and adds an
MCP server so Claude and ChatGPT can query it mid‑conversation without any setup beyond pasting a URL.
The practical difference: no credentials. Most Korean stock MCP servers proxy the DART or
brokerage APIs live, so you have to register for a key before the first call. This one serves
pre‑built public files, so it works the moment you paste the URL.
Quick start — connect an AI in 30 seconds
Claude / ChatGPT (MCP connector)
Add this URL as a custom connector in settings. No authentication.
code
https://mcp.aikstockdata.com/mcp
Claude Code — one line:
bash
claude mcp add --transport http aikstockdata https://mcp.aikstockdata.com/mcp
Or, for tools that take a config file (claude_desktop_config.json and friends):
Whole market in one call — breadth, tone, top filings
search_stock · get_stock
Find a ticker · full detail (price, financials, filings)
get_rankings · get_market_summary
Ranking tables · market digest
get_disclosures
What was filed, and when exactly — receipt time (HH:MM) and session (pre-open / intraday / after-close). Not exposed by any public Korean API
list_stocks
The list, not just the count — turnaround to profit, 52-week high/low, with a cap÷annualised-operating-income ceiling
get_earnings
Preliminary results included — filed ~2 weeks before the regular report
get_earnings_calendar
Who has filed, who hasn't — statutory deadline D-day plus a diff of what's new since the previous publish. For stateless agents, polling this replaces a webhook
get_history
Daily prices for one stock (its full stored span) + 52w high/low, drawdown, volume ratio
get_disclosure_impact
Market-adjusted price path at +1/+5 trading days after each filing type; +20 appears per type once it has enough samples — read h20_status
get_data_urls
Catalogue of raw JSON — the tool list is not the extent of the data
Then just ask: "오늘 한국 시장 어땠어?" or "Samsung Electronics latest disclosures?" or
"Which stocks turned profitable and trade under 10× operating income?"
Any AI, without MCP — paste a URL
code
https://aikstockdata.com/data/public/today.json 을 읽고 오늘 한국 시장을 요약해줘.
Why the User-Agent header? The CDN's bot filter rejects the default Python-urllib user agent with a 403. requests, curl, httpx and browser fetch work without it. Sending any UA string is enough.
from datasets import load_dataset
px = load_dataset("aikstockdata/korea-equity-daily", "daily_prices", split="train")
# 880,740 rows across 2,787 stocks (2025-05-28 → 2026-09-17) — a dated snapshot. The live# per-stock files keep growing. Counts come from the dataset card and change every# trading day — index.json's `coverage` has the live universe size.
Four configs: daily_prices, stocks, filing_impact_summary, and filing_price_impact —
the individual filings behind the summary, one row each, so the published medians can be
recomputed rather than taken on trust.
The loadable files are JSON Lines, not CSV. A Korean ticker is six digits including leading
zeros, and type inference on CSV turns 000020 into 20, at which point it joins to nothing.
The snapshot is frozen at its upload date — the endpoints below are the ones that stay current.
Endpoints
Start at the catalog — it lists every file with its size, freshness and archive dates:
code
https://aikstockdata.com/data/public/index.json
Endpoint
What it is
Size
today.json
One‑day digest — KOSPI/KOSDAQ index close, breadth, top filings, rankings
small (~11 KB)
s/{code6}.json
One stock — quote, financials, recent filings, signals
small (~6 KB × 2,837 files)
s/{code6}_history.json
One stock, full stored history — [date, close, volume]; count/period/retention say how much
small (~11 KB × 2,796 files)
disclosure_impact.json
What happened after each filing type — market‑adjusted median return at +1/+5 trading days (+20 once that type's sample is full — see h20_status)
Sizes are bands, not fixed numbers. Files grow every trading day, so a number
written here is stale the next evening. Measured 2026-09-21 18:10 KST from
index.json — its file_bytes always
has the current byte count, and fetch_guide.small_alternatives names the smaller file to
use instead. Right now 12 of 35 files are over the 150 KB
truncation threshold.
Also: /openapi.json (OpenAPI 3.1 — drop it into a
ChatGPT custom GPT as an Action, or generate an SDK) ·
/llms.txt ·
/llms-full.txt ·
/feed.xml ·
JSON Schemas under /data/public/schemas/
⚠️ Large files get truncated by AI fetch tools
Most AI fetch tools cut responses at 50–150 KB, and a truncated JSON is unparseable — which
produces silently wrong answers rather than an error. index.json carries a machine‑readable
fetch_guide block with the small alternative for every large file. Rule of thumb: if you need
one stock, always use s/{code}.json.
What the public APIs don't give you directly
0. Filing receipt times (HH:MM) — not in the public DART API
The DART search API returns a receipt date, never a time. Neither does the filing viewer,
nor the search screen. But an intraday filing and an after-close filing mean opposite things
for that day's close: the first is already in the price, the second is not.
code
/data/public/disclosures.json # around 18:30 KST · events[].receipt_time and .session
/data/public/disclosures_intraday.json # 15:00 KST · filings received that day, for the types we classify (label)
/data/public/dart_receipt_times.json # receipt number to time lookup
session splits on the Korean regular session (09:00-15:30): pre_open (the whole day
follows the filing — the only identifiable case), intraday (mixed), after_close (the whole
day precedes it — not a reaction at all). Measured: roughly 40% of filings arrive after the
close. Without the minute, that 40% gets read as same-day reaction.
1. What actually happened after each filing type
Every filing is joined to that stock's daily closes and to its market index, so you can ask
"what did the market do after this kind of filing, historically?" — as a record, not a forecast.
For each filing type: the median market‑adjusted return at +1 / +5 trading days
(stock return minus its own index over the same window), plus how often it beat the market.
+20 trading days appears per type once that type's sample is full — read h20_status
in the response before concluding it's missing.
Per‑filing values are keyed by DART receipt number, so you can join back to the original document.
(배당 결정 = dividend decision. Live values as of 2026.09.21; they change every trading evening — always read the interval from the file, not from this page. This block is generated from the live summary, not typed here.)
Read median_ci95 before median_excess_pct. Of the cells currently carrying a
number, most have an interval spanning zero — those values are not distinguishable
from zero. The interval ships in the same object so you cannot take the median alone
by accident.
Types with fewer than 20 samples are not given a number — a median over a handful of cases
turns coincidence into a statistic. This is a record of what happened, not a claim about cause,
and not a prediction.
2. Each stock's full daily price history, as one small file
s/{code6}_history.json — the stock's full stored history of [date, close, volume]; since the 2026-09-14 publish it is not cut at 250 days and gains one row every trading day.
Rows are arrays, not objects: repeating six key names on every row doubles the file for no
information (measured on a 250-row file: 14.3 KB → 6.8 KB).
3. Index and breadth are kept separate — because they disagree
today.json carries both the KOSPI/KOSDAQ close and the advance/decline count, because they
routinely point opposite ways. On 2026‑08‑03 KOSPI fell 5.12% while 855 stocks rose and 518 fell:
the index is cap‑weighted, the count is one vote per stock. Most sources give you only one of the
two and let you assume they agree.
4. A dated page per trading day
https://aikstockdata.com/market/{YYYY-MM-DD} — the URL date is the closing‑price date, not
the publish date. (We got that wrong once and a crash day carried a +17.9% headline for a few
hours. Now the date and the data cannot disagree.)
Design decisions that matter for AI
null never means zero. A missing value is null. 0 means an actual measured zero
(e.g. no trades that day, flagged by has_trade: false).
Two different "as of" dates.quote_as_of (price date, T+1 settled close) and
disclosure_through (last filing receipt date) are separate fields, because they move
independently. Never collapse them into one "today".
Freshness is computed, not asserted.index.json → freshness.status is derived from the
actual age of the data (fresh ≤4d / delayed 5–7d / stale 8d+), and
quote_as_of_age_days is exposed so you can check the arithmetic yourself.
Numbers that violate accounting identities are withdrawn, not published. If a parsed filing
shows net income exceeding revenue, the numbers are dropped and only the filing title and the
DART original link remain, tagged value_status: "withdrawn_inconsistent".
Every ranking formula is published inside rankings.json itself, with per‑component scores,
so any result can be recomputed.
Failures are logged in public.notices.json records pipeline failures and corrections.
When a run fails, the last good snapshot is kept rather than publishing a partial one.
Not investment advice. Rankings are mechanical screens over public filings. No target
prices, no analyst opinions, no buy/sell recommendations — by design.
What is not here
No real‑time quotes (data is the previous trading day's settled close, T+1). No analyst consensus,
target prices or forward PER from brokerage sources — trailing PER (TTM) and PBR are published, computed
from public filings (DART) and settled closes only, with null plus a reason (pe_note/pb_note) where
they cannot be computed. No order execution. These are deliberate.
Data sources & license
Data derives from Korean public sources:
금융감독원 전자공시시스템 (DART) — regulatory filings
금융위원회 공공데이터포털 — daily settled closing prices
The published files (/data/public/*) are licensed under aiksd-public-1.1.
Non-commercial use with attribution; commercial redistribution is not permitted.
Data published here (/data/public/*) may be quoted and used for non-commercial purposes with attribution. Commercial redistribution is not permitted in any form. Market prices come from the Financial Services Commission's public data portal and are also subject to that source's licence (KOGL Type 4: attribution, non-commercial, no derivatives) and notices; disclosure content follows FSS DART's terms. Real-time quotes are never redistributed here.
The code in this repository is MIT licensed (see LICENSE). The data license above applies to the
published JSON/CSV files, not to this repository's code.
The data is provided for information purposes and is not investment advice. It is a machine
aggregation of past records and does not recommend buying or selling any security.
Repository contents
code
mcp/worker.js MCP server (Cloudflare Worker, stateless JSON-RPC over HTTP)
examples/ Runnable Python / JavaScript / shell examples
The data pipeline that produces the published files is maintained separately.
Keywords: Korean stock market API, KOSPI JSON, KOSDAQ data, DART disclosures API, MCP server Korea,
free Korean stock data, 한국 주식 API 무료, 한국 주식 MCP, DART 공시 JSON, 코스피 종가 CSV