{"url_pattern":"^https?://([a-z0-9-]+\\.)?eastmoney\\.com(/.*)?$","site_name":"eastmoney","allowed_domains":["eastmoney.com","np-listapi.eastmoney.com","push2.eastmoney.com","quote.eastmoney.com","searchapi.eastmoney.com"],"tools":[{"name":"eastmoney_news","description":"获取东方财富网财经热点新闻","inputSchema":{"type":"object","properties":{"count":{"type":"string","description":"返回新闻条数，默认 20，最大 50"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      var count = Math.min(parseInt(args.count) || 20, 50);\n      var trace = Date.now().toString();\n\n      // column=350 is the main finance news feed\n      var url = 'https://np-listapi.eastmoney.com/comm/web/getNewsByColumns?client=web&biz=web_news_col&column=350&pageSize=' + count + '&page=1&req_trace=' + trace;\n\n      var resp = await fetch(url);\n      if (!resp.ok) return {error: '新闻获取失败: HTTP ' + resp.status};\n\n      var data = await resp.json();\n      if (data.code !== '1' && data.code !== 1) {\n        return {error: '接口返回错误: ' + (data.message || JSON.stringify(data))};\n      }\n\n      var list = (data.data && data.data.list) || [];\n      if (list.length === 0) return {error: '暂无新闻数据'};\n\n      var news = list.map(function(item, i) {\n        return {\n          rank: i + 1,\n          title: item.title,\n          summary: (item.summary || '').substring(0, 200),\n          source: item.mediaName || '',\n          time: item.showTime || '',\n          url: item.uniqueUrl || item.url || ''\n        };\n      });\n\n      return {\n        count: news.length,\n        fetchTime: new Date().toISOString(),\n        news: news\n      };\n  };\n  return run(params || {});\n}"},{"name":"eastmoney_stock","description":"获取东方财富网股票实时行情","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"股票名称或代码，如 贵州茅台 或 600519"}},"required":["query"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.query) return {error: 'Missing argument: query', hint: '请输入股票名称或代码'};\n\n      // Step 1: Search for the stock to resolve secid\n      var q = encodeURIComponent(args.query);\n      var searchResp = await fetch('https://searchapi.eastmoney.com/api/suggest/get?input=' + q + '&type=14&count=5');\n      if (!searchResp.ok) return {error: '搜索失败: HTTP ' + searchResp.status};\n\n      var searchData = await searchResp.json();\n      var results = (searchData.QuotationCodeTable && searchData.QuotationCodeTable.Data) || [];\n      if (results.length === 0) return {error: '未找到股票: ' + args.query};\n\n      // Use the first match\n      var match = results[0];\n      var secid = match.QuoteID; // e.g. \"1.600519\"\n      if (!secid) {\n        // Fallback: construct from MktNum and Code\n        secid = match.MktNum + '.' + match.Code;\n      }\n\n      // Step 2: Fetch real-time quote\n      // f43=最新价 f44=最高 f45=最低 f46=开盘 f47=成交量(手) f48=成交额\n      // f57=代码 f58=名称 f60=昨收 f170=涨跌幅(bp) f169=涨跌额 f171=振幅\n      // f116=总市值 f117=流通市值 f162=市盈率(动) f167=市净率\n      var fields = 'f43,f44,f45,f46,f47,f48,f57,f58,f60,f169,f170,f171,f116,f117,f162,f167';\n      var quoteResp = await fetch('https://push2.eastmoney.com/api/qt/stock/get?secid=' + secid + '&fields=' + fields);\n      if (!quoteResp.ok) return {error: '行情获取失败: HTTP ' + quoteResp.status};\n\n      var quoteData = await quoteResp.json();\n      var d = quoteData.data;\n      if (!d) return {error: '无行情数据', secid: secid};\n\n      // Prices are in cents (分), convert to yuan\n      var divisor = 100;\n      var price = d.f43 != null ? (d.f43 / divisor).toFixed(2) : null;\n      var high = d.f44 != null ? (d.f44 / divisor).toFixed(2) : null;\n      var low = d.f45 != null ? (d.f45 / divisor).toFixed(2) : null;\n      var open = d.f46 != null ? (d.f46 / divisor).toFixed(2) : null;\n      var prevClose = d.f60 != null ? (d.f60 / divisor).toFixed(2) : null;\n      var change = d.f169 != null ? (d.f169 / divisor).toFixed(2) : null;\n      var changePercent = d.f170 != null ? (d.f170 / 100).toFixed(2) + '%' : null;\n      var amplitude = d.f171 != null ? (d.f171 / 100).toFixed(2) + '%' : null;\n\n      // Volume in lots (手), amount in yuan\n      var volume = d.f47 != null ? d.f47 : null;\n      var amount = d.f48 != null ? d.f48 : null;\n\n      // Market cap in yuan\n      var marketCap = d.f116 != null ? d.f116 : null;\n      var floatMarketCap = d.f117 != null ? d.f117 : null;\n      var pe = d.f162 != null ? (d.f162 / 100).toFixed(2) : null;\n      var pb = d.f167 != null ? (d.f167 / 100).toFixed(2) : null;\n\n      // Format large numbers\n      function fmtAmount(v) {\n        if (v == null) return null;\n        if (v >= 1e12) return (v / 1e12).toFixed(2) + '万亿';\n        if (v >= 1e8) return (v / 1e8).toFixed(2) + '亿';\n        if (v >= 1e4) return (v / 1e4).toFixed(2) + '万';\n        return v.toString();\n      }\n\n      return {\n        name: d.f58 || match.Name,\n        code: d.f57 || match.Code,\n        secid: secid,\n        market: match.SecurityTypeName || (match.MktNum === '1' ? '沪A' : '深A'),\n        price: price,\n        change: change,\n        changePercent: changePercent,\n        open: open,\n        high: high,\n        low: low,\n        prevClose: prevClose,\n        amplitude: amplitude,\n        volume: volume != null ? volume + '手' : null,\n        amount: fmtAmount(amount),\n        marketCap: fmtAmount(marketCap),\n        floatMarketCap: fmtAmount(floatMarketCap),\n        pe: pe,\n        pb: pb,\n        url: 'https://quote.eastmoney.com/' + match.Code + '.html',\n        otherMatches: results.length > 1 ? results.slice(1).map(function(r) {\n          return {code: r.Code, name: r.Name, type: r.SecurityTypeName};\n        }) : []\n      };\n  };\n  return run(params || {});\n}"}]}