# io.github.redoxnet/lsopenapi (nuget · RedoxNet.Mcp.LsOpenApi)

LS Securities OpenAPI MCP server: Korean + overseas stocks, charts, screeners, portfolio, accounts.

- Trust score: 39/100 (low)
- Change this week: −8
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- nuget · `RedoxNet.Mcp.LsOpenApi`: 39/100 (this document), [markdown](https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi.md), [page](https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi)

## Channel facts

- Registry: `nuget`
- Package: `RedoxNet.Mcp.LsOpenApi`
- Version: `1.6.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - No production dependencies, so there is no dependency health to assess.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 66 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 0/100
  - Schema quality not yet verified: our sandbox run of this package did not complete, so we have no schema to assess.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: our sandbox run of this package did not complete, so we have no schema to compare.
- **Tool Coverage**: 0/100
  - Tool coverage not yet verified: our sandbox run of this package did not complete, so we have no tool definitions to assess.
- **Capabilities**: 0/100
  - Protocol version not yet verified: our sandbox run of this package did not complete, so we never saw its MCP handshake.

**Unverified: 4 categories.** Categories scored 0 because our sandbox run of this package has not given us the schema these checks need to read. That is a gap on our side rather than a finding about the package, and we only credit what we can confirm, so the score stands at 0 until the capture succeeds. We are working through the fleet, so this normally clears without any action from you.

## Install

### Claude

```bash
claude mcp add redoxnet-lsopenapi -- dnx RedoxNet.Mcp.LsOpenApi@1.6.0 --yes
```

### Codex

```bash
codex mcp add redoxnet-lsopenapi -- dnx RedoxNet.Mcp.LsOpenApi@1.6.0 --yes
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "redoxnet-lsopenapi": {
      "type": "local",
      "command": [
        "dnx",
        "RedoxNet.Mcp.LsOpenApi@1.6.0",
        "--yes"
      ],
      "enabled": true
    }
  }
}
```

### Hermes

```yaml
mcp_servers:
  redoxnet-lsopenapi:
    command: "dnx"
    args: ["RedoxNet.Mcp.LsOpenApi@1.6.0", "--yes"]
