xstock-mcp 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.js +46 -1
- package/package.json +1 -1
- package/src/data/yahoo.ts +42 -0
- package/src/tools/index.ts +2 -1
- package/src/tools/us-market-b.ts +28 -0
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
| `get_dividend_history` | 分红历史、股息率、除息日 |
|
|
31
31
|
| `get_institutional_holders` | 前10大机构持仓比例及变动 |
|
|
32
32
|
| `get_similar_stocks` | 同行业可比公司估值对比 |
|
|
33
|
+
| `get_short_interest` | 做空比例、空头回补天数、与上月对比 |
|
|
33
34
|
| `get_stock_full_overview` | 复合工具:行情 + 基本面 + 评级 + 新闻,一次返回 |
|
|
34
35
|
| `search_stock` | 按名称或代码搜索 |
|
|
35
36
|
|
package/dist/index.js
CHANGED
|
@@ -368,6 +368,28 @@ async function fetchInsiderActivity(symbol) {
|
|
|
368
368
|
sharesAfter: tx.shareholderAfter ?? null
|
|
369
369
|
}));
|
|
370
370
|
}
|
|
371
|
+
async function fetchShortInterest(symbol) {
|
|
372
|
+
process.stderr.write(`[yahoo] fetchShortInterest symbol=${symbol}
|
|
373
|
+
`);
|
|
374
|
+
const summary = await yf.quoteSummary(symbol, {
|
|
375
|
+
modules: ["defaultKeyStatistics"]
|
|
376
|
+
});
|
|
377
|
+
const stats = summary.defaultKeyStatistics;
|
|
378
|
+
const sharesShort = stats?.sharesShort != null ? Number(stats.sharesShort) : null;
|
|
379
|
+
const priorMonth = stats?.sharesShortPriorMonth != null ? Number(stats.sharesShortPriorMonth) : null;
|
|
380
|
+
const change = sharesShort !== null && priorMonth !== null && priorMonth !== 0 ? Math.round((sharesShort - priorMonth) / priorMonth * 1e4) / 100 : null;
|
|
381
|
+
return {
|
|
382
|
+
symbol,
|
|
383
|
+
sharesShort,
|
|
384
|
+
sharesShortPriorMonth: priorMonth,
|
|
385
|
+
shortRatio: stats?.shortRatio != null ? Number(stats.shortRatio) : null,
|
|
386
|
+
shortPercentOfFloat: stats?.shortPercentOfFloat != null ? Math.round(Number(stats.shortPercentOfFloat) * 1e4) / 100 : null,
|
|
387
|
+
floatShares: stats?.floatShares != null ? Number(stats.floatShares) : null,
|
|
388
|
+
sharesOutstanding: stats?.sharesOutstanding != null ? Number(stats.sharesOutstanding) : null,
|
|
389
|
+
settlementDate: stats?.dateShortInterest instanceof Date ? stats.dateShortInterest.toISOString().slice(0, 10) : null,
|
|
390
|
+
changeFromPriorMonth: change
|
|
391
|
+
};
|
|
392
|
+
}
|
|
371
393
|
function mapQuoteToMover(q) {
|
|
372
394
|
return {
|
|
373
395
|
symbol: String(q.symbol ?? ""),
|
|
@@ -1602,6 +1624,28 @@ var getSimilarStocksTool = {
|
|
|
1602
1624
|
}
|
|
1603
1625
|
}
|
|
1604
1626
|
};
|
|
1627
|
+
var getShortInterestTool = {
|
|
1628
|
+
tool: {
|
|
1629
|
+
name: "get_short_interest",
|
|
1630
|
+
description: "\u83B7\u53D6\u7F8E\u80A1\u505A\u7A7A\u6570\u636E\uFF1A\u7A7A\u5934\u80A1\u6570\u3001\u505A\u7A7A\u5360\u6D41\u901A\u76D8\u6BD4\u4F8B\u3001\u7A7A\u5934\u56DE\u8865\u5929\u6570\uFF08Short Ratio\uFF09\u3001\u4E0E\u4E0A\u6708\u5BF9\u6BD4\u53D8\u5316\u3002\u7A7A\u5934\u56DE\u8865\u5929\u6570\u8D8A\u9AD8\u4EE3\u8868\u903C\u7A7A\u98CE\u9669\u8D8A\u5927\u3002",
|
|
1631
|
+
inputSchema: {
|
|
1632
|
+
type: "object",
|
|
1633
|
+
properties: {
|
|
1634
|
+
symbol: { type: "string", description: "\u7F8E\u80A1\u4EE3\u7801\uFF0C\u5982 GME\u3001TSLA\u3001NVDA" }
|
|
1635
|
+
},
|
|
1636
|
+
required: ["symbol"]
|
|
1637
|
+
}
|
|
1638
|
+
},
|
|
1639
|
+
handler: async (input) => {
|
|
1640
|
+
const parsed = SymbolInput3.safeParse(input);
|
|
1641
|
+
if (!parsed.success) return err(parsed.error.message);
|
|
1642
|
+
try {
|
|
1643
|
+
return ok(await fetchShortInterest(parsed.data.symbol));
|
|
1644
|
+
} catch (e) {
|
|
1645
|
+
return err(e.message);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1605
1649
|
|
|
1606
1650
|
// src/tools/index.ts
|
|
1607
1651
|
var tools = [
|
|
@@ -1626,7 +1670,8 @@ var tools = [
|
|
|
1626
1670
|
getMarketMoversTool,
|
|
1627
1671
|
getDividendHistoryTool,
|
|
1628
1672
|
getInstitutionalHoldersTool,
|
|
1629
|
-
getSimilarStocksTool
|
|
1673
|
+
getSimilarStocksTool,
|
|
1674
|
+
getShortInterestTool
|
|
1630
1675
|
];
|
|
1631
1676
|
var toolMap = new Map(
|
|
1632
1677
|
tools.map((t) => [t.tool.name, t])
|
package/package.json
CHANGED
package/src/data/yahoo.ts
CHANGED
|
@@ -340,6 +340,48 @@ export async function fetchInsiderActivity(symbol: string): Promise<InsiderTrans
|
|
|
340
340
|
}));
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
// ─── Short Interest ───────────────────────────────────────────────────────────
|
|
344
|
+
|
|
345
|
+
export interface ShortInterest {
|
|
346
|
+
symbol: string;
|
|
347
|
+
sharesShort: number | null;
|
|
348
|
+
sharesShortPriorMonth: number | null;
|
|
349
|
+
shortRatio: number | null;
|
|
350
|
+
shortPercentOfFloat: number | null;
|
|
351
|
+
floatShares: number | null;
|
|
352
|
+
sharesOutstanding: number | null;
|
|
353
|
+
settlementDate: string | null;
|
|
354
|
+
changeFromPriorMonth: number | null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export async function fetchShortInterest(symbol: string): Promise<ShortInterest> {
|
|
358
|
+
process.stderr.write(`[yahoo] fetchShortInterest symbol=${symbol}\n`);
|
|
359
|
+
const summary = await yf.quoteSummary(symbol, {
|
|
360
|
+
modules: ["defaultKeyStatistics"] as never[],
|
|
361
|
+
});
|
|
362
|
+
const stats = summary.defaultKeyStatistics as Record<string, unknown> | undefined;
|
|
363
|
+
|
|
364
|
+
const sharesShort = stats?.sharesShort != null ? Number(stats.sharesShort) : null;
|
|
365
|
+
const priorMonth = stats?.sharesShortPriorMonth != null ? Number(stats.sharesShortPriorMonth) : null;
|
|
366
|
+
const change = sharesShort !== null && priorMonth !== null && priorMonth !== 0
|
|
367
|
+
? Math.round(((sharesShort - priorMonth) / priorMonth) * 10000) / 100
|
|
368
|
+
: null;
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
symbol,
|
|
372
|
+
sharesShort,
|
|
373
|
+
sharesShortPriorMonth: priorMonth,
|
|
374
|
+
shortRatio: stats?.shortRatio != null ? Number(stats.shortRatio) : null,
|
|
375
|
+
shortPercentOfFloat: stats?.shortPercentOfFloat != null
|
|
376
|
+
? Math.round(Number(stats.shortPercentOfFloat) * 10000) / 100 : null,
|
|
377
|
+
floatShares: stats?.floatShares != null ? Number(stats.floatShares) : null,
|
|
378
|
+
sharesOutstanding: stats?.sharesOutstanding != null ? Number(stats.sharesOutstanding) : null,
|
|
379
|
+
settlementDate: stats?.dateShortInterest instanceof Date
|
|
380
|
+
? stats.dateShortInterest.toISOString().slice(0, 10) : null,
|
|
381
|
+
changeFromPriorMonth: change,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
343
385
|
// ─── Market Movers ────────────────────────────────────────────────────────────
|
|
344
386
|
|
|
345
387
|
export interface MoverItem {
|
package/src/tools/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { searchStockTool } from "./search";
|
|
|
5
5
|
import { getUsIndicesTool, getStockProfileTool, getEarningsCalendarTool, getUsSectorHeatmapTool } from "./us-market";
|
|
6
6
|
import { getCryptoOverviewTool, getCryptoTopTool, getCryptoCatsTool, getCryptoFundingTool, getCryptoLiquidationTool } from "./crypto";
|
|
7
7
|
import { getFinancialsTool, getAnalystRatingTool, getStockNewsTool, getInsiderActivityTool, getStockFullOverviewTool } from "./us-fundamentals";
|
|
8
|
-
import { getMarketMoversTool, getDividendHistoryTool, getInstitutionalHoldersTool, getSimilarStocksTool } from "./us-market-b";
|
|
8
|
+
import { getMarketMoversTool, getDividendHistoryTool, getInstitutionalHoldersTool, getSimilarStocksTool, getShortInterestTool } from "./us-market-b";
|
|
9
9
|
|
|
10
10
|
export * from "./types";
|
|
11
11
|
|
|
@@ -32,6 +32,7 @@ export const tools: ToolDef[] = [
|
|
|
32
32
|
getDividendHistoryTool,
|
|
33
33
|
getInstitutionalHoldersTool,
|
|
34
34
|
getSimilarStocksTool,
|
|
35
|
+
getShortInterestTool,
|
|
35
36
|
];
|
|
36
37
|
|
|
37
38
|
export const toolMap = new Map<string, ToolDef>(
|
package/src/tools/us-market-b.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
fetchDividendHistory,
|
|
5
5
|
fetchInstitutionalHolders,
|
|
6
6
|
fetchSimilarStocks,
|
|
7
|
+
fetchShortInterest,
|
|
7
8
|
} from "../data/yahoo";
|
|
8
9
|
import type { ToolDef } from "./types";
|
|
9
10
|
import { ok, err } from "./types";
|
|
@@ -126,3 +127,30 @@ export const getSimilarStocksTool: ToolDef = {
|
|
|
126
127
|
}
|
|
127
128
|
},
|
|
128
129
|
};
|
|
130
|
+
|
|
131
|
+
// ─── get_short_interest ───────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
export const getShortInterestTool: ToolDef = {
|
|
134
|
+
tool: {
|
|
135
|
+
name: "get_short_interest",
|
|
136
|
+
description:
|
|
137
|
+
"获取美股做空数据:空头股数、做空占流通盘比例、空头回补天数(Short Ratio)、与上月对比变化。" +
|
|
138
|
+
"空头回补天数越高代表逼空风险越大。",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
symbol: { type: "string", description: "美股代码,如 GME、TSLA、NVDA" },
|
|
143
|
+
},
|
|
144
|
+
required: ["symbol"],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
handler: async (input) => {
|
|
148
|
+
const parsed = SymbolInput.safeParse(input);
|
|
149
|
+
if (!parsed.success) return err(parsed.error.message);
|
|
150
|
+
try {
|
|
151
|
+
return ok(await fetchShortInterest(parsed.data.symbol));
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return err((e as Error).message);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
};
|