@pipeworx/mcp-ecb 0.1.4 → 0.1.6

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
  European Central Bank Data Portal MCP — exchange rates, interest rates, monetary aggregates, HICP, bank lending. No auth.
4
4
 
5
- Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1855+ live data sources. This is an independent, unofficial integration — not affiliated with, endorsed by, or published by the upstream provider.
5
+ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1881+ 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
 
@@ -71,7 +71,7 @@ directly, instead of just this one's:
71
71
  }
72
72
  ```
73
73
 
74
- Both URLs reach the same gateway and the same 1855+ data sources. The
74
+ Both URLs reach the same gateway and the same 1881+ data sources. The
75
75
  only difference is which pack's tools are listed **directly**; `ask_pipeworx`
76
76
  reaches all of them from either one.
77
77
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-ecb",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "ECB Data Portal MCP — European Central Bank statistical data",
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-ab883f34ae882027b585171d95c9b8c5f3467180a89e01691b2894af4f901431",
30
- "sourceCommit": "5749f83c0ea115fab4c0c0ef04b66b05f2507d67"
29
+ "sourceHash": "v1-0c919aa84baead00fcec6845dd177b1997a602cf9d00824ea0d26f48a1c787b2",
30
+ "sourceCommit": "24e32b525f9c0b2fd7d94b519b08abb108cc11cd"
31
31
  }
32
32
  }
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/ecb",
4
4
  "title": "Ecb",
5
5
  "description": "ECB Data Portal MCP — European Central Bank statistical data",
6
- "version": "0.1.4",
6
+ "version": "0.1.6",
7
7
  "websiteUrl": "https://pipeworx.io/packs/ecb",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-ecb",
package/src/index.ts CHANGED
@@ -295,12 +295,28 @@ async function httpErrorMessage(res: Response, name: string): Promise<string> {
295
295
  // internal-host-class.ts; no-op for every third-party upstream, which is why
296
296
  // this touches 481 packs' error text and changes none of it.
297
297
  return markInternalOrigin(
298
- `${name}: ${res.status}${detailSuffix(await readDetail(res))}`,
298
+ `${name}: ${res.status}${detailSuffix(await readDetail(res))}${responseHints(res)}`,
299
299
  res.url,
300
300
  res.status,
301
301
  );
302
302
  }
303
303
 
304
+ /**
305
+ * Facts about a FAILED response that live in its headers, not its body, appended
306
+ * so the gateway's classifier (which only ever sees this string) can tell a limit
307
+ * from a wall from a refusal (fleet #3477). Both are standard, both are absent on
308
+ * almost every response, and neither is invented: `Retry-After` is the server
309
+ * saying "come back later" (the one thing that makes a 403 a throttle), and
310
+ * Cloudflare marks a bot challenge with `cf-mitigated: challenge`.
311
+ */
312
+ function responseHints(res: Response): string {
313
+ const hints: string[] = [];
314
+ const retryAfter = res.headers.get('retry-after');
315
+ if (retryAfter) hints.push(`retry-after: ${retryAfter.slice(0, 40)}`);
316
+ if ((res.headers.get('cf-mitigated') ?? '').toLowerCase() === 'challenge') hints.push('Cloudflare bot challenge (cf-mitigated: challenge)');
317
+ return hints.length ? ` (${hints.join('; ')})` : '';
318
+ }
319
+
304
320
  /**
305
321
  * Just the upstream's own explanation — no name, no status.
306
322
  *
@@ -1161,8 +1177,30 @@ async function hicpInflation(args: Record<string, unknown>) {
1161
1177
  });
1162
1178
  }
1163
1179
 
1180
+ /**
1181
+ * An ECB Data Portal series key is written FLOW.dim.dim..., e.g.
1182
+ * MIR.M.IT.B.A2C.A.R.A.2250.EUR.P, so callers hand the whole string over as
1183
+ * flow_ref, or repeat the flow id at the head of key (fleet #3669). The ECB has
1184
+ * no series whose first dimension equals its own flow id (the first dimension
1185
+ * is FREQ), so stripping that prefix cannot change the meaning of a well-formed
1186
+ * call; it only turns a guaranteed 404 into the series the caller named.
1187
+ */
1188
+ function splitFlowPrefixedKey(flow: string, key: string): { flow: string; key: string } {
1189
+ const flowDot = flow.indexOf('.');
1190
+ if (flowDot > 0) {
1191
+ // flow_ref carries the whole key ("MIR.M.IT...."). An explicit key that is
1192
+ // not the same remainder wins nothing - the dotted flow_ref is the series.
1193
+ return { flow: flow.slice(0, flowDot), key: flow.slice(flowDot + 1) };
1194
+ }
1195
+ if (key.startsWith(flow + '.')) return { flow, key: key.slice(flow.length + 1) };
1196
+ return { flow, key };
1197
+ }
1198
+
1164
1199
  async function getData(args: Record<string, unknown>) {
1165
- return fetchData(reqStr(args, 'flow_ref', '"EXR"'), reqStr(args, 'key', '"D.USD.EUR.SP00.A"'), {
1200
+ const flowArg = reqStr(args, 'flow_ref', '"EXR"').trim();
1201
+ const keyArg = flowArg.includes('.') && args.key == null ? '' : reqStr(args, 'key', '"D.USD.EUR.SP00.A"').trim();
1202
+ const split = splitFlowPrefixedKey(flowArg, keyArg);
1203
+ return fetchData(split.flow, split.key, {
1166
1204
  start_period: args.start_period as string | undefined,
1167
1205
  end_period: args.end_period as string | undefined,
1168
1206
  last_n: args.last_n as number | undefined,
package/src/server.ts CHANGED
@@ -10,7 +10,7 @@ import pack from './index.js';
10
10
 
11
11
 
12
12
  const server = new Server(
13
- { name: '@pipeworx/mcp-ecb', version: '0.1.4' },
13
+ { name: '@pipeworx/mcp-ecb', version: '0.1.6' },
14
14
  { capabilities: { tools: {} } },
15
15
  );
16
16