Content
# Tool List
**English** · [English](README.en.md)
This is an MCP server that exposes the Kiwoom Securities REST API in **read-only** mode.
It allows users to query domestic stock prices, charts, quotes, indices, rankings, and supply and demand,
as well as their account balance, holdings, and transaction history, using natural language.
> ⚠️ **Security Warning**
>
> - The default execution is **local stdio**. If you need to use it remotely, you must use the HTTP mode with authentication ([Remote Connection](#remote-connection-http-mode--claudeai-webmobile) for details).
> - The AppKey and AppSecret in `.env` are used for real account queries. Do not commit them.
> - The order (buy/sell/modify/cancel) function is not included in the design. This server does not modify your account.
## Provided Tools
**Market Data** (independent of account, can be used with app key):
| Tool | Description | Kiwoom TR |
|---|---|---|
| `search_stock` | Search stock code by name (KOSPI/KOSDAQ, ETF/ETN included) + investment warning | ka10099 |
| `get_stock_price` | Current price, price change ratio, trading volume, basic indicators + industry, listing date, investment warning | ka10001, ka10099 |
| `get_stock_quotes` | Batch stock quotes for multiple stocks (up to 30) - current price, price change ratio, trading volume, trading value, market capitalization | ka10095, ka10099 |
| `get_stock_chart` | Daily/weekly/monthly/yearly/minute/tick candlestick chart (adjusted price) | ka10079~83, ka10094 |
| `get_orderbook` | 10-level sell/buy quotes and volumes | ka10004 |
| `get_market_index` | KOSPI/KOSDAQ comprehensive and sector indices | ka20003 |
| `get_sector_price` | Sector index current price details (price change composition, 52-week high/low, time-series trend) | ka20001 |
| `get_sector_stocks` | Sector constituent stock quotes (current price, price change ratio, trading volume, high/low price) | ka20002 |
| `get_sector_chart` | Sector index daily/weekly/monthly/yearly/minute/tick candlestick chart | ka20004~08, ka20019 |
| `get_ranking` | Top rankings for price change ratio, trading volume, trading value | ka10027/30/32 |
| `get_market_movers` | New highs/lows, upper/lower limits, and unusual stocks | ka10016/17/19 |
| `get_vi_stocks` | Stocks with volatility interruption (VI) triggered (trigger price, deviation rate, time) | ka10054 |
| `get_investor_trend` | Individual/foreign/institutional net buying trends (period total + daily) | ka10059, ka10061 |
| `get_investor_rank` | Top stocks for foreign/institutional net buying/selling | ka90009, ka10131 |
| `get_broker_activity` | Top 5 brokers for stock trading (buy/sell) | ka10002 |
| `get_etf_info` | ETF tracking index, tax type, quote, NAV/deviation rate | ka40002, ka10001, ka40009 |
| `get_etf_returns` | ETF returns for different periods (1 week/1 month/6 months/1 year) vs. benchmark index | ka40001 |
| `get_short_selling` | Daily short selling trends for stocks (short selling volume, ratio, average price) | ka10014 |
| `get_stock_lending` | Stock lending trends (execution, redemption, increase/decrease, balance) - by stock or market | ka10068, ka20068 |
| `get_foreign_holding` | Foreign holding trends for stocks (holding shares, ratio, limit utilization rate) | ka10008 |
| `get_program_trading` | Program trading net buying/selling for the day (KOSPI/KOSDAQ) | ka90003 |
**Watchlist** ( saved in Kiwoom HTS, read-only):
| Tool | Description | Kiwoom TR |
|---|---|---|
| `get_watchlist_groups` | Watchlist group list (group code + group name) | ka01300 |
| `get_watchlist` | Stock list in a group (stock name, previous day's closing price, market, investment warning) | ka01301, ka10099 |
> Kiwoom REST API does not support editing watchlists, only querying.
**Themes**:
| Tool | Description | Kiwoom TR |
|---|---|---|
| `get_theme_groups` | Theme group list (price change ratio, number of stocks, period return, main stocks) | ka90001 |
| `get_theme_stocks` | Constituent stocks and quotes for a theme (current price, price change ratio, trading volume, period return) | ka90002 |
**Account** (based on the account associated with the app key):
| Tool | Description | Kiwoom TR |
|---|---|---|
| `get_account_balance` | Deposit + total evaluation amount/evaluation profit/loss/estimated deposit asset + daily/monthly/cumulative profit/loss | kt00001, kt00018, kt00004 |
| `get_account_holdings` | Holdings - quantity/average price/current price/evaluation profit/loss | kt00018 |
| `get_account_trend` | Daily estimated deposit asset trend + period return/evaluation profit/loss/deposit/withdrawal summary (default 30 days, no support for simulated investment) | kt00002, kt00016 |
| `get_transactions` | Transaction history for a period (execution date, price, settlement amount) | kt00015 |
| `get_pending_orders` | Unsettled orders (order number, type, status, order/unsettled quantity, order price) | ka10075 |
| `get_trading_journal` | Today's trading journal (stock-wise buy/sell average price, quantity, realized profit/loss, total profit/loss) | ka10170 |
| `calc_isa_tax_status` | ISA tax status calculation (non-taxable limit vs. profit/loss) | kt00015, ka10074, kt00018 |
Besides, there's a `ping` tool (no app key required). All responses have a prefix indicating which server responded: `[Simulated Trading]` or `[Real Trading]`. The first call to `search_stock` takes a few seconds to download the stock master (~4,300 stocks) and caches for 12 hours.
### `calc_isa_tax_status` Usage
- Start date: `.env`'s `ISA_OPENED_ON` (account opening date) by default, can be overridden with `from_date`.
- Dividends/distributions not automatically detected from transaction history can be manually input with `dividends_received`.
- Stock tax type (taxable vs. domestic stock) is automatically classified based on stock name; incorrect classifications can be corrected with `overrides: [{stock_code, tax_type}]`. Results are for reference only - actual tax calculation is based on the brokerage firm's settlement.
## Requirements
- **Node.js 20.12 or higher** (using `process.loadEnvFile`)
- Kiwoom Securities REST API app key - issued after app registration on [Kiwoom Open API Portal](https://openapi.kiwoom.com)
- Simulated trading (VIRTUAL) and real trading (REAL) require **separate app keys**, and the issued key type must match `KIWOOM_MODE`.
- Accounts are tied to app keys, so no account number input is required.
## Installation
Published on npm, can be executed directly with `npx` without cloning:
```json
{
"mcpServers": {
"kiwoom": {
"command": "npx",
"args": ["-y", "kiwoom-mcp-server"],
"env": {
"KIWOOM_APP_KEY": "…",
"KIWOOM_APP_SECRET": "…",
"KIWOOM_MODE": "REAL"
}
}
}
}
```
To build from source or modify code:
```sh
git clone <repository URL>
cd kiwoom-mcp-server
npm install
cp .env.example .env # fill in values according to the table
npm run build # generate dist/
npm test # unit tests (no network required)
```
## Environment Variables (`.env`)
| Variable | Required | Description |
|---|---|---|
| `KIWOOM_APP_KEY` | ✅ | Kiwoom REST API app key |
| `KIWOOM_APP_SECRET` | ✅ | Kiwoom REST API app secret |
| `KIWOOM_MODE` | | `VIRTUAL` (simulated trading, default) or `REAL` (real trading) |
| `ISA_ENABLED` | | `true` enables `calc_isa_tax_status` tool. Default `false` (general account) |
| `ISA_TYPE` | | `GENERAL` (general type, 2 million KRW limit, default) or `SEOMIN` (low-income/farmer type, 4 million KRW). Used only when `ISA_ENABLED=true` |
| `ISA_OPENED_ON` | | ISA account opening date `yyyy-MM-dd` - default start date for `calc_isa_tax_status`. Used only when `ISA_ENABLED=true` |
| `MCP_TRANSPORT` | | `stdio` (default) or `http` - see [Remote Connection](#remote-connection-http-mode--claudeai-webmobile) |
| `MCP_AUTH_TOKEN` | required for HTTP mode ✅ | Bearer token for all `/mcp` requests in HTTP mode |
| `MCP_HTTP_PORT` | | HTTP mode port (default `8000`) |
| `MCP_HTTP_HOST` | | HTTP mode bind address (default `127.0.0.1`) |
| `MCP_HTTP_NO_AUTH` | | Allow HTTP mode without authentication (not recommended - see security notice) |
Default settings are for **general (non-ISA) accounts** - market and account query tools are exposed without additional settings. To connect an ISA account and use the non-taxable limit tool, set `ISA_ENABLED=true` and fill in `ISA_TYPE`/`ISA_OPENED_ON`. If disabled, `calc_isa_tax_status` is not registered, and the rest of the tools work as usual.
`.env` is loaded from the project root, so it works even when executed from an arbitrary working directory.
## Claude Desktop Connection
Configuration file location:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
**npx (distributed) - execute without cloning. App key passed as `env` block:**
```json
{
"mcpServers": {
"kiwoom": {
"command": "npx",
"args": ["-y", "kiwoom-mcp-server"],
"env": {
"KIWOOM_APP_KEY": "…",
"KIWOOM_APP_SECRET": "…",
"KIWOOM_MODE": "REAL"
}
}
}
}
```
**Source build - execute `dist/index.js` directly. App key used from project root `.env`:**
```json
{
"mcpServers": {
"kiwoom": {
"command": "/opt/homebrew/bin/node",
"args": ["/absolute/path/kiwoom-mcp-server/dist/index.js"]
}
}
}
```
> **`command` should use the **absolute path** of the executable for safety (`which node`, `which npx` for confirmation). GUI apps do not inherit shell PATH, so just writing `"node"`/`"npx"` might not work.
After saving, completely exit Claude Desktop (macOS: ⌘Q) and restart to see the tools. **Rebuild with `npm run build` and restart** for changes to take effect.
## Claude Code Connection
npx (distributed) - app key passed with `-e` flag:
```sh
claude mcp add kiwoom \
-e KIWOOM_APP_KEY=… -e KIWOOM_APP_SECRET=… -e KIWOOM_MODE=REAL \
-- npx -y kiwoom-mcp-server
```
Source build - use project root `.env`:
```sh
claude mcp add kiwoom -- node /absolute/path/kiwoom-mcp-server/dist/index.js
```
## Remote Connection (HTTP Mode) — claude.ai Web/Mobile
The **custom connector** on claude.ai (web/mobile) cannot directly connect to a local stdio server and requires a **Streamable HTTP** MCP server accessible via public HTTPS.
```sh
MCP_AUTH_TOKEN="$(openssl rand -hex 32)" npx -y kiwoom-mcp-server --http --port 8000
# Endpoint: http://127.0.0.1:8000/mcp · Health check: /healthz
```
- **Authentication is mandatory.** Without `MCP_AUTH_TOKEN`, the server will refuse to start - every `/mcp` request must have an `Authorization: Bearer <token>` header. To allow unauthenticated access, use `--no-auth`, but be cautious as account query tools are exposed.
## Verification
Can be verified directly with stdio without an MCP client:
```sh
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ping","arguments":{}}}' \
| node dist/index.js
```
`ping` responds without an app key. Market and account tools require an app key.
## Troubleshooting
| Symptom | Check |
|---|---|
| Tools not visible on Desktop | Is `command` an **absolute path**? Did you run `npm run build` and restart Desktop? |
| "Configuration not found or incorrect" | Is `.env` in the project root? Are required variables filled? |
| "Failed to authenticate with Kiwoom" | Does the app key type (simulated/real) match `KIWOOM_MODE`? Is the app active on the portal? |
| "Request limit exceeded" | Kiwoom rate limit (about 1 request per second per TR). If the server still exceeds the limit after automatic retries, try again after a while. |
| Cash and D+2 estimated cash differ | Normal if there are unsettled (D+2 settlement) trades. |
## Development
```sh
npm run dev # execute source directly with tsx
npm run typecheck # tsc --noEmit
npm test # vitest
npm run build # tsc → dist/
```
Structure: `src/kiwoom/` (authentication, HTTP, TR layer) → `src/tools/` (MCP tools, format separation) → `src/isa/` (tax type classification, profit/loss reconstruction, profit/loss aggregation). Detailed rules and verified API contracts are in `CLAUDE.md`.
## License
[MIT](LICENSE)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available