@tensorfeed/mcp-server 1.25.1 → 1.27.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/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to the [TensorFeed.ai MCP server](https://github.com/RipperMercs/tensorfeed-mcp). Free tools work without configuration; premium tools require a bearer token via the `TENSORFEED_TOKEN` env var. Buy credits at [tensorfeed.ai/developers/agent-payments](https://tensorfeed.ai/developers/agent-payments).
4
4
 
5
+ ## 1.27.0 - 2026-05-09
6
+
7
+ ### Added
8
+ - `get_recent_earthquakes` (free): wraps `/api/climate/earthquakes`. USGS Earthquake Hazards Program pre-built summary feeds. Magnitude bucket (significant | 4.5 | 2.5 | 1.0 | all) crossed with period (hour | day | week | month). Returns id, magnitude, place, time, depth, lat/lon, tsunami flag, USGS detail URL. License: US Government public domain (17 USC §105).
9
+ - `get_weather_alerts` (free, US-only): wraps `/api/climate/weather-alerts`. NWS Active Weather Alerts. Filter by 2-letter state, exact NWS event name, severity, urgency, status. Returns flattened alerts list with effective/expires windows and the canonical NWS web URL. License: US Government public domain.
10
+ - `get_agent_opportunities` (free): wraps `/api/agents/opportunities`. Daily 13:30 UTC scan of new repositories across the AI agent ecosystem (Anthropic / OpenAI / Microsoft / ModelContextProtocol / HuggingFace / LangChain / frontier-lab orgs plus MCP, x402, agent-skills keyword sweeps and a vertical-pattern catch). Eleven signals deduped + composite-scored with per-signal MIN/MAX caps so smaller signals are never starved. Optional `signal` filter to one source.
11
+
12
+ Tool count: 42 -> 45. Brings the stdio package up to parity with the new public-domain feeds and the daily agent-ecosystem scan that landed on the hosted HTTP transport this same day.
13
+
14
+ ## 1.26.0 - 2026-05-09
15
+
16
+ ### Added
17
+ - `remotes` array on `server.json` advertising the hosted Streamable HTTP MCP variant at `https://tensorfeed.ai/api/mcp`. The official MCP Registry can now route MCP-aware clients (Claude Code, Cursor, Codex, anything spec-compliant) to the hosted server directly, with no install step. The existing `packages` array (npm stdio at `@tensorfeed/mcp-server`) coexists, so clients can still pick the local-stdio path. After publish via `mcp-publisher`, the `ai.tensorfeed/mcp-server` registry entry will surface both transports for the same server.
18
+
5
19
  ## 1.25.1 - 2026-05-07
6
20
 
7
21
  ### Fixed
package/dist/index.js CHANGED
@@ -1180,6 +1180,105 @@ registerTool('get_hf_daily_papers', 'Hugging Face Daily Papers: editor-curated A
1180
1180
  return { content: [{ type: 'text', text }] };
1181
1181
  });
1182
1182
  // ── Tool: get_ai_ecosystem_today (free, composite) ──────────────────
