data-aggregator-mcp 1.0.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 +336 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +333 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/exchange.d.ts +15 -0
- package/dist/tools/exchange.d.ts.map +1 -0
- package/dist/tools/exchange.js +195 -0
- package/dist/tools/exchange.js.map +1 -0
- package/dist/tools/news.d.ts +20 -0
- package/dist/tools/news.d.ts.map +1 -0
- package/dist/tools/news.js +175 -0
- package/dist/tools/news.js.map +1 -0
- package/dist/tools/public-data.d.ts +24 -0
- package/dist/tools/public-data.d.ts.map +1 -0
- package/dist/tools/public-data.js +262 -0
- package/dist/tools/public-data.js.map +1 -0
- package/dist/tools/scraper.d.ts +19 -0
- package/dist/tools/scraper.d.ts.map +1 -0
- package/dist/tools/scraper.js +185 -0
- package/dist/tools/scraper.js.map +1 -0
- package/dist/tools/stocks.d.ts +14 -0
- package/dist/tools/stocks.d.ts.map +1 -0
- package/dist/tools/stocks.js +172 -0
- package/dist/tools/stocks.js.map +1 -0
- package/dist/tools/weather.d.ts +15 -0
- package/dist/tools/weather.d.ts.map +1 -0
- package/dist/tools/weather.js +172 -0
- package/dist/tools/weather.js.map +1 -0
- package/dist/types.d.ts +160 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +45 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +88 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/http.d.ts +39 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/dist/utils/http.js +103 -0
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +34 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +95 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/package.json +42 -0
- package/src/index.ts +461 -0
- package/src/tools/exchange.ts +241 -0
- package/src/tools/news.ts +238 -0
- package/src/tools/public-data.ts +325 -0
- package/src/tools/scraper.ts +217 -0
- package/src/tools/stocks.ts +205 -0
- package/src/tools/weather.ts +216 -0
- package/src/types.ts +184 -0
- package/src/utils/cache.ts +103 -0
- package/src/utils/http.ts +156 -0
- package/src/utils/rate-limiter.ts +114 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query_stocks - Fetch stock and crypto market data.
|
|
3
|
+
*
|
|
4
|
+
* Free data sources:
|
|
5
|
+
* - CoinGecko API (crypto, no key required)
|
|
6
|
+
* - Yahoo Finance v8 unofficial API (stocks, no key required)
|
|
7
|
+
* - Alpha Vantage (stocks, optional key via ALPHA_VANTAGE_KEY env)
|
|
8
|
+
*/
|
|
9
|
+
import { cache, TTL } from "../utils/cache.js";
|
|
10
|
+
import { rateLimiter } from "../utils/rate-limiter.js";
|
|
11
|
+
import { httpGetJson, formatError } from "../utils/http.js";
|
|
12
|
+
// ─── CoinGecko ID mapping for common crypto symbols ────────────────────────
|
|
13
|
+
const CRYPTO_MAP = {
|
|
14
|
+
btc: "bitcoin",
|
|
15
|
+
eth: "ethereum",
|
|
16
|
+
sol: "solana",
|
|
17
|
+
ada: "cardano",
|
|
18
|
+
dot: "polkadot",
|
|
19
|
+
matic: "matic-network",
|
|
20
|
+
avax: "avalanche-2",
|
|
21
|
+
link: "chainlink",
|
|
22
|
+
doge: "dogecoin",
|
|
23
|
+
shib: "shiba-inu",
|
|
24
|
+
xrp: "ripple",
|
|
25
|
+
bnb: "binancecoin",
|
|
26
|
+
ltc: "litecoin",
|
|
27
|
+
uni: "uniswap",
|
|
28
|
+
atom: "cosmos",
|
|
29
|
+
near: "near",
|
|
30
|
+
apt: "aptos",
|
|
31
|
+
arb: "arbitrum",
|
|
32
|
+
op: "optimism",
|
|
33
|
+
sui: "sui",
|
|
34
|
+
};
|
|
35
|
+
function isCrypto(symbol) {
|
|
36
|
+
return symbol.toLowerCase() in CRYPTO_MAP;
|
|
37
|
+
}
|
|
38
|
+
function coingeckoId(symbol) {
|
|
39
|
+
return CRYPTO_MAP[symbol.toLowerCase()] ?? symbol.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
// ─── Crypto via CoinGecko ──────────────────────────────────────────────────
|
|
42
|
+
async function fetchCryptoQuote(symbol, vsCurrency = "usd") {
|
|
43
|
+
const id = coingeckoId(symbol);
|
|
44
|
+
const url = `https://api.coingecko.com/api/v3/coins/${id}` +
|
|
45
|
+
`?localization=false&tickers=false&community_data=false&developer_data=false`;
|
|
46
|
+
await rateLimiter.acquire("coingecko");
|
|
47
|
+
const data = await httpGetJson(url);
|
|
48
|
+
const md = data.market_data;
|
|
49
|
+
return {
|
|
50
|
+
symbol: data.symbol.toUpperCase(),
|
|
51
|
+
name: data.name,
|
|
52
|
+
price: md.current_price[vsCurrency] ?? md.current_price.usd,
|
|
53
|
+
currency: vsCurrency.toUpperCase(),
|
|
54
|
+
change24h: md.price_change_24h ?? 0,
|
|
55
|
+
changePercent24h: md.price_change_percentage_24h ?? 0,
|
|
56
|
+
volume24h: md.total_volume[vsCurrency] ?? md.total_volume.usd ?? 0,
|
|
57
|
+
marketCap: md.market_cap[vsCurrency] ?? md.market_cap.usd ?? 0,
|
|
58
|
+
high24h: md.high_24h?.[vsCurrency],
|
|
59
|
+
low24h: md.low_24h?.[vsCurrency],
|
|
60
|
+
timestamp: new Date().toISOString(),
|
|
61
|
+
source: "CoinGecko",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// ─── Stocks via Yahoo Finance (unofficial v8 endpoint) ─────────────────────
|
|
65
|
+
async function fetchStockQuoteYahoo(symbol) {
|
|
66
|
+
const url = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(symbol)}?range=1d&interval=1d`;
|
|
67
|
+
await rateLimiter.acquire("generic");
|
|
68
|
+
const data = await httpGetJson(url, { rotateUserAgent: true });
|
|
69
|
+
const result = data?.chart?.result?.[0];
|
|
70
|
+
if (!result)
|
|
71
|
+
throw new Error(`No data found for symbol "${symbol}"`);
|
|
72
|
+
const meta = result.meta;
|
|
73
|
+
const price = meta.regularMarketPrice ?? meta.previousClose;
|
|
74
|
+
const prevClose = meta.chartPreviousClose ?? meta.previousClose ?? price;
|
|
75
|
+
return {
|
|
76
|
+
symbol: meta.symbol ?? symbol.toUpperCase(),
|
|
77
|
+
price,
|
|
78
|
+
currency: (meta.currency ?? "USD").toUpperCase(),
|
|
79
|
+
change: +(price - prevClose).toFixed(4),
|
|
80
|
+
changePercent: prevClose ? +(((price - prevClose) / prevClose) * 100).toFixed(4) : 0,
|
|
81
|
+
volume: meta.regularMarketVolume,
|
|
82
|
+
high: meta.regularMarketDayHigh,
|
|
83
|
+
low: meta.regularMarketDayLow,
|
|
84
|
+
open: meta.regularMarketOpen ?? meta.openPrice,
|
|
85
|
+
previousClose: prevClose,
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
source: "Yahoo Finance",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// ─── Stocks via Alpha Vantage (if key is available) ────────────────────────
|
|
91
|
+
async function fetchStockQuoteAlphaVantage(symbol, apiKey) {
|
|
92
|
+
const url = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${encodeURIComponent(symbol)}&apikey=${apiKey}`;
|
|
93
|
+
await rateLimiter.acquire("generic");
|
|
94
|
+
const data = await httpGetJson(url);
|
|
95
|
+
const q = data["Global Quote"];
|
|
96
|
+
if (!q || !q["05. price"]) {
|
|
97
|
+
throw new Error(`Alpha Vantage returned no data for "${symbol}"`);
|
|
98
|
+
}
|
|
99
|
+
const price = parseFloat(q["05. price"]);
|
|
100
|
+
const prevClose = parseFloat(q["08. previous close"]);
|
|
101
|
+
return {
|
|
102
|
+
symbol: q["01. symbol"] ?? symbol.toUpperCase(),
|
|
103
|
+
price,
|
|
104
|
+
currency: "USD",
|
|
105
|
+
change: parseFloat(q["09. change"]) || 0,
|
|
106
|
+
changePercent: parseFloat(q["10. change percent"]?.replace("%", "")) || 0,
|
|
107
|
+
volume: parseInt(q["06. volume"], 10) || undefined,
|
|
108
|
+
high: parseFloat(q["03. high"]) || undefined,
|
|
109
|
+
low: parseFloat(q["04. low"]) || undefined,
|
|
110
|
+
open: parseFloat(q["02. open"]) || undefined,
|
|
111
|
+
previousClose: prevClose || undefined,
|
|
112
|
+
timestamp: new Date().toISOString(),
|
|
113
|
+
source: "Alpha Vantage",
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// ─── Public handler ────────────────────────────────────────────────────────
|
|
117
|
+
export async function queryStocks(args) {
|
|
118
|
+
try {
|
|
119
|
+
const symbol = args.symbol.trim();
|
|
120
|
+
const assetType = args.type === "crypto" || (args.type !== "stock" && isCrypto(symbol))
|
|
121
|
+
? "crypto"
|
|
122
|
+
: "stock";
|
|
123
|
+
const cacheKey = `stocks:${assetType}:${symbol.toLowerCase()}`;
|
|
124
|
+
// Check cache
|
|
125
|
+
const cached = cache.get(cacheKey);
|
|
126
|
+
if (cached) {
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "text",
|
|
131
|
+
text: JSON.stringify({ ...cached, cached: true }, null, 2),
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
let result;
|
|
137
|
+
if (assetType === "crypto") {
|
|
138
|
+
result = await fetchCryptoQuote(symbol);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Try Yahoo first; fall back to Alpha Vantage if a key is available
|
|
142
|
+
try {
|
|
143
|
+
result = await fetchStockQuoteYahoo(symbol);
|
|
144
|
+
}
|
|
145
|
+
catch (yahooErr) {
|
|
146
|
+
const avKey = process.env.ALPHA_VANTAGE_KEY;
|
|
147
|
+
if (avKey) {
|
|
148
|
+
result = await fetchStockQuoteAlphaVantage(symbol, avKey);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
throw yahooErr;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
cache.set(cacheKey, result, TTL.MARKET);
|
|
156
|
+
return {
|
|
157
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: "text",
|
|
165
|
+
text: `Error fetching market data: ${formatError(err)}`,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
isError: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=stocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stocks.js","sourceRoot":"","sources":["../../src/tools/stocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query_weather - Weather data via Open-Meteo API.
|
|
3
|
+
*
|
|
4
|
+
* Open-Meteo is 100% free, no API key required.
|
|
5
|
+
* Provides current conditions + 7-day forecast.
|
|
6
|
+
* Accepts city name (geocoded) or direct lat/lon.
|
|
7
|
+
*/
|
|
8
|
+
import type { ToolResult } from "../types.js";
|
|
9
|
+
export declare function queryWeather(args: {
|
|
10
|
+
city?: string;
|
|
11
|
+
latitude?: number;
|
|
12
|
+
longitude?: number;
|
|
13
|
+
units?: "celsius" | "fahrenheit";
|
|
14
|
+
}): Promise<ToolResult>;
|
|
15
|
+
//# sourceMappingURL=weather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather.d.ts","sourceRoot":"","sources":["../../src/tools/weather.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAA8C,UAAU,EAAE,MAAM,aAAa,CAAC;AA6I1F,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CAClC,GAAG,OAAO,CAAC,UAAU,CAAC,CA0DtB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query_weather - Weather data via Open-Meteo API.
|
|
3
|
+
*
|
|
4
|
+
* Open-Meteo is 100% free, no API key required.
|
|
5
|
+
* Provides current conditions + 7-day forecast.
|
|
6
|
+
* Accepts city name (geocoded) or direct lat/lon.
|
|
7
|
+
*/
|
|
8
|
+
import { cache, TTL } from "../utils/cache.js";
|
|
9
|
+
import { rateLimiter } from "../utils/rate-limiter.js";
|
|
10
|
+
import { httpGetJson, formatError } from "../utils/http.js";
|
|
11
|
+
// ─── WMO Weather Code Descriptions ────────────────────────────────────────
|
|
12
|
+
const WMO_CODES = {
|
|
13
|
+
0: "Clear sky",
|
|
14
|
+
1: "Mainly clear",
|
|
15
|
+
2: "Partly cloudy",
|
|
16
|
+
3: "Overcast",
|
|
17
|
+
45: "Fog",
|
|
18
|
+
48: "Depositing rime fog",
|
|
19
|
+
51: "Light drizzle",
|
|
20
|
+
53: "Moderate drizzle",
|
|
21
|
+
55: "Dense drizzle",
|
|
22
|
+
56: "Light freezing drizzle",
|
|
23
|
+
57: "Dense freezing drizzle",
|
|
24
|
+
61: "Slight rain",
|
|
25
|
+
63: "Moderate rain",
|
|
26
|
+
65: "Heavy rain",
|
|
27
|
+
66: "Light freezing rain",
|
|
28
|
+
67: "Heavy freezing rain",
|
|
29
|
+
71: "Slight snowfall",
|
|
30
|
+
73: "Moderate snowfall",
|
|
31
|
+
75: "Heavy snowfall",
|
|
32
|
+
77: "Snow grains",
|
|
33
|
+
80: "Slight rain showers",
|
|
34
|
+
81: "Moderate rain showers",
|
|
35
|
+
82: "Violent rain showers",
|
|
36
|
+
85: "Slight snow showers",
|
|
37
|
+
86: "Heavy snow showers",
|
|
38
|
+
95: "Thunderstorm",
|
|
39
|
+
96: "Thunderstorm with slight hail",
|
|
40
|
+
99: "Thunderstorm with heavy hail",
|
|
41
|
+
};
|
|
42
|
+
function weatherDescription(code) {
|
|
43
|
+
return WMO_CODES[code] ?? `Unknown (code ${code})`;
|
|
44
|
+
}
|
|
45
|
+
async function geocodeCity(city) {
|
|
46
|
+
const url = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1&language=en&format=json`;
|
|
47
|
+
await rateLimiter.acquire("open-meteo");
|
|
48
|
+
const data = await httpGetJson(url);
|
|
49
|
+
if (!data.results || data.results.length === 0) {
|
|
50
|
+
throw new Error(`Could not find location "${city}". Try a different spelling or use latitude/longitude.`);
|
|
51
|
+
}
|
|
52
|
+
const r = data.results[0];
|
|
53
|
+
return {
|
|
54
|
+
name: [r.name, r.admin1, r.country].filter(Boolean).join(", "),
|
|
55
|
+
latitude: r.latitude,
|
|
56
|
+
longitude: r.longitude,
|
|
57
|
+
timezone: r.timezone ?? "UTC",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// ─── Weather fetch ─────────────────────────────────────────────────────────
|
|
61
|
+
async function fetchWeather(lat, lon, locationName, timezone, units) {
|
|
62
|
+
const tempUnit = units === "fahrenheit" ? "fahrenheit" : "celsius";
|
|
63
|
+
const windUnit = units === "fahrenheit" ? "mph" : "kmh";
|
|
64
|
+
const params = new URLSearchParams({
|
|
65
|
+
latitude: String(lat),
|
|
66
|
+
longitude: String(lon),
|
|
67
|
+
timezone,
|
|
68
|
+
temperature_unit: tempUnit,
|
|
69
|
+
wind_speed_unit: windUnit,
|
|
70
|
+
current: "temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m,wind_direction_10m,is_day",
|
|
71
|
+
daily: "weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,wind_speed_10m_max,sunrise,sunset",
|
|
72
|
+
forecast_days: "7",
|
|
73
|
+
});
|
|
74
|
+
const url = `https://api.open-meteo.com/v1/forecast?${params.toString()}`;
|
|
75
|
+
await rateLimiter.acquire("open-meteo");
|
|
76
|
+
const data = await httpGetJson(url);
|
|
77
|
+
const c = data.current;
|
|
78
|
+
const current = {
|
|
79
|
+
temperature: c.temperature_2m,
|
|
80
|
+
feelsLike: c.apparent_temperature,
|
|
81
|
+
humidity: c.relative_humidity_2m,
|
|
82
|
+
windSpeed: c.wind_speed_10m,
|
|
83
|
+
windDirection: c.wind_direction_10m,
|
|
84
|
+
precipitation: c.precipitation,
|
|
85
|
+
weatherCode: c.weather_code,
|
|
86
|
+
weatherDescription: weatherDescription(c.weather_code),
|
|
87
|
+
isDay: c.is_day === 1,
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
};
|
|
90
|
+
const d = data.daily;
|
|
91
|
+
const forecast = [];
|
|
92
|
+
for (let i = 0; i < (d.time?.length ?? 0); i++) {
|
|
93
|
+
forecast.push({
|
|
94
|
+
date: d.time[i],
|
|
95
|
+
temperatureMax: d.temperature_2m_max[i],
|
|
96
|
+
temperatureMin: d.temperature_2m_min[i],
|
|
97
|
+
precipitationSum: d.precipitation_sum[i],
|
|
98
|
+
precipitationProbability: d.precipitation_probability_max[i],
|
|
99
|
+
windSpeedMax: d.wind_speed_10m_max[i],
|
|
100
|
+
weatherCode: d.weather_code[i],
|
|
101
|
+
weatherDescription: weatherDescription(d.weather_code[i]),
|
|
102
|
+
sunrise: d.sunrise[i],
|
|
103
|
+
sunset: d.sunset[i],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
location: locationName,
|
|
108
|
+
latitude: lat,
|
|
109
|
+
longitude: lon,
|
|
110
|
+
timezone,
|
|
111
|
+
current,
|
|
112
|
+
forecast,
|
|
113
|
+
source: "Open-Meteo",
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// ─── Public handler ────────────────────────────────────────────────────────
|
|
117
|
+
export async function queryWeather(args) {
|
|
118
|
+
try {
|
|
119
|
+
const { city, units = "celsius" } = args;
|
|
120
|
+
let { latitude, longitude } = args;
|
|
121
|
+
if (!city && (latitude === undefined || longitude === undefined)) {
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: "text",
|
|
126
|
+
text: 'Please provide either a city name or both latitude and longitude.',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
let locationName;
|
|
133
|
+
let timezone;
|
|
134
|
+
if (city) {
|
|
135
|
+
const geo = await geocodeCity(city);
|
|
136
|
+
latitude = geo.latitude;
|
|
137
|
+
longitude = geo.longitude;
|
|
138
|
+
locationName = geo.name;
|
|
139
|
+
timezone = geo.timezone;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
locationName = `${latitude.toFixed(4)}, ${longitude.toFixed(4)}`;
|
|
143
|
+
timezone = "UTC";
|
|
144
|
+
}
|
|
145
|
+
const cacheKey = `weather:${latitude.toFixed(2)}:${longitude.toFixed(2)}:${units}`;
|
|
146
|
+
const cached = cache.get(cacheKey);
|
|
147
|
+
if (cached) {
|
|
148
|
+
return {
|
|
149
|
+
content: [
|
|
150
|
+
{
|
|
151
|
+
type: "text",
|
|
152
|
+
text: JSON.stringify({ ...cached, cached: true }, null, 2),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const weather = await fetchWeather(latitude, longitude, locationName, timezone, units);
|
|
158
|
+
cache.set(cacheKey, weather, TTL.WEATHER);
|
|
159
|
+
return {
|
|
160
|
+
content: [{ type: "text", text: JSON.stringify(weather, null, 2) }],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
return {
|
|
165
|
+
content: [
|
|
166
|
+
{ type: "text", text: `Error fetching weather: ${formatError(err)}` },
|
|
167
|
+
],
|
|
168
|
+
isError: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=weather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather.js","sourceRoot":"","sources":["../../src/tools/weather.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/** Generic API response wrapper */
|
|
2
|
+
export interface ApiResponse<T> {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: T;
|
|
5
|
+
error?: string;
|
|
6
|
+
cached?: boolean;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
}
|
|
9
|
+
export interface StockQuote {
|
|
10
|
+
symbol: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
price: number;
|
|
13
|
+
currency: string;
|
|
14
|
+
change: number;
|
|
15
|
+
changePercent: number;
|
|
16
|
+
volume?: number;
|
|
17
|
+
marketCap?: number;
|
|
18
|
+
high?: number;
|
|
19
|
+
low?: number;
|
|
20
|
+
open?: number;
|
|
21
|
+
previousClose?: number;
|
|
22
|
+
timestamp: string;
|
|
23
|
+
source: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CryptoQuote {
|
|
26
|
+
symbol: string;
|
|
27
|
+
name: string;
|
|
28
|
+
price: number;
|
|
29
|
+
currency: string;
|
|
30
|
+
change24h: number;
|
|
31
|
+
changePercent24h: number;
|
|
32
|
+
volume24h: number;
|
|
33
|
+
marketCap: number;
|
|
34
|
+
high24h?: number;
|
|
35
|
+
low24h?: number;
|
|
36
|
+
timestamp: string;
|
|
37
|
+
source: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CurrentWeather {
|
|
40
|
+
temperature: number;
|
|
41
|
+
feelsLike: number;
|
|
42
|
+
humidity: number;
|
|
43
|
+
windSpeed: number;
|
|
44
|
+
windDirection: number;
|
|
45
|
+
precipitation: number;
|
|
46
|
+
weatherCode: number;
|
|
47
|
+
weatherDescription: string;
|
|
48
|
+
isDay: boolean;
|
|
49
|
+
timestamp: string;
|
|
50
|
+
}
|
|
51
|
+
export interface DailyForecast {
|
|
52
|
+
date: string;
|
|
53
|
+
temperatureMax: number;
|
|
54
|
+
temperatureMin: number;
|
|
55
|
+
precipitationSum: number;
|
|
56
|
+
precipitationProbability: number;
|
|
57
|
+
windSpeedMax: number;
|
|
58
|
+
weatherCode: number;
|
|
59
|
+
weatherDescription: string;
|
|
60
|
+
sunrise: string;
|
|
61
|
+
sunset: string;
|
|
62
|
+
}
|
|
63
|
+
export interface WeatherData {
|
|
64
|
+
location: string;
|
|
65
|
+
latitude: number;
|
|
66
|
+
longitude: number;
|
|
67
|
+
timezone: string;
|
|
68
|
+
current: CurrentWeather;
|
|
69
|
+
forecast: DailyForecast[];
|
|
70
|
+
source: string;
|
|
71
|
+
}
|
|
72
|
+
export interface NewsArticle {
|
|
73
|
+
title: string;
|
|
74
|
+
description: string;
|
|
75
|
+
url: string;
|
|
76
|
+
source: string;
|
|
77
|
+
publishedAt: string;
|
|
78
|
+
author?: string;
|
|
79
|
+
imageUrl?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface ExchangeRate {
|
|
82
|
+
base: string;
|
|
83
|
+
target: string;
|
|
84
|
+
rate: number;
|
|
85
|
+
timestamp: string;
|
|
86
|
+
source: string;
|
|
87
|
+
}
|
|
88
|
+
export interface CurrencyConversion {
|
|
89
|
+
from: string;
|
|
90
|
+
to: string;
|
|
91
|
+
amount: number;
|
|
92
|
+
convertedAmount: number;
|
|
93
|
+
rate: number;
|
|
94
|
+
timestamp: string;
|
|
95
|
+
}
|
|
96
|
+
export interface ScrapedPage {
|
|
97
|
+
url: string;
|
|
98
|
+
title: string;
|
|
99
|
+
metaDescription: string;
|
|
100
|
+
headings: {
|
|
101
|
+
level: number;
|
|
102
|
+
text: string;
|
|
103
|
+
}[];
|
|
104
|
+
mainContent: string;
|
|
105
|
+
links: {
|
|
106
|
+
text: string;
|
|
107
|
+
href: string;
|
|
108
|
+
}[];
|
|
109
|
+
selectedContent?: string;
|
|
110
|
+
timestamp: string;
|
|
111
|
+
}
|
|
112
|
+
export interface WikipediaSummary {
|
|
113
|
+
title: string;
|
|
114
|
+
extract: string;
|
|
115
|
+
url: string;
|
|
116
|
+
thumbnail?: string;
|
|
117
|
+
timestamp: string;
|
|
118
|
+
}
|
|
119
|
+
export interface IpGeolocation {
|
|
120
|
+
ip: string;
|
|
121
|
+
country: string;
|
|
122
|
+
countryCode: string;
|
|
123
|
+
region: string;
|
|
124
|
+
city: string;
|
|
125
|
+
latitude: number;
|
|
126
|
+
longitude: number;
|
|
127
|
+
timezone: string;
|
|
128
|
+
isp: string;
|
|
129
|
+
}
|
|
130
|
+
export interface DnsRecord {
|
|
131
|
+
domain: string;
|
|
132
|
+
type: string;
|
|
133
|
+
records: string[];
|
|
134
|
+
ttl?: number;
|
|
135
|
+
}
|
|
136
|
+
export interface UrlInfo {
|
|
137
|
+
originalUrl: string;
|
|
138
|
+
expandedUrl: string;
|
|
139
|
+
statusCode: number;
|
|
140
|
+
contentType?: string;
|
|
141
|
+
}
|
|
142
|
+
export interface CacheEntry<T> {
|
|
143
|
+
data: T;
|
|
144
|
+
expiresAt: number;
|
|
145
|
+
createdAt: number;
|
|
146
|
+
}
|
|
147
|
+
export interface RateLimitConfig {
|
|
148
|
+
maxRequests: number;
|
|
149
|
+
windowMs: number;
|
|
150
|
+
source: string;
|
|
151
|
+
}
|
|
152
|
+
export interface ToolResult {
|
|
153
|
+
[key: string]: unknown;
|
|
154
|
+
content: Array<{
|
|
155
|
+
type: "text";
|
|
156
|
+
text: string;
|
|
157
|
+
}>;
|
|
158
|
+
isError?: boolean;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8EAA8E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory cache with per-key TTL support.
|
|
3
|
+
*
|
|
4
|
+
* TTL defaults (in milliseconds):
|
|
5
|
+
* - Market data: 5 minutes (300_000)
|
|
6
|
+
* - Exchange rates: 30 minutes (1_800_000)
|
|
7
|
+
* - Weather: 1 hour (3_600_000)
|
|
8
|
+
* - News: 15 minutes (900_000)
|
|
9
|
+
* - Web scraping: 10 minutes (600_000)
|
|
10
|
+
* - Public data: 1 hour (3_600_000)
|
|
11
|
+
*/
|
|
12
|
+
export declare const TTL: {
|
|
13
|
+
readonly MARKET: number;
|
|
14
|
+
readonly EXCHANGE: number;
|
|
15
|
+
readonly WEATHER: number;
|
|
16
|
+
readonly NEWS: number;
|
|
17
|
+
readonly SCRAPE: number;
|
|
18
|
+
readonly PUBLIC: number;
|
|
19
|
+
};
|
|
20
|
+
export declare class Cache {
|
|
21
|
+
private store;
|
|
22
|
+
private cleanupInterval;
|
|
23
|
+
constructor(cleanupIntervalMs?: number);
|
|
24
|
+
/** Retrieve a cached value, or undefined if missing / expired. */
|
|
25
|
+
get<T>(key: string): T | undefined;
|
|
26
|
+
/** Store a value with a TTL (milliseconds). */
|
|
27
|
+
set<T>(key: string, data: T, ttlMs: number): void;
|
|
28
|
+
/** Check whether a non-expired entry exists. */
|
|
29
|
+
has(key: string): boolean;
|
|
30
|
+
/** Remove a single key. */
|
|
31
|
+
delete(key: string): void;
|
|
32
|
+
/** Remove all entries. */
|
|
33
|
+
clear(): void;
|
|
34
|
+
/** Number of entries (including possibly-expired ones until next sweep). */
|
|
35
|
+
get size(): number;
|
|
36
|
+
/** Build a deterministic cache key from parts. */
|
|
37
|
+
static key(...parts: (string | number | boolean | undefined | null)[]): string;
|
|
38
|
+
/** Remove all expired entries. */
|
|
39
|
+
private evictExpired;
|
|
40
|
+
/** Tear down the cleanup interval (for graceful shutdown). */
|
|
41
|
+
destroy(): void;
|
|
42
|
+
}
|
|
43
|
+
/** Singleton cache instance shared across the server. */
|
|
44
|
+
export declare const cache: Cache;
|
|
45
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,GAAG;;;;;;;CAON,CAAC;AAEX,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,eAAe,CAAiC;gBAE5C,iBAAiB,SAAS;IAStC,kEAAkE;IAClE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAYlC,+CAA+C;IAC/C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQjD,gDAAgD;IAChD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,2BAA2B;IAC3B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,0BAA0B;IAC1B,KAAK,IAAI,IAAI;IAIb,4EAA4E;IAC5E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,kDAAkD;IAClD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM;IAM9E,kCAAkC;IAClC,OAAO,CAAC,YAAY;IASpB,8DAA8D;IAC9D,OAAO,IAAI,IAAI;CAGhB;AAED,yDAAyD;AACzD,eAAO,MAAM,KAAK,OAAc,CAAC"}
|