etf-research-mcp 1.1.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 ADDED
@@ -0,0 +1,47 @@
1
+ # etf-research-mcp
2
+
3
+ MCP server for real-time ETF research. Gives Claude tools to look up quotes, holdings, expense ratios, and fund comparisons using Yahoo Finance — no API key required.
4
+
5
+ ## Tools
6
+
7
+ | Tool | What it does |
8
+ |------|-------------|
9
+ | `search_etfs` | Discover ETFs by keyword or theme ("AI ETF", "dividend growth") |
10
+ | `get_etf_quote` | Current price, change, volume, 52-week range, moving averages |
11
+ | `get_etf_summary` | Expense ratio, AUM, NAV, fund family, beta, dividend yield |
12
+ | `get_etf_holdings` | Top holdings with portfolio weight percentages |
13
+ | `compare_etfs` | Side-by-side comparison of 2–5 ETFs |
14
+ | `get_etf_performance` | Historical price data over 1m / 3m / 6m / 1y / 3y / 5y |
15
+ | `get_similar_etfs` | Find alternative ETFs similar to a given ticker |
16
+
17
+ ## Install in Claude Code
18
+
19
+ ```bash
20
+ claude mcp add etf-research --scope user -- npx -y etf-research-mcp
21
+ ```
22
+
23
+ ## Example prompts
24
+
25
+ > "Find me AI-focused ETFs"
26
+
27
+ > "Compare QQQM, VOO, and VUG expense ratios and YTD returns"
28
+
29
+ > "What are the top 10 holdings of IJR?"
30
+
31
+ > "How has QQQM performed over the last year?"
32
+
33
+ > "What ETFs are similar to QQQM?"
34
+
35
+ ## No API key required
36
+
37
+ Data comes from Yahoo Finance via [yahoo-finance2](https://github.com/gadicc/yahoo-finance2). No sign-up, no key.
38
+
39
+ ## Built with
40
+
41
+ - [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk)
42
+ - [yahoo-finance2](https://github.com/gadicc/yahoo-finance2)
43
+ - TypeScript + Node 18+
44
+
45
+ ## Author
46
+
47
+ Myan Patel — [GitHub](https://github.com/myanptl)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,434 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
5
+ import YahooFinance from "yahoo-finance2";
6
+ // Must use `new YahooFinance()` — calling methods on the default export directly is deprecated.
7
+ const yf = new YahooFinance({ suppressNotices: ["yahooSurvey"] });
8
+ const server = new Server({ name: "etf-research-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
9
+ // ─── Tool Definitions ────────────────────────────────────────────────────────
10
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
11
+ tools: [
12
+ {
13
+ name: "get_etf_quote",
14
+ description: "Get the current price, change, volume, and key stats for any ETF ticker (e.g. QQQM, VOO, VUG).",
15
+ inputSchema: {
16
+ type: "object",
17
+ properties: {
18
+ symbol: {
19
+ type: "string",
20
+ description: "ETF ticker symbol (e.g. QQQM)",
21
+ },
22
+ },
23
+ required: ["symbol"],
24
+ },
25
+ },
26
+ {
27
+ name: "get_etf_summary",
28
+ description: "Get detailed fund info for an ETF: expense ratio, category, AUM, NAV, fund family, and inception date.",
29
+ inputSchema: {
30
+ type: "object",
31
+ properties: {
32
+ symbol: {
33
+ type: "string",
34
+ description: "ETF ticker symbol (e.g. VUG)",
35
+ },
36
+ },
37
+ required: ["symbol"],
38
+ },
39
+ },
40
+ {
41
+ name: "get_etf_holdings",
42
+ description: "Get the top holdings of an ETF with their portfolio weight percentages.",
43
+ inputSchema: {
44
+ type: "object",
45
+ properties: {
46
+ symbol: {
47
+ type: "string",
48
+ description: "ETF ticker symbol (e.g. VOO)",
49
+ },
50
+ },
51
+ required: ["symbol"],
52
+ },
53
+ },
54
+ {
55
+ name: "compare_etfs",
56
+ description: "Compare 2–5 ETFs side by side: price, expense ratio, AUM, YTD return, category.",
57
+ inputSchema: {
58
+ type: "object",
59
+ properties: {
60
+ symbols: {
61
+ type: "array",
62
+ items: { type: "string" },
63
+ description: 'List of 2–5 ETF ticker symbols (e.g. ["QQQM", "VOO", "VUG"])',
64
+ minItems: 2,
65
+ maxItems: 5,
66
+ },
67
+ },
68
+ required: ["symbols"],
69
+ },
70
+ },
71
+ {
72
+ name: "get_etf_performance",
73
+ description: "Get historical price performance for an ETF over a given period (1m, 3m, 6m, 1y, 3y, 5y).",
74
+ inputSchema: {
75
+ type: "object",
76
+ properties: {
77
+ symbol: { type: "string", description: "ETF ticker symbol" },
78
+ period: {
79
+ type: "string",
80
+ enum: ["1m", "3m", "6m", "1y", "3y", "5y"],
81
+ description: "Time period for performance data",
82
+ },
83
+ },
84
+ required: ["symbol", "period"],
85
+ },
86
+ },
87
+ {
88
+ name: "search_etfs",
89
+ description: "Search for ETFs by keyword or theme (e.g. 'AI', 'clean energy', 'small cap value'). Returns matching tickers and fund names.",
90
+ inputSchema: {
91
+ type: "object",
92
+ properties: {
93
+ query: {
94
+ type: "string",
95
+ description: "Search term (e.g. 'technology ETF', 'dividend growth')",
96
+ },
97
+ limit: {
98
+ type: "number",
99
+ description: "Max results to return (default 10, max 20)",
100
+ },
101
+ },
102
+ required: ["query"],
103
+ },
104
+ },
105
+ {
106
+ name: "get_similar_etfs",
107
+ description: "Find ETFs similar to a given ticker based on Yahoo Finance's recommendation engine. Useful for discovering alternatives.",
108
+ inputSchema: {
109
+ type: "object",
110
+ properties: {
111
+ symbol: {
112
+ type: "string",
113
+ description: "ETF ticker to find alternatives for (e.g. QQQM)",
114
+ },
115
+ },
116
+ required: ["symbol"],
117
+ },
118
+ },
119
+ ],
120
+ }));
121
+ function get(obj, key) {
122
+ return obj?.[key];
123
+ }
124
+ function pct(value) {
125
+ if (value == null)
126
+ return "N/A";
127
+ return `${(value * 100).toFixed(2)}%`;
128
+ }
129
+ function currency(value, decimals = 2) {
130
+ if (value == null)
131
+ return "N/A";
132
+ return `$${value.toFixed(decimals)}`;
133
+ }
134
+ function formatAum(value) {
135
+ if (value == null)
136
+ return "N/A";
137
+ if (value >= 1e12)
138
+ return `$${(value / 1e12).toFixed(2)}T`;
139
+ if (value >= 1e9)
140
+ return `$${(value / 1e9).toFixed(2)}B`;
141
+ if (value >= 1e6)
142
+ return `$${(value / 1e6).toFixed(2)}M`;
143
+ return `$${value.toLocaleString()}`;
144
+ }
145
+ function periodToDate(period) {
146
+ const d = new Date();
147
+ const offsets = {
148
+ "1m": () => d.setMonth(d.getMonth() - 1),
149
+ "3m": () => d.setMonth(d.getMonth() - 3),
150
+ "6m": () => d.setMonth(d.getMonth() - 6),
151
+ "1y": () => d.setFullYear(d.getFullYear() - 1),
152
+ "3y": () => d.setFullYear(d.getFullYear() - 3),
153
+ "5y": () => d.setFullYear(d.getFullYear() - 5),
154
+ };
155
+ offsets[period]?.();
156
+ return d;
157
+ }
158
+ // ─── Tool Handlers ────────────────────────────────────────────────────────────
159
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
160
+ const { name, arguments: args } = request.params;
161
+ try {
162
+ switch (name) {
163
+ // ── get_etf_quote ─────────────────────────────────────────────────────
164
+ case "get_etf_quote": {
165
+ const symbol = args.symbol.toUpperCase();
166
+ const q = (await yf.quote(symbol));
167
+ const changeRaw = get(q, "regularMarketChangePercent");
168
+ const changeFmt = changeRaw != null ? `${changeRaw.toFixed(2)}%` : "N/A";
169
+ const lines = [
170
+ `## ${get(q, "longName") ?? get(q, "shortName") ?? symbol} (${symbol})`,
171
+ ``,
172
+ `**Price:** ${currency(get(q, "regularMarketPrice"))}`,
173
+ `**Change:** ${currency(get(q, "regularMarketChange"))} (${changeFmt})`,
174
+ `**Previous Close:** ${currency(get(q, "regularMarketPreviousClose"))}`,
175
+ `**Day Range:** ${currency(get(q, "regularMarketDayLow"))} – ${currency(get(q, "regularMarketDayHigh"))}`,
176
+ `**52-Week Range:** ${currency(get(q, "fiftyTwoWeekLow"))} – ${currency(get(q, "fiftyTwoWeekHigh"))}`,
177
+ `**Volume:** ${(get(q, "regularMarketVolume") ?? 0).toLocaleString() || "N/A"}`,
178
+ `**Avg Volume (3m):** ${(get(q, "averageDailyVolume3Month") ?? 0).toLocaleString() || "N/A"}`,
179
+ `**Market Cap / AUM:** ${formatAum(get(q, "marketCap"))}`,
180
+ `**50-Day MA:** ${currency(get(q, "fiftyDayAverage"))}`,
181
+ `**200-Day MA:** ${currency(get(q, "twoHundredDayAverage"))}`,
182
+ `**YTD Return:** ${get(q, "ytdReturn") != null ? `${get(q, "ytdReturn").toFixed(2)}%` : "N/A"}`,
183
+ ];
184
+ return { content: [{ type: "text", text: lines.join("\n") }] };
185
+ }
186
+ // ── get_etf_summary ───────────────────────────────────────────────────
187
+ case "get_etf_summary": {
188
+ const symbol = args.symbol.toUpperCase();
189
+ const summary = (await yf.quoteSummary(symbol, {
190
+ modules: ["fundProfile", "defaultKeyStatistics", "summaryDetail"],
191
+ }));
192
+ const fp = get(summary, "fundProfile");
193
+ const ks = get(summary, "defaultKeyStatistics");
194
+ const sd = get(summary, "summaryDetail");
195
+ const fei = get(fp, "feesExpensesInvestment");
196
+ const lines = [
197
+ `## ${symbol} — Fund Summary`,
198
+ ``,
199
+ `**Category:** ${get(fp, "categoryName") ?? "N/A"}`,
200
+ `**Fund Family:** ${get(fp, "family") ?? "N/A"}`,
201
+ `**Expense Ratio:** ${pct(get(fei, "annualReportExpenseRatio"))}`,
202
+ `**AUM:** ${formatAum(get(ks, "totalAssets"))}`,
203
+ `**NAV:** ${currency(get(sd, "navPrice"))}`,
204
+ `**Beta (5Y Monthly):** ${get(ks, "beta")?.toFixed(2) ?? "N/A"}`,
205
+ `**Dividend Yield:** ${pct(get(sd, "dividendYield"))}`,
206
+ `**52-Week High:** ${currency(get(sd, "fiftyTwoWeekHigh"))}`,
207
+ `**52-Week Low:** ${currency(get(sd, "fiftyTwoWeekLow"))}`,
208
+ ];
209
+ return { content: [{ type: "text", text: lines.join("\n") }] };
210
+ }
211
+ // ── get_etf_holdings ──────────────────────────────────────────────────
212
+ case "get_etf_holdings": {
213
+ const symbol = args.symbol.toUpperCase();
214
+ const summary = (await yf.quoteSummary(symbol, {
215
+ modules: ["topHoldings"],
216
+ }));
217
+ const th = get(summary, "topHoldings");
218
+ const holdings = get(th, "holdings");
219
+ if (!holdings?.length) {
220
+ return {
221
+ content: [
222
+ {
223
+ type: "text",
224
+ text: `No holdings data available for ${symbol}. This ticker may not be an ETF or mutual fund.`,
225
+ },
226
+ ],
227
+ };
228
+ }
229
+ const sc = get(th, "stockConcentration");
230
+ const concentration = get(sc, "tenHoldingsPercentage");
231
+ const holdingLines = holdings.map((h, i) => {
232
+ const weight = get(h, "holdingPercent");
233
+ const weightFmt = weight != null ? pct(weight) : "N/A";
234
+ return `${i + 1}. **${get(h, "symbol") ?? "N/A"}** — ${get(h, "holdingName") ?? ""} (${weightFmt})`;
235
+ });
236
+ const lines = [
237
+ `## ${symbol} — Top Holdings`,
238
+ ``,
239
+ `**Top-10 Concentration:** ${pct(concentration)}`,
240
+ ``,
241
+ ...holdingLines,
242
+ ];
243
+ return { content: [{ type: "text", text: lines.join("\n") }] };
244
+ }
245
+ // ── compare_etfs ──────────────────────────────────────────────────────
246
+ case "compare_etfs": {
247
+ const symbols = args.symbols.map((s) => s.toUpperCase());
248
+ const results = await Promise.all(symbols.map(async (sym) => {
249
+ const [q, summary] = await Promise.all([
250
+ yf.quote(sym),
251
+ yf.quoteSummary(sym, {
252
+ modules: ["fundProfile", "defaultKeyStatistics"],
253
+ }),
254
+ ]);
255
+ const fp = get(summary, "fundProfile");
256
+ const ks = get(summary, "defaultKeyStatistics");
257
+ const fei = get(fp, "feesExpensesInvestment");
258
+ return { sym, q, fp, ks, fei };
259
+ }));
260
+ const row = (label, fn) => `| ${label} | ${results.map(fn).join(" | ")} |`;
261
+ const table = [
262
+ `## ETF Comparison: ${symbols.join(" vs ")}`,
263
+ ``,
264
+ `| Metric | ${symbols.join(" | ")} |`,
265
+ `|--------|${symbols.map(() => "--------|").join("")}`,
266
+ row("Price", ({ q }) => currency(get(q, "regularMarketPrice"))),
267
+ row("1-Day Change", ({ q }) => {
268
+ const v = get(q, "regularMarketChangePercent");
269
+ return v != null ? `${v.toFixed(2)}%` : "N/A";
270
+ }),
271
+ row("YTD Return", ({ q }) => {
272
+ const v = get(q, "ytdReturn");
273
+ return v != null ? `${v.toFixed(2)}%` : "N/A";
274
+ }),
275
+ row("AUM", ({ ks }) => formatAum(get(ks, "totalAssets"))),
276
+ row("Expense Ratio", ({ fei }) => pct(get(fei, "annualReportExpenseRatio"))),
277
+ row("Category", ({ fp }) => get(fp, "categoryName") ?? "N/A"),
278
+ row("Fund Family", ({ fp }) => get(fp, "family") ?? "N/A"),
279
+ row("Beta (5Y)", ({ ks }) => get(ks, "beta")?.toFixed(2) ?? "N/A"),
280
+ row("52W High", ({ q }) => currency(get(q, "fiftyTwoWeekHigh"))),
281
+ row("52W Low", ({ q }) => currency(get(q, "fiftyTwoWeekLow"))),
282
+ ].join("\n");
283
+ return { content: [{ type: "text", text: table }] };
284
+ }
285
+ // ── get_etf_performance ───────────────────────────────────────────────
286
+ case "get_etf_performance": {
287
+ const { symbol, period } = args;
288
+ const sym = symbol.toUpperCase();
289
+ const intervalMap = {
290
+ "1m": "1d",
291
+ "3m": "1wk",
292
+ "6m": "1wk",
293
+ "1y": "1mo",
294
+ "3y": "1mo",
295
+ "5y": "1mo",
296
+ };
297
+ const historical = await yf.historical(sym, {
298
+ period1: periodToDate(period),
299
+ interval: intervalMap[period] ?? "1mo",
300
+ });
301
+ if (!historical.length) {
302
+ return {
303
+ content: [
304
+ { type: "text", text: `No historical data found for ${sym}.` },
305
+ ],
306
+ };
307
+ }
308
+ const first = historical[0];
309
+ const last = historical[historical.length - 1];
310
+ const totalReturn = ((last.close - first.close) / first.close) * 100;
311
+ const highPrice = Math.max(...historical.map((d) => d.high));
312
+ const lowPrice = Math.min(...historical.map((d) => d.low));
313
+ const recentRows = historical
314
+ .slice(-10)
315
+ .reverse()
316
+ .map((d) => `| ${d.date.toISOString().split("T")[0]} | ${currency(d.close)} | ${currency(d.high)} | ${currency(d.low)} |`);
317
+ const lines = [
318
+ `## ${sym} — ${period.toUpperCase()} Performance`,
319
+ ``,
320
+ `**Period:** ${first.date.toISOString().split("T")[0]} → ${last.date.toISOString().split("T")[0]}`,
321
+ `**Total Return:** ${totalReturn.toFixed(2)}%`,
322
+ `**Start Price:** ${currency(first.close)}`,
323
+ `**End Price:** ${currency(last.close)}`,
324
+ `**Period High:** ${currency(highPrice)}`,
325
+ `**Period Low:** ${currency(lowPrice)}`,
326
+ ``,
327
+ `### Most Recent Data Points`,
328
+ `| Date | Close | High | Low |`,
329
+ `|------|-------|------|-----|`,
330
+ ...recentRows,
331
+ ];
332
+ return { content: [{ type: "text", text: lines.join("\n") }] };
333
+ }
334
+ // ── search_etfs ───────────────────────────────────────────────────────
335
+ case "search_etfs": {
336
+ const { query, limit = 10 } = args;
337
+ const cap = Math.min(limit, 20);
338
+ const result = (await yf.search(query));
339
+ const quotes = get(result, "quotes") ?? [];
340
+ const etfs = quotes
341
+ .filter((q) => get(q, "quoteType") === "ETF")
342
+ .slice(0, cap);
343
+ if (!etfs.length) {
344
+ return {
345
+ content: [
346
+ {
347
+ type: "text",
348
+ text: `No ETFs found for "${query}". Try a different search term.`,
349
+ },
350
+ ],
351
+ };
352
+ }
353
+ const rows = etfs.map((e, i) => {
354
+ const sym = get(e, "symbol") ?? "N/A";
355
+ const name = get(e, "longname") ?? get(e, "shortname") ?? "N/A";
356
+ const exchange = get(e, "exchange") ?? "";
357
+ return `${i + 1}. **${sym}** — ${name}${exchange ? ` (${exchange})` : ""}`;
358
+ });
359
+ const lines = [
360
+ `## ETF Search: "${query}"`,
361
+ ``,
362
+ `Found ${etfs.length} result${etfs.length === 1 ? "" : "s"}:`,
363
+ ``,
364
+ ...rows,
365
+ ``,
366
+ `_Use \`get_etf_quote\`, \`get_etf_summary\`, or \`compare_etfs\` to dig into any of these._`,
367
+ ];
368
+ return { content: [{ type: "text", text: lines.join("\n") }] };
369
+ }
370
+ // ── get_similar_etfs ──────────────────────────────────────────────────
371
+ case "get_similar_etfs": {
372
+ const symbol = args.symbol.toUpperCase();
373
+ const result = (await yf.recommendationsBySymbol(symbol));
374
+ const recommended = get(result, "recommendedSymbols") ?? [];
375
+ if (!recommended.length) {
376
+ return {
377
+ content: [
378
+ {
379
+ type: "text",
380
+ text: `No similar ETFs found for ${symbol}.`,
381
+ },
382
+ ],
383
+ };
384
+ }
385
+ const symbols = recommended.map((r) => get(r, "symbol")).filter(Boolean);
386
+ // Fetch a quick quote for each to show name + price
387
+ const quotes = await Promise.all(symbols.map(async (sym) => {
388
+ try {
389
+ const q = (await yf.quote(sym));
390
+ return { sym, q };
391
+ }
392
+ catch {
393
+ return { sym, q: null };
394
+ }
395
+ }));
396
+ const rows = quotes.map((item, i) => {
397
+ const name = item.q
398
+ ? (get(item.q, "longName") ?? get(item.q, "shortName") ?? item.sym)
399
+ : item.sym;
400
+ const price = item.q ? currency(get(item.q, "regularMarketPrice")) : "N/A";
401
+ const ytd = item.q ? get(item.q, "ytdReturn") : null;
402
+ const ytdFmt = ytd != null ? ` | YTD: ${ytd.toFixed(2)}%` : "";
403
+ return `${i + 1}. **${item.sym}** — ${name} (${price}${ytdFmt})`;
404
+ });
405
+ const lines = [
406
+ `## ETFs Similar to ${symbol}`,
407
+ ``,
408
+ ...rows,
409
+ ``,
410
+ `_Use \`compare_etfs\` to run a side-by-side with any of these._`,
411
+ ];
412
+ return { content: [{ type: "text", text: lines.join("\n") }] };
413
+ }
414
+ default:
415
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
416
+ }
417
+ }
418
+ catch (err) {
419
+ if (err instanceof McpError)
420
+ throw err;
421
+ const message = err instanceof Error ? err.message : String(err);
422
+ throw new McpError(ErrorCode.InternalError, `Yahoo Finance error: ${message}`);
423
+ }
424
+ });
425
+ // ─── Start ────────────────────────────────────────────────────────────────────
426
+ async function main() {
427
+ const transport = new StdioServerTransport();
428
+ await server.connect(transport);
429
+ }
430
+ main().catch((err) => {
431
+ process.stderr.write(`Fatal: ${err}\n`);
432
+ process.exit(1);
433
+ });
434
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,sBAAsB,EACtB,QAAQ,GACT,MAAM,oCAAoC,CAAC;AAC5C,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAE1C,gGAAgG;AAChG,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;AAElE,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC9C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;AAEF,gFAAgF;AAEhF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE;QACL;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EACT,gGAAgG;YAClG,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+BAA+B;qBAC7C;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;QACD;YACE,IAAI,EAAE,iBAAiB;YACvB,WAAW,EACT,wGAAwG;YAC1G,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,8BAA8B;qBAC5C;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;QACD;YACE,IAAI,EAAE,kBAAkB;YACxB,WAAW,EACT,yEAAyE;YAC3E,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,8BAA8B;qBAC5C;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,iFAAiF;YACnF,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,OAAO,EAAE;wBACP,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,WAAW,EACT,8DAA8D;wBAChE,QAAQ,EAAE,CAAC;wBACX,QAAQ,EAAE,CAAC;qBACZ;iBACF;gBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;aACtB;SACF;QACD;YACE,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EACT,2FAA2F;YAC7F,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;oBAC5D,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;wBAC1C,WAAW,EAAE,kCAAkC;qBAChD;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;aAC/B;SACF;QACD;YACE,IAAI,EAAE,aAAa;YACnB,WAAW,EACT,8HAA8H;YAChI,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,wDAAwD;qBACtE;oBACD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,4CAA4C;qBAC1D;iBACF;gBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;aACpB;SACF;QACD;YACE,IAAI,EAAE,kBAAkB;YACxB,WAAW,EACT,0HAA0H;YAC5H,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,iDAAiD;qBAC/D;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;KACF;CACF,CAAC,CAAC,CAAC;AAMJ,SAAS,GAAG,CAAI,GAAY,EAAE,GAAW;IACvC,OAAQ,GAAmB,EAAE,CAAC,GAAG,CAAkB,CAAC;AACtD,CAAC;AAED,SAAS,GAAG,CAAC,KAAgC;IAC3C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAgC,EAAE,QAAQ,GAAG,CAAC;IAC9D,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,SAAS,CAAC,KAAgC;IACjD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3D,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACzD,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACzD,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,MAAM,OAAO,GAA+B;QAC1C,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC9C,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC9C,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;KAC/C,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;IACpB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,IAAI,CAAC;QACH,QAAQ,IAAI,EAAE,CAAC;YACb,yEAAyE;YACzE,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,MAAM,MAAM,GAAI,IAA2B,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACjE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAgB,CAAC;gBAElD,MAAM,SAAS,GAAG,GAAG,CAAS,CAAC,EAAE,4BAA4B,CAAC,CAAC;gBAC/D,MAAM,SAAS,GACb,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBAEzD,MAAM,KAAK,GAAG;oBACZ,MAAM,GAAG,CAAS,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,IAAI,MAAM,KAAK,MAAM,GAAG;oBACvF,EAAE;oBACF,cAAc,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,oBAAoB,CAAC,CAAC,EAAE;oBAC9D,eAAe,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,qBAAqB,CAAC,CAAC,KAAK,SAAS,GAAG;oBAC/E,uBAAuB,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,4BAA4B,CAAC,CAAC,EAAE;oBAC/E,kBAAkB,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,qBAAqB,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,sBAAsB,CAAC,CAAC,EAAE;oBACzH,sBAAsB,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,iBAAiB,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE;oBACrH,eAAe,CAAC,GAAG,CAAS,CAAC,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,IAAI,KAAK,EAAE;oBACvF,wBAAwB,CAAC,GAAG,CAAS,CAAC,EAAE,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,IAAI,KAAK,EAAE;oBACrG,yBAAyB,SAAS,CAAC,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE;oBACjE,kBAAkB,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,iBAAiB,CAAC,CAAC,EAAE;oBAC/D,mBAAmB,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,sBAAsB,CAAC,CAAC,EAAE;oBACrE,mBAAmB,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAS,CAAC,EAAE,WAAW,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;iBACjH,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED,yEAAyE;YACzE,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,MAAM,GAAI,IAA2B,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACjE,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;oBAC7C,OAAO,EAAE,CAAC,aAAa,EAAE,sBAAsB,EAAE,eAAe,CAAC;iBAClE,CAAC,CAAgB,CAAC;gBAEnB,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,aAAa,CAAC,CAAC;gBACpD,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,sBAAsB,CAAC,CAAC;gBAC7D,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,eAAe,CAAC,CAAC;gBACtD,MAAM,GAAG,GAAG,GAAG,CAAc,EAAE,EAAE,wBAAwB,CAAC,CAAC;gBAE3D,MAAM,KAAK,GAAG;oBACZ,MAAM,MAAM,iBAAiB;oBAC7B,EAAE;oBACF,iBAAiB,GAAG,CAAS,EAAE,EAAE,cAAc,CAAC,IAAI,KAAK,EAAE;oBAC3D,oBAAoB,GAAG,CAAS,EAAE,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE;oBACxD,sBAAsB,GAAG,CAAC,GAAG,CAAS,GAAG,EAAE,0BAA0B,CAAC,CAAC,EAAE;oBACzE,YAAY,SAAS,CAAC,GAAG,CAAS,EAAE,EAAE,aAAa,CAAC,CAAC,EAAE;oBACvD,YAAY,QAAQ,CAAC,GAAG,CAAS,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE;oBACnD,0BAA0B,GAAG,CAAS,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE;oBACxE,uBAAuB,GAAG,CAAC,GAAG,CAAS,EAAE,EAAE,eAAe,CAAC,CAAC,EAAE;oBAC9D,qBAAqB,QAAQ,CAAC,GAAG,CAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC,EAAE;oBACpE,oBAAoB,QAAQ,CAAC,GAAG,CAAS,EAAE,EAAE,iBAAiB,CAAC,CAAC,EAAE;iBACnE,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED,yEAAyE;YACzE,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,MAAM,GAAI,IAA2B,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACjE,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;oBAC7C,OAAO,EAAE,CAAC,aAAa,CAAC;iBACzB,CAAC,CAAgB,CAAC;gBAEnB,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,aAAa,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,GAAG,CAAgB,EAAE,EAAE,UAAU,CAAC,CAAC;gBAEpD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;oBACtB,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,kCAAkC,MAAM,iDAAiD;6BAChG;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,MAAM,EAAE,GAAG,GAAG,CAAc,EAAE,EAAE,oBAAoB,CAAC,CAAC;gBACtD,MAAM,aAAa,GAAG,GAAG,CAAS,EAAE,EAAE,uBAAuB,CAAC,CAAC;gBAE/D,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACzC,MAAM,MAAM,GAAG,GAAG,CAAS,CAAC,EAAE,gBAAgB,CAAC,CAAC;oBAChD,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;oBACvD,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,GAAG,CAAS,CAAC,EAAE,QAAQ,CAAC,IAAI,KAAK,QAAQ,GAAG,CAAS,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,KAAK,SAAS,GAAG,CAAC;gBACtH,CAAC,CAAC,CAAC;gBAEH,MAAM,KAAK,GAAG;oBACZ,MAAM,MAAM,iBAAiB;oBAC7B,EAAE;oBACF,6BAA6B,GAAG,CAAC,aAAa,CAAC,EAAE;oBACjD,EAAE;oBACF,GAAG,YAAY;iBAChB,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED,yEAAyE;YACzE,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChE,CAAC,CAAC,WAAW,EAAE,CAChB,CAAC;gBAEF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACxB,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;wBACrC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAyB;wBACrC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE;4BACnB,OAAO,EAAE,CAAC,aAAa,EAAE,sBAAsB,CAAC;yBACjD,CAAyB;qBAC3B,CAAC,CAAC;oBACH,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,aAAa,CAAC,CAAC;oBACpD,MAAM,EAAE,GAAG,GAAG,CAAc,OAAO,EAAE,sBAAsB,CAAC,CAAC;oBAC7D,MAAM,GAAG,GAAG,GAAG,CAAc,EAAE,EAAE,wBAAwB,CAAC,CAAC;oBAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;gBACjC,CAAC,CAAC,CACH,CAAC;gBAEF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAAsC,EAAE,EAAE,CACpE,KAAK,KAAK,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBAElD,MAAM,KAAK,GAAG;oBACZ,sBAAsB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAC5C,EAAE;oBACF,cAAc,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI;oBACrC,aAAa,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;oBACtD,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC;oBACvE,GAAG,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;wBAC5B,MAAM,CAAC,GAAG,GAAG,CAAS,CAAC,EAAE,4BAA4B,CAAC,CAAC;wBACvD,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;oBAChD,CAAC,CAAC;oBACF,GAAG,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;wBAC1B,MAAM,CAAC,GAAG,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,CAAC;wBACtC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;oBAChD,CAAC,CAAC;oBACF,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAS,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;oBACjE,GAAG,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAC/B,GAAG,CAAC,GAAG,CAAS,GAAG,EAAE,0BAA0B,CAAC,CAAC,CAClD;oBACD,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAS,EAAE,EAAE,cAAc,CAAC,IAAI,KAAK,CAAC;oBACrE,GAAG,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAS,EAAE,EAAE,QAAQ,CAAC,IAAI,KAAK,CAAC;oBAClE,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAS,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;oBAC1E,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC;oBACxE,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAS,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC;iBACvE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YACtD,CAAC;YAED,yEAAyE;YACzE,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAA0C,CAAC;gBACtE,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;gBAEjC,MAAM,WAAW,GAAyC;oBACxD,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,KAAK;iBACZ,CAAC;gBAEF,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE;oBAC1C,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC;oBAC7B,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,KAAK;iBACvC,CAAC,CAAC;gBAEH,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;oBACvB,OAAO;wBACL,OAAO,EAAE;4BACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gCAAgC,GAAG,GAAG,EAAE;yBAC/D;qBACF,CAAC;gBACJ,CAAC;gBAED,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC5B,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC/C,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;gBACrE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAE3D,MAAM,UAAU,GAAG,UAAU;qBAC1B,KAAK,CAAC,CAAC,EAAE,CAAC;qBACV,OAAO,EAAE;qBACT,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAChH,CAAC;gBAEJ,MAAM,KAAK,GAAG;oBACZ,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,cAAc;oBACjD,EAAE;oBACF,eAAe,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;oBAClG,qBAAqB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;oBAC9C,oBAAoB,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;oBAC3C,kBAAkB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;oBACxC,oBAAoB,QAAQ,CAAC,SAAS,CAAC,EAAE;oBACzC,mBAAmB,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBACvC,EAAE;oBACF,6BAA6B;oBAC7B,+BAA+B;oBAC/B,+BAA+B;oBAC/B,GAAG,UAAU;iBACd,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED,yEAAyE;YACzE,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,IAAyC,CAAC;gBACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAChC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAgB,CAAC;gBAEvD,MAAM,MAAM,GAAG,GAAG,CAAgB,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC1D,MAAM,IAAI,GAAG,MAAM;qBAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,KAAK,KAAK,CAAC;qBACpD,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAEjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACjB,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,sBAAsB,KAAK,iCAAiC;6BACnE;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBAC7B,MAAM,GAAG,GAAG,GAAG,CAAS,CAAC,EAAE,QAAQ,CAAC,IAAI,KAAK,CAAC;oBAC9C,MAAM,IAAI,GAAG,GAAG,CAAS,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,CAAS,CAAC,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC;oBAChF,MAAM,QAAQ,GAAG,GAAG,CAAS,CAAC,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC;oBAClD,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,GAAG,QAAQ,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7E,CAAC,CAAC,CAAC;gBAEH,MAAM,KAAK,GAAG;oBACZ,mBAAmB,KAAK,GAAG;oBAC3B,EAAE;oBACF,SAAS,IAAI,CAAC,MAAM,UAAU,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;oBAC7D,EAAE;oBACF,GAAG,IAAI;oBACP,EAAE;oBACF,6FAA6F;iBAC9F,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED,yEAAyE;YACzE,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,MAAM,GAAI,IAA2B,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACjE,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAgB,CAAC;gBAEzE,MAAM,WAAW,GAAG,GAAG,CAAgB,MAAM,EAAE,oBAAoB,CAAC,IAAI,EAAE,CAAC;gBAE3E,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;oBACxB,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,6BAA6B,MAAM,GAAG;6BAC7C;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAS,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC;gBAE7F,oDAAoD;gBACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACxB,IAAI,CAAC;wBACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAgB,CAAC;wBAC/C,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;oBACpB,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;oBAC1B,CAAC;gBACH,CAAC,CAAC,CACH,CAAC;gBAEF,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;oBAClC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC;wBACjB,CAAC,CAAC,CAAC,GAAG,CAAS,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,CAAS,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC;wBACnF,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;oBACb,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAS,IAAI,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;oBACnF,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAS,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBAC7D,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/D,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,KAAK,GAAG,MAAM,GAAG,CAAC;gBACnE,CAAC,CAAC,CAAC;gBAEH,MAAM,KAAK,GAAG;oBACZ,sBAAsB,MAAM,EAAE;oBAC9B,EAAE;oBACF,GAAG,IAAI;oBACP,EAAE;oBACF,iEAAiE;iBAClE,CAAC;gBAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAED;gBACE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ;YAAE,MAAM,GAAG,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,aAAa,EACvB,wBAAwB,OAAO,EAAE,CAClC,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "etf-research-mcp",
3
+ "version": "1.1.0",
4
+ "description": "MCP server for real-time ETF research — quotes, holdings, expense ratios, and fund comparisons via Yahoo Finance",
5
+ "keywords": ["mcp", "etf", "finance", "yahoo-finance", "investing", "model-context-protocol"],
6
+ "author": "Myan Patel",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/myanptl/etf-research-mcp#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/myanptl/etf-research-mcp.git"
12
+ },
13
+ "type": "module",
14
+ "bin": {
15
+ "etf-research-mcp": "./dist/index.js"
16
+ },
17
+ "files": ["dist"],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "start": "node dist/index.js",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.29.0",
26
+ "yahoo-finance2": "^3.15.3"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.0.0",
30
+ "typescript": "^5.7.0"
31
+ },
32
+ "engines": {
33
+ "node": ">=18"
34
+ }
35
+ }