@pipeworx/mcp-emarket-storage 0.1.5 → 0.1.7
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 +2 -2
- package/package.json +3 -3
- package/server.json +1 -1
- package/src/index.ts +52 -7
- package/src/server.ts +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Italian regulated company disclosures direct from eMarket Storage (Teleborsa)
|
|
|
5
5
|
built to fix the months-long lag in the community ESEF index for current-year
|
|
6
6
|
Italian filings.
|
|
7
7
|
|
|
8
|
-
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to
|
|
8
|
+
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1879+ live data sources. This is an independent, unofficial integration — not affiliated with, endorsed by, or published by the upstream provider.
|
|
9
9
|
|
|
10
10
|
## Tools
|
|
11
11
|
|
|
@@ -200,7 +200,7 @@ directly, instead of just this one's:
|
|
|
200
200
|
}
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
Both URLs reach the same gateway and the same
|
|
203
|
+
Both URLs reach the same gateway and the same 1879+ data sources. The
|
|
204
204
|
only difference is which pack's tools are listed **directly**; `ask_pipeworx`
|
|
205
205
|
reaches all of them from either one.
|
|
206
206
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipeworx/mcp-emarket-storage",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Italian regulated disclosures direct from eMarket Storage (Teleborsa) — keyless, same-day-fresh.",
|
|
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-
|
|
30
|
-
"sourceCommit": "
|
|
29
|
+
"sourceHash": "v1-c488d3b103d079ab0c22c02afc29c1e6a843505c54b1ce4232ad37d6df4fbdb4",
|
|
30
|
+
"sourceCommit": "445bacc5596a845c12d6945fbfcdf330ef60dcc4"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.pipeworx-io/emarket-storage",
|
|
4
4
|
"title": "Emarket Storage",
|
|
5
5
|
"description": "Italian regulated disclosures direct from eMarket Storage (Teleborsa) — keyless, same-day-fresh.",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.7",
|
|
7
7
|
"websiteUrl": "https://pipeworx.io/packs/emarket-storage",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/pipeworx-io/mcp-emarket-storage",
|
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
|
*
|
|
@@ -997,6 +1013,13 @@ interface SecEntity {
|
|
|
997
1013
|
* `matched_by: 'company_name'` alone cannot (fleet #3100).
|
|
998
1014
|
*/
|
|
999
1015
|
matched_kind?: MatchKind;
|
|
1016
|
+
/**
|
|
1017
|
+
* Other companies whose names also matched — distinct companies, deduped
|
|
1018
|
+
* by CIK, excluding this issuer's own share classes (never the winner's
|
|
1019
|
+
* own ticker/CIK under a different symbol). Consumers read this to tell a
|
|
1020
|
+
* genuinely CONTESTED name match from a clean one. See
|
|
1021
|
+
* `distinctCompanyAlternatives` below for how it's built (fleet #3621).
|
|
1022
|
+
*/
|
|
1000
1023
|
alternatives?: { ticker: string; company_name: string; cik: string; kind: MatchKind }[];
|
|
1001
1024
|
}
|
|
1002
1025
|
|
|
@@ -1034,12 +1057,7 @@ async function resolveSecEntity(
|
|
|
1034
1057
|
if (ranked.length) {
|
|
1035
1058
|
const best = toEntity(ranked[0].item, 'company_name');
|
|
1036
1059
|
best.matched_kind = ranked[0].kind;
|
|
1037
|
-
const alts = ranked
|
|
1038
|
-
ticker: m.item.ticker,
|
|
1039
|
-
company_name: m.item.title,
|
|
1040
|
-
cik: String(m.item.cik_str),
|
|
1041
|
-
kind: m.kind,
|
|
1042
|
-
}));
|
|
1060
|
+
const alts = distinctCompanyAlternatives(ranked);
|
|
1043
1061
|
if (alts.length) best.alternatives = alts;
|
|
1044
1062
|
return best;
|
|
1045
1063
|
}
|
|
@@ -1047,6 +1065,33 @@ async function resolveSecEntity(
|
|
|
1047
1065
|
throw new Error(`No SEC company matches "${query}". Pass a US-listed ticker ("AAPL") or the exact listed-company name ("Apple Inc."). If this is a clinical-trial sponsor, an operating subsidiary (e.g. "Merck Sharp & Dohme" → Merck & Co), or a foreign/private entity, call sponsor_to_filer({sponsor}) instead — it resolves subsidiaries to the listed parent and honestly reports when no US-listed filer exists.`);
|
|
1048
1066
|
}
|
|
1049
1067
|
|
|
1068
|
+
/** `alternatives` lists at most this many OTHER companies; company-spine.test.ts pins it to the real function. */
|
|
1069
|
+
const ALTERNATIVES_CAP = 3;
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* The runners-up for a name match, as DISTINCT COMPANIES (fleet #3621).
|
|
1073
|
+
*
|
|
1074
|
+
* company_tickers.json lists one row per ticker, so an issuer with preferred
|
|
1075
|
+
* shares appears several times under one CIK (Ford: F, F-PB, F-PC, F-PD; AT&T:
|
|
1076
|
+
* T, TBB, T-PA, T-PC). Slicing the ranked rows left those rows to fill every
|
|
1077
|
+
* alternatives slot, hiding any real rival ranked behind them, and made a company
|
|
1078
|
+
* its own "alternative". So: drop every row that is the winner's own CIK, keep
|
|
1079
|
+
* only the best-ranked row of each other CIK, THEN cap. The winner's other
|
|
1080
|
+
* tickers are not lost information: they are the same company, and `ticker` /
|
|
1081
|
+
* `cik` already identify it. `ranked` is already best-first, so first-seen wins.
|
|
1082
|
+
*/
|
|
1083
|
+
function distinctCompanyAlternatives(ranked: RankedMatch<SecTickerRow>[]): NonNullable<SecEntity['alternatives']> {
|
|
1084
|
+
const seen = new Set<number>([ranked[0].item.cik_str]);
|
|
1085
|
+
const out: NonNullable<SecEntity['alternatives']> = [];
|
|
1086
|
+
for (const m of ranked.slice(1)) {
|
|
1087
|
+
if (seen.has(m.item.cik_str)) continue;
|
|
1088
|
+
seen.add(m.item.cik_str);
|
|
1089
|
+
out.push({ ticker: m.item.ticker, company_name: m.item.title, cik: String(m.item.cik_str), kind: m.kind });
|
|
1090
|
+
if (out.length >= ALTERNATIVES_CAP) break;
|
|
1091
|
+
}
|
|
1092
|
+
return out;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1050
1095
|
function toEntity(r: SecTickerRow, matched_by: 'ticker' | 'company_name'): SecEntity {
|
|
1051
1096
|
return {
|
|
1052
1097
|
ticker: r.ticker,
|
package/src/server.ts
CHANGED