```

### Other

```json
{
  "mcpServers": {
    "redoxnet-lsopenapi": {
      "command": "dnx",
      "args": [
        "RedoxNet.Mcp.LsOpenApi@1.6.0",
        "--yes"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 39, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-08-01 (score 24, −5)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-31 (score 29, −18)

- [security regression] Malware scan: pass → unverified

### 2026-07-28 (score 47, 0)

- [functional] Tool coverage: Tool coverage not yet verified: our sandbox run of this package did not complete, so we have no tool definitions to assess.
- [functional] Schema quality: Schema quality not yet verified: our sandbox run of this package did not complete, so we have no schema to assess.

### 2026-07-26 (score 47)

First indexed and scored.

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

## MCP tools (50)

### `ls_get_market_warnings` (~605 tokens)

Returns Korean-market warning / surveillance designations. Wraps t1404 + t1405 behind a single tool so the model can answer *"내 보유 중 관리종목 있어?"*, *"매매정지 종목"*, or *"단기과열 지정 종목"* in one call.

Two source TRs underpin it:
\- **t1404** — 관리 / 불성실공시 / 투자유의 / 투자환기.
\- **t1405** — 투자경고 / 매매정지 / 정리매매 / 투자주의 / 투자위험 / 위험예고 / 단기과열지정 / 이상급등 / 상장주식수부족.

USE WHEN: the user is screening for KRX-side risk flags, or asking "are any of my holdings on a watchlist". AVOID WHEN: the user wants disclosure feed (공시) or news — those belong to other TRs.

kinds: list of English snake_case ('designated_admin', 'trading_halt', 'short_term_overheating', 'liquidation_trading', …), Korean labels ('관리종목', '매매정지', '단기과열', '정리매매', …), or LS jongchk codes prefixed with the source TR ('t1404:1', 't1405:7'). When omitted, only 관리 (designated_admin) is queried — pass an explicit list (e.g. ['관리', '매매정지', '단기과열']) for a wider surveillance sweep.

shcodes: optional whitelist (typically the user's holdings). When supplied, only matching rows pass through; otherwise the full market scope is returned.

market: 'all' (default) / 'kospi' / 'kosdaq'.

limit: max rows to return (1-200, default 50). total_available echoes the full pre-cap row count so the model can tell the user how many were elided.

Each row carries the source TR and the LS jongchk code so the model can cite the exact designation type.

For KRX designation status (관리 / 매매정지 등), prefer this LS-backed tool before web search; use web search only for the story behind a designation.

Input parameters:

- `kinds` (array): Optional list of warning kinds. English snake_case, Korean label, or 'trCode:jongchk' (e.g. 't1405:7') accepted. When omitted, only 관리 (designated_admin) is queried — pass an explicit list for wider…
- `limit` (integer): Max rows to return (1-200). Default 50.
- `market` (string): Market scope: 'all' (default), 'kospi', or 'kosdaq'.
- `shcodes` (array): Optional subset of 6-digit shcodes to keep. Useful for filtering against a user's holdings list.

### `ls_account` (~696 tokens)

Manages portfolio account labels — both manually-tracked paper portfolios AND the auto-discovered LS live broker label. Does not require LS credentials. Pick the operation with `action`:

\- action="list" — returns {paper_accounts, live_accounts} so the model can distinguish manually-tracked paper portfolios (broker label = display only) from the appkey-bound LS live row (auto-managed). Returns empty arrays when nothing is registered; no other parameters.
\- action="upsert" — creates or updates a PAPER-portfolio account by `account_number` (also requires `nickname`). `broker` is a free-form display label ("유안타증권", "한투", "LS증권" — all valid). `set_default=true` promotes it to the sole default paper account; the first paper account is auto-promoted. Rename-broker sub-mode: set `rename_broker_from` to relabel a broker across every paper account using it, with the replacement in `broker`.
\- action="remove" — removes the paper account identified by `account` (account_number or nickname). RequiresConfirmation envelope when it owns holdings unless `confirm=true`. Removing the default auto-promotes the oldest remaining paper account.
\- action="set_live_nickname" — sets or clears a friendly nickname on a LIVE LS account row. Requires `account_number` (the LS-side AcntNo) and `nickname` (passing empty/null clears it). Returns the updated live row, or NotFound when no live row matches.

USE WHEN: the user wants to register a manual paper-portfolio account ("내 한투 계좌 등록해줘. 번호 X 닉네임 한투"), list both registries, rename a broker label, delete a paper account, or rename their LS live account.

Live broker accounts are NOT created here — they are auto-discovered on the first successful ls_account_balance / ls_account_bep / ls_account_credit_limit / ls_account_max_order_qty call. To force discovery without inspecting balances, call ls_account_balance once.

v0.10 BREAKING: replaces ls_accounts_list / ls_account_upsert / ls_account_remove. v1.6 BREAKING: list response shape is {paper_acco…

Input parameters:

- `account` (string): remove: paper account identifier (account_number or nickname).
- `account_number` (string): upsert / set_live_nickname: brokerage account number (required unless rename_broker_from is set).
- `action` (string, required): Operation to perform: 'list', 'upsert', 'remove', or 'set_live_nickname'.
- `broker` (string): upsert: free-text display label for the paper account (defaults to 'paper'). In rename-broker sub-mode this is REQUIRED — the replacement label.
- `confirm` (boolean): remove: must be true to cascade-delete holdings owned by the paper account.
- `nickname` (string): upsert: human-readable nickname, unique across paper accounts (required for a normal upsert). set_live_nickname: the nickname to set on the live row (empty string clears it).
- `rename_broker_from` (string): upsert: set this to enter rename-broker sub-mode — the current broker label to replace across every paper account.
- `set_default` (boolean): upsert: if true, promote this paper account to the sole default.

### `ls_get_investor_flow` (~819 tokens)

Returns investor-type flow in one of two modes. Up to 12 LS-tracked investor categories are available (개인 / 외국인 / 기관계 / 증권 / 투신 / 은행 / 보험 / 종금 / 기금 / 국가 / 기타 / 사모펀드), but the wrapper surfaces only the three macro categories (`foreign`, `institution_total`, `individual`) by default to keep responses compact. Pass `investors=["all"]` or an explicit subset to expand.

\- INTRADAY MARKET-WIDE MODE (`shcode` 미지정): wraps t1601. Returns one snapshot per market segment LS ships (KOSPI / KOSDAQ / 선물 / 옵션 등). LS does not label the segments in the wire response, so the wrapper surfaces them as `segments[].block_index = 1..6` with each segment's selected investors as a `{kind: {buy, sell, net, change}}` map. Use this for *"지금 외인 / 기관 누가 사고 있어?"* style market commentary.
\- SINGLE-STOCK DAILY MODE (`shcode` 지정): wraps t1702. Returns a daily time series of investor-type flow for the named stock plus a `summary` block (period totals + per-investor largest buy/sell day). `fromdt` / `todt` clip the range; `direction` picks net / buy / sell (LS-side msmdgb); `metric` picks 수량 / 금액 / 단가; `cumulative=true` reports running totals instead of per-day deltas.

AVOID WHEN: the user wants top-N stocks by foreign / institution net buying — that's a separate ranking TR (t1471/t1717) not in v0.7. AVOID using daily mode without a shcode (will error).

Units: t1601 magnitudes are 천주 (unit=volume) or 백만원 (unit=value). t1702 magnitudes follow `metric` — 천주 / 백만원 / 원 per share.

For 외국인 / 기관 수급 figures, prefer this LS-backed tool before web search; use web search only for the narrative behind a flow.

Input parameters:

- `count` (integer): Daily mode: how many trading days to return when fromdt is omitted. 1-200, default 30.
- `cumulative` (boolean): Daily mode: false (per-day, default) or true (누적). Maps to t1702.gubun.
- `direction` (string): Daily mode: 'net' (순매수, default), 'buy' (매수), or 'sell' (매도). Maps to t1702.msmdgb.
- `exchange` (string): Exchange filter: 'unified' (통합 — default), 'krx', or 'nxt'.
- `fromdt` (string): Daily mode: start date YYYYMMDD. Default = todt - count business days (server clips).
- `investors` (array): Investor categories to surface. Default is the three macro categories ['foreign','institution_total','individual']. Pass ['all'] to include all 12, or list specific kinds: securities, investment_trus…
- `metric` (string): Daily mode: 'volume' (수량, default), 'value' (금액), or 'price' (단가). Maps to t1702.volvalgb.
- `shcode` (string): 6-digit Korean stock code (optional). When supplied, switches to single-stock daily mode (t1702).
- `todt` (string): Daily mode: end date YYYYMMDD. Default = today (LS server time).
- `unit` (string): Intraday mode: 'volume' (수량, default) or 'value' (금액). Maps to t1601.gubun1/2/4.

### `ls_add_indicator` (~257 tokens)

Adds a technical indicator to a chart dataset previously returned by ls_get_chart. Use this for follow-up requests like "MA200도 추가해줘" without sending raw OHLCV back through the model context.

The tool resolves dataset_id from the process-local handle cache, refetches the selected frame with the requested indicator's warm-up window, updates the same dataset_id, and returns a compact summary plus optional structuredContent.chart. If the dataset has multiple timeframes, pass period_type to choose the frame.

Input parameters:

- `dataset_id` (string, required): dataset_id returned by ls_get_chart, e.g. 'ds_a8f3c012'.
- `indicator` (string, required): Indicator spec to add, e.g. 'ma:200', 'ema:60', 'bb:20,2'.
- `period_type` (string): Optional period frame to update when dataset_id contains multiple frames. Required for ambiguous multi-timeframe datasets.
- `theme` (string): Optional chart theme override: "light", "dark", or "auto". Null (default) inherits the dataset's theme from the original ls_get_chart call. Pass to switch theme mid-conversation (e.g. "이걸 다크로 바꿔서").

### `ls_get_etf_holdings` (~624 tokens)

Returns the PDF (portfolio deposit file / 구성종목) of a Korean ETF: each holding's short code, name, weight (%), price, change, market value, and a summary block (ETF price, NAV, constituent count, total AUM, cash portion).

USE WHEN: the user asks "이 ETF 안에 뭐 들어있어?", "KODEX 2차전지 비중 1위 종목", "TIGER 미국S&P500 구성종목", "ETF 보유종목", "ETF holdings/composition/PDF".
AVOID WHEN: the user wants the ETF's price/NAV/괴리율 only — `ls_get_etf_info` is lighter; for a regular stock use `ls_get_stock_info`.

The basis date defaults to today (KST). LS publishes PDF per trading day, so on weekends or before today's PDF is posted, pass an explicit `date` (yyyyMMdd) of a recent trading day. Holdings come back sorted by valuation amount (LS InBlock `sgb=1`); the alternative `sgb=2` (share count) is accessible via `ls_call_tr` if needed.

\`limit` caps the constituent array — it defaults to 20, since the largest holdings carry most of an ETF's weight. Pass `limit=-1` for the full list; an ETF with 200+ holdings (KODEX 200 ≈ 201) returned in full would blow past inline token budgets. The summary block (`holdings_count`, AUM, NAV, etc.) always reflects the full ETF regardless — only the `holdings[]` array is capped, and `holdings_truncated` flags when it was.

Set include_chart=true for inline composition rendering on hosts that support MCP Apps. When the connected host can render charts, a Plotly treemap + top-10 side panel ships as structuredContent (not in the model's text context — zero token cost) and the host renders it inline; on a text-only host the parameter is not offered. The panel surfaces a concentration badge (분산형 / 균형형 / 집중형 / 초집중형 by top-5 cumulative weight), the top-10 cumulative weights, and notes for single-name concentrations ≥30% and cash buffers.

Note units: `total_assets` is in 억원 (100M KRW), per-holding `value` is in 백만원 (1M KRW), all other monetary fields are raw 원 (KRW).

Input parameters:

- `date` (string): Optional PDF basis date in 'yyyyMMdd' format. Defaults to today (KST). Use an explicit weekday date if today's PDF hasn't been posted yet.
- `limit` (integer): Cap on the holdings array. Default 20 — the largest holdings carry most of an ETF's weight. Pass -1 for the full list.
- `shcode` (string, required): 6-digit Korean short code of an ETF, e.g. '069500'.

### `ls_account_order_history` (~327 tokens)

Returns the order/fill history for a specific date via TR CSPAQ13700. Per-order rows include the entire lifecycle — placed / modified / cancelled / executed — so the model sees both the live orders and what they ultimately became.

USE WHEN: the user asks "어제 주문 내역", "지난 주문 다 보여줘", or wants a forensic per-order log on a specific date.
AVOID WHEN: the user wants today's live order book — use ls_account_orders. AVOID WHEN: they want raw transaction history including deposits — use ls_account_transactions.

\`order_date` defaults to today. Filters: `status` (all / filled / pending), `side` (all / buy / sell), `symbol`, `market` (all / kospi / kosdaq / freeboard), `sort` (asc default / desc).

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `market` (string): Market filter: 'all' (default), 'kospi', 'kosdaq', 'freeboard'.
- `order_date` (string): Date to inspect (YYYY-MM-DD or YYYYMMDD). Default = today.
- `side` (string): Side filter: 'all' (default), 'buy', or 'sell'.
- `sort` (string): Sort: 'asc' (default, oldest first) or 'desc'.
- `status` (string): Status filter: 'all' (default), 'filled', or 'pending'.
- `symbol` (string): Optional 6-digit shcode. Omit for all symbols.

### `ls_account_holdings` (~246 tokens)

Returns the LIVE LS broker holdings for the appkey-bound account via TR t0424. Real-time read of what LS actually holds — separate from the manually-tracked ls_holdings_list (which lives in the local portfolio.db).

USE WHEN: the user asks "내 LS 계좌 잔고", "실제 보유 종목", "지금 LS 증권에 뭐가 있어?", or any phrasing that asks for the broker's view of positions.
AVOID WHEN: the user wants their paper-portfolio or manually-recorded holdings — use ls_holdings_list. AVOID WHEN: the user wants the watchlist — use ls_watchlist.

No `account` argument — LS account-inquiry TRs do not accept AcntNo in the request, the appkey's authenticated session resolves to one subaccount server-side. The label in _meta.account_used is whatever LS returns; nicknames can be attached via ls_account(action="set_live_nickname").

Output: per-symbol rows + a portfolio summary (estimated net assets, deposit, total evaluation / P&L), plus _meta.account_used / data_as_of / tr_code / source="live".

### `ls_get_global_market_quote` (~265 tokens)

Returns a one-shot quote for major overseas indices, FX rates, or overseas futures via LS t3521.

USE WHEN: the user asks for US/global index snapshots ("나스닥", "S&P 500", "필라델피아 반도체"), FX rates ("원달러 환율", "USD/KRW"), or simple commodity/futures snapshots ("WTI", "금").
AVOID WHEN: the user wants Korean KOSPI/KOSDAQ indices — use ls_get_index_quote. For historical/minute/tick overseas series use ls_call_tr with t3518 until a dedicated wrapper ships.

Common symbol aliases: nasdaq→NAS@IXIC, sp500→SPI@SPX, dow→DJI@DJI, soxx→USI@SOXX, usdkrw→USDKRWSMBS, wti→NYM@CL, gold→COM@GC. Raw LS symbols are accepted.

Input parameters:

- `kind` (string): Asset kind: index/S, fx/R, futures/F. Default index.
- `symbol` (string): Alias or raw LS symbol. Examples: nasdaq, sp500, dow, soxx, usdkrw, wti, gold, or NAS@IXIC.

### `ls_get_stock_events` (~406 tokens)

Returns the corporate-action / shareholder-meeting calendar for a single Korean stock via t3202 (종목별 증시일정). Events include dividends, AGMs, rights issues, bonus issues, capital changes, mergers/splits, stock-option exercises, CB conversions, etc.

USE WHEN: the user asks "다음 주총 언제", "삼성전자 배당 일정", "내 보유 종목 다음 이벤트", or any forward-looking corporate-action question for a specific symbol. The wrapper is read-only and one TR call.
AVOID WHEN: the user wants market-wide screening (this is single-symbol only) or wants real-time disclosure feeds (t3202 covers scheduled actions, not breaking 공시).

Filtering:
\- `from` / `to` clip the returned events to a [YYYYMMDD, YYYYMMDD] window. Events with `recdt = "00000000"` (TBD / undated) are kept regardless of the window so the model still surfaces "scheduled, date TBD" entries.
\- `kinds` accepts English snake_case (dividend, shareholder_meeting, rights_issue, …), Korean labels (배당, 주주총회, …), or raw two-char upgu codes ("03", "09").

Each event row carries the LS upgu code plus normalized English / Korean labels so the model can render whichever fits the question's language.

Input parameters:

- `from` (string): Optional inclusive start date YYYYMMDD. Events with recdt='00000000' (TBD) are always kept.
- `kinds` (array): Optional event-kind filter. List of English snake_case names, Korean labels, or raw upgu codes (e.g. ['dividend','주주총회','01']).
- `shcode` (string, required): 6-digit Korean stock code, e.g. '005930' for Samsung Electronics.
- `to` (string): Optional inclusive end date YYYYMMDD.

### `ls_watchlist` (~516 tokens)

Manages the local saved watchlist — stock items and their groups. Does not require LS credentials to save. Pick the operation with `action`:

\- action="list" — lists watchlist data. Default returns grouped items, each enriched with current price / change_pct (batch t8407 when LS credentials are available; partial quote failures allowed). `scope="groups"` instead returns group metadata only ({name, description, sort_order, item_count}). Optional `group_name` filters items.
\- action="add" — adds `shcode` to a watchlist group (`group_name`, defaults 'default'). Optional `note`. The item is saved even when LS credentials are unavailable.
\- action="remove" — removes `shcode` from `group_name` (defaults 'default').
\- action="group_upsert" — creates a group, updates its description, or renames one. `name` is the target group name; with `rename_from` set it renames that group to `name`, otherwise it inserts (or upserts the description). Optional `description`.
\- action="group_delete" — deletes the group `name` and cascades its saved items.

USE WHEN: the user wants to remember / track / 관심종목 추가 a stock, see their watchlist, or manage watchlist groups. AVOID for general market questions unrelated to saved watchlists.

v0.10 BREAKING: replaces ls_watchlist_add / ls_watchlist_remove / ls_watchlist_list / ls_watchlist_group_create / ls_watchlist_group_delete.

Input parameters:

- `action` (string, required): Operation to perform: 'list', 'add', 'remove', 'group_upsert', or 'group_delete'.
- `description` (string): group_upsert: optional group description.
- `group_name` (string): add / remove: watchlist group name (defaults to 'default'). list: optional group filter (scope='items' only).
- `name` (string): group_upsert / group_delete: the target group name.
- `note` (string): add: optional user note for this watchlist item.
- `rename_from` (string): group_upsert: optional existing group name to rename to `name`.
- `scope` (string): list: 'items' (default — grouped items + quote enrichment) or 'groups' (group metadata only).
- `shcode` (string): add / remove: 6-character Korean short code (e.g. '005930' or '0117V0').

### `ls_account_credit_limit` (~291 tokens)

Returns the credit margin loan limits (융자/대주 한도) for one of your LS accounts via TR CSPAQ00600. Reports both the broker-wide limits and your remaining headroom for the selected loan type.

USE WHEN: the user asks "신용한도", "융자 한도", "대주 한도", "담보비율" — anything about margin trading capacity.
AVOID WHEN: the user is asking about regular cash-account orderable amounts — use ls_account_balance.

\`loan_type` defaults to '유통융자' (the most common case). `symbol` and `order_price` are required by LS (the limit calculation is symbol-aware); omitting them defaults to a low-impact probe (price=1 on the same default test symbol LS uses).

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `loan_type` (string): Loan type: 'distribution_margin' (유통융자, default), 'self_margin' (자기융자), 'distribution_short' (유통대주), 'self_short' (자기대주').
- `order_price` (number): Order price reference for the limit calculation. Default 1.0.
- `symbol` (string): 6-digit Korean short code that anchors the limit calculation. Default '005930' (Samsung) as a low-impact probe.

### `ls_watched_themes` (~243 tokens)

Manages the local watched-themes list (LS t1531 theme codes); no LS credentials needed to save. `action`: "list" (watched themes, enriched with t1531 avgdiff as change_pct when credentials exist), "add" (requires `theme_code` — a 4-char tmcode, e.g. '0064' 2차전지; optional `theme_name`, `note`), "remove" (drops `theme_code`). USE WHEN the user wants to track / 관심 테마 추가 an LS theme; theme codes are not stock short codes (use ls_watchlist for stocks). v0.10 BREAKING: replaces ls_watched_themes_add / _remove / _list.

Input parameters:

- `action` (string, required): Operation to perform: 'list', 'add', or 'remove'.
- `note` (string): add: optional user note for this theme.
- `theme_code` (string): add / remove: LS theme code (tmcode, 4-char), e.g. '0064'.
- `theme_name` (string): add: optional human-readable theme name (defaults to theme_code).

### `ls_get_quote` (~120 tokens)

Returns a real-time snapshot for a single Korean stock: last price, 10-level order book, session open/high/low, accumulated volume, and percent change.

USE WHEN: the user asks for a quote, current price, 호가, 시세, 주가, or how a specific stock is doing right now.
AVOID WHEN: the user wants historical data — use ls_get_chart for OHLCV bars instead.

Input parameters:

- `shcode` (string, required): 6-digit Korean short code, e.g. '005930' for Samsung Electronics.

### `ls_get_etf_info` (~326 tokens)

Returns an ETF-specific snapshot for a Korean ETF or ETN: price + NAV + 괴리율 (divergence) + 추적오차율 (tracking error) + reference index + AUM + LP list + 52-week and year ranges + related futures.

USE WHEN: the user asks about an ETF/ETN (e.g. "KODEX 200 NAV", "TIGER 미국S&P500 괴리율", "ETF 시가총액", "추적오차", "LP 누구야?", "기초지수"), or when a `ls_search_stock` result has `etf != "0"`.
AVOID WHEN: the shcode is a regular stock — `ls_get_stock_info` returns fundamentals (PER/PBR/EPS, 거래원) which ETFs lack; `ls_get_quote` returns the 10-level order book.

For PDF (구성종목 / "ETF 안에 뭐 들어있어?") use `ls_get_etf_holdings`.

Notes:
\- `divergence_percent` = 괴리율 (NAV vs market price)
\- `tracking_error_percent` = 추적오차율 (how closely the ETF tracks its underlying index)
\- `total_assets` is in 억원 (100M KRW); `listing_shares` is the raw share count (LS reports in 천, the tool converts).

Input parameters:

- `shcode` (string, required): 6-digit Korean short code, e.g. '069500' for KODEX 200.

### `ls_get_short_selling_trend` (~444 tokens)

Returns a Korean stock's daily short-selling (공매도) trend via LS t1927: per day the short-sale volume, short-sale value, short-sale share of total volume, average short-sale price, cumulative short volume, and the uptick-rule applied vs. exempt split.

USE WHEN: the user asks about short selling / 공매도 for a named stock ("삼성전자 공매도 추이", "공매도 비중 어때?").
AVOID WHEN: the user wants market-wide short-sale rankings (not available) or general investor flow (use ls_get_investor_flow).

Date range: pass `from`/`to` (YYYYMMDD) to clip; otherwise the last `count` trading days up to today are returned. `short_value` and `total_short_value` are in 백만원; `short_ratio_pct` is the short-sale share of that day's total volume; `cumulative_short_volume` accumulates from the query start date.

Publishing lag: short-sale figures are reported on T+1 by KRX, so the latest row may trail today by one business day around market open. `data_as_of` reports the actual latest row date (not today). If `query_date` is a weekend or holiday, LS automatically returns data from the most recent prior trading day — `data_as_of` tells you which one.

For 공매도 figures, prefer this LS-backed tool before web search; use web search only for narrative context.

Input parameters:

- `count` (integer): Trading days to return when 'from' is omitted (1-120). Default 30.
- `from` (string): Start date YYYYMMDD (optional). Default = to - count trading days.
- `query_date` (string): Optional basis date in yyyyMMdd used when 'to' is omitted. Weekends resolve to the prior Friday; future dates clamp to the latest available trading day.
- `shcode` (string, required): 6-digit Korean stock code, e.g. 005930.
- `to` (string): End date YYYYMMDD (optional). Default = today.

### `ls_get_index_history` (~1079 tokens)

Returns a daily / weekly / monthly time series for a Korean market index: closing value, change vs. previous bar, OHLC, volume + transaction value, market breadth, and per-bar foreign / institutional net flow.

USE WHEN: the user asks for "코스피 최근 한 달 추이", "KOSDAQ 일봉", "KRX 100 주간 흐름" or any index time-series question.
AVOID WHEN: the user wants stock candles (use ls_get_chart), or a single live snapshot of one index (use ls_get_index_quote).

index_code aliases: kospi→001, kosdaq→301, kospi200→101, krx100→501. Numeric 3-char codes pass through.

period_type semantics mirror t1514.gubun2: 'day' (=1), 'week' (=2), 'month' (=3). 'min' is intentionally not supported — minute-level index time series belong to a separate roadmap item.

verbosity controls payload size — keep the default; widen it only when the user truly needs every bar:
\- 'summary' (default): the aggregate digest only — period open/close, total change, period high/low with dates, biggest up/down days, average breadth & flows. This ALREADY answers trend / 추세 / 흐름 / range / "how much did it move" questions. Do NOT request bars for those.
\- 'compact': the digest + the 5 most recent bars. Use only when the user asks specifically about the most recent days.
\- 'full': every per-bar point, no digest — roughly 30× the summary's token cost, and the whole series then lingers in conversation context for every later turn. Use ONLY when the user explicitly wants the entire per-bar series or needs a custom per-bar calculation the digest cannot give.

output_mode controls whether the series is returned inline or cached for drill-down:
\- 'summary' (default): the response is shaped by `verbosity` above.
\- 'export': fetches up to `count` bars (raise `count` toward 2500 for a multi-year series), caches the whole series under a `dataset_id`, and returns ONLY the aggregate digest + that handle — no per-bar points enter context. Then call ls_get_index_history again with that `dataset_id` (plus optional `from` / `to` / `recent…

Input parameters:

- `count` (integer): Number of bars to fetch. 1–500 for output_mode='summary'; 1–2500 for 'export' (raise it for a multi-year series). Default 60.
- `cts_date` (string): Optional pagination cursor. Pass the cts_date echoed by a prior response to fetch the next (older) page.
- `dataset_id` (string): Drill mode: pass a dataset_id from a prior output_mode='export' call to slice its cached bars with no API call. When set, index_code / period_type / count / cts_date / verbosity / output_mode are all…
- `from` (string): Drill mode only: keep cached bars on or after this yyyyMMdd date.
- `index_code` (string): Index code. Aliases: 'kospi' (001), 'kosdaq' (301), 'kospi200' (101), 'krx100' (501). Or a 3-character LS upcode like '002'.
- `output_mode` (string): 'summary' (default) returns the series inline per verbosity. 'export' caches the full series under a dataset_id and returns only the digest + handle for follow-up drill.
- `period_type` (string): Bar size: 'day' (default), 'week', or 'month'.
- `recent_n` (integer): Drill mode only: after from/to filtering, keep only the most recent N bars.
- `to` (string): Drill mode only: keep cached bars on or before this yyyyMMdd date.
- `verbosity` (string): Response shape. 'summary' (default) is a digest that already answers trend / range questions — prefer it. 'compact' adds the 5 most recent bars. 'full' returns every bar (~30x the tokens, and it ling…

### `ls_search_stock` (~247 tokens)

Searches the Korean stock universe (KOSPI + KOSDAQ) by Korean or English name fragment and returns the matching short codes.

USE WHEN: the user mentions a stock by name but the 6-digit code is needed (e.g. "삼성전자 알려줘", "find Hyundai Motor's code").
AVOID WHEN: the user already supplied a 6-digit code — use ls_get_quote / ls_get_chart directly.

Use instrument='stock' to exclude ETFs/ETNs (e.g. "바이오 관련 일반주만 찾아줘"), instrument='etf' to keep only ETF/ETN rows, instrument='all' (default) for the full mix.

Input parameters:

- `instrument` (string): Instrument filter: 'all' (default), 'stock' (일반주 only), or 'etf' (ETF/ETN only).
- `keyword` (string): Korean or English name fragment, e.g. '삼성', 'Samsung'.
- `limit` (integer): Max results (1–100). Default 20.
- `market` (string): Market filter: 'all' (default), 'kospi', or 'kosdaq'.

### `ls_analyze_program_flow` (~369 tokens)

Analysis Layer — classifies a Korean stock's program-trading footprint into a deterministic verdict.

USE WHEN: the user asks what the program-trading channel is doing for a stock — whether program flows are accumulating, distributing, or churning beyond the raw numbers.
AVOID WHEN: the user just wants the raw program-trading series or a chart — use ls_get_program_trading.

IMPORTANT — Program-trading flow is a channel, not an investor class: it blends foreign baskets, index arbitrage, and institutional baskets, and misses off-program institutional (direct-order) buying. Do not read this verdict as whether 기관 / 외국인 are accumulating; cross-check ls_get_investor_flow (investors=["all"]) for investor-class flow.

Pulls the stock's intraday and daily program-trading flow (TR t1637) and computes a regime — accumulation / distribution / churn / neutral — with a 0–1 direction_confidence and these signals: window/today net, buy- and sell-day counts, consecutive-day streak, churn_ratio (one-directional vs two-way), intensity (today vs the window's average day), intraday pace (steady TWAP-like vs bursty), open/close loading, and price_coupling (cumulative net vs price correlation). The evidence[] array is plain-language findings ready to narrate to the user.

window sets the daily look-back (10–60 trading days, default 20).

Input parameters:

- `name` (string): Optional stock name for the report, e.g. '삼성전자'.
- `shcode` (string, required): 6-digit Korean short code, e.g. '005930'.
- `window` (integer): Daily look-back window in trading days (10–60). Default 20.

### `ls_portfolio_io` (~326 tokens)

Backs up or restores the local portfolio — accounts, holdings, watchlists, watched themes — as a single versioned JSON file. Does not require LS credentials. Pick the operation with `action`:

\- action="export" — writes the portfolio to a JSON file. `path` is optional; when omitted a timestamped file is written under exports/ next to portfolio.db. The stocks metadata cache is intentionally not exported — it rebuilds from quote enrichment after import.
\- action="import" — restores from a previously-exported JSON file at `path` (required). `mode="merge"` (default) skips rows that already exist; `mode="replace"` wipes accounts/holdings/watchlists/themes first, requires `confirm=true`, and writes a before-import auto-backup.

USE WHEN: the user asks to back up / export / "백업해줘", or restore / import / "복원해줘" / migrate to a new machine.

v0.10 BREAKING: replaces ls_portfolio_export / ls_portfolio_import.

Input parameters:

- `action` (string, required): Operation to perform: 'export' or 'import'.
- `confirm` (boolean): import: must be true to proceed with replace mode. Ignored for merge.
- `mode` (string): import: 'merge' (default — skips duplicates) or 'replace' (wipes export-covered domains first, requires confirm).
- `path` (string): export: optional absolute output path (default: timestamped file under exports/). import: REQUIRED absolute path to the JSON file.

### `ls_get_industry_indices` (~250 tokens)

Returns the top-N Korean industry/sector indices sorted by change percent descending. Internally fetches the catalog via t8424 then the per-index snapshot via t1511 for each upcode, caches the full array for 60 seconds.

USE WHEN: the user asks "오늘 강한 업종은?", "업종 등락률", "sector ranking", or wants the market-wide industry leader/laggard board.
AVOID WHEN: the user names a single index (KOSPI/KOSDAQ) — use ls_get_index_quote. For per-stock ranking inside one industry use ls_get_industry_stocks.

market: kospi (default), kosdaq, or all. Cold-cache cost scales with N upcodes returned by t8424 — usually a few seconds for kospi.
limit: number of rows to return. The same 60s cache is reused for different limit requests, so 'top 5' then 'top 30' is two cheap lookups.

Input parameters:

- `limit` (integer): Max rows returned (1-200). Default 30.
- `market` (string): Market filter: kospi, kosdaq, or all. Default kospi.

### `ls_account_max_order_qty` (~280 tokens)

Returns the maximum orderable quantity for a specific symbol / side / price triple via TR CSPBQ00200. INQUIRY ONLY — this never places an order. Lets the model answer "how many can I afford to buy at price X" without simulating any execution.

USE WHEN: the user asks "최대 몇 주 살 수 있어", "주문 가능 수량", "지금 가격에 풀매수 하면 몇 주", or anywhere they want to know capacity before placing an order.
AVOID WHEN: the user wants to actually place an order — v1.6 does NOT support order placement. v1.7 will ship ls_place_order with proper safety gating.

Returns 증거금률별 (20% / 30% / 40% / 100% margin tiers) quantities so the model can distinguish between cash-only capacity and leveraged capacity. order_price=0 lets LS pick the current best quote automatically.

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `order_price` (number): Order price reference. Default 0 — LS uses the current best quote.
- `side` (string, required): Side: 'buy' (매수) or 'sell' (매도).
- `symbol` (string, required): 6-digit Korean short code (e.g. '005930' Samsung).

### `ls_get_industry_stocks` (~497 tokens)

Returns the stocks inside a Korean industry/sector with the industry index summary attached. Wraps LS t1516 with body-based continuation paging (last shcode echoed) and resolves an industry_keyword against the cached t8424 catalog.

USE WHEN: the user asks "전기전자 업종 종목", "반도체 업종 비교", "코스피 운수창고 종목들" — i.e. peer-comparison across one industry.
AVOID WHEN: the user wants market-wide industry rankings (use ls_get_industry_indices) or a single stock detail (use ls_get_quote).

upcode XOR industry_keyword: pass either a 3-char LS upcode (e.g. '013' 전기전자) or a Korean keyword that resolves against the catalog (LIKE match). Multiple matches return an AmbiguousIndustry envelope with candidates. When both are supplied, upcode wins.
market: t1516 gubun. '1'=코스피업종 (default), '2'=코스닥업종, '3'=섹터지수.

Caveat (LS-side, v0.6 testbed-observed): when market='3' (섹터지수), some synthetic sector indices — notably the KRX 산업분류 family like 503 KRX반도체 — return an empty stocks array because LS publishes them as computed indices without an exposed stock basket. If '3' returns 0 rows for a code you expected to be populated, fall back to ls_get_theme_stocks (theme TR family covers the same conceptual surface with concrete memberships).

Input parameters:

- `industry_keyword` (string): Industry name keyword (e.g. '반도체', '전기전자'). Resolved via t8424 catalog LIKE match. 0 matches → IndustryNotFound; 2+ → AmbiguousIndustry envelope with candidates.
- `limit` (integer): Max stock rows returned (1-200). Default 30.
- `market` (string): t1516 gubun. '1'=코스피업종 (default), '2'=코스닥업종, '3'=섹터지수.
- `upcode` (string): 3-character LS upcode (e.g. '001' KOSPI종합, '013' 전기전자). Mutually exclusive with industry_keyword (upcode wins on conflict).

### `ls_get_index_quote` (~365 tokens)

Returns a real-time snapshot for a single Korean market index: current value, change vs. previous close, session OHLC with timestamps, 52-week and YTD range, market breadth (advancers/decliners/unchanged/limit), and four related auxiliary indices (e.g. for KOSPI 종합 you also get 대형주/중형주/소형주).

USE WHEN: the user asks "오늘 코스피 어땠어?", "코스닥 지수", "KOSPI 200 현재가" or wants a single-index snapshot.
AVOID WHEN: the user wants ETFs that track an index — use ls_get_quote with the ETF shcode. For per-sector ranking across many industries use ls_get_industry_indices.

index_code aliases: kospi→001, kosdaq→301, kospi200→101, krx100→501. Numeric codes (3-char) are passed through.

Envelope semantics:
\- open/high/low.change_pct: percent vs *previous session's close*, NOT vs current. So low.change_pct=-8.14 means "intraday low reached −8.14% from yesterday's close" — i.e. the day's maximum drawdown.
\- related_indices: 4 auxiliary indices LS attaches to the response. When the first entry is the queried index itself, its change_pct is normalized against the top-level value to bypass a known LS-side scale bug (observed for KRX 100).

Input parameters:

- `index_code` (string): Index code. Aliases: 'kospi' (001), 'kosdaq' (301), 'kospi200' (101), 'krx100' (501). Or a 3-character LS upcode like '002'.

### `ls_get_high_low_stocks` (~401 tokens)

Returns Korean stocks at a new high or new low via LS t1442. For each stock: current price, change, volume, and the prior reference price the new high/low was measured against.

USE WHEN: the user asks for 신고가 / 신저가 stocks ("오늘 신고가 종목", "52주 신저가 뭐 있어?").
AVOID WHEN: the user wants gainers/losers ranked by percent (use ls_get_top_stocks).

direction: 'high' (신고가, default) or 'low' (신저가).
period: look-back window — prev_day, 5d, 10d, 20d, 60d, 90d, '52w' (default), ytd.
maintained: true (default) = 돌파유지 (still holding the breakout); false = 일시돌파 (touched the high/low but did not hold — these rows can be down on the day).
market: 'all' (default), 'kospi', 'kosdaq'. exclude_etf (default true) drops ETF / ETN from the result.

Input parameters:

- `direction` (string): 'high' (신고가, default) or 'low' (신저가).
- `exclude_etf` (boolean): Drop ETF / ETN from the result (default true).
- `limit` (integer): Maximum rows to return (1-100). Default 20.
- `maintained` (boolean): true (default) = 돌파유지 (still holding); false = 일시돌파 (touched but not holding).
- `market` (string): Market filter: all (default), kospi, kosdaq.
- `period` (string): Look-back window: prev_day, 5d, 10d, 20d, 60d, 90d, 52w (default), ytd.

### `ls_reframe_chart` (~283 tokens)

Reframes a chart dataset returned by ls_get_chart to a different period/count using the same symbol and indicator specs. Use this for follow-up requests like "이걸 일봉으로 바꿔서 최근 6개월만 보여줘".

Until persistent candles.db is introduced, this tool refetches the requested frame from LS using the original shcode and replaces the dataset_id's current view in the process-local handle cache.

Input parameters:

- `count` (integer): Number of candles for the new view (1-500). Default 60.
- `dataset_id` (string, required): dataset_id returned by ls_get_chart, e.g. 'ds_a8f3c012'.
- `from` (string): Optional start date in 'yyyyMMdd'.
- `minute_unit` (integer): For period_type='min': minute interval (1, 3, 5, 10, 15, 30, 60). Default 5.
- `period_type` (string, required): New period type: 'day', 'week', 'month', 'year', 'min', or 'tick'.
- `theme` (string): Optional chart theme override: "light", "dark", or "auto". Null (default) inherits the dataset's theme. Pass to switch theme mid-conversation.
- `to` (string): Optional end date in 'yyyyMMdd'.

### `ls_account_balance` (~243 tokens)

Returns the LIVE cash, buying power, and total valuation for one of your LS broker accounts via TR CSPAQ12200. Reports the full asset snapshot: deposit, D1/D2, orderable amounts (cash / kospi / kosdaq / margin tiers), substitute amount, evaluation amount, deposited asset total, investment principal, investment P&L, and pledge ratios.

USE WHEN: the user asks "예수금 얼마야", "내 잔고", "주문가능금액", "총 평가금액", "투자원금 대비 손익" — anything about cash, buying power, or roll-up portfolio value.
AVOID WHEN: the user wants per-symbol positions — use ls_account_holdings. AVOID WHEN: the user wants per-day P&L history — use ls_account_performance.

Like every ls_account_* tool, no `account` argument — appkey resolves the bound LS subaccount server-side; CSPAQ12200 additionally returns BrnNm / AcntNm which the wrapper caches into the live registry on first call. _meta carries account_used, data_as_of, tr_code, and source="live".

### `ls_get_stock_info` (~606 tokens)

Returns a company profile + fundamentals snapshot for a Korean stock, split into selectable sections.

USE WHEN: the user wants company/financial context ("삼성전자 어떤 회사야?", "PER 얼마야?", "52주 신고가 근처야?"). Pairs well with ls_get_quote for the level-2 book.
AVOID WHEN: only the latest price + 10-level order book are needed — use ls_get_quote. For foreign / institutional *flow* (일별 순매수, "외국인 매수세 어때?") use ls_get_investor_flow — the "foreign" section here is the holding *level* (지분율 / 소진율), not the daily flow.

sections (default ["snapshot","fundamentals"]) — request only what the question needs:
\- "snapshot": 현재가 / 등락 / 거래량 / OHLC / 상하한가 / 회전율.
\- "fundamentals": PER / PBR / EPS, 분기 재무(직전 분기 latest + 그 전 분기 previous — t1102는 당기 진행분을 주지 않음) + 전년대비 성장률, 시가총액·상장주식수·자본금. *Note:* PER / PBR can come back as 0 when LS lacks the data — typical for ETFs/ETNs, SPACs, recently listed names, and companies with no published earnings. Treat 0 as "missing/unavailable" (not a real zero ratio) and surface that to the user; lean on EPS / growth rates / flags for valuation context instead.
\- "periods": 52주 / 연중(YTD) 고저 범위.
\- "brokers": 매수 / 매도 상위 5 거래원.
\- "flags": SPAC / 단기과열 / 저유동성 / 배분 구분 플래그 + 공시 텍스트.
\- "foreign": 외국인 보유주식수 / 지분율 / 소진율 — 보유 잔량(level)이지 일별 흐름이 아님. t1716 별도 호출이라 이 섹션을 고를 때만 추가 API 호출 1회 발생.

Identity fields (shcode, name, market, currency, listing_date, par_value, trade_unit) are always returned. Unselected sections are omitted; sections_shown echoes what was returned.

For these fundamentals and status flags, prefer this LS-backed tool before web search or model memory; use web search only for news / narrative context.

Input parameters:

- `sections` (array): Sections to return — any of "snapshot", "fundamentals", "periods", "brokers", "flags", "foreign". Omit for the default ["snapshot","fundamentals"].
- `shcode` (string, required): 6-digit Korean short code, e.g. '005930'.

### `ls_get_overseas_quote` (~304 tokens)

Returns a quote snapshot for a single overseas stock via LS g3101, optionally adding profile/fundamental fields (g3104) and 10-level order book (g3106).

USE WHEN: the user asks for a US/overseas stock price, "미장 TSLA 현재가", "엔비디아 호가", or overseas stock snapshot.
AVOID WHEN: the user wants Korean stocks — use ls_get_quote. For OHLCV history use ls_get_overseas_chart.

Pass keysymbol from ls_search_overseas_stock when available. Without keysymbol, exchcd + symbol is used (default exchcd='82' for Nasdaq). The timestamp field is the Seoul wall-clock when the call was made (matches the LS broker's view), not the US local-market time.

Input parameters:

- `exchcd` (string): Exchange code: '82' Nasdaq (default) or '81' NYSE/AMEX. Aliases nasdaq/nyse/amex accepted.
- `include_orderbook` (boolean): If true, add 10-level order book from g3106.
- `include_profile` (boolean): If true, add company/security metadata from g3104.
- `keysymbol` (string): LS key symbol such as '82TSLA'. Preferred when known.
- `symbol` (string): Ticker symbol, e.g. 'TSLA'. If keysymbol is supplied this may be omitted.

### `ls_search_overseas_stock` (~359 tokens)

Searches the LS overseas stock master (g3190) and returns symbols plus keysymbol/exchcd for quote and chart calls.

USE WHEN: the user names a US stock but only knows the ticker or Korean/English name, e.g. "테슬라", "Tesla", "NVDA", "미장 엔비디아".
AVOID WHEN: the user already supplied keysymbol/exchcd/symbol; call ls_get_overseas_quote or ls_get_overseas_chart directly.

Best results: pass the US ticker when you know it (e.g. "NVDA" for 엔비디아). A ticker keyword routes through a fast direct lookup, while a Korean/English name falls back to a paginated master scan that is slower and may miss symbols deep in the alphabetical listing.

US exchange defaults: exchange='nasdaq' maps to exgubun=2/exchcd=82, exchange='nyse' or 'amex' maps to exgubun=1/exchcd=81, exchange='all' scans both with exgubun=0. natcode defaults to 'US'; non-US queries require passing natcode and exchange='all' (or a numeric exgubun).

Input parameters:

- `exchange` (string): Exchange filter: 'all' (default), 'nasdaq', 'nyse', 'amex', '82', or '81'.
- `keyword` (string): Ticker or Korean/English name fragment, e.g. 'TSLA', '테슬라', 'Tesla'.
- `limit` (integer): Max results (1-100). Default 20.
- `natcode` (string): Country code. Default 'US'.

### `ls_account_orders` (~339 tokens)

Returns today's orders (filled + pending) for one of your LS broker accounts via TR t0425. Real-time read from LS — no cache.

USE WHEN: the user asks "오늘 주문", "체결됐나", "미체결 남은 거", "오늘 매매 내역", or wants the live order book for the active account.
AVOID WHEN: the user wants a historical multi-day order log — use ls_account_order_history (TR CSPAQ13700) instead. AVOID WHEN: the user wants positions — use ls_account_holdings.

Filters: `status` ("all" default / "filled" / "pending") maps to LS chegb. `side` ("all" / "buy" / "sell") maps to medosu (매수/매도). `symbol` narrows to a specific shcode. Sort default is ascending by order number (older first).

Like every ls_account_* tool, no `account` argument — the appkey's session resolves to the bound LS subaccount. _meta carries account_used / data_as_of / tr_code / source="live".

Input parameters:

- `side` (string): Side filter: 'all' (default), 'buy' (매수), or 'sell' (매도).
- `sort` (string): Sort order: 'asc' (default, oldest first by ordno) or 'desc'.
- `status` (string): Order status filter: 'all' (default), 'filled', or 'pending'.
- `symbol` (string): Optional 6-character Korean short code to narrow the result. Omit for all symbols.

### `ls_stocks_refresh_metadata` (~315 tokens)

Synchronously refreshes the local metadata cache (themes / FICS industry) for the requested symbols. Blocks until every fetch completes — typical cold cost is ~1s per symbol per kind due to LS's 1 TPS limit on t1532 and t3320.

USE WHEN: the user explicitly asks to "다시 가져와", "업데이트해 줘", "refresh", or wants a known-bad cache row repaired right now without waiting for a write-path fire-and-forget.
AVOID WHEN: you're just listing holdings — the list path already dispatches enrichment in the background.

shcodes omitted → refreshes every symbol across holdings ∪ watchlist (deduplicated). Pass an explicit list for targeted refresh.
kinds omitted → refreshes BOTH themes and industry. Pass ["themes"] or ["industry"] to scope a single kind.

Response shape:
  {
    kinds: ["themes", "industry"],
    refreshed: [{ shcode, themes_updated, industry_updated }, ...],
    errors:    [{ shcode, kind, error }, ...]
  }
themes_updated / industry_updated are TRUE when the cache landed (including fetched-but-empty sentinels for ETF / SPAC); errors lists per-(shcode, kind) failures.

Input parameters:

- `kinds` (array): Optional subset of kinds to refresh: 'themes', 'industry'. Omit for both.
- `shcodes` (array): Optional list of 6-char short codes. Omit to refresh every holding + watchlist symbol.

### `ls_get_program_trading` (~881 tokens)

Returns program-trading (프로그램매매) flow for KOSPI / KOSDAQ via LS TRs. Program trades are basket / arbitrage orders routed through the program channel — a blend of foreign and institutional baskets, not an investor-specific feed.

scope='market' (default): market-wide program-trading flow — period='intraday' (t1662 ~1-minute 차익/비차익 series + KOSPI200 + futures basis) or period='daily' (t1633 per-day 차익/비차익 history). Applies: market, period, day (intraday), chart_view (intraday).
scope='ranking': per-stock net-buy ranking via t1636 — which stocks programs are buying / selling right now. Applies: market, sort, measure, limit.
scope='stock': one stock's program-trading flow via t1637. Applies: shcode (required), period ('intraday' cumulative minute series, or 'daily' per-day history), name, limit (daily day count).

USE WHEN: the user asks about 프로그램매매 / program trading / 차익·비차익 / basket flow, which stocks programs are accumulating, or program flow for a specific stock.
AVOID WHEN: the user wants investor-class flow (개인/외국인/기관) — use ls_get_investor_flow.

Non-arbitrage (비차익) net buying is the directional basket signal (foreign and institutional baskets blended, not 기관-specific); arbitrage (차익) is basis-driven and mechanical. In ranking scope, mktcap_ratio (net buying ÷ market cap) is the normalized footprint — a small-cap with a high ratio is a stronger signal than a large-cap with a big absolute number. sort='mktcap_weight' ranks by that footprint directly.

Set include_chart=true to ship a Plotly v5 chart as structuredContent so MCP Apps hosts render it inline at zero token cost.
\- market intraday chart_view: flow_overview (default — K200 vs cumulative 전체/비차익/차익), basis_arbitrage (basis vs 차익), intensity_bars (per-minute net bars), gross_flow (per-5-min gross 매수/매도 in 비차익/차익 panels).
\- market daily: a per-day 비차익/차익 stacked-bar chart vs the index (chart_view is ignored).
\- ranking scope: a horizontal bar chart of the top stocks by net buying (chart_view is ignored).
\-…

Input parameters:

- `chart_view` (string): Market scope only — chart view: 'flow_overview' (default), 'basis_arbitrage', 'intensity_bars', or 'gross_flow'.
- `day` (string): Market scope only — session: 'today' (default) or 'yesterday'.
- `limit` (integer): Row cap. Ranking: number of stocks (5–20). Daily periods (market or stock): number of days (10–120). Default 20.
- `market` (string): Target market: 'kospi' (default) or 'kosdaq'.
- `measure` (string): Ranking scope only — metric: 'amount' (default) or 'quantity'.
- `name` (string): Stock scope only — optional stock name for the chart title, e.g. '삼성전자'.
- `period` (string): Market & stock scope — 'intraday' (default) or 'daily'. market+daily uses t1633, stock+daily uses t1637 daily.
- `scope` (string): Data scope: 'market' (default, intraday market-wide via t1662) or 'ranking' (per-stock ranking via t1636).
- `shcode` (string): Stock scope only — 6-digit short code (required when scope='stock'), e.g. '005930'.
- `sort` (string): Ranking scope only — sort: 'net_buy' (default), 'net_sell', or 'mktcap_weight' (footprint).

### `ls_run_screener` (~499 tokens)

Runs one of LS's curated Q-Click / 씽큐스마트 stock signals via t1825 and returns matching Korean stocks. Signals are LS-maintained (catalog of 99 across five groups — 핵심검색 / 지표검색 / 시세동향 / 투자자동향 / 급변종목, ids 6001-6412) and identical for every account.

USE WHEN: the user names a signal exactly ("이평 골든크로스(5,20) 매칭"), gives a 4-digit search_cd ("6116 실행"), or describes a setup that maps to a single catalog entry ("골든크로스 뜬 종목" → if ambiguous between (5,20) and (20,60), the tool returns both candidates + the indicator group catalog so the model can disambiguate).
AVOID WHEN: the user wants MULTIPLE signals combined ("골든크로스 + 외인 순매수") — use ls_combine_screeners; user-authored HTS [1892] conditions (not exposed in v1.4); arbitrary expression-based screening (use ls_get_top_stocks / ls_get_high_low_stocks / ls_get_fundamentals_rank).

name_or_id accepts: (1) exact 4-character search_cd, (2) exact catalog name (case-insensitive), or (3) a Korean keyword like "골든크로스" — the tool matches against the cached catalog. An ambiguous keyword returns an error envelope with the candidates and the full group catalog (β policy) so the model can pick the precise entry without an extra ls_list_screeners round trip.
market: all (default), kospi, or kosdaq. Results carry shcode so follow-up calls can use ls_get_quote / ls_get_chart / ls_get_stock_info. data_as_of + query_date_resolution match the cross-cutting envelope used by other daily-snapshot tools.

Input parameters:

- `limit` (integer): Maximum matching rows to return (1-100). Default 20.
- `market` (string): Market filter: all (default), kospi, or kosdaq.
- `name_or_id` (string, required): Q-Click signal: exact name ("이평 골든크로스(5,20)", case-insensitive), 4-character search_cd ("6116"), or Korean keyword ("골든크로스"; ambiguous keywords return candidates).

### `ls_get_stock_themes` (~175 tokens)

Returns every LS curated theme (tmcode) that a Korean stock belongs to, with the theme's recent average percent change. Wraps LS t1532. An empty array is a valid response — many stocks aren't pinned to any theme.

USE WHEN: the user asks "삼성전자는 어떤 테마야?", "이 종목 테마 묶음", or before calling ls_get_theme_stocks to discover the actual tmcode.
AVOID WHEN: the user wants the industry classification ("이 종목 업종은?") — that's the FICS industry sourced from t3320 and surfaced on ls_holdings_list as `industry` / `industry_raw`, not LS themes.

Input parameters:

- `shcode` (string, required): 6-character Korean short code, e.g. '005930' for Samsung Electronics.

### `ls_list_screeners` (~410 tokens)

Lists LS's curated Q-Click / 씽큐스마트 stock-signal catalog via t1826. These are standard signals LS maintains (e.g. 이평 골든크로스, 20일 매물대 상향돌파, 외인 3일연속 순매수); every account sees the same 99-signal catalog from the first call. NOT user-authored conditions: HTS [1892] (KRX)조건검색 is a separate system that does not flow into this surface.

USE WHEN: the user asks "Q-클릭 조건 뭐 있어?", "LS가 제공하는 시그널 목록", "골든크로스 같은 시그널 있어?", or the model needs to learn the exact catalog names before running / combining signals.
AVOID WHEN: the user already named a signal (use ls_run_screener) or asked for a compound condition (use ls_combine_screeners — both tools accept Korean keywords directly and surface candidates if a keyword is ambiguous).

search_group: all (default) returns the full catalog, or filter by core (핵심검색, 23) / indicator (지표검색, 33) / market_trend (시세동향, 16) / investor_trend (투자자동향, 15) / rapid_change (급변종목, 12). LS codes 0/1/2/3/4 also accepted; LS spec doc enumerates only 0-3 but search_gb=4 (rapid_change, ids 6401-6412) is verified active as of 2026-05-25.

Input parameters:

- `search_group` (string): Signal group: all (default, 99 signals) / core (23) / indicator (33) / market_trend (16) / investor_trend (15) / rapid_change (12). LS codes 0/1/2/3/4 also accepted.

### `ls_holding` (~655 tokens)

Records a change to one of the user's locally registered holdings — the write path. To VIEW holdings use ls_holdings_list instead. Does not require LS credentials. `shcode` is required for every action. Pick the operation with `action`:

\- action="set" — replaces the holding with the supplied state. Requires `quantity` (≥1) and `avg_price`. USE FOR "현재 보유 수량은 N주, 평단 M원이야" or initial registration.
\- action="buy" — records an incremental buy, merging with any existing lot at weighted-average cost. Requires `quantity` and `price`. USE FOR "삼성전자 N주 더 샀어. 단가 P원".
\- action="sell" — records a sell. Requires `quantity`. Subtracts shares; the row is auto-removed at zero; returns InsufficientQuantity when quantity exceeds the position.
\- action="remove" — removes the holding row outright regardless of quantity (returns removed=false when the symbol is not held).
\- action="corporate_action" — applies a corporate action that preserves cost basis. Requires `type` ('split' 액면분할, 'reverse_split' 액면병합, 'bonus' 무상증자) and `ratio` (split/reverse_split: integer ≥2; bonus: positive fraction, 0.1 = 10%).

\`account` is optional — auto-resolved when the symbol is held in exactly one account, AmbiguousAccount otherwise. For corporate_action, omitting `account` applies the event to every account holding the symbol.

USE WHEN: the user reports buying / selling / setting / removing one of their own positions, or a corporate action on a stock they hold.

v0.10 BREAKING: replaces ls_holdings_set / ls_holdings_buy / ls_holdings_sell / ls_holdings_remove / ls_holdings_corporate_action. The read tool ls_holdings_list is unchanged.

Input parameters:

- `account` (string): Optional account identifier (account_number or nickname). Auto-resolved when unambiguous; for corporate_action, omit to apply across every account holding the symbol.
- `action` (string, required): Operation to perform: 'set', 'buy', 'sell', 'remove', or 'corporate_action'.
- `avg_price` (number): Average purchase price (≥0). Required for action='set'.
- `note` (string): set: optional user note for the holding.
- `price` (number): Price per share for this transaction. Required for action='buy'.
- `quantity` (integer): Share quantity. Required for 'set' (≥1), 'buy', and 'sell'. Unused by 'remove' / 'corporate_action'.
- `ratio` (number): corporate_action: ratio. split/reverse_split require an integer ≥2; bonus is a positive fraction (0.1 = 10%).
- `shcode` (string, required): 6-character Korean short code (e.g. '005930' or '0117V0'). Required for every action.
- `type` (string): corporate_action: type — 'split', 'reverse_split', or 'bonus'.

### `ls_holdings_list` (~807 tokens)

Lists the user's locally registered holdings grouped by account, enriches them with current price, market_value, PnL, and PnL percent using batch t8407 when LS credentials are available, and computes a per-account summary plus a total_summary across all accounts. v0.6 adds optional theme filters; when at least one filter is active the response also echoes the filter and a matched_themes array so LIKE false positives are visible.

USE WHEN: the user refers to their own position or portfolio, including Korean phrases like "내 보유 주식", "내 보유 주식 현황", "보유 현황", "내가 가진", "내가 산", "보유 중", "들고 있는", "내 종목", "내 잔고", "내 포트폴리오", or English phrases like "my holdings", "my position", "my portfolio". This is local data the user registered themselves — do NOT refuse such questions for lack of brokerage access. Before calling general stock tools such as ls_get_chart or ls_get_quote, call this tool first to check the user's registered holdings. If it returns empty, guide the user to register holdings or fall back to general analysis.
AVOID WHEN: the user asks about a stock in general without personal ownership context, e.g. "삼성전자 어때?"; use market/quote/chart tools directly.

Filter natural-language mapping:
\- "내 보유 중 2차전지 테마" → theme_keyword="2차전지"
\- "내 한투 계좌의 AI 테마" → account="한투", theme_keyword="AI"
\- "테마 코드 0064 보유" → theme_code="0064"
\- "내 보유 중 반도체 업종" / "내 금융주" → industry="반도체" / industry="금융"
All filters AND-combine. The `industry` filter is a case-insensitive substring match against the FICS industry label sourced from t3320 (the "FICS " prefix is stripped before matching, so "반도체" matches "반도체 및 관련장비"). ETF / SPAC symbols have no industry record and are excluded from any industry-filtered list.

Payload size: themes_limit caps themes per holding (default 5; 0 = count only; -1 = all), include_industry / include_quote drop those blocks when false. Lightest call — themes_limit=0, include_industry=false, include_quote=false — returns just the holding rows + account/total summaries.

Input parameters:

- `account` (string): Optional account identifier (account_number or nickname). When omitted, holdings across all accounts are returned grouped.
- `include_industry` (boolean): Include the FICS industry label per holding. Default true; pass false to omit it.
- `include_quote` (boolean): Include the live quote + market_value / PnL per holding. Default true; pass false to drop the per-holding valuation block (account and total summaries are still computed).
- `industry` (string): Optional FICS industry substring (case-insensitive). '반도체' matches FICS 반도체 및 관련장비. ETF/SPAC symbols are excluded automatically since they have no industry record.
- `theme_code` (string): Optional exact 4-character LS theme code (tmcode), e.g. '0064'. Keeps only holdings whose cached themes contain this code.
- `theme_keyword` (string): Optional theme name keyword. Case-sensitive LIKE match against cached theme names. '2차전지' matches '2차전지 셀', '2차전지 소재', etc.
- `themes_limit` (integer): Max themes shown per holding. Default 5; 0 omits the theme items (themes count only); -1 returns every theme. Each holding's themes is a {count, shown, items} object.

### `ls_account_performance` (~183 tokens)

Returns period P&L for the account via TR FOCCQ33600 — total invested principal, period return %, and a per-period breakdown (daily / weekly / monthly).

USE WHEN: the user asks "이번 달 수익률", "지난 분기 손익", "주간 성과", or any time-bucketed performance question.
Date range defaults to the last 30 days; `term` chooses bucket granularity (daily / weekly / monthly).

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `end_date` (string): End date YYYY-MM-DD or YYYYMMDD. Default = today.
- `start_date` (string): Start date YYYY-MM-DD or YYYYMMDD. Default = 30 days ago.
- `term` (string): Bucket: 'daily' (default), 'weekly', or 'monthly'.

### `ls_account_transactions` (~291 tokens)

Returns the full transaction log over a date range via TR CDPCQ04700 — deposits, withdrawals, fills, transfers, all in one timeline. Differs from ls_account_order_history (orders only) and ls_account_balance (current snapshot).

USE WHEN: the user asks "거래내역", "입출금 내역", "통장", or wants reconciliation across a period.
Filter `kind` ('all' default / 'cashflow' (입출금) / 'transfer' (입출고) / 'trade' (매매) / 'fx' (환전) / 'misc' (기타)) lets the model narrow without re-querying.

Date range defaults to the past 7 days; both bounds inclusive.

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `end_date` (string): End date YYYY-MM-DD or YYYYMMDD. Default = today.
- `kind` (string): Kind filter: 'all' (default), 'cashflow' (입출금), 'transfer' (입출고), 'trade' (매매), 'fx' (환전), 'misc' (기타).
- `start_date` (string): Start date YYYY-MM-DD or YYYYMMDD. Default = 7 days ago.
- `symbol` (string): Optional 6-digit shcode to narrow to one symbol.

### `ls_get_theme_stocks` (~332 tokens)

Returns the stocks inside one LS curated theme (e.g. "AI", "2차전지", "반도체 장비") with the theme's roll-up summary attached. Wraps LS t1537 with header-based continuation paging (tr_cont/tr_cont_key) and resolves a theme_keyword against the cached t1531 catalog.

USE WHEN: the user asks "AI 테마 종목", "2차전지 테마 종목 비교", "테마 0064 안에 뭐 있어?".
AVOID WHEN: the user wants industry/sector (KRX 산업분류) — use ls_get_industry_stocks. For market-wide theme rankings, t1531 directly via ls_call_tr.

theme_code XOR theme_keyword: pass a 4-character tmcode (e.g. '0064') or a Korean keyword. 0 matches → ThemeNotFound; 2+ → AmbiguousTheme with candidates. theme_code wins when both supplied.

Input parameters:

- `limit` (integer): Max stock rows returned (1-200). Default 30.
- `theme_code` (string): 4-character LS theme code (tmcode), e.g. '0064' (2차전지), '0012' (반도체 장비). Mutually exclusive with theme_keyword (theme_code wins on conflict).
- `theme_keyword` (string): Theme name keyword (e.g. '2차전지', 'AI'). Resolved via t1531 catalog LIKE match. 0 matches → ThemeNotFound; 2+ → AmbiguousTheme envelope with candidates.

### `ls_combine_screeners` (~582 tokens)

Runs multiple LS Q-Click signals and combines matched stocks by shcode set operation (AND intersection / OR union). This expresses compound screening that no single HTS screen offers — e.g. "골든크로스가 뜨면서 동시에 외인이 3일연속 순매수한 종목".

USE WHEN: the user asks for stocks satisfying MULTIPLE Q-Click signals together ("AND") or ANY of a set ("OR"). Compound natural-language patterns: "A 이면서 B", "A + B + C 모두", "A 또는 B".
AVOID WHEN: the user wants exactly one signal (use ls_run_screener); simple metric ranking (use ls_get_top_stocks / ls_get_fundamentals_rank); user-authored HTS conditions (out of scope).

signals (2-8 entries): each entry is an exact catalog name (one of 99), a 4-character search_cd (6001-6412), or a Korean keyword ("골든크로스"). Server-side matched against the cached catalog. If any entry is ambiguous (matches multiple) or not found, the tool returns an envelope listing per-input candidates and the full mini-catalog of each ambiguous group (β policy), so the next call can pass exact ids without a separate ls_list_screeners round trip.
mode: "and" intersection (default) keeps only stocks matched by EVERY listed signal. "or" union keeps stocks matched by AT LEAST ONE, deduplicated by shcode. Each result row carries signals_matched listing which signals fired for that stock. Ordering: AND preserves first-signal rank order (filtered to the intersection). OR sorts by descending signals_matched count first, then by best (smallest) rank — so when limit truncates, the higher-conviction "matched by multiple signals" stocks surface before single-signal matches.
market: all / kospi / kosdaq. limit: max rows after combination (1-100, default 20). Results share the same envelope (shcode, name, price, change_pct, volume, data_as_of, query_date_resolution) as ls_run_screener for downstream chaining.

Input parameters:

- `limit` (integer): Max rows after combination (1-100). Default 20.
- `market` (string): Market filter: all (default), kospi, or kosdaq.
- `mode` (string): Combination mode: 'and' (intersection, default) or 'or' (union). 'intersection' / 'union' / '교집합' / '합집합' also accepted.
- `signals` (array, required): 2-8 Q-Click signals: exact names, 4-character search_cds, or Korean keywords. Ambiguous keywords get resolved via the catalog or returned as candidates.

### `ls_account_bep` (~222 tokens)

Returns the break-even price (BEP 단가) per holding via TR CSPAQ12300. BEP is the price you'd need to sell at to fully cover commissions and taxes — different from the raw average purchase price.

USE WHEN: the user asks "BEP 단가", "손익분기 단가", "수수료 포함 평단", or wants the after-fee breakeven on their LS positions.
AVOID WHEN: the user wants just the simple average purchase price — that's already in ls_account_holdings.average_price.

\`symbol` optionally narrows to a single 6-digit code (Korean shcode); the LS field IsuNo accepts the "A+code" form but the wrapper takes the bare 6-digit shcode for the user. Like every ls_account_* tool, no `account` argument — the appkey-bound LS subaccount answers.

Input parameters:

- `symbol` (string): Optional 6-digit Korean short code (e.g. '005930'). Omit to return BEP for every holding.

### `ls_get_analyst_opinions` (~321 tokens)

Returns a Korean stock's brokerage (sell-side) investment-opinion history via LS t3401: each entry carries the opinion-day date, 회원사 (broker), the rating before/after the change, the target price before/after, and the stock's close on that day. A current-price snapshot is included.

This is the authoritative, structured source for Korean 투자의견 / 목표주가 / analyst-consensus change history — LS supplies the official per-broker opinion-change record directly. Prefer this tool before web search for the rating / target-price numbers; use web search only for the narrative around a change (the broker's rationale, the market reaction).

USE WHEN: the user asks about analyst opinions / 투자의견 / 목표주가 / target price / sell-side coverage / 컨센서스 for a named stock ("삼성전자 투자의견", "SK하이닉스 목표주가 어떻게 바뀌었어?").
AVOID WHEN: the user wants fundamentals/valuation numbers (use ls_get_stock_info or ls_get_fundamentals_rank).

Returns the most recent opinion changes (up to 20). Target prices are in 원; opinion labels are LS-supplied strings such as BUY / HOLD. An empty `opinion_from` means a newly initiated rating.

Input parameters:

- `count` (integer): Maximum opinion entries to return, most recent first (1-20). Default 20.
- `shcode` (string, required): 6-digit Korean stock code, e.g. 005930.

### `ls_get_fundamentals_rank` (~474 tokens)

Returns a fundamental-metric ranking of Korean stocks via t3341 (재무순위종합). One TR call covers all metrics — pass the metric name as `field`.

Supported `field` values (LS-side ordering rules in parentheses):
\- "per" (forced ascending — undervalued first)
\- "pbr" (forced ascending)
\- "peg" (forced ascending)
\- "eps", "bps", "roe" (LS default — typically descending)
\- "sales_growth", "operating_income_growth", "ordinary_income_growth" (LS default)
\- "debt_to_equity" (부채비율), "retained_earnings_ratio" (유보율)

USE WHEN: the user asks for screener-style ranking — "PER 낮은 종목", "ROE 상위 30", "코스닥 영업이익 증가율 1위" — without specifying individual symbols.
AVOID WHEN: the user already has a single symbol in mind (use ls_get_stock_info for that symbol's fundamentals instead).

market: 'both' (default) / 'kospi' / 'kosdaq'.
limit: number of rows to return (1 - 200, default 30). The wrapper pages through t3341 as needed; total_available echoes the full ranking size.

Each row echoes the full fundamental snapshot LS attaches (rank, shcode, name, per/pbr/peg/eps/bps/roe/growth metrics) so the model doesn't need a follow-up call to compare two metrics on the same stock.

For fundamental rankings, prefer this LS-backed tool before web search; use web search only for narrative context around the numbers.

Input parameters:

- `field` (string, required): Metric name. See the description for the supported set; aliases like 'pe' / 'pb' / 'peg' / 'eps' / 'bps' / 'roe' / 'sales_growth' / 'operating_income_growth' / 'debt_to_equity' / 'retained_earnings_r…
- `limit` (integer): Number of rows to return (1-200, default 30).
- `market` (string): Market scope: 'both' (default), 'kospi', or 'kosdaq'.

### `ls_get_top_stocks` (~470 tokens)

Returns Korean stock ranking screens: top gainers/losers/unchanged, market-cap leaders, volume leaders, trading-value leaders, and volume-surge leaders. Wraps LS TRs t1441, t1444, t1452, t1463, and t1466 behind one kind parameter.

USE WHEN: the user asks for market-wide screeners such as "오늘 급등주", "하락률 상위", "시총 상위", "거래량 상위", "거래대금 상위", "거래 급증 종목", or a quick idea-generation list before drilling into ls_get_quote / ls_get_chart / ls_get_stock_info.
AVOID WHEN: the user already named a specific stock and wants detail — use ls_get_quote, ls_get_chart, or ls_get_stock_info instead.

kind: gainers | losers | unchanged | market_cap | volume | amount | volume_surge.
market: all | kospi | kosdaq. For kind=market_cap and market=all, the tool calls KOSPI and KOSDAQ ranking screens and merges by market cap.
basis: today | previous_day. Ignored for market_cap and volume_surge.
exchange: unified | krx | nxt. Applies to gainers/losers/unchanged, amount, and volume_surge.
Price and volume filters apply only where the underlying LS TR supports them; kind=market_cap ignores those filters.

Input parameters:

- `basis` (string): today or previous_day. Applies to gainers/losers/unchanged, volume, and amount. Default today.
- `exchange` (string): unified, krx, or nxt. Applies where LS supports exchange selection. Default unified.
- `kind` (string, required): Ranking kind: gainers, losers, unchanged, market_cap, volume, amount, or volume_surge.
- `limit` (integer): Maximum rows to return (1-100). Default 20.
- `market` (string): Market filter: all, kospi, or kosdaq. Default all.
- `max_price` (integer): Optional maximum current price. 0 means no upper bound.
- `min_price` (integer): Optional minimum current price.
- `min_volume` (integer): Optional minimum volume.

### `ls_get_chart` (~1185 tokens)

Returns OHLCV candles for a Korean stock with optional technical indicators and pre-computed analysis context (divergence from MAs, volume averages, drawdown from period high, MA trend, bullish alignment).

USE WHEN: the user asks for a chart, 차트, 일봉/주봉/월봉/분봉/틱, OHLCV, technical analysis, or multi-timeframe analysis (e.g. "삼성전자 일봉과 주봉, 월봉 같이 보여줘").
AVOID WHEN: the user wants the current snapshot only — use ls_get_quote instead.

Single timeframe: period_type='day' → response has top-level summary/context/dataset_id.
Multi timeframe: period_type='day,week,month' → response has a frames[] array, one compact entry per timeframe.

Set include_chart=true (single timeframe only) for inline chart rendering on hosts that support MCP Apps. When the connected host can render charts, the Plotly v5 spec ships as structuredContent (not in the model's text context — zero token cost) and the host renders it inline; on a text-only host the parameter is not offered. Multi-timeframe with include_chart is a no-op for inline rendering (call once per period_type for charts); the structured candles/indicators/context payload is unaffected.

output_mode controls token cost:
\- display: chart rendering; text contains dataset_id + AnalyticalSummary, chart spec goes to structuredContent.
\- analyze: model reasoning; text contains dataset_id + AnalyticalSummary + context, no raw bars.
\- export: ONLY when the user explicitly asks for raw/table/CSV data; includes full OHLCV and indicator arrays in text.
\- reference: follow-up tool handle only; returns dataset_id and metadata.

Raw candles and full indicator arrays are intentionally absent unless output_mode='export'. summary_only is legacy and maps to analyze when output_mode is omitted.

Warm-up behavior (with_warmup):
\- Omitted (default): auto-pads the fetch when `from` is unspecified so the summary's long-period indicators (MA60 slope, MA200, change_1y, key_turns) populate. RECOMMENDED for "최근 흐름" / "show me the recent pict…

Input parameters:

- `count` (integer): Number of candles per timeframe (1–500). Default 60.
- `from` (string): Optional start date in 'yyyyMMdd' format.
- `indicators` (array): Optional indicator specs, e.g. ['ma:5','ma:20','rsi:14','macd:12,26,9','bb:20,2'].
- `minute_unit` (integer): For period_type='min': minute interval (1, 3, 5, 10, 15, 30, 60). Default 5.
- `name` (string): Optional human-readable stock name (e.g. '삼성전자'). Used only for the inline chart title — pass it when you already know the name so the chart reads '삼성전자 (005930) — 일봉' instead of just the code. The T…
- `output_mode` (string): "display" for chart rendering (summary text + structured chart), "analyze" for model reasoning (summary only), "export" only for explicit raw data/table requests, or "reference" for dataset_id-only f…
- `period_type` (string, required): Period type: 'day', 'week', 'month', 'year', 'min', or 'tick'. Multiple via comma-separated string: 'day,week,month'.
- `shcode` (string, required): 6-digit Korean short code, e.g. '005930'.
- `summary_only` (boolean): If true, keep only the last 5 candles and the last value of each indicator series (context is kept intact). Use for the screening pass when scanning many stocks/timeframes. Default false.
- `theme` (string): Optional chart theme override: "light", "dark", or "auto" (default). Pass when the user explicitly asks for a dark/light chart (e.g. "다크 차트로 보여줘") — the iframe overrides hostContext.theme. Follow-up…
- `to` (string): Optional end date in 'yyyyMMdd' format.
- `with_warmup` (boolean): Warm-up policy override. Omit (null) for auto: pad when `from` is unspecified, skip when `from` is given. Pass true to force pad with explicit `from` (analyze trends inside a narrow window). Pass fal…

### `ls_account_daily_pnl` (~205 tokens)

Returns the trade log + commission/tax summary for a single trading day via TR t0150 (today) or t0151 (any other date). Aggregate sell/buy quantities, fees, and net settlement; plus per-trade rows.

USE WHEN: the user asks "오늘 매매일지", "어제 매수/매도 내역", "수수료 얼마 냈어", or wants the day-level closing log with fees.
AVOID WHEN: the user wants a multi-day period — use ls_account_performance. AVOID WHEN: the user wants every transaction including deposits — use ls_account_transactions.

\`date` defaults to today (t0150). Any other date uses t0151. The wrapper picks the right TR automatically.

Like every ls_account_* tool, no `account` argument.

Input parameters:

- `date` (string): Date YYYY-MM-DD / YYYYMMDD / 'today' / 'yesterday'. Default = today.

### `ls_get_market_funds_trend` (~387 tokens)

Returns the Korean stock-market liquidity ("증시 주변 자금") trend via LS t8428: per day the index, customer deposits (고객예탁금), deposit change, credit balance (신용잔고), receivables (미수금), futures deposits, and fund money split across equity / mixed / bond / MMF buckets.

USE WHEN: the user asks about market liquidity, 고객예탁금, 신용잔고, 미수금, 대기자금, or fund flows ("요즘 예탁금 추이", "신용잔고 늘었어?").
AVOID WHEN: the user wants per-stock investor flow (use ls_get_investor_flow) or an index time series (use ls_get_index_history).

\`market` selects the index context: 'kospi' (default) or 'kosdaq'. All monetary fields are in 억원.

Publishing lag: investor-deposit and credit-balance figures are sourced from KSD (한국예탁결제원) with a T+2~T+3 publishing delay, so the latest row often trails today by 2-3 business days. `data_as_of` reports the actual latest row date (not today); when narrating "최근" / "오늘" deposits, use that date. If the user's `query_date` falls on a weekend or holiday, LS returns the most recent prior trading day automatically — read `data_as_of` and tell the user.

Input parameters:

- `count` (integer): Trading days to return (1-120). Default 20.
- `market` (string): Index context: 'kospi' (default) or 'kosdaq'.
- `query_date` (string): Optional basis date in yyyyMMdd. Weekends resolve to the prior Friday; future dates clamp to the latest available trading day.

### `ls_get_multi_quote` (~174 tokens)

Returns a compact current-price snapshot for multiple Korean stocks in a single call. Each entry includes price, OHLC, volume, best ask/bid (1 level), 매도/매수 총잔량, and 체결강도(chdegree).

USE WHEN: comparing 2+ stocks side-by-side ("삼성전자 vs SK하이닉스 vs LS증권 비교"), or fetching a small watchlist's prices efficiently. Up to 50 codes per call.
AVOID WHEN: 10-level order book is needed for a single stock — use ls_get_quote instead.

Input parameters:

- `shcodes` (array, required): Array of 6-character Korean short codes (usually 6 digits, some ETFs include an uppercase letter, e.g. ['005930','000660','0117V0']). Max 50.

### `ls_get_overseas_chart` (~681 tokens)

Returns OHLCV candles for an overseas stock via LS g3204 (day/week/month/year), g3203 (minute), or g3202 (tick), with optional indicators and Plotly chart rendering.

USE WHEN: the user asks for a US/overseas stock chart, 미장 일봉/주봉/월봉/분봉/틱, OHLCV, or technical-analysis context for a stock such as TSLA/NVDA/AAPL.
AVOID WHEN: the user wants Korean stock candles — use ls_get_chart. For current price only use ls_get_overseas_quote.

output_mode controls token cost:
\- display: summary text + structuredContent.chart when include_chart=true.
\- analyze: summary + compact context, no raw candles.
\- export: raw OHLCV and indicator arrays.
\- reference: dataset_id and metadata only.

The returned dataset_id is accepted by ls_add_indicator and ls_reframe_chart for follow-up calls like "MA200도 추가" or "일봉으로 바꿔서 6개월" — KR and US datasets share the same handle cache.

Date/time semantics: daily/weekly/monthly/yearly bars are indexed by the US local trading day (ET); minute/tick bars carry US ET timestamps via LS's loctime field. The response's bar_timezone field surfaces this ('America/New_York' for Nasdaq/NYSE/AMEX) so a "5/22 일봉" can be read as "the NYSE 5/22 session", which lands ~14 hours behind Asia/Seoul during DST.

Input parameters:

- `adjusted` (boolean): For day/week/month/year charts, apply adjusted prices. Default true.
- `count` (integer): Number of candles (1-500). Default 60.
- `exchcd` (string): Exchange code: '82' Nasdaq (default) or '81' NYSE/AMEX. Aliases nasdaq/nyse/amex accepted.
- `from` (string): Optional start date in yyyyMMdd format.
- `indicators` (array): Optional indicator specs, e.g. ['ma:20','rsi:14','macd:12,26,9','bb:20,2'].
- `keysymbol` (string): LS key symbol such as '82TSLA'. Preferred when known.
- `name` (string): Optional human-readable stock name for the chart title.
- `output_mode` (string): Output intent: display, analyze, export, or reference. Defaults to display when include_chart=true, otherwise analyze.
- `period_type` (string): Period type: 'day', 'week', 'month', 'year', 'min', or 'tick'.
- `symbol` (string): Ticker symbol, e.g. 'TSLA'. If keysymbol is supplied this may be omitted.
- `theme` (string): Optional chart theme override: "light", "dark", or "auto" (default). Pass when the user explicitly asks for a dark/light chart. Follow-up ls_add_indicator / ls_reframe_chart inherit this on the same…
- `to` (string): Optional end date in yyyyMMdd format.
- `unit` (integer): For period_type='min': minute interval. For 'tick': tick grouping. Default 5.

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi#diagnostics

## Score history

- 2026-08-03: 39
- 2026-08-02: 39
- 2026-08-01: 24
- 2026-07-31: 29
- 2026-07-29: 47
- 2026-07-28: 47
- 2026-07-27: 47
- 2026-07-26: 47

## Links

- NuGet package: https://www.nuget.org/packages/RedoxNet.Mcp.LsOpenApi
- Socket report: https://socket.dev/nuget/package/RedoxNet.Mcp.LsOpenApi
- Repository: https://github.com/redoxnet/mcp-lsopenapi
- Changelog RSS feed: https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi/changelog.json
- HTML version of this page: https://verifymcp.io/servers/redoxnet-lsopenapi/redoxnet-mcp-lsopenapi
