@tensorfeed/mcp-server 1.20.0 → 1.22.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,17 @@
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.22.0 - 2026-05-04
6
+
7
+ ### Added
8
+ - Cross-provider uptime leaderboard tools: `status_leaderboard_free` (free, 7-day cap) and `status_leaderboard` (premium, 1 credit, up to 90 days). Returns providers ranked by uptime % DESC computed from minute-resolution counters (~720 samples per provider per day at the 2-min poll cadence). Premium adds `incident_count` and `mttr_minutes` (mean time to recover) per provider. Aimed at SRE/ops/procurement teams comparing AI vendor reliability for vendor selection or post-incident reviews.
9
+ - 4 new monitored providers behind every status tool: Google Gemini (via Google Cloud incidents), GitHub Copilot, Perplexity (via Instatus), and Groq. Brings total monitored to 10 major LLM providers.
10
+
11
+ ## 1.21.0 - 2026-05-04
12
+
13
+ ### Added
14
+ - Three free history-series tools: `pricing_series_free`, `benchmark_series_free`, `status_uptime_free`. Each returns up to 7 days of daily snapshots (price/score/uptime) for one model or provider. Max range capped at 7 days; for the full 90-day window keep using the paid `pricing_series`, `benchmark_series`, `status_uptime` tools (1 credit each). Reason for the split: agents discovering the data need a free way to see "yes, TensorFeed actually has historical pricing for this model" before deciding to spend a credit. The 7-day teaser shows the trend without giving away the long tail.
15
+
5
16
  ## 1.20.0 - 2026-05-04
6
17
 
7
18
  ### Changed
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
4
4
  import { z } from 'zod';
5
5
  import { sanitizeToolResponse } from './sanitize.js';
6
6
  const API_BASE = 'https://tensorfeed.ai/api';