1183
+ // ── Tool: get_recent_earthquakes (free) ─────────────────────────────
1184
+ registerTool('get_recent_earthquakes', "Recent earthquakes from the USGS Earthquake Hazards Program pre-built summary feeds. Choose a magnitude bucket (significant | 4.5 | 2.5 | 1.0 | all) and a time window (hour | day | week | month). Returns id, magnitude, place, time (ISO 8601), depth_km, longitude, latitude, tsunami flag, USGS detail URL. Upstream feeds refresh every minute. License: US Government public domain (17 USC §105). Free, no auth.", {
1185
+ magnitude: z.enum(['significant', '4.5', '2.5', '1.0', 'all']).optional().describe('Magnitude bucket (default 4.5)'),
1186
+ period: z.enum(['hour', 'day', 'week', 'month']).optional().describe('Time window (default day)'),
1187
+ limit: z.number().min(1).max(50).optional().describe('Max earthquakes to render (default 15, max 50). Worker accepts up to 500 but text rendering caps lower.'),
1188
+ }, async ({ magnitude, period, limit }) => {
1189
+ const params = new URLSearchParams();
1190
+ params.set('magnitude', magnitude ?? '4.5');
1191
+ params.set('period', period ?? 'day');
1192
+ params.set('limit', String(Math.min(limit ?? 15, 50)));
1193
+ const data = (await fetchJSON(`/climate/earthquakes?${params}`));
1194
+ if (!data.ok || !data.earthquakes) {
1195
+ return { content: [{ type: 'text', text: `USGS earthquakes unavailable: ${data.error ?? 'unknown error'}` }] };
1196
+ }
1197
+ const eqs = data.earthquakes;
1198
+ const lines = eqs.map((q, i) => {
1199
+ const mag = q.magnitude !== null ? `M${q.magnitude.toFixed(1)}` : 'M?';
1200
+ const tsu = q.tsunami ? ' [tsunami flag]' : '';
1201
+ const time = q.time ? q.time.slice(0, 19).replace('T', ' ') + ' UTC' : 'unknown time';
1202
+ const depth = q.depth_km !== null ? `${q.depth_km.toFixed(0)}km deep` : 'depth unknown';
1203
+ const coords = q.latitude !== null && q.longitude !== null ? ` (${q.latitude.toFixed(2)}, ${q.longitude.toFixed(2)})` : '';
1204
+ return `${i + 1}. ${mag} ${q.place ?? 'location unknown'}${coords}\n ${time}, ${depth}${tsu}\n ${q.url ?? ''}`;
1205
+ }).join('\n\n');
1206
+ const meta = data.feed_metadata;
1207
+ const header = `USGS earthquakes (${data.query?.magnitude ?? '?'} / ${data.query?.period ?? '?'}). ${eqs.length} of ${meta?.upstream_count ?? '?'} returned.`;
1208
+ return { content: [{ type: 'text', text: `${header}\n\n${lines || ' (no events in this window)'}\n\nSource: USGS Earthquake Hazards Program. Public domain (17 USC §105).` }] };
1209
+ });
1210
+ // ── Tool: get_weather_alerts (free, US only) ────────────────────────
1211
+ registerTool('get_weather_alerts', "Active US weather alerts from the National Weather Service. US-only. Filter by 2-letter state code (area), exact NWS event name, severity, urgency, status. Returns id, event, severity, urgency, headline, description, areaDesc, sent/effective/expires/ends, sender_name, web URL. Active alerts only — expired alerts fall off the upstream feed automatically. License: US Government public domain. Free, no auth.", {
1212
+ area: z.string().regex(/^[A-Za-z]{2}$/).optional().describe('2-letter US state or territory code (CA, TX, PR, etc)'),
1213
+ event: z.string().optional().describe('Exact NWS event name (e.g. "Tornado Warning", "Heat Advisory")'),
1214
+ severity: z.enum(['Extreme', 'Severe', 'Moderate', 'Minor', 'Unknown']).optional().describe('Severity filter'),
1215
+ urgency: z.enum(['Immediate', 'Expected', 'Future', 'Past', 'Unknown']).optional().describe('Urgency filter'),
1216
+ status: z.enum(['actual', 'exercise', 'system', 'test', 'draft']).optional().describe('Status filter (default actual unfiltered)'),
1217
+ limit: z.number().min(1).max(50).optional().describe('Max alerts to render (default 15, max 50). Worker accepts up to 500 but text rendering caps lower.'),
1218
+ }, async ({ area, event, severity, urgency, status, limit }) => {
1219
+ const params = new URLSearchParams();
1220
+ if (area)
1221
+ params.set('area', area.toUpperCase());
1222
+ if (event)
1223
+ params.set('event', event);
1224
+ if (severity)
1225
+ params.set('severity', severity);
1226
+ if (urgency)
1227
+ params.set('urgency', urgency);
1228
+ if (status)
1229
+ params.set('status', status);
1230
+ params.set('limit', String(Math.min(limit ?? 15, 50)));
1231
+ const data = (await fetchJSON(`/climate/weather-alerts?${params}`));
1232
+ if (!data.ok || !data.alerts) {
1233
+ return { content: [{ type: 'text', text: `NWS weather alerts unavailable: ${data.error ?? 'unknown error'}` }] };
1234
+ }
1235
+ const alerts = data.alerts;
1236
+ const lines = alerts.map((a, i) => {
1237
+ const ev = a.event ?? 'unknown event';
1238
+ const sev = a.severity ? `[${a.severity}]` : '';
1239
+ const eff = a.effective ? a.effective.slice(0, 19).replace('T', ' ') + ' UTC' : '';
1240
+ const exp = a.expires ? a.expires.slice(0, 19).replace('T', ' ') + ' UTC' : 'no expiry';
1241
+ return `${i + 1}. ${sev} ${ev}\n Where: ${a.area_desc ?? 'unspecified'}\n ${a.headline ?? ''}\n Effective: ${eff} → ${exp}\n ${a.web ?? ''}`;
1242
+ }).join('\n\n');
1243
+ const filters = [];
1244
+ if (area)
1245
+ filters.push(`area=${area.toUpperCase()}`);
1246
+ if (event)
1247
+ filters.push(`event=${event}`);
1248
+ if (severity)
1249
+ filters.push(`severity=${severity}`);
1250
+ const filterText = filters.length > 0 ? ` (${filters.join(', ')})` : '';
1251
+ const header = `NWS active US weather alerts${filterText}. ${alerts.length} of ${data.feed_metadata?.upstream_count ?? '?'} returned.`;
1252
+ return { content: [{ type: 'text', text: `${header}\n\n${lines || ' (no active alerts matching filters)'}\n\nSource: api.weather.gov. Public domain (17 USC §105). US-only coverage.` }] };
1253
+ });
1254
+ // ── Tool: get_agent_opportunities (free) ────────────────────────────
1255
+ registerTool('get_agent_opportunities', "TensorFeed's daily scan of new repositories across the AI agent ecosystem (Anthropic, OpenAI, Microsoft, ModelContextProtocol, HuggingFace, LangChain, frontier-lab orgs) plus recent MCP, x402, and skill keyword sweeps. Eleven signals total, deduped + composite-scored (signal_weight × log10(stars+1) × recency decay) with per-signal MIN/MAX caps so smaller signals are never starved. Refreshed daily at 13:30 UTC. Useful for surfacing distribution targets, integration ideas, or a daily brief on what's launching across the agent space. Free, no auth.", {
1256
+ signal: z.enum([
1257
+ 'anthropic-org', 'openai-org', 'microsoft-org', 'mcp-org', 'huggingface-org',
1258
+ 'langchain-org', 'frontier-labs', 'mcp-keyword', 'x402-keyword', 'skill-keyword',
1259
+ 'vertical-pattern',
1260
+ ]).optional().describe('Filter to one signal source. Omit to get the cross-signal ranked top-N.'),
1261
+ limit: z.number().min(1).max(25).optional().describe('Max opportunities to render (default 10, max 25)'),
1262
+ }, async ({ signal, limit }) => {
1263
+ const data = (await fetchJSON('/agents/opportunities'));
1264
+ if (data.error) {
1265
+ return { content: [{ type: 'text', text: `Agent opportunities unavailable: ${data.error}` }] };
1266
+ }
1267
+ const all = data.opportunities ?? [];
1268
+ const filtered = signal ? all.filter(o => o.signal === signal) : all;
1269
+ const cap = Math.min(limit ?? 10, 25);
1270
+ const top = filtered.slice(0, cap);
1271
+ const lines = top.map((o, i) => {
1272
+ const updated = o.updated_at ? o.updated_at.slice(0, 10) : '';
1273
+ const desc = o.description ? `\n ${o.description.length > 140 ? o.description.slice(0, 140) + '...' : o.description}` : '';
1274
+ return `${i + 1}. [${o.signal}] ${o.full_name} ${o.stars.toLocaleString()}★, score ${o.composite_score.toFixed(1)}, updated ${updated}${desc}\n ${o.html_url}`;
1275
+ }).join('\n\n');
1276
+ const filt = signal ? ` filtered to ${signal}` : '';
1277
+ const header = `Agent ecosystem opportunities for ${data.date ?? 'today'}${filt}. ${top.length} of ${filtered.length} (total snapshot: ${data.total_opportunities ?? all.length}).`;
1278
+ const bySignal = data.summary?.by_signal ? Object.entries(data.summary.by_signal).map(([k, v]) => `${k}=${v}`).join(', ') : '';
1279
+ const sig = bySignal ? `\nBy signal: ${bySignal}` : '';
1280
+ return { content: [{ type: 'text', text: `${header}${sig}\n\n${lines || ' (no opportunities returned)'}\n\nSource: TensorFeed daily GitHub scan via the public Search API.` }] };
1281
+ });
1183
1282
  // Single fetch to /api/today which fans out worker-side. The previous
