Skip to main content
Glama
dongkyucho17

krx-etf-mcp

by dongkyucho17

krx-etf-mcp

Find Korean ETFs by what they actually are — and rank them by what they actually did.

An MCP server that puts the Korean ETF market (about 1,160 listings) in front of an AI assistant. Lookup comes first — find a fund by name, issuer, underlying index or category, and read its full detail including the NAV premium. Then rank, compare, and chart.

🇰🇷 한국어 README

Data source: 공공데이터포털 (data.go.kr), service 금융위원회_증권상품시세정보 (GetSecuritiesProductInfoService). Prices originate from the Korea Exchange (KRX). This project is independent and not affiliated with either organisation.

Scope: ETF only. The same upstream service also carries ETN and ELW. They are deliberately out of scope — see Why ETF only.


Table of contents


Related MCP server: kookmin-stock

What it's for

In priority order:

  1. Finding an ETF. By name, by issuer, by underlying index, by category — and reading its full detail once found. This is the daily use.

  2. Ranking. Which of these did best over a period.

  3. Detail and comparison. Full quote fields, price history, head-to-head.

The sections below are ordered the same way.

The problem this solves

The lookup problem and the ranking problem have the same root cause, so it's worth seeing it through the question that started this project:

"Of the bond-mixed ETFs, which ten rose the most over the last three months?"

That sounds like a lookup. It isn't. Answering it correctly requires six separate things, and the public API provides none of them:

  1. Find today's data. Ask for today and you get totalCount: 0 — the portal publishes with a lag. You have to walk backwards to find a day that has rows.

  2. Identify bond-mixed ETFs. There is no asset-class field. None. The only signal is the product name.

  3. Fetch the whole universe twice. ~1,160 rows per day, paginated, for both ends of the period.

  4. Join the two days by ticker and compute the change.

  5. Handle the ones that don't join. Nine of the thirty bond-mixed ETFs listed during the period. Drop them silently and your ranking is quietly biased toward survivors.

  6. Say what the number means. It is a price return. Distributions are excluded — which matters a great deal for exactly this category.

An assistant asked to do that on the fly will write six pieces of throwaway code and get at least one of them wrong, differently each time. The arithmetic belongs in tested code; the judgement belongs to you.

By the way, the honest answer to the original question was: only five of them rose at all. A naive "top 10" quietly lists five losers as winners. This server reports positive_count alongside the ranking so that fact is visible rather than buried.

What the raw API gives you

What you want to ask

What getETFPriceInfo returns

What this server does

"Today's prices"

totalCount: 0 — data lands a day late

Resolves backwards to the last day with rows, and tells you which day it used

"Bond-mixed ETFs"

No category field at all

Infers asset class, region and strategy from product names, with an audit trail

"Top 10 over 3 months"

No return calculation, no ranking

Joins two daily snapshots and ranks, with filters

"The whole ETF universe"

~1,160 rows across paged requests

Pages and caches per day, in process

"Was anything skipped?"

Silence

Returns an excluded list with a reason for every omission

"Is this total return?"

Nothing

Says price return only on every return-bearing response

"How far is it from NAV?"

Ships clpr and nav, leaves you the division

nav_premium_pct on every record

"Who issues it?"

Nothing — it's in the name, unparsed

issuer field and filter

"What else tracks this index?"

Nothing

find_similar_etf groups by underlying index

Install

Requires Python 3.10+ and a free data.go.kr service key.

1. Get a service key

  1. Sign up at data.go.kr (Korean phone/ID not required for the basic tier).

  2. Go to 금융위원회_증권상품시세정보 and click 활용신청 (request access). Approval for the development tier is immediate.

  3. Copy your key from 마이페이지 → 인증키.

The portal shows the key in two forms, Encoding and Decoding. Either works — this server detects which one you pasted and normalises it. (Getting this wrong is the single most common cause of NO_MANDATORY_REQUEST_PARAMETERS_ERROR.)

2. Register the server with your MCP client

Claude Desktop (claude_desktop_config.json) or Claude Code (.mcp.json):

{
  "mcpServers": {
    "krx-etf": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/dongkyucho17/krx-etf-mcp", "krx-etf-mcp"],
      "env": { "DATA_GO_KR_API_KEY": "paste-your-key-here" }
    }
  }
}

Cursor / Cline / Zed — same shape, in that client's MCP config file.

Any agent framework that speaks stdio MCP:

DATA_GO_KR_API_KEY=... uvx --from git+https://github.com/dongkyucho17/krx-etf-mcp krx-etf-mcp

From a local checkout:

git clone https://github.com/dongkyucho17/krx-etf-mcp && cd krx-etf-mcp
cp .env.example .env          # paste your key into .env
uv run krx-etf-mcp

The key is read from DATA_GO_KR_API_KEY, or KRX_ETF_API_KEY if you prefer to scope it. It is never written to disk, never logged, and never appears in a tool response — see Why the key needs care.

3. Check it works

Ask your assistant: "What's the latest KRX ETF trading day?" You should get a resolved date and a lag count.

Tools

Eleven tools, grouped by what you're doing.

Finding an ETF — the primary use

Tool

Purpose

search_etf

Find ETFs by name, issuer, index and/or classification. Sortable

get_etf_quote

Full detail for one ETF, by code, ISIN or name

find_similar_etf

Every ETF tracking the same underlying index

