CNEquity — China A-Share Data Lake for AI Agents
CNEquity MCP server gives read-only, coverage-aware access to a local China A-share data lake for symbol resolution, price/fundamental/dataset queries, and SQL analytics.
Describe lake datasets, coverage windows, freshness, history mode, query contract, and live-vs-lake status.
Resolve company names or partial codes to canonical symbols, including delisted names and ambiguity flags.
Query daily/intraday bars with qfq/hfq/total-return adjustment, optional universe filtering, paging, and provenance.
Query point-in-time financial statement items using an as-of date, item filters, strict/best-effort PIT, and vintage options.
Read other datasets by date/symbol, such as fund flow, margin trading, dragon-tiger lists, block trades, northbound holdings, unlocks, corporate actions, valuation metrics, and index constituents.
Run read-only DuckDB SELECTs across dataset views for ranking, aggregation, percentiles, and joins, including adjusted-price views/functions.
Use paging/limits and optionally include per-row source/version/fetch time; no writes, DDL, or multiple statements.
CNEquity 是开源的中国 A股本地数据湖:整理沪深股票行情、股票数据、财务与期货数据,面向量化研究、量化交易与回测。86 个数据集落到本地 Parquet,可增量续跑,也能通过 MCP 让 AI 直接查 A 股。

cne serve 控制台真实录屏。
为什么用 CNEquity
和常用取数工具的区别(完整说明见对比页):
AKShare | Tushare Pro | Baostock | CNEquity | |
账号与 Token | 不需要 | 注册 + Token,按积分开放 | 不需要,匿名登录 | 基础采集不需要 |
数据落盘与增量 | 调用方自己做 | 调用方自己做 | 调用方自己做 | 本地 Parquet,内置增量与续跑 |
退市股与 PIT 财报 | 取决于接口 | 取决于接口 | 部分提供 | 保留退市股,财报按公告日严格 PIT |
行级溯源 | 无 | 无 | 无 | 每行带来源、版本和抓取时间 |
给 AI 用 | 自己封装 | 自己封装 | 自己封装 |
|
Related MCP server: ashareapi
快速开始
需要 Python 3.10+(macOS / Linux / Windows),不需要账号或 token。
① 一分钟试用。 用真实数据源抓 5 只股票最近 30 个交易日,建在独立目录里,不影响以后的正式湖:
pip install cnequity
cne init --profile demo # 约 1 分钟;结束时打印行情表、查询示例和接给 AI 的命令
cne serve --config configs/cnequity.demo.toml # 在浏览器里打开上面的控制台② 让 AI 直接查 A 股。 把湖以只读方式接给 Claude、ChatGPT、Codex、Gemini CLI、Cursor、VS Code 等支持 MCP 的客户端(--config 用绝对路径)。以 Claude Code 为例:
claude mcp add cnequity -- cne mcp --config /abs/path/to/configs/cnequity.demo.toml各家客户端的写法见 MCP 接入指南;ChatGPT 只接公网网址,用 cne mcp --http --token 加隧道接入。然后直接问:「宁德时代最近 30 个交易日的最高收盘价是哪天?」
真实 MCP 工具调用与返回;收盘价为未复权价。
③ 建正式湖。 沪深京全市场、最近 3 年:
cne init # 开始建正式湖,支持中断续传
cne check # 检查数据是否完整、可用from cnequity.query import load
bars = load("daily_bars", symbols=["600519.SH"])
print(bars.tail())之后每天运行一次 cne run daily 保持更新。想要更长的历史,或了解 init 具体做了什么,见初始化指南。
能用它研究什么
你的问题 | 数据与入口 |
跨分红、送转后的历史收益 |
|
某个调仓日已经知道哪些财报信息 |
|
历史股票池、退市前行情 |
|
估值、资金流、行业轮动 |
|
期货期限结构、期权链与 Greeks | 逐合约行情和派生数据 · 衍生品指南 |
数据范围
支持 86 个数据集(78 个 curated、8 个 derived),按用途分为 L0–L9。字段、主键、历史起点和来源见数据集目录与数据源说明。
层次 | 研究用途 | 代表数据集 |
L0 | 基础参考 | 证券主数据、交易日历、交易状态 |
L1 | 行情 | 日线、指数、复权因子、可选分钟线与分笔、退市事件 |
L2 | 公司事件 | 公司行为、公告索引、业绩披露预约 |
L3 | 基本面 | 财报、估值、股本、股东、一致预期 |
L4 | 资金面 | 北向、融资融券、龙虎榜、大宗交易、资金流 |
L5 | 结构行业 | 指数成分、行业与板块成分、行业指数 |
L6 | 宏观 | 宏观指标、市场宽度 |
L7 | 舆情与轮动 | 新闻、快讯、情绪、人气、板块行情与资金流 |
L8 | 风险合规 | 解禁日程、监管事件 |
L9 | 衍生品 | 期货与期权合约、逐合约行情、连续合约、Greeks、分钟线 |
分钟线、分笔、期货/期权,以及资金流、新闻、人气榜等拓展数据集默认关闭,需要时用户自行打开。
架构

