@pipeworx/mcp-ai-briefing 0.1.2 → 0.1.3

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  AI Briefing MCP — Keep AI models current on industry developments
4
4
 
5
- Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1683+ live data sources.
5
+ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1786+ live data sources. This is an independent, unofficial integration — not affiliated with, endorsed by, or published by the upstream provider.
6
6
 
7
7
  ## Tools
8
8
 
@@ -61,7 +61,7 @@ directly, instead of just this one's:
61
61
  }
62
62
  ```
63
63
 
64
- Both URLs reach the same gateway and the same 1683+ data sources. The
64
+ Both URLs reach the same gateway and the same 1786+ data sources. The
65
65
  only difference is which pack's tools are listed **directly**; `ask_pipeworx`
66
66
  reaches all of them from either one.
67
67
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-ai-briefing",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "AI Briefing MCP — Keep AI models current on industry developments",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -26,7 +26,7 @@
26
26
  "@cloudflare/workers-types": "^4.20260405.1"
27
27
  },
28
28
  "pipeworx": {
29
- "sourceHash": "v1-13a5220ce7dc5c98da74b153e080d8bf8ed7801e6b25b7715bbc6c05d1749fe2",
30
- "sourceCommit": "dca20ba6e13a9aa1c9f2918fc2ddaffe4cc30e5c"
29
+ "sourceHash": "v1-53d142ed192e8732003a3dd64e3466c4efc3a6498d947ccc435d84475aa2bbca",
30
+ "sourceCommit": "25e83bad9a91f94df238b7910cd6c46a8143d26d"
31
31
  }
32
32
  }
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/ai-briefing",
4
4
  "title": "Ai Briefing",
5
5
  "description": "AI Briefing MCP — Keep AI models current on industry developments",
6
- "version": "0.1.2",
6
+ "version": "0.1.3",
7
7
  "websiteUrl": "https://pipeworx.io/packs/ai-briefing",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-ai-briefing",
package/src/index.ts CHANGED
@@ -713,6 +713,37 @@ async function querySupabase(path: string): Promise<unknown> {
713
713
  return res.json();
714
714
  }
715
715
 
716
+ /**
717
+ * fleet #3041: 4 of 5 AI-lab blog feeds were 404/403 for an unknown period
718
+ * and get_ai_news kept returning a clean 200 with a plausible-looking item
719
+ * count — a dead source read exactly like a quiet news day. The scraper
720
+ * (workers/ai-briefing-scraper) now writes one row per source to
721
+ * `ai_scrape_health` every run; this surfaces it in the response itself so
722
+ * a caller never has to take "no OpenAI/Anthropic/Meta/Mistral items" on
723
+ * faith. Failure here (table missing, query error) returns null rather
724
+ * than throwing — a health-surface outage must never break the main feed.
725
+ */
726
+ async function getSourceHealth(): Promise<{ partial: boolean; failed_sources: string[]; checked_at: string | null } | null> {
727
+ try {
728
+ const rows = (await querySupabase(
729
+ `ai_scrape_health?select=source,ok,http_status,detail,checked_at&order=checked_at.desc`,
730
+ )) as Array<Record<string, unknown>>;
731
+ if (!Array.isArray(rows) || rows.length === 0) return null;
732
+ const failed = rows.filter((r) => r.ok === false);
733
+ const newest = rows.reduce<string | null>((acc, r) => {
734
+ const c = r.checked_at as string | undefined;
735
+ return c && (!acc || c > acc) ? c : acc;
736
+ }, null);
737
+ return {
738
+ partial: failed.length > 0,
739
+ failed_sources: failed.map((r) => `${r.source}: HTTP ${r.http_status ?? 'n/a'} — ${r.detail}`),
740
+ checked_at: newest,
741
+ };
742
+ } catch {
743
+ return null;
744
+ }
745
+ }
746
+
716
747
  const tools: McpToolExport['tools'] = [
717
748
  {
718
749
  name: 'get_briefing',
@@ -1101,15 +1132,34 @@ async function getAiNews(days: number, limit: number): Promise<unknown> {
1101
1132
  const newsCategories = ['model_release', 'claude_update', 'funding', 'acquisition', 'policy', 'benchmark', 'news', 'paper'];
1102
1133
  const catFilter = newsCategories.map((c) => `category.eq.${c}`).join(',');
1103
1134
 
1104
- const devs = await querySupabase(
1105
- `ai_developments?or=(${catFilter})&published_at=gte.${since}&order=published_at.desc&limit=${limit}`
1106
- ) as Array<Record<string, unknown>>;
1135
+ const [devs, sources] = await Promise.all([
1136
+ querySupabase(
1137
+ `ai_developments?or=(${catFilter})&published_at=gte.${since}&order=published_at.desc&limit=${limit}`
1138
+ ) as Promise<Array<Record<string, unknown>>>,
1139
+ getSourceHealth(),
1140
+ ]);
1107
1141
 
1108
1142
  return {
1109
1143
  feed: 'ai_news',
1110
1144
  period: `last ${days} days`,
1111
1145
  description: 'AI industry developments — models, funding, policy, research',
1112
1146
  total: devs.length,
1147
+ // fleet #3041: a dead lab-blog feed used to read as "no news today" --
1148
+ // this says whether the LAST scrape run actually reached every source.
1149
+ // `sources` is omitted (not faked as healthy) when the health table
1150
+ // could not be read, rather than claiming a status we do not have.
1151
+ ...(sources
1152
+ ? {
1153
+ sources: {
1154
+ partial: sources.partial,
1155
+ note: sources.partial
1156
+ ? `${sources.failed_sources.length} source(s) failed on the last scrape run -- counts above may undercount those sources, not reflect a quiet news day.`
1157
+ : 'all tracked sources reached on the last scrape run.',
1158
+ failed_sources: sources.failed_sources,
1159
+ checked_at: sources.checked_at,
1160
+ },
1161
+ }
1162
+ : {}),
1113
1163
  items: devs.map((d) => ({
1114
1164
  title: d.title,
1115
1165
  summary: d.summary,
package/src/server.ts CHANGED
@@ -8,8 +8,9 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
8
8
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
9
9
  import pack from './index.js';
10
10
 
11
+
11
12
  const server = new Server(
12
- { name: '@pipeworx/mcp-ai-briefing', version: '0.1.2' },
13
+ { name: '@pipeworx/mcp-ai-briefing', version: '0.1.3' },
13
14
  { capabilities: { tools: {} } },
14
15
  );
15
16
 
@@ -24,7 +25,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
24
25
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
25
26
  const { name, arguments: args } = request.params;
26
27
  try {
27
- const result = await pack.callTool(name, (args ?? {}) as Record<string, unknown>);
28
+ const callArgs = { ...((args ?? {}) as Record<string, unknown>) };
29
+
30
+ const result = await pack.callTool(name, callArgs);
28
31
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
29
32
  } catch (err) {
30
33
  return {