list_indices

Which underlying indices exist, and how many ETFs track each

list_filters

The accepted filter and sort values

explain_classification

Which keywords drove a classification verdict

Performance

Tool

Purpose

rank_etf_return

Rank by price return over a period, within a filter

compare_etf

Compare specific tickers over one shared period

get_etf_history

Daily closing-price series for one ticker

Housekeeping

Tool

Purpose

latest_trading_day

Resolve the newest date that actually has data

server_info

Version, data source, and limitations

Every tool returns {"ok": true, ...} or {"ok": false, "error": ..., "message": ...}. Nothing raises across the MCP boundary, so a bad date or an expired key produces a readable answer rather than a dead tool.

Usage examples

All output below is real, captured from live responses.

Look up one ETF by name

You rarely know the six-digit code. get_etf_quote takes a code, an ISIN or a name.

get_etf_quote(code_or_name="KODEX 200")
{
  "ok": true,
  "base_date": "20260812",
  "quote": {
    "code": "069500", "isin": "KR7069500007", "name": "KODEX 200", "issuer": "KODEX",
    "close": 103250.0, "change": 1000.0, "change_pct": 1.02,
    "open": 97570.0, "high": 100350.0, "low": 96650.0,       // OHLC
    "volume": 15084783.0, "trade_value": 1391450049502.0,
    "market_cap": 24119200000000.0,
    "nav": 103464.35, "nav_premium_pct": -0.207,             // ← computed here, not in the feed
    "net_asset_total": 23178762287104.0, "listed_shares": 231850000.0,
    "index_name": "코스피 200", "index_close": 987.4,
    "asset_class": "주식", "region": "국내", "strategies": []
  }
}

A partial name that matches several products returns candidates instead of guessing:

get_etf_quote(code_or_name="반도체")
{
  "ok": true, "quote": null, "ambiguous": true,
  "message": "59 ETFs match '반도체'. Pick one by code.",
  "candidates": [
    { "code": "396500", "name": "TIGER 반도체TOP10" },
    { "code": "091160", "name": "KODEX 반도체" }
  ]
}

Browse one issuer's line-up, sorted how you want

search_etf(issuer="TIGER", sort_by="volume", limit=5)
TIGER — 230 listings, sorted volume desc
  252710  TIGER 200선물인버스2X          134,043,548
  0195S0  TIGER SK하이닉스단일종목레버리지     26,619,021
  360750  TIGER 미국S&P500              23,437,266

Former brand names resolve too — issuer="KBSTAR" returns the 143 RISE listings, and ARIRANG / KINDEX / KOSEF behave the same way. Sort on market_cap, volume, trade_value, close, change_pct, nav_premium_pct, name or code, ascending or descending.

"Which KOSPI 200 ETF should I hold?"

25 ETFs track 코스피 200. find_similar_etf puts them side by side on the three things that separate them: size, liquidity, and how far the price sits from NAV.

find_similar_etf(code_or_name="KODEX 200", sort_by="market_cap")
reference: KODEX 200   index: 코스피 200   peers: 25

  name              market cap (억)      volume    nav premium %
  KODEX 200                 241,192  15,084,783          -0.207
  TIGER 200                  99,632   9,257,408          -0.203
  KODEX 레버리지               58,676  20,595,774          -0.612
  RISE 200                   44,367     802,169          -0.205
  ACE 200                    18,277     235,324          -0.132
  PLUS 200                   14,559     288,751          -0.279

Note that leveraged products appear here — they genuinely track the same index. Their strategies field says so, and search_etf(index_name="코스피 200") plus a filter narrows it.

Map the market by underlying index

list_indices(min_etf_count=10)
  25  코스피 200            largest: KODEX 200
  24  S&P 500             largest: TIGER 미국S&P500
  16  NASDAQ 100          largest: TIGER 미국나스닥100
  16  코스피 200 선물지수      largest: KODEX 인버스
  13  코스피                largest: KODEX 코스피
  12  코스닥 150            largest: KODEX 코스닥150
  11  코리아 밸류업 지수       largest: RISE 코리아밸류업
  11  미국달러선물지수         largest: KODEX 미국달러선물인버스2X

Use the exact strings from here with search_etf(index_name=...).

Find the widest NAV premiums and discounts

search_etf(min_volume=10000, sort_by="nav_premium_pct", limit=3)
search_etf(min_volume=10000, sort_by="nav_premium_pct", ascending=True, limit=3)
  +7.785%  RISE 코리아밸류업위클리고정커버드콜
  +6.991%  RISE 미국AI클라우드인프라
  ...
  -2.987%  TIGER 차이나항셍테크레버리지(합성 H)
  -2.841%  KODEX 차이나H레버리지(H)

Rank a category by return

You: "Top 3 bond-mixed ETFs by 3-month return."