7
- const SDK_VERSION = '1.9.0';
7
+ const SDK_VERSION = '1.10.0';
8
8
  async function fetchJSON(path, opts = {}) {
9
9
  const headers = {
10
10
  'User-Agent': `TensorFeed-MCP/${SDK_VERSION}`,
@@ -235,6 +235,95 @@ registerTool('premium_routing', 'Get a ranked list of recommended AI models for
235
235
  : '';
236
236
  return { content: [{ type: 'text', text: `Routing for "${data.task}":\n\n${list}${billing}` }] };
237
237
  });
238
+ // ── Tool: pricing_series_free (free, 7-day cap) ─────────────────────
239
+ registerTool('pricing_series_free', 'Daily price points for one AI model over the last 1 to 7 days, free. For windows up to 90 days use pricing_series (1 credit).', {
240
+ model: z.string().describe('Model id or display name (e.g. "Claude Opus 4.7" or "claude-opus-4-7")'),
241
+ days: z.number().min(1).max(7).optional().describe('Rolling window length 1 to 7 days (default 7)'),
242
+ }, async ({ model, days }) => {
243
+ const params = new URLSearchParams({ model });
244
+ if (typeof days === 'number')
245
+ params.set('days', String(days));
246
+ const data = (await fetchJSON(`/history/pricing/series?${params}`));
247
+ const s = data.summary;
248
+ const summary = s.first && s.latest
249
+ ? `${s.first.date} blended $${s.first.blended} -> ${s.latest.date} blended $${s.latest.blended} (${s.delta_pct_blended}%, min $${s.min_blended}, max $${s.max_blended})`
250
+ : 'no data points in range';
251
+ return {
252
+ content: [
253
+ {
254
+ type: 'text',
255
+ text: `${data.model} (${data.provider ?? 'unknown'}) ${data.points.length} points over ${data.points.length} days\n${summary}\nFor up to 90 days, use the pricing_series tool (1 credit).`,
256
+ },
257
+ ],
258
+ };
259
+ });
260
+ // ── Tool: benchmark_series_free (free, 7-day cap) ───────────────────
261
+ registerTool('benchmark_series_free', 'Daily benchmark scores for one model+benchmark over the last 1 to 7 days, free. Benchmark keys: swe_bench, mmlu_pro, gpqa_diamond, math, human_eval. For windows up to 90 days use benchmark_series (1 credit).', {
262
+ model: z.string().describe('Model id or display name'),
263
+ benchmark: z.string().describe('Benchmark key'),
264
+ days: z.number().min(1).max(7).optional().describe('Rolling window length 1 to 7 days (default 7)'),
265
+ }, async ({ model, benchmark, days }) => {
266
+ const params = new URLSearchParams({ model, benchmark });
267
+ if (typeof days === 'number')
268
+ params.set('days', String(days));
269
+ const data = (await fetchJSON(`/history/benchmarks/series?${params}`));
270
+ const s = data.summary;
271
+ const summary = s.first && s.latest
272
+ ? `${s.first.date} score ${s.first.score} -> ${s.latest.date} score ${s.latest.score} (delta ${s.delta_pp} pp)`
273
+ : 'no data in range';
274
+ return {
275
+ content: [
276
+ {
277
+ type: 'text',
278
+ text: `${data.model} on ${data.benchmark}: ${data.points.length} points\n${summary}`,
279
+ },
280
+ ],
281
+ };
282
+ });
283
+ // ── Tool: status_uptime_free (free, 7-day cap) ──────────────────────
284
+ registerTool('status_uptime_free', 'Daily uptime rollup for one provider over the last 1 to 7 days, free. For windows up to 90 days use status_uptime (1 credit).', {
285
+ provider: z.string().describe('Provider name (e.g. anthropic, openai, google)'),
286
+ days: z.number().min(1).max(7).optional().describe('Rolling window length 1 to 7 days (default 7)'),
287
+ }, async ({ provider, days }) => {
288
+ const params = new URLSearchParams({ provider });
289
+ if (typeof days === 'number')
290
+ params.set('days', String(days));
291
+ const data = (await fetchJSON(`/history/status/uptime?${params}`));
292
+ return {
293
+ content: [
294
+ {
295
+ type: 'text',
296
+ text: `${data.provider} over ${data.days_total} days: ${data.uptime_pct ?? '?'}% uptime (${data.days_operational} operational, ${data.days_degraded} degraded, ${data.days_down} down)`,
297
+ },
298
+ ],
299
+ };
300
+ });
301
+ // ── Tool: status_leaderboard_free (free, 7-day cap) ─────────────────
302
+ registerTool('status_leaderboard_free', 'Cross-provider uptime leaderboard, ranked by uptime % DESC. Free, 7-day cap. Computed from minute-resolution counters (~720 samples per provider per day). For 90-day windows plus incident_count and mttr_minutes per provider use status_leaderboard (1 credit).', {
303
+ days: z.number().min(1).max(7).optional().describe('Rolling window length 1 to 7 days (default 7)'),
304
+ }, async ({ days }) => {
305
+ const params = new URLSearchParams();
306
+ if (typeof days === 'number')
307
+ params.set('days', String(days));
308
+ const qs = params.toString();
309
+ const data = (await fetchJSON(`/status/leaderboard${qs ? `?${qs}` : ''}`));
310
+ if (!data.ok) {
311
+ return {
312
+ content: [{ type: 'text', text: `Leaderboard unavailable: ${data.error ?? 'unknown'} - ${data.message ?? ''}` }],
313
+ };
314
+ }
315
+ const lines = (data.entries ?? [])
316
+ .slice(0, 10)
317
+ .map((e) => `#${e.rank} ${e.provider}: ${e.uptime_pct}% (${e.downtime_minutes}m downtime, ${e.hard_down_minutes}m hard-down)`);
318
+ return {
319
+ content: [
320
+ {
321
+ type: 'text',
322
+ text: `AI provider uptime leaderboard ${data.range?.from} to ${data.range?.to}\n${lines.join('\n')}`,
323
+ },
324
+ ],
325
+ };
326
+ });
238
327
  // ── Tool: pricing_series (1 credit) ─────────────────────────────────
239
328
  registerTool('pricing_series', 'Daily price points for one AI model with min/max/delta summary. Default range = last 30 days, max 90 days. Costs 1 credit.', {
240
329
  model: z.string().describe('Model id or display name (e.g. "Claude Opus 4.7" or "claude-opus-4-7")'),
@@ -313,6 +402,32 @@ registerTool('status_uptime', 'Daily uptime rollup for one provider with operati
313
402
  ],
314
403
  };
315
404
  });