1184
1283
  // implementation made 9 separate fetches per agent invocation; now
1185
1284
  // the worker's edge cache absorbs the load and serves one cached
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tensorfeed/mcp-server",
3
- "version": "1.25.1",
3
+ "version": "1.27.0",
4
4
  "mcpName": "ai.tensorfeed/mcp-server",
5
5
  "description": "MCP server for TensorFeed.ai - AI news, status, model data, and premium endpoints (routing, cost projection, forecast, history series, news search, webhook watches with digest tier, enriched directory) for AI agents",
6
6
  "main": "dist/index.js",
package/server.json CHANGED
@@ -3,18 +3,24 @@
3
3
  "name": "ai.tensorfeed/mcp-server",
4
4
  "title": "TensorFeed",
5
5
  "description": "AI news, model pricing, service status, and machine-payable premium tools. AFTA-certified.",
6
- "version": "1.25.1",
6
+ "version": "1.27.0",
7
7
  "websiteUrl": "https://tensorfeed.ai/developers/agent-payments",
8
8
  "repository": {
9
9
  "url": "https://github.com/RipperMercs/tensorfeed-mcp",
10
10
  "source": "github"
11
11
  },
12
+ "remotes": [
13
+ {
14
+ "type": "streamable-http",
15
+ "url": "https://tensorfeed.ai/api/mcp"
16
+ }
17
+ ],
12
18
  "packages": [
13
19
  {
14
20
  "registryType": "npm",
15
21
  "registryBaseUrl": "https://registry.npmjs.org",
16
22
  "identifier": "@tensorfeed/mcp-server",
17
- "version": "1.25.1",
23
+ "version": "1.27.0",
18
24
  "runtimeHint": "npx",
19
25
  "transport": {
20
26
  "type": "stdio"
@@ -53,6 +59,9 @@
53
59
  "get_openrouter_models",
54
60
  "get_hf_daily_papers",
55
61
  "get_ai_ecosystem_today",
62
+ "get_recent_earthquakes",
63
+ "get_weather_alerts",
64
+ "get_agent_opportunities",
56
65
  "pricing_series_free",
57
66
  "benchmark_series_free",
58
67
  "status_uptime_free",