rank_etf_return(asset_class="채권혼합", months=3, top=3)
{
  "ok": true,
  "start_date": "20260511",       // both ends resolved to days that have data
  "end_date": "20260811",
  "requested_start": "20260511",
  "candidates": 30,
  "positive_count": 5,            // ← only 5 of 30 actually rose
  "negative_count": 25,
  "ranking": [
    {
      "rank": 1,
      "code": "447660",
      "name": "PLUS 애플채권혼합",
      "start_close": 13495.0,
      "end_close": 13690.0,
      "return_pct": 1.44,
      "market_cap": 22588500000.0,
      "volume": 21545.0,
      "nav": 13689.78,
      "index_name": "FnGuide 애플채권혼합 지수",
      "asset_class": "채권혼합",
      "region": "미국",
      "strategies": []
    },
    { "rank": 2, "code": "0049K0", "name": "ACE 미국배당퀄리티채권혼합50",
      "return_pct": 1.43, "region": "미국", "strategies": ["배당"] },
    { "rank": 3, "code": "447620", "name": "SOL 미국TOP5채권혼합50",
      "return_pct": 0.68, "region": "미국", "strategies": [] }
  ],
  "excluded_count": 9,            // ← reported, not silently dropped
  "excluded": [
    { "code": "0184N0", "name": "PLUS 은채권혼합",
      "reason": "no_data_at_period_start",
      "detail": "Listed after the start date, or not traded that day." }
  ],
  "return_disclaimer": "Price return only: computed from closing prices, distributions excluded. ..."
}

Note what the shape of this answer lets an assistant say: "Five of thirty rose; the top three are all US-underlying; nine were excluded because they listed mid-period." That is a different answer from "here are the top three", and a more honest one.

Find the losers instead

rank_etf_return(asset_class="채권혼합", months=3, top=3, worst=True)
{
  "start_date": "20260511", "end_date": "20260811",
  "ranking": [
    { "rank": 1, "code": "0186S0", "name": "1Q 코스닥150채권혼합50액티브",
      "start_close": 9870.0, "end_close": 8630.0, "return_pct": -12.56,
      "region": "국내", "strategies": ["액티브"] },
    { "rank": 2, "code": "0132K0", "name": "PLUS 테슬라위클리커버드콜채권혼합",
      "start_close": 9165.0, "end_close": 8120.0, "return_pct": -11.4 }
  ]
}

Search by strategy and region

You: "Show me US covered-call ETFs."

search_etf(strategy="커버드콜", region="미국", limit=3)
{
  "ok": true,
  "base_date": "20260811",
  "universe_size": 1163,
  "match_count": 38,
  "results": [
    {
      "code": "486290",
      "isin": "KR7486290000",
      "name": "TIGER 미국나스닥100타겟데일리커버드콜",
      "close": 10965.0,
      "change": -65.0,
      "change_pct": -0.59,
      "volume": 1109611.0,
      "market_cap": 2357475000000.0,
      "nav": 10936.12,
      "index_name": "NASDAQ 100 Daily Covered Call Target Premium 15% 지수(TR)",
      "issuer": "TIGER",
      "nav_premium_pct": 0.264,
      "asset_class": "주식",
      "region": "미국",
      "strategies": ["커버드콜", "데일리"],
      "region_inferred": false,
      "asset_class_inferred": true   // ← no asset keyword fired; equity was assumed
    }
  ]
}

Results default to market-cap order, so the liquid names come first. Filters combine freely:

search_etf(asset_class="채권혼합", region="미국")
search_etf(strategy="레버리지", issuer="KODEX")
search_etf(query="반도체", min_market_cap=1e11, sort_by="change_pct")
search_etf(index_name="S&P 500", sort_by="nav_premium_pct", ascending=True)

Price history for one ETF

get_etf_history(code="069500", months=1)
{
  "ok": true,
  "code": "069500",
  "name": "KODEX 200",
  "start_date": "20260713",
  "end_date": "20260811",
  "trading_days": 21,
  "period_return_pct": -8.78,
  "series": [
    { "base_date": "20260713", "close": 108820.0, "change_pct": -9.77,
      "volume": 28358089.0, "nav": 108583.09, "market_cap": 23793493000000.0 },
    { "base_date": "20260714", "close": 109720.0, "change_pct": 0.83, "volume": 33989327.0 },
    { "base_date": "20260715", "close": 116735.0, "change_pct": 6.39, "volume": 21886708.0 }
  ]
}

Compare specific tickers

You: "KODEX 200 vs TIGER 나스닥100 vs TIGER S&P500, past 6 months."

compare_etf(codes=["069500", "133690", "360750"], months=6)
{
  "start_date": "20260211",
  "end_date": "20260811",
  "comparison": [
    { "rank": 1, "code": "069500", "name": "KODEX 200",
      "start_close": 79115.0, "end_close": 99265.0, "return_pct": 25.47, "region": "국내" },
    { "rank": 2, "code": "133690", "name": "TIGER 미국나스닥100",
      "start_close": 161860.0, "end_close": 185825.0, "return_pct": 14.81, "region": "미국" },
    { "rank": 3, "code": "360750", "name": "TIGER 미국S&P500",
      "start_close": 25015.0, "end_close": 27215.0, "return_pct": 8.79, "region": "미국" }
  ],
  "not_found": []
}

Audit a classification you don't trust

explain_classification(name="SOL 팔란티어커버드콜OTM채권혼합")
{
  "name": "SOL 팔란티어커버드콜OTM채권혼합",
  "asset_class": "채권혼합",
  "region": "미국",
  "strategies": ["커버드콜"],
  "matched_keywords": ["채권혼합", "팔란티어", "커버드콜"],
  "region_inferred": false,
  "asset_class_inferred": false
}

Three keywords fired, and you can see all three. If a verdict looks wrong, this is where you find out why — and it makes a good bug report.

Prompts that work well

