Skip to main content
Glama
qqzhangyanhua

MCP Stock Assistant

get-stock-history

Retrieve historical stock price data including daily, weekly, and monthly candlestick charts to analyze past performance trends.

Instructions

获取单个股票的历史数据、过去价格、K线数据,支持日K、周K、月K线,用于分析股票过去的表现

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
stock_codeYes股票代码或名称 (例如: 600519 或 贵州茅台)
periodNo时间周期: 1d=日K线, 1w=周K线, 1m=月K线1d
daysNo获取天数 (1-500天)

Implementation Reference

  • src/index.ts:50-110 (registration)
    Registration of the 'get-stock-history' tool via server.tool(), including input schema (Zod) and inline async handler function that orchestrates data fetching and formatting.
    server.tool(
      "get-stock-history",
      "获取单个股票的历史数据、过去价格、K线数据,支持日K、周K、月K线,用于分析股票过去的表现",
      {
        stock_code: z
          .string()
          .describe("股票代码或名称 (例如: 600519 或 贵州茅台)"),
        period: z
          .enum(["1d", "1w", "1m"])
          .default("1d")
          .describe("时间周期: 1d=日K线, 1w=周K线, 1m=月K线"),
        days: z
          .number()
          .min(1)
          .max(500)
          .default(30)
          .describe("获取天数 (1-500天)"),
      },
      async ({ stock_code, period, days }) => {
        // Convert period to API format
        const periodMap = { "1d": "101", "1w": "102", "1m": "103" };
        const apiPeriod = periodMap[period];
    
        const historyData = await fetchStockHistory(stock_code, apiPeriod, days);
    
        if (!historyData || historyData.length === 0) {
          return {
            content: [
              {
                type: "text",
                text: `无法获取股票 ${stock_code} 的历史数据。请检查输入是否正确。`,
              },
            ],
          };
        }
    
        // Get stock name for display
        let stockName = stock_code;
        if (!stock_code.match(/^\d{6}$/)) {
          const searchResult = await searchStock(stock_code);
          if (searchResult) {
            stockName = `${searchResult[1]}(${searchResult[0]})`;
          }
        } else {
          // Try to get name from current data
          const currentData = await fetchStockData(stock_code);
          if (currentData) {
            stockName = `${currentData.name}(${currentData.code})`;
          }
        }
    
        return {
          content: [
            {
              type: "text",
              text: formatHistoryData(historyData, stockName),
            },
          ],
        };
      }
    );
  • Inline handler function for 'get-stock-history' tool: validates inputs, maps period, calls fetchStockHistory, handles stock name resolution, and returns formatted content.
    async ({ stock_code, period, days }) => {
      // Convert period to API format
      const periodMap = { "1d": "101", "1w": "102", "1m": "103" };
      const apiPeriod = periodMap[period];
    
      const historyData = await fetchStockHistory(stock_code, apiPeriod, days);
    
      if (!historyData || historyData.length === 0) {
        return {
          content: [
            {
              type: "text",
              text: `无法获取股票 ${stock_code} 的历史数据。请检查输入是否正确。`,
            },
          ],
        };
      }
    
      // Get stock name for display
      let stockName = stock_code;
      if (!stock_code.match(/^\d{6}$/)) {
        const searchResult = await searchStock(stock_code);
        if (searchResult) {
          stockName = `${searchResult[1]}(${searchResult[0]})`;
        }
      } else {
        // Try to get name from current data
        const currentData = await fetchStockData(stock_code);
        if (currentData) {
          stockName = `${currentData.name}(${currentData.code})`;
        }
      }
    
      return {
        content: [
          {
            type: "text",
            text: formatHistoryData(historyData, stockName),
          },
        ],
      };
    }
  • Zod input schema for 'get-stock-history': stock_code (string), period (enum 1d/1w/1m), days (number 1-500).
    {
      stock_code: z
        .string()
        .describe("股票代码或名称 (例如: 600519 或 贵州茅台)"),
      period: z
        .enum(["1d", "1w", "1m"])
        .default("1d")
        .describe("时间周期: 1d=日K线, 1w=周K线, 1m=月K线"),
      days: z
        .number()
        .min(1)
        .max(500)
        .default(30)
        .describe("获取天数 (1-500天)"),
    },
  • fetchStockHistory helper: resolves stock code, constructs API params, fetches K-line data from HISTORY_API, parses response into HistoryDataPoint array.
    export async function fetchStockHistory(
      stockInput: string,
      period: string = "101",
      days: number = 30
    ): Promise<HistoryDataPoint[] | null> {
      try {
        let stockCode = stockInput;
    
        if (!stockInput.match(/^\d{6}$/)) {
          const searchResult = await searchStock(stockInput);
          if (!searchResult) {
            console.error(`未找到股票:${stockInput}`);
            return null;
          }
          [stockCode] = searchResult;
        }
    
        const [market, fullCode] = getStockMarket(stockCode);
    
        const params = {
          secid: fullCode,
          klt: period,
          fqt: "1",
          lmt: days.toString(),
          end: "20500101",
          iscca: "1",
          fields1: "f1,f2,f3,f4,f5,f6",
          fields2: "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
        };
    
        const response = await makeRequest(HISTORY_API, params);
        const data = (await response.json()) as HistoryResponse;
    
        if (data.rc !== 0 || !data.data || !data.data.klines) {
          throw new Error(data.msg || "获取历史数据失败");
        }
    
        const historyData: HistoryDataPoint[] = data.data.klines.map((kline) => {
          const parts = kline.split(",");
          return {
            date: parts[0],
            open: parseFloat(parts[1]),
            close: parseFloat(parts[2]),
            high: parseFloat(parts[3]),
            low: parseFloat(parts[4]),
            volume: parseInt(parts[5]) / 100,
            amount: parseFloat(parts[6]) / 10000,
            changePercent: parseFloat(parts[8]),
          };
        });
    
        return historyData.reverse();
      } catch (error) {
        console.error("Error fetching stock history:", error);
        return null;
      }
    }
  • formatHistoryData helper: converts history data array and stock name into formatted markdown text with table, stats (high/low/avg/total vol).
    export function formatHistoryData(data: HistoryDataPoint[], stockName: string): string {
      let result = `
    📈 ${stockName} 历史数据 (最近${data.length}个交易日)
    
    `;
    
      const recentData = data.slice(0, Math.min(10, data.length));
      
      result += "日期        开盘    收盘    最高    最低    成交量(手)  涨跌幅\n";
      result += "─".repeat(65) + "\n";
      
      for (const point of recentData) {
        const changeColor = point.changePercent >= 0 ? "📈" : "📉";
        result += `${point.date} ${formatPrice(point.open).padStart(6)} ${formatPrice(point.close).padStart(6)} ${formatPrice(point.high).padStart(6)} ${formatPrice(point.low).padStart(6)} ${formatVolume(point.volume).padStart(8)} ${changeColor}${point.changePercent.toFixed(2)}%\n`;
      }
    
      const prices = data.map(d => d.close);
      const maxPrice = Math.max(...prices);
      const minPrice = Math.min(...prices);
      const avgPrice = prices.reduce((a, b) => a + b, 0) / prices.length;
      const totalVolume = data.reduce((sum, d) => sum + d.volume, 0);
    
      result += `\n📊 统计信息:
    最高价: ${formatPrice(maxPrice)}
    最低价: ${formatPrice(minPrice)}
    平均价: ${formatPrice(avgPrice)}
    总成交量: ${formatVolume(totalVolume)}手
    `;
    
      return result;
    }

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/qqzhangyanhua/mcp-stock'

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