Skip to main content
Glama
Xxx00xxX33

FinanceMCP

by Xxx00xxX33

csi_index_constituents

Retrieve CSI index constituents with weights and financial metrics like PE, PB, dividend yield, and profitability ratios for specified date ranges.

Instructions

获取中证指数公司(CSI)指数(含行业/主题)的区间行情、成分权重与估值/财务摘要(PE TTM、PB、股息率、ROE、ROA、净利率、每股经营现金流、资产负债率、营收同比、资产周转率、毛利率、三费比率、现金分红率)。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
index_codeYes指数代码(仅限CSI,含行业/主题)。请使用 .SH/.SZ 形式且能在 Tushare index_weight 查询到权重的代码,例如中证证券公司 '399975.SZ';也支持宽基 '000300.SH'、'000905.SH',以及 'sh000300'、'sz399006' 形式
start_dateYes开始日期,YYYYMMDD 或 YYYY-MM-DD
end_dateYes结束日期,YYYYMMDD 或 YYYY-MM-DD

Implementation Reference

  • The primary handler function that executes the tool: normalizes index code and dates, fetches index and constituent stock data from Tushare API, computes summaries, retrieves valuations and financial metrics, and formats a comprehensive Markdown table report.
    async run(args: { index_code: string; start_date: string; end_date: string; }) {
      try {
        const normIndex = normalizeIndexCode(args.index_code);
        const start = parseDateString(args.start_date);
        const end = parseDateString(args.end_date);
    
        if (!TUSHARE_CONFIG.API_TOKEN) {
          throw new Error('请配置TUSHARE_TOKEN环境变量');
        }
    
        // 指数行情
        const indexDaily = await getIndexDaily(normIndex, start, end);
        const indexSummary = summarizePrices(indexDaily);
        const indexRet = calcReturn(indexSummary.open_at_start, indexSummary.close_at_end);
    
        // 成分权重(以end为基准回退查找)
        const weights = await getIndexWeights(normIndex, end);
        if (weights.length === 0) {
          return {
            content: [
              { type: 'text', text: `# ${normIndex} 指数区间与成分股摘要\n\n❌ 未能获取到指数成分权重(仅支持中证指数公司CSI),请检查指数代码或日期范围。` }
            ]
          };
        }
    
        // 使用全部成分股(按权重降序)
        const allConstituents = weights;
    
        // 并发拉取全部成分股行情
        const stockRows = await Promise.all(allConstituents.map(c => getStockDaily(normalizeIndexCode(c.ts_code), start, end).catch(() => [])));
        const stockSummaries = stockRows.map(rows => summarizePrices(rows));
    
        // 估值:以结束日向前回退查找最近可用 daily_basic(最多回退10日)
        const { date: basicDate, map: basicMap } = await getNearestDailyBasicMap(end, 10);
    
        // 财务指标:为每只股票获取最近披露的 ROE/ROA/净利率/资产周转率/毛利率/三费比率/EPS(按公告日或报告期倒序取最近)
        const finaSnapshots = await Promise.all(
          allConstituents.map(c => getFinaIndicatorLatest(normalizeIndexCode(c.ts_code), end).catch(() => null))
        );
    
        // 现金分红率:获取最近每股分红,结合 EPS 估算 分红率 = 每股分红 / 每股收益 * 100%
        const latestDpsList = await Promise.all(
          allConstituents.map(c => getLatestCashDividendPerShare(normalizeIndexCode(c.ts_code), end).catch(() => null))
        );
    
        // 组装输出
        const pct = (v: number | null) => v == null ? 'N/A' : (v * 100).toFixed(2) + '%';
        const num = (v: number | null) => v == null ? 'N/A' : String(Number(v.toFixed(4)));
    
        let out = `# ${normIndex} 指数区间与成分股摘要\n\n` +
          `仅支持中证指数公司(CSI)指数。查询区间: ${start} - ${end}\n\n` +
          `## 指数价格摘要\n` +
          `- 起始开盘: ${num(indexSummary.open_at_start)}\n` +
          `- 区间最低: ${num(indexSummary.low_min)} (${indexSummary.low_min_date || 'N/A'})\n` +
          `- 区间最高: ${num(indexSummary.high_max)} (${indexSummary.high_max_date || 'N/A'})\n` +
          `- 结束收盘: ${num(indexSummary.close_at_end)}\n` +
          `- 区间涨跌幅: ${pct(indexRet)}\n\n` +
          `## 成分股列表(按权重降序)\n`;
    
        out += `| 代码 | 权重(%) | 起始开盘 | 区间最低 | 区间最高 | 结束收盘 | 区间涨跌幅 | PE(TTM) | PB | 股息率(%) | ROE(%) | ROA(%) | 净利率(%) | 每股经营现金流 | 资产负债率(%) | 营收同比(%) | 资产周转率 | 毛利率(%) | 三费比率(%) | 现金分红率(%) |\n`;
        out += `|-----|---------|-----------|-----------|-----------|-----------|-----------|---------|----|-----------|--------|--------|-----------|--------------|--------------|-----------|------------|-----------|------------|--------------|\n`;
        allConstituents.forEach((c, i) => {
          const s = stockSummaries[i];
          const r = calcReturn(s.open_at_start, s.close_at_end);
          const code = normalizeIndexCode(c.ts_code);
          const val = basicMap[code] || basicMap[c.ts_code] || null;
          const fmt = (v: number | null | undefined, digits = 4) => v == null ? 'N/A' : String(Number(v.toFixed(digits)));
          const f = finaSnapshots[i];
          const fmtPct = (v: number | null | undefined, digits = 2) => v == null ? 'N/A' : String(Number(v.toFixed(digits)));
          const dps = latestDpsList[i];
          const payoutPct = (dps != null && f?.eps != null && f.eps !== 0) ? Number(((dps / f.eps) * 100).toFixed(2)) : null;
          out += `| ${code} | ${num(c.weight)} | ${num(s.open_at_start)} | ${num(s.low_min)} | ${num(s.high_max)} | ${num(s.close_at_end)} | ${pct(r)} | ${fmt(val?.pe_ttm)} | ${fmt(val?.pb)} | ${val?.dividend_yield_pct == null ? 'N/A' : Number(val.dividend_yield_pct.toFixed(2))} | ${fmtPct(f?.roe_pct)} | ${fmtPct(f?.roa_pct)} | ${fmtPct(f?.netprofit_margin_pct)} | ${fmt(f?.ocfps)} | ${fmtPct(f?.debt_to_assets_pct)} | ${fmtPct(f?.revenue_yoy_pct)} | ${fmt(f?.assets_turn, 3)} | ${fmtPct(f?.grossprofit_margin_pct)} | ${fmtPct(f?.three_expense_ratio_pct)} | ${payoutPct == null ? 'N/A' : payoutPct} |\n`;
        });
    
        // 收集所有成分股代码并生成说明
        const stockCodes = allConstituents.map(c => normalizeIndexCode(c.ts_code));
        const stockExplanation = await resolveStockCodes(stockCodes);
        
        return {
          content: [ { type: 'text', text: out + stockExplanation } ]
        };
      } catch (error) {
        return {
          content: [ { type: 'text', text: `❌ CSI指数成分摘要查询失败: ${error instanceof Error ? error.message : String(error)}` } ],
          isError: true
        };
      }
    }
  • JSON Schema defining the input parameters for the tool: index_code (CSI index), start_date, and end_date.
    parameters: {
      type: 'object',
      properties: {
        index_code: {
          type: 'string',
          description: "指数代码(仅限CSI,含行业/主题)。请使用 .SH/.SZ 形式且能在 Tushare index_weight 查询到权重的代码,例如中证证券公司 '399975.SZ';也支持宽基 '000300.SH'、'000905.SH',以及 'sh000300'、'sz399006' 形式"
        },
        start_date: {
          type: 'string',
          description: '开始日期,YYYYMMDD 或 YYYY-MM-DD'
        },
        end_date: {
          type: 'string',
          description: '结束日期,YYYYMMDD 或 YYYY-MM-DD'
        }
      },
      required: ['index_code', 'start_date', 'end_date']
    },
  • src/index.ts:388-392 (registration)
    Tool dispatch/registration in the MCP stdio server's CallToolRequest handler switch statement.
    case "csi_index_constituents": {
      const index_code = String(request.params.arguments?.index_code);
      const start_date = String(request.params.arguments?.start_date);
      const end_date = String(request.params.arguments?.end_date);
      return normalizeResult(await csiIndexConstituents.run({ index_code, start_date, end_date }));
  • src/index.ts:246-248 (registration)
    Tool registration in the ListToolsRequest handler, exposing name, description, and inputSchema.
    name: csiIndexConstituents.name,
    description: csiIndexConstituents.description,
    inputSchema: csiIndexConstituents.parameters
  • Tool dispatch/registration in the HTTP MCP server's tools/call handler switch statement.
    case 'csi_index_constituents':
      return await csiIndexConstituents.run({
        index_code: String(args?.index_code),
        start_date: String(args?.start_date),
        end_date: String(args?.end_date),
      });
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It lists what data is retrieved but doesn't mention rate limits, authentication requirements, data freshness, pagination, error conditions, or whether this is a read-only operation. For a data retrieval tool with 3 parameters, this leaves significant 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.

Conciseness4/5

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

The description is a single, dense sentence that efficiently lists all data types retrieved. While comprehensive, it could benefit from structural separation of the different data categories. However, every element serves a purpose and there's no wasted text.

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?

For a data retrieval tool with 3 parameters and no output schema, the description provides good coverage of what data is returned but lacks information about return format, structure, or limitations. Without annotations or output schema, the agent has incomplete context about how to interpret results.

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

Parameters3/5

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

Schema description coverage is 100%, providing good documentation for all 3 parameters. The description doesn't add parameter-specific information beyond what's in the schema, but with complete schema coverage, the baseline score of 3 is appropriate as the schema handles the parameter documentation adequately.

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 retrieves data for CSI indices including market performance, constituent weights, and valuation/financial metrics. It specifies the resource (CSI indices) and verb (获取/retrieve), but doesn't explicitly differentiate from sibling tools like 'index_data' which might have overlapping functionality.

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 about when to use this tool versus alternatives. The description doesn't mention sibling tools like 'index_data' or specify use cases, prerequisites, or exclusions. The agent must infer usage from the description alone.

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

Install Server

Other Tools

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/Xxx00xxX33/FinanceMCP'

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