Lookup:

  • "What is KODEX 200 trading at, and how far is it from NAV?"

  • "Show me every TIGER ETF with US exposure, biggest first."

  • "Which ETFs track the S&P 500? Sort them by how tightly they hold NAV."

  • "I want a KOSPI 200 ETF. Which one is largest and most liquid?"

  • "What indices have the most ETFs competing on them?"

Performance:

  • "Which US-underlying bond-mixed ETFs beat their domestic equivalents over 6 months?"

  • "Find covered-call ETFs with more than 100 billion KRW in market cap, ranked by 3-month return."

  • "What were the worst-performing leveraged ETFs last month, and how many were excluded?"

Classification: how it works and when it lies

The upstream service exposes no category field whatsoever. Asset class, region and strategy are therefore derived from the product name.

This works better than it sounds, because Korean ETF names are highly conventional — the issuer prefix, underlying, and strategy are all encoded in the name by convention. It is still a heuristic, and it will be wrong sometimes.

Accepted values (from list_filters):

Dimension

Values

Rule

asset_class

채권혼합, 채권, 멀티에셋, 부동산, 원자재, 통화, 주식

First match wins; 주식 is the default

region

미국, 중국, 일본, 인도, 베트남, 유럽, 신흥국, 글로벌, 국내

First match wins; 국내 is the default

strategy

커버드콜, 레버리지, 인버스, 액티브, 배당, 환헤지, 위클리, 데일리, 월배당, TR

Additive — an ETF can carry several

issuer

KODEX, TIGER, RISE, ACE, PLUS, SOL, KIWOOM, HANARO, 1Q, KoAct, TIME, WON, …

Not a heuristic — see below

issuer is the one classification that never guesses. Every listed Korean ETF leads with its brand, so the first token identifies it exactly, for all 1,163 current listings. It is deliberately not mapped to a management-company name: the brand is what the data contains, and a hard-coded company table would rot every time a line is renamed or sold. Renames are handled the other way round — a query for a former brand (KBSTAR, ARIRANG, KINDEX, KOSEF, 히어로즈) resolves to the current one, so older write-ups still work as search terms.

Order matters, deliberately. 채권혼합 (bond-mixed) is checked before 채권 (bond), because "채권혼합" contains "채권" — a naive rule set files every bond-mixed fund as a plain bond fund. There is a regression test pinning exactly this.

Three safeguards against the heuristic quietly misleading you:

  1. asset_class_inferred / region_inferred are true when no keyword fired and a default was assumed. A true here means "guessed", not "determined".

  2. explain_classification shows every keyword that matched.

  3. Each search response repeats classification_note so a reading assistant relays the caveat.

Known blind spots. A bond-mixed fund whose name omits "채권혼합" will be missed. A US-underlying fund named only after an index this server doesn't recognise falls back to 국내. Company names are enumerated, so a newly popular underlying may not be recognised until it's added. Issues with the product name and the verdict you expected are welcome and easy to fix — the rules are plain tuples in categories.py.

Three things to know before trusting a number

1. Returns are price returns. The feed carries closing prices only, so distributions are not reinvested. This understates total return — materially for high-distribution categories such as covered-call and bond-mixed ETFs, which is to say exactly the categories people most often rank. Every return-bearing response repeats this in return_disclaimer.

2. Dates resolve backwards, silently but visibly. The portal publishes with roughly a one-day lag; weekends and holidays add more. Any date you pass is walked back up to 14 days to the newest day with rows. The date actually used is echoed in every response as start_date / end_date / base_date. Never assume the date you asked for is the date you got — read it back.

3. Nothing is dropped silently. ETFs missing a price at either end of a period are returned in excluded with a machine-readable reason, not omitted. This is not politeness: in the founding example, 9 of 39 bond-mixed ETFs had listed mid-period, and dropping them without comment would have biased the ranking toward whatever happened to have survived the whole window.

API traps encoded in this server

These cost real debugging time. They're documented here so you don't repeat them, and encoded in the code so you don't have to.

Trap

What happens

Where it's handled

endBasDt is exclusive

The spec reads "기준일자가 검색값보다 작은" — strictly less than — while beginBasDt is inclusive. Passing your end date verbatim silently drops the most recent day

dates.next_day

Service key must be spliced into the URL pre-encoded

Letting an HTTP library encode it via params= yields NO_MANDATORY_REQUEST_PARAMETERS_ERROR

client._build_url

Encoding vs decoding key

The portal issues both; double-encoding the encoded one fails

client._normalise_key

resultType=json is required

The XML branch is less consistent under the same parameters

client._call

Errors arrive as XML even when JSON was requested

Auth and quota failures return an XML envelope, so a naive json.loads throws something unhelpful

client._parse

Today is usually empty

totalCount: 0 is normal, not an error

client.resolve_trading_day

Rates arrive as ".71"

Not "0.71" — a strict parser chokes

returns.to_float

Why the key needs care

Because the key must live inside the URL (see above), it lands in any HTTP request log. httpx logs every request line at INFO, so a default setup writes your key in plaintext to wherever your agent's stderr goes. This server:

  • lowers the httpx and httpcore loggers to WARNING at import,

  • redacts the key from every exception message before re-raising (both encoded and decoded forms),

  • and uses raise ... from None so the chained traceback, which also carries the URL, is dropped.

If you use another data.go.kr client alongside this one, check its logs. This is easy to get wrong and invisible until you look.