405
+ // ── Tool: status_leaderboard (1 credit) ─────────────────────────────
406
+ registerTool('status_leaderboard', 'Cross-provider uptime leaderboard for a custom date range up to 90 days. Same minute-resolution counter source as status_leaderboard_free, but adds incident_count and mttr_minutes (mean time to recover) per provider. Sorted by uptime % DESC. Costs 1 credit.', {
407
+ from: z.string().optional().describe('Start date YYYY-MM-DD UTC (default: 30 days ago)'),
408
+ to: z.string().optional().describe('End date YYYY-MM-DD UTC (default: today)'),
409
+ }, async ({ from, to }) => {
410
+ const params = new URLSearchParams();
411
+ if (from)
412
+ params.set('from', from);
413
+ if (to)
414
+ params.set('to', to);
415
+ const data = (await fetchJSON(`/premium/status/leaderboard?${params}`, { auth: true }));
416
+ if (!data.ok) {
417
+ return {
418
+ content: [{ type: 'text', text: `Leaderboard unavailable: ${data.error ?? 'unknown'} - ${data.message ?? ''}` }],
419
+ };
420
+ }
421
+ const lines = (data.entries ?? []).map((e) => `#${e.rank} ${e.provider}: ${e.uptime_pct}% uptime, ${e.downtime_minutes}m downtime (${e.hard_down_minutes}m hard-down), ${e.incident_count ?? 0} incidents, MTTR ${e.mttr_minutes ?? 'n/a'}m`);
422
+ return {
423
+ content: [
424
+ {
425
+ type: 'text',
426
+ text: `AI provider uptime leaderboard ${data.range?.from} to ${data.range?.to}\n${lines.join('\n')}\n\nCredits remaining: ${data.billing?.credits_remaining ?? '?'}`,
427
+ },
428
+ ],
429
+ };
430
+ });
316
431
  // ── Tool: premium_agents_directory (1 credit) ───────────────────────
317
432
  registerTool('premium_agents_directory', 'Enriched AI agents catalog joined with live status, recent news, agent traffic, flagship pricing, and a 0-100 trending_score. Costs 1 credit.', {
318
433
  category: z.string().optional().describe('coding, research, general, creative, frameworks'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tensorfeed/mcp-server",
3
- "version": "1.20.0",
3
+ "version": "1.22.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,7 +3,7 @@
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.20.0",
6
+ "version": "1.22.0",
7
7
  "websiteUrl": "https://tensorfeed.ai/developers/agent-payments",
8
8
  "repository": {
9
9
  "url": "https://github.com/RipperMercs/tensorfeed-mcp",
@@ -14,7 +14,7 @@
14
14
  "registryType": "npm",
15
15
  "registryBaseUrl": "https://registry.npmjs.org",
16
16
  "identifier": "@tensorfeed/mcp-server",
17
- "version": "1.20.0",
17
+ "version": "1.22.0",
18
18
  "runtimeHint": "npx",
19
19
  "transport": {
20
20
  "type": "stdio"
@@ -52,13 +52,18 @@
52
52
  "get_reddit_trending",
53
53
  "get_openrouter_models",
54
54
  "get_hf_daily_papers",
55
- "get_ai_ecosystem_today"
55
+ "get_ai_ecosystem_today",
56
+ "pricing_series_free",
57
+ "benchmark_series_free",
58
+ "status_uptime_free",
59
+ "status_leaderboard_free"
56
60
  ],
57
61
  "premiumTools": [
58
62
  "premium_routing",
59
63
  "pricing_series",
60
64
  "benchmark_series",
61
65
  "status_uptime",
66
+ "status_leaderboard",
62
67
  "premium_agents_directory",
63
68
  "news_search",
64
69
  "cost_projection",