幸存者偏差
今天的名单不能代替历史股票池。
日常更新与升级
cne schedule install # 为当前用户安装每日定时任务(macOS / Linux / Windows)
cne run daily # 或者自己每天运行一次
cne check # 验收;有缺口或质量 error 时返回非零升级:pip install -U cnequity,然后 cne config upgrade 和 cne migrate(先预览,确认后加 --apply)。调度、操作页和失败后续见日常运维,范围与续跑见初始化指南。
适合与边界
适合持续积累历史、反复查询和自托管。
项目处于 0.x,不含回测引擎或下单。代码采用 Apache-2.0,数据另受上游许可约束,仓库不附带数据湖。
文档与参与
想做什么 | 从这里开始 |
安装、跑通首个查询 | |
常见问题 | 免费获取 A股历史数据 · 回测避免未来函数 · 用 AI 查 A股 · 与 AKShare、Tushare、Baostock 对比 |
找数据、确认口径 | |
查命令、参数和副作用 | |
配调度、处理失败 | |
理解产品方向与反馈问题 |
欢迎提交带最小复现的 Issue、文档修正或数据适配 PR。研究引用见 CITATION.cff;安全问题请按安全策略私下报告。
觉得有用?点一个 Star,或把项目分享给同样在维护 A 股数据的人。
Available Tools
6 toolsdescribe_lakeARead-only
START HERE. Returns what this lake actually holds — every dataset with its coverage window, history mode and freshness — plus the query contract that makes an answer correct (adjustment, point-in-time, which series have no real history). Cheap, reads no data. Call it before answering anything factual about A-share data, and use its coverage_start/coverage_end to tell 'this lake has no such data' apart from 'this did not happen'. It also reports live_mode — when that is on, some answers come from the vendor rather than the lake and say so. Then pick a tool: resolve_symbol for names, query_bars for prices, query_fundamentals for financials, query_dataset for everything else, run_sql for aggregation.
| Name | Required | Description | Default |
|---|---|---|---|
| include_empty | No | Also list registered datasets with no data yet. Use it to tell an empty dataset from an unknown name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true; the description adds substantial behavior beyond that: it is cheap and reads no data, it discloses live_mode where answers come from the vendor rather than the lake and are labeled as such, and it explains that coverage bounds are the mechanism for absence-vs-nonexistence. That is real operational context an agent cannot get from the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with 'START HERE' and the core return contract before any routing detail. Despite being several sentences, each one carries load: return contents, coverage semantics, live_mode caveat, then the sibling routing table.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-value burden and does so — it enumerates datasets, coverage window, history mode, freshness, and the query contract, plus live_mode. For a zero-required-param orientation tool, nothing an agent needs before calling is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single include_empty parameter, and its own schema description already explains the empty-vs-unknown distinction. The description adds nothing further about the parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (returns/describes) and resource (what this lake holds: datasets, coverage windows, history modes, freshness) plus the query contract. It is unmistakable against siblings like query_bars or run_sql, which retrieve data rather than describe the lake.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'START HERE' and 'Call it before answering anything factual about A-share data', with a concrete decision rule (use coverage_start/coverage_end to separate 'no such data' from 'did not happen'). It then names each alternative tool and the condition that selects it (resolve_symbol for names, query_bars for prices, query_fundamentals for financials, query_dataset for everything else, run_sql for aggregation).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_barsARead-only
Daily or intraday price bars. PRICES ARE STORED UNADJUSTED: pass adjust='hfq' for any comparison across time (returns, charts, drawdowns) or a split reads as a crash. Use adjust='qfq' when the levels must match what a quote screen shows today. Pass universe='all_a' for cross-sectional work to drop names that were not tradable that day. datasets: daily_bars, index_bars, minute_bars (1m), minute_bars_5m (5m), and minute_bars_15m / _30m / _60m when the user has derived them (each bar's resampled_from says whether 1m or 5m built it). Every response carries origin: 'lake' is stored and validated; 'live' was fetched just now and cannot be adjusted or universe-filtered — read its warning before using the numbers for anything but a current quote. Not for financial statements (query_fundamentals), other datasets such as fund flow (query_dataset), or ranking and aggregating across many symbols (run_sql).
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | Inclusive end date, YYYY-MM-DD. | |
| limit | No | Max rows to return (default 200, cap 2000). Responses always report the true total and set `truncated`. | |
| start | No | Inclusive start date, YYYY-MM-DD. | |
| adjust | No | hfq = back-adjusted, the correct choice for return series. qfq = forward-adjusted to today's price level. total_return (daily_bars only) = hfq with fund cash distributions reinvested; stocks read as hfq, whose factor already reinvests dividends. Omit only when you specifically want raw traded prices for a single day. | |
| offset | No | Rows to skip, for paging with `limit`. | |
| dataset | No | Default daily_bars. | |
| symbols | No | Symbols as '<code>.<EX>', e.g. ['600519.SH', '000001.SZ']. Omit for every symbol in range. Use resolve_symbol to turn a company name into a code. | |
| universe | No | Drop rows for names unlisted/delisted that day, and ST/suspended ones where trading_status covers it. `all_a` includes SH/SZ/BJ; `all_a_sh_sz` is an explicit SH/SZ-only research subset that excludes BJ. The lake path also requires versioned historical ST evidence; incomplete research fails instead of treating unknown names as normal. daily_bars only. | |
| include_provenance | No | Include per-row source/data_version/fetched_at. Off by default — the response lists the distinct sources instead, at a fraction of the size. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true, so the description carries the real behavioral burden and does: prices are stored UNADJUSTED with a concrete failure mode (a split reads as a crash), the `origin` field distinguishes validated lake data from freshly fetched live data that cannot be adjusted or universe-filtered, and incomplete research fails rather than silently defaulting. This is richer behavioral context than the read-only hint alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the unadjusted-price hazard is stated in the first sentence, before the softer dataset and origin details. Nearly every clause carries information, though the dataset enumeration and resampling parenthetical are slightly overstuffed for a single block of prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema in play, the description compensates by explaining what the response carries (`origin`, its warning, the true total and `truncated` flag) and what the source variants mean. For a 9-parameter analytical tool this is an unusually complete brief.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, and the description adds genuine use-case framing on top ('hfq for return series', 'qfq when levels must match a quote screen', 'all_a for cross-sectional work to drop names that were not tradable that day'). It also surfaces the resampled_from and truncation semantics. It stops short of documenting every parameter, but the marginal value is real.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific resource and scope ('Daily or intraday price bars') and explicitly distinguishes itself from siblings by naming query_fundamentals, query_dataset, and run_sql as the wrong tools for adjacent tasks. An agent can route to this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use rules for the tricky parameters ('adjust=\'hfq\' for any comparison across time', 'adjust=\'qfq\' when levels must match a quote screen', 'universe=\'all_a\' for cross-sectional work') plus a clear exclusion list pointing at three alternative tools. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_datasetARead-only
Read any other dataset by date window and symbol — fund_flow, margin_trading, dragon_tiger, block_trades, northbound_holdings, share_unlock_schedule, corporate_actions, valuation_metrics, index_constituents and the rest. Call describe_lake for the full list and each one's coverage. Bars go through query_bars and financial statements through query_fundamentals. Results are paged with limit/offset and the response reports the true total and a truncated flag; for cross-sectional ranking use run_sql instead of paging.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | Inclusive end date, YYYY-MM-DD. | |
| limit | No | Max rows to return (default 200, cap 2000). Responses always report the true total and set `truncated`. | |
| start | No | Inclusive start date, YYYY-MM-DD. | |
| offset | No | Rows to skip, for paging with `limit`. | |
| dataset | Yes | Dataset name from describe_lake. | |
| symbols | No | Symbols as '<code>.<EX>', e.g. ['600519.SH', '000001.SZ']. Omit for every symbol in range. Use resolve_symbol to turn a company name into a code. | |
| include_provenance | No | Include per-row source/data_version/fetched_at. Off by default — the response lists the distinct sources instead, at a fraction of the size. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description nonetheless adds real behavioral context beyond that: results are paged, the response reports the true total and a truncated flag, and the paging pattern is unsuitable for cross-sectional ranking. It stops short of discussing auth, rate limits, or result freshness, which is why this is a 4 rather than a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb and scope, then routing, then pagination behavior — a logical order where most sentences earn their place. The long dataset enumeration is informative but slightly heavy; a pointer to describe_lake alone might have sufficed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter read tool with no output schema, the description covers the essentials an agent needs: what datasets exist, where to find the canonical list, how results are paged, that the response reports a true total and truncated flag, and when to prefer run_sql. Nothing critical to correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including date formats, the limit default/cap, offset paging, symbol format, and the provenance default — so the schema carries the parameter burden. The description's mentions of 'date window', 'symbol', and 'paged with limit/offset' restate schema content rather than adding syntax or semantics. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Read any other dataset by date window and symbol') and enumerates concrete datasets (fund_flow, margin_trading, dragon_tiger, etc.). It explicitly carves out the sibling tools that handle other data classes (bars → query_bars, financials → query_fundamentals), so an agent can distinguish it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing rules in both directions: use describe_lake for the dataset list and coverage, use query_bars/query_fundamentals for bars and statements, and use run_sql instead of paging when doing cross-sectional ranking. These are concrete when/when-not/alternative statements rather than implied guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_fundamentalsARead-only
Financial statement items, point-in-time. as_of is REQUIRED and is what prevents look-ahead: only figures publicly announced on or before that date come back, and a restated figure returns the vintage that was current then. For a present-day view pass today's date; for a historical study pass the date being studied, never today. Results are paged with limit/offset. For prices use query_bars; for valuation ratios read valuation_metrics through query_dataset. Set pit_mode='strict' only to audit what the lake itself held on that date.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | Yes | YYYY-MM-DD knowledge cutoff, applied to announce_date. | |
| items | No | item_code filter, e.g. ['roe', 'net_profit']. | |
| limit | No | Max rows to return (default 200, cap 2000). Responses always report the true total and set `truncated`. | |
| offset | No | Rows to skip, for paging with `limit`. | |
| symbols | No | Symbols as '<code>.<EX>', e.g. ['600519.SH', '000001.SZ']. Omit for every symbol in range. Use resolve_symbol to turn a company name into a code. | |
| pit_mode | No | best_effort (default) also returns rows a later backfill recorded, flagged pit_is_exact=false; strict keeps only rows the lake held by as_of, which is none for a backfilled history. | |
| all_vintages | No | Return every vintage announced by as_of instead of only the one current then. For studying restatements; it double-counts a fact in any cross-sectional screen. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true; the description adds the non-obvious semantics: look-ahead prevention, restated figures returning the then-current vintage, and the warning that all_vintages double-counts a fact in cross-sectional screens. That is exactly the behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the resource and the required parameter, then trades one sentence each for date choice, siblings, paging, and pit_mode. High information density with no filler or restatement of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still covers paging/truncation behavior and result semantics, and every parameter is documented either in the schema or here. An agent has everything needed to call it correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real interpretation: why `as_of` is required and which value to choose, and the audit-only intent behind pit_mode='strict'. The rest (items, limit, offset, symbols) is left to the already-complete schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (financial statement items) plus the defining scope: point-in-time with a required `as_of` knowledge cutoff. It explicitly separates itself from query_bars (prices) and query_dataset (valuation ratios), so an agent can pick it without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use rules for the key decision — pass today's date for a present-day view, the studied date for a historical study, 'never today'. It names the two sibling alternatives by function and restricts pit_mode='strict' to lake-audit use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_symbolARead-only
Look up a symbol by company name or partial code — '茅台', 'maotai', '600519' all resolve to 600519.SH. Do this before any query when the user named a company rather than a code: a guessed suffix returns an empty result rather than an error. Delisted names are included and flagged with delist_date. Returns the canonical symbol, name and delist_date; several rows mean the fragment is ambiguous, so pick by name before querying.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max rows to return (default 200, cap 2000). Responses always report the true total and set `truncated`. | |
| query | Yes | Company-name fragment, or a code prefix with or without the exchange suffix (.SH/.SZ/.BJ). The match returns the canonical suffixed symbol to use in later calls. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true; the description goes well beyond by disclosing that delisted names are included and flagged with delist_date, that a wrong suffix silently yields an empty result instead of an error, and that multiple rows signal an ambiguous fragment. These are non-obvious behaviors that materially change how an agent should interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero padding: example, precondition/consequence, then return shape and ambiguity handling. The most actionable constraint (resolve before querying) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still covers what comes back (canonical symbol, name, delist_date) and how to interpret multi-row results. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds accepted-form examples and clarifies that the match returns the canonical suffixed symbol for later calls. The `limit` parameter is left to the schema, which documents it thoroughly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Look up a symbol') and immediately grounds it with concrete examples ('茅台', 'maotai', '600519' → 600519.SH). An agent can distinguish this resolver from sibling query tools (query_bars, run_sql) without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use it ('Do this before any query when the user named a company rather than a code') and why ('a guessed suffix returns an empty result rather than an error'). It also handles the ambiguous-fragment case, instructing the agent to pick by name before querying.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_sqlARead-only
One read-only DuckDB SELECT over every dataset, each exposed as a view under its own name. Use this for ranking, aggregation, percentiles and joins across datasets — computing them here is both correct and far cheaper than paging thousands of rows back and adding them up. daily_bars_adj is a ready-made view carrying hfq_open/high/low/close and open-lake qfq_* beside the raw columns; for a bounded historical qfq window use daily_bars_qfq(start_date, end_date) so the anchor matches that window. Prefer these over joining adj_factors yourself. Single SELECT only: no writes, DDL or multiple statements. For one symbol's bars use query_bars, and for plain dataset reads query_dataset.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | A single DuckDB SELECT. Table names are dataset names (see describe_lake). | |
| limit | No | Max rows to return (default 200, cap 2000). Responses always report the true total and set `truncated`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint=true, it discloses a hard constraint not visible in annotations: single SELECT only, no writes, DDL, or multiple statements. It also explains the pre-built view semantics (daily_bars_adj columns, daily_bars_qfq window anchoring) and warns to prefer them over manual adj_factors joins.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and constraint, and the alternative-tool routing lands at the end. It is dense with backticked identifiers and multi-clause sentences, but nearly every clause carries actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-query tool with no output schema and fully described parameters, the description covers scope, constraints, view semantics, and sibling routing. Nothing critical for a correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented, including the limit default/cap and truncated flag. The description adds view/table-name context implicitly but no syntax or format detail for the sql or limit arguments themselves, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: a read-only DuckDB SELECT executed over every dataset, each exposed as a view under its own name. It also names the sibling tools it is not (query_bars, query_dataset), so an agent can route without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('ranking, aggregation, percentiles and joins across datasets') with a rationale (cheaper than paging rows), plus explicit alternatives for the two adjacent cases: query_bars for one symbol's bars and query_dataset for plain reads.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.17.2- Changed
describe_lake1 field changed- changed
Input schema / properties / include_empty / descriptionPrevious value: -"Also list registered datasets with no data yet."New value: +"Also list registered datasets with no data yet. Use it to tell an empty dataset from an unknown name."
- Changed
resolve_symbol1 field changed- changed
Input schema / properties / query / descriptionPrevious value: -"Name fragment or code."New value: +"Company-name fragment, or a code prefix with or without the exchange suffix (.SH/.SZ/.BJ). The match returns the canonical suffixed symbol to use in later calls."
- Changed
run_sql1 field changed- changed
Input schema / properties / sql / descriptionPrevious value: -"A single SELECT statement."New value: +"A single DuckDB SELECT. Table names are dataset names (see describe_lake)."
6 tool updates
v0.17.1- First observed
describe_lake - First observed
query_bars - First observed
query_dataset - First observed
query_fundamentals - First observed
resolve_symbol - First observed
run_sql
TDQS
Scored across 6 tools
Each tool owns a distinct job: describe_lake for metadata/contract, resolve_symbol for identifier lookup, query_bars for prices, query_fundamentals for statements, query_dataset for all other datasets, and run_sql for aggregation. The descriptions actively cross-route ('Bars go through query_bars... for cross-sectional ranking use run_sql'), neutralizing the one potential overlap between query_dataset and run_sql.
All names follow a consistent snake_case verb_noun pattern (describe_lake, resolve_symbol, query_bars, query_fundamentals, query_dataset, run_sql). Verbs vary appropriately by action rather than arbitrarily, so the convention is predictable and readable.
Six tools is well-scoped for a data lake spanning dozens of datasets: rather than one tool per dataset, the design consolidates with query_dataset and run_sql, so every tool earns its place. Neither bloated nor thin.
The read lifecycle is essentially complete — discover contents, resolve identifiers, query prices, financials, and arbitrary datasets, then aggregate in SQL with adjustment views provided. Minor gap: no explicit per-dataset column/schema discovery tool, though DuckDB views via run_sql largely fill it.
Maintenance
Related MCP Connectors
China A-share market data for research, backtesting and AI agents via MCP.
China A-share data for AI agents: 57 read-only tools plus 6 tools for your own watchlist.
Aligned market data for AI agents: crypto, stocks, FX and macro on one clock. Local or hosted.
China A-share market data over MCP: 22 tools for quotes, K-line, financials, money flow, top-trader boards, sectors, macro, convertible bonds and factor screening. Five tools need no API key, so you can connect and try it immediately.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query Chinese A-share market data — real-time quotes, K-lines, order books, financials, fund flows, dragon-tiger lists, sectors, convertible bonds, macro data, and factor screening — through 24 tools, five of which require no API key. It can be used via a hosted endpoint with no installation or self-hosted locally over stdio.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to pull live China A-share market data through 24 tools spanning real-time quotes, K-lines, five-level order books, financials, money flow, dragon-tiger lists, sector and valuation data, convertible bonds, ETFs, IPOs, macro indicators, and factor-based stock screening. Five of the tools work with no API key, while the rest require a paid key.340 npm1MIT
- FlicenseNot gradedqualityAmaintenanceEnables AI agents and regular backends to fetch and analyze financial market data across A-shares, US equities, ETFs, indices, and crypto, including quotes, K-lines, technical indicators, fundamentals, money flow, filings, and news search. Exposes these capabilities both as MCP tools for clients like Claude Desktop and Cursor and as an HTTP API with CSV/JSON export suited to code-executing agent workflows.-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents and regular backends or scripts to access standardized financial market data and analysis across A-shares, US equities, ETFs, indices, and crypto, including technical indicators, fundamentals, money flow, news, filings, and CSV/JSON exports.-