Development

uv sync --extra dev
uv run pytest

Or with no dependencies at all:

PYTHONPATH=src python -m unittest discover -s tests

31 tests, no network and no key required. Fixtures are real product names and real closing prices captured from live responses, so they double as a regression net for the classification rules.

src/krx_etf_mcp/
├── client.py       # HTTP, paging, date resolution, key handling, caching
├── categories.py   # name → asset class / region / strategy
├── dates.py        # YYYYMMDD maths, including the exclusive-endBasDt shift
├── returns.py      # normalisation, filtering, period-return join
└── server.py       # MCP tool definitions

The three modules below server.py have no MCP dependency and can be imported directly if you want the data without an agent.

Contributions are welcome — especially classification rules for products this misfiles.

Limitations

  • ETF only. No ETN, ELW, or non-KRX listings.

  • Price return only. No distributions, so no total return.

  • Name-based classification. Not an official KRX taxonomy.

  • Daily closes only. No intraday, no order book, no flows.

  • No holdings data. The upstream service carries prices, not constituents.

  • Rate limits. 30 TPS upstream; daily call quotas depend on your data.go.kr account tier. Daily snapshots are cached in-process, so a session that ranks several categories over the same period costs one pair of fetches, not one per query.

  • History depth is whatever the portal retains; it does not extend to an ETF's full history.

Why ETF only

The same upstream service exposes ETN and ELW, and adding them would be perhaps fifty lines. They are excluded on purpose: their response schemas differ (ETN carries indicative value, ELW carries strike and expiry), the classification rules would not transfer, and a tool named for one job it does well is more useful than one named for three it does adequately. If you want them, open an issue — the case is worth hearing.

FAQ

Is the data real-time? No. Daily closes, published with roughly a one-day lag.

Does it cost anything? No. The data.go.kr development tier is free.

Can I use it without an AI assistant? Yes — import client.py, categories.py and returns.py directly. They are plain Python with no MCP dependency.

Why not use the KRX API directly? KRX's own open API exists but requires separate registration and returns a different shape. This server uses the public-portal relay because the key is easier to get and the data is the same, sourced from KRX.

A classification is wrong. Run explain_classification on the name, then open an issue with the name and the verdict you expected. The rules are plain tuples and easy to correct.

Which mcp SDK versions work? Both 1.x (FastMCP) and 2.x (MCPServer) — the import is version-detecting.

License

MIT — see LICENSE.

Available Tools

11 tools
compare_etfA

Compare price returns of specific ETFs over one shared period.

Args: codes: 6-digit short codes to compare. months: Lookback when start_date is omitted. start_date: YYYYMMDD override for the period start. end_date: YYYYMMDD override for the period end.

ParametersJSON Schema
NameRequiredDescriptionDefault
codesYes
monthsNo
end_dateNo
start_dateNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description bears the burden. It does disclose behavioral details: 'months: Lookback when start_date is omitted' and 'start_date/end_date override' clarify precedence and parameter semantics. However, it omits output format, error handling, and edge cases (e.g., invalid codes, mismatched periods), leaving some behavioral gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description leads with a one-sentence purpose, followed by a tight Args list. Every line earns its place; there is no redundancy or filler. The structure is scannable and appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

All four parameters are semantically explained, and an output schema exists, so return values don't need description. It lacks explicit usage alternatives and edge-case handling, but the provided information is sufficient for correct basic invocation. A perfect score would require more guidance on when to prefer alternatives like get_etf_history or rank_etf_return.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage, but the Args section fully compensates. It explains that codes are 6-digit, months is a lookback when start_date is omitted, and start/end dates are YYYYMMDD overrides with explicit precedence. This adds significant semantic meaning beyond the schema's bare types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'Compare price returns of specific ETFs over one shared period,' identifying both the action (compare) and the resource (price returns of ETFs). This differentiates it from siblings like get_etf_history (single ETF history) and rank_etf_return (ranking), making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied through phrases like 'over one shared period' and the argument descriptions (months as lookback, start/end overrides), but no explicit 'use when' guidance or exclusions are provided. The description doesn't contrast with sibling tools, so an agent must infer when this is the preferred choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

explain_classificationA

Show which keywords drove the classification of an ETF name.

Use this to audit a filter result that looks wrong.

Args: name: The ETF product name, e.g. "KODEX 삼성전자채권혼합".

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden for behavioral disclosure. 'Show' implies a read-only operation and the purpose is clear, but it does not state side effects, permission requirements, or behavior for invalid inputs. This is adequate for a simple diagnostic tool but lacks depth beyond the obvious read-only implication.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, front-loaded with the core behavior, followed by a usage hint and parameter documentation. Every sentence earns its place, and the Args section is clearly structured. There is no redundant text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter), the presence of an output schema, and the explicit usage context, the description is fairly complete. It covers the purpose, the scenario, and the parameter. It could add notes on error cases or limitations, but those are not essential for such a straightforward tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero description coverage, so the description must compensate. It does so effectively by explaining the parameter as 'The ETF product name' and providing a concrete example ('KODEX 삼성전자채권혼합'), which adds meaning beyond the schema's bare 'name' field. For a single parameter this fully resolves ambiguity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Show which keywords drove the classification of an ETF name.' This clearly distinguishes it from siblings like search_etf or list_filters, as it is the only tool that explains classification decisions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear context: 'Use this to audit a filter result that looks wrong.' This tells the agent when to invoke the tool, though it does not explicitly mention when not to use it or name alternative tools. That fits the 'clear context, no exclusions' level.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_similar_etfA

List every ETF tracking the same underlying index as the given one.

Answers "which of these should I hold?" -- 25 ETFs track 코스피 200 and 24 track S&P 500, and picking between them comes down to size, liquidity and NAV premium, which are all returned side by side here.

Args: code_or_name: The reference ETF: code, ISIN or name. sort_by: market_cap (default), volume, trade_value, close, change_pct, nav_premium_pct, name, or code. base_date: YYYYMMDD; resolved backwards to a day with data. limit: Max peers to return.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sort_byNomarket_cap
base_dateNo
code_or_nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations are provided, the description carries the full burden of behavioral disclosure. It reveals that the tool returns side-by-side metrics (size, liquidity, NAV premium) and that base_date is resolved backwards to a day with data. It does not explicitly state read-only behavior, but the list semantic implies it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: a concise opening statement, an illustrative example that adds context without bloat, and a clean parameter list. Every sentence contributes value and the format is easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to explain return formats. It covers purpose, use cases, and all parameter semantics, and even provides a concrete example. No critical gaps are apparent for a read-only list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description's Args section fully documents all four parameters: code_or_name, sort_by (with all allowed values), base_date (including backward resolution), and limit (max peers). This adds significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists every ETF tracking the same underlying index as the given one, using the specific verb 'List' and defining the resource scope. It distinguishes itself from siblings by focusing on peer comparison rather than quotes, history, or ranking.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear use case ('which of these should I hold?') and an illustrative example comparing ETFs tracking the same index. It implies when to use the tool but does not explicitly name alternatives or exclusions, so it stops short of full guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_etf_historyA

Daily closing-price history for one ETF.

Args: code: 6-digit short code. start_date: YYYYMMDD. Defaults to months before the end date. end_date: YYYYMMDD. Defaults to the latest day with data. months: Lookback used when start_date is omitted.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYes
monthsNo
end_dateNo
start_dateNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It explains important default behavior for start_date, end_date, and months (e.g., 'Defaults to the latest day with data'), which goes beyond the raw schema. It does not explicitly declare read-only status, but the tool's purpose makes that obvious, and the output schema covers return structure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a one-line purpose followed by a compact argument list. Every sentence adds value, and the main purpose is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the presence of an output schema, and thorough parameter documentation, the description is complete for an agent to use it effectively. No critical information appears missing, and an example is optional rather than necessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully compensates by defining each parameter meaningfully: code as a '6-digit short code,' date formats as YYYYMMDD, and the roles of start_date, end_date, and months with their default relationships. This adds substantial clarity beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool provides 'Daily closing-price history for one ETF,' which is a specific data product and scope. It naturally distinguishes from siblings like get_etf_quote (current quote) and compare_etf (comparison), even without naming them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus alternatives. The description does not mention sibling tools, prerequisites, or exclusions, leaving the agent to infer usage solely from the tool name and the description's first line.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_etf_quoteA

Full one-day detail for a single ETF, looked up by code, ISIN or name.

Returns every field the feed carries -- OHLC, volume, trade value, market cap, NAV, net assets, listed shares, underlying index and its close -- plus the NAV premium/discount, which the feed does not compute.

If a partial name matches several products, no quote is returned; instead candidates lists the matches so you can pick one.

Args: code_or_name: "069500", "KR7069500007", "KODEX 200", or "반도체". base_date: YYYYMMDD; resolved backwards to a day with data.

ParametersJSON Schema
NameRequiredDescriptionDefault
base_dateNo
code_or_nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that the tool returns every feed field, computes the NAV premium/discount, returns candidates for ambiguous matches, and resolves base_date backwards to a day with data. These are substantial behavioral details beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: a purpose sentence, a list of return fields, a disambiguation note, and an Args section. It is front-loaded with the main purpose, and each sentence earns its place without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists to define return structure, the description covers the key contextual behaviors: ambiguous-name handling, date resolution, and computed metrics. It is complete for a single-quote tool, leaving no major gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description compensates with an 'Args' section that provides concrete examples for code_or_name ('069500', 'KR7069500007', 'KODEX 200') and explains base_date's backward resolution. This adds essential meaning beyond the bare field titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Full one-day detail for a single ETF, looked up by code, ISIN or name.' This clearly states the tool's specific verb ('get'), resource ('ETF quote'), and scope (single ETF, one-day detail), distinguishing it from siblings like get_etf_history and search_etf.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (single-day snapshot, disambiguation via candidates) and gives concrete examples, but it does not explicitly name alternative tools or state when not to use it. This is clear context without explicit exclusions, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

latest_trading_dayA

Resolve the most recent date that actually has ETF data.

The portal publishes with a lag, so "today" is often empty. Call this before assuming any date is usable.

Args: on_or_before: YYYYMMDD to search back from. Defaults to today.

ParametersJSON Schema
NameRequiredDescriptionDefault
on_or_beforeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the portal lag and that 'today' is often empty, which explains the tool's behavior. However, it doesn't explicitly state side effects or error conditions, and doesn't confirm read-only status beyond inference.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three short, purposeful sentences plus an Args line. It's front-loaded with the main purpose, and every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter utility, the description is sufficiently complete: it explains what, why, and when to call it, plus the parameter. The output schema can handle return value documentation. It could briefly mention edge cases like no valid date found, but it's not a significant gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only a type and default for on_or_before, with no description, so coverage is 0%. The description compensates by specifying the format (YYYYMMDD) and the meaning ('search back from'), plus the default behavior. This fully explains the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Resolve' and clearly identifies the resource: the most recent date with ETF data. This distinguishes it from sibling tools that operate on ETFs, quotes, history, etc., making it clear this is a date-resolution utility.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs to 'Call this before assuming any date is usable,' providing clear timing guidance. It explains the portal lag context, which tells the agent when to use this tool, though it doesn't name alternative tools or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_filtersB

List the values accepted by the filter and sort arguments.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the full burden of behavioral disclosure. It only states that values are listed, but does not describe the return format, whether the list is static or dynamic, or any side effects (none presumably). Minimal transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that immediately conveys the tool's purpose with no redundant or filler content. It is front-loaded and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although the tool is simple and has an output schema, the description lacks explicit context about how this tool relates to sibling tools or when an agent should call it (e.g., before using other ETF tools to know valid filter/sort values). It is minimally adequate but not complete in guiding broader task workflow.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so per the rubric the baseline is 4. The schema has no properties, and the description does not need to explain parameters. It adds no parameter information, but none is required.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists accepted values for filter and sort arguments. The verb 'List' and resource 'filter and sort arguments' are specific, distinguishing it from sibling tools that operate on ETF data. However, it does not specify which context or endpoint these arguments refer to, leaving minor ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives, nor any mention of prerequisites or situations where it would be necessary. The description simply states what it does without context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_indicesA

List underlying indices and how many ETFs track each.

A map of the market: use it to find the exact index_name string that search_etf and find_similar_etf expect.

Args: query: Substring filter on the index name, e.g. "코스피". min_etf_count: Only indices tracked by at least this many ETFs. base_date: YYYYMMDD; resolved backwards to a day with data. limit: Max indices to return, most-tracked first.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryNo
base_dateNo
min_etf_countNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden. It adds some behavioral context like base_date resolving backwards to a trading day and ordering by most-tracked first. However, it does not explicitly state that the operation is read-only or mention any potential side effects, permissions, or error conditions. Still, the verb 'list' implies a safe read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: a one-sentence purpose, a usage note, and a compact bulleted list of parameters. Every sentence is informative and there is no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, usage guidance, and all parameters thoroughly. There is an output schema, so return structure is already specified. It could be more complete by mentioning behavior when no indices match or edge cases, but for a list tool with well-documented inputs, this is largely sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description fully compensates by explaining each parameter's meaning: query as substring filter with an example, min_etf_count as a threshold, base_date's format and backward resolution, and limit's ordering. This adds significant value beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action ('List underlying indices and how many ETFs track each') and its role in the broader system as a 'map of the market' to find exact index_name strings. This specific verb+resource+scope distinguishes it from sibling tools like search_etf and find_similar_etf.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs when to use this tool: 'use it to find the exact index_name string that search_etf and find_similar_etf expect.' This provides a clear use case and directs the agent to related tools, fulfilling the 'explicit when' criterion without ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rank_etf_returnA

Rank ETFs by price return over a period, within an optional filter set.

Both endpoints are resolved to days that actually have data, then joined by ticker. ETFs missing a price at either end are reported separately in excluded rather than dropped silently.

Args: months: Lookback when start_date is omitted. top: How many rows to return. query: Name substring filter, e.g. "채권혼합". asset_class: Classification filter, e.g. 채권혼합. region: Classification filter, e.g. 미국. strategy: Classification filter, e.g. 커버드콜. issuer: Brand prefix filter, e.g. KODEX, TIGER, RISE. exclude: Drop names containing this substring. min_market_cap: Minimum market cap in KRW, to skip illiquid tickers. min_volume: Minimum share volume on the end date. start_date: YYYYMMDD override for the period start. end_date: YYYYMMDD override for the period end. worst: Rank ascending (biggest losers first) instead of descending.

ParametersJSON Schema
NameRequiredDescriptionDefault
topNo
queryNo
worstNo
issuerNo
monthsNo
regionNo
excludeNo
end_dateNo
strategyNo
min_volumeNo
start_dateNo
asset_classNo
min_market_capNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of disclosing behavior. It explains how endpoints are resolved to trading days, how missing prices are reported in `excluded` rather than dropped, and the effect of the `worst` flag. This goes beyond basic expectations and provides significant behavioral insight, though it does not mention aspects like pagination or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured, starting with a concise purpose statement and then a clean Args list. Each parameter line is compact and informative, with examples where helpful. There is no redundant or irrelevant content; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of 13 optional parameters and the existence of an output schema, the description provides all necessary context: the tool's purpose, filter options, behavioral nuances (missing data handling, worst flag), and parameter semantics. Since the output schema exists, it does not need to detail the return structure, making this description effectively complete for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description compensates by listing all 13 parameters with short, meaningful explanations and examples (e.g., 'query: Name substring filter, e.g. "채권혼합"'). This fully adds semantic value beyond the raw schema properties, which contain no descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Rank ETFs by price return over a period', which clearly states the specific action and resource. This distinguishes it from siblings like compare_etf (which compares specific ETFs) and get_etf_history (which provides historical data). The optional filter set further clarifies the scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states the tool's use case: ranking ETFs by return with optional filters. It does not explicitly mention when not to use it or name alternatives, but the purpose is unambiguous enough for an agent to select it when a ranked list is needed. The context is clear, though exclusions are not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_etfA

Find ETFs by name fragment, issuer, index and/or classification.

The main lookup tool. Filters combine with AND. Classification is derived from the product name (see list_filters) because the upstream feed has no category field.

Args: query: Substring of the ETF name, or an exact 6-digit ticker. asset_class: e.g. 채권혼합, 채권, 주식, 원자재, 부동산, 통화, 멀티에셋. region: e.g. 국내, 미국, 중국, 일본, 인도, 유럽, 신흥국, 글로벌. strategy: e.g. 커버드콜, 레버리지, 인버스, 액티브, 배당, 환헤지, TR. issuer: Brand prefix, e.g. KODEX, TIGER, RISE, ACE, PLUS, SOL. Former brand names (KBSTAR, ARIRANG, KINDEX, KOSEF) resolve too. index_name: Exact underlying index, e.g. "코스피 200". Use list_indices to see what exists. exclude: Drop results whose name contains this substring. min_market_cap: Minimum market cap in KRW. min_volume: Minimum share volume on the base date. sort_by: market_cap (default), volume, trade_value, close, change_pct, nav_premium_pct, name, or code. ascending: Sort ascending instead of descending. base_date: YYYYMMDD; resolved backwards to a day with data. limit: Max rows to return.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryNo
issuerNo
regionNo
excludeNo
sort_byNomarket_cap
strategyNo
ascendingNo
base_dateNo
index_nameNo
min_volumeNo
asset_classNo
min_market_capNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden and does so well: it notes classification is derived from the product name because the upstream feed lacks a category field, and that base_date resolves backwards to a day with data. It also explains exclude behavior and former brand-name resolution, adding context beyond simple parameter lists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a one-sentence purpose, followed by a clear 'Args' block that groups parameter semantics. Despite length, it remains scannable and every line adds necessary detail for a 13-parameter tool; there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (0 required params, 13 optional, no annotations) and the presence of an output schema, the description covers all necessary behavioral and parameter-level nuances. It even notes tricky behaviors like base_date backward resolution and former issuer brand names, making it complete for an agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description compensates fully by explaining every parameter with examples and nuanced details. For instance, issuer supports former brand names, index_name should be an exact underlying index with a pointer to list_indices, and sort_by enumerates all valid values. This gives the agent far more than the raw schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Find ETFs by name fragment, issuer, index and/or classification,' which clearly states the verb (find) and resource (ETFs). It also calls itself 'The main lookup tool,' distinguishing it from sibling tools like get_etf_quote or find_similar_etf.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description identifies this as the main lookup tool and explains how filters combine with AND, giving a clear usage context. It references list_filters and list_indices for valid values, but does not explicitly contrast with alternative search-related siblings like find_similar_etf.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

server_infoA

Version, data source, and known limitations of this server.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that the tool returns known limitations, indicating transparency about server constraints. However, it does not mention whether it is read-only or if there are any other behavioral caveats, though for an info endpoint this is largely self-evident.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that directly lists the key information categories. It is front-loaded, containing no filler or redundant phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter informational tool with an existing output schema, the description is complete. It names the three key content areas (version, data source, known limitations), and the output schema can provide further structural details. There is no additional context needed for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the empty schema fully covers the input requirements. The baseline for 0 params is 4, and the description adds no parameter-specific detail, which is appropriate given there is nothing to explain.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly specifies the tool's purpose: providing version, data source, and known limitations of this server. It is distinct from all sibling tools, which focus on ETF data retrieval, making it immediately recognizable as a server metadata endpoint.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus alternatives, but the use case is implied: when you need server version, data source, or known limitations. Since no sibling tool serves this purpose, the lack of explicit exclusion is not a major gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.1/5.0
Disambiguation5/5

Each tool targets a distinct aspect of ETF data discovery and analysis: search, quote, history, ranking, comparison, and classification audit are clearly separated. No two tools would cause an agent to pick the wrong one for a standard task.

Naming Consistency4/5

Most tools follow a verb_noun pattern with snake_case (search_etf, list_filters, get_etf_quote), but latest_trading_day and server_info deviate from the verb-first convention. This is a minor inconsistency in an otherwise predictable naming scheme.

Tool Count5/5

11 tools is well-scoped for a specialized ETF market data server, covering search, quotes, histories, rankings, and comparisons without bloat. Each tool earns its place.

Completeness4/5

The tool surface covers core read-only workflows for ETF analysis: finding, quoting, history, ranking, comparing, and interpreting classifications. The only minor gap is the lack of a way to enumerate all ETFs without any filter (search_etf requires a query), but this is workable via list_indices and broad filters.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    MCP server that provides Korean stock market data including indices, top gainers, stock quotes, news, fundamentals, and buy recommendations. Enables LLMs to access real-time and historical Korean stock information.
    6
  • A
    license
    Not graded
    quality
    B
    maintenance
    An MCP server that lets you talk to your AI trading assistant in plain English to research stocks, generate trade recommendations, manage a portfolio, and execute trades through natural language.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dongkyucho17/krx-etf-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server