@pipeworx/mcp-edgar 0.3.15 → 0.3.16

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
  The Securities and Exchange Commission's filings database. Every public company in the US files here, every filing is timestamped and immutable, and every disclosure (revenue, debt, risk factors, executive compensation, M&A activity, insider trading) is structured for machine retrieval. Free and authoritative.
4
4
 
5
- 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.
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
  ## Why this matters for AI agents
8
8
 
@@ -111,7 +111,7 @@ directly, instead of just this one's:
111
111
  }
112
112
  ```
113
113
 
114
- Both URLs reach the same gateway and the same 1879+ data sources. The
114
+ Both URLs reach the same gateway and the same 1881+ data sources. The
115
115
  only difference is which pack's tools are listed **directly**; `ask_pipeworx`
116
116
  reaches all of them from either one.
117
117
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-edgar",
3
- "version": "0.3.15",
3
+ "version": "0.3.16",
4
4
  "description": "EDGAR MCP — SEC EDGAR public APIs (free, no auth)",
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-786eb4a2338149a713e1e23d15c1173ad5ffa949b94abc23a72ee39bf75db46e",
30
- "sourceCommit": "445bacc5596a845c12d6945fbfcdf330ef60dcc4"
29
+ "sourceHash": "v1-7833dc290ad97eca84fde46549d82a1502b8e5f9f99ce63b465d3fe526f25542",
30
+ "sourceCommit": "24e32b525f9c0b2fd7d94b519b08abb108cc11cd"
31
31
  }
32
32
  }
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/edgar",
4
4
  "title": "Edgar",
5
5
  "description": "EDGAR MCP — SEC EDGAR public APIs (free, no auth)",
6
- "version": "0.3.15",
6
+ "version": "0.3.16",
7
7
  "websiteUrl": "https://pipeworx.io/packs/edgar",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-edgar",
package/src/index.ts CHANGED
@@ -1065,25 +1065,64 @@ function rankMatches<T>(
1065
1065
  query: string,
1066
1066
  items: T[],
1067
1067
  getName: (item: T) => string,
1068
+ getAliases?: (item: T) => string[],
1068
1069
  ): RankedMatch<T>[] {
1069
1070
  const q = normalize(query);
1070
1071
  if (!q) return [];
1071
1072
  const scored: { item: T; kind: MatchKind; score: number; len: number }[] = [];
1072
1073
  for (const item of items) {
1073
1074
  const name = getName(item);
1074
- const n = normalize(name);
1075
+ // `getAliases` (optional, fleet #3607) are OTHER spellings of the same name,
1076
+ // each scored on its own; the best-scoring spelling wins. Additive on
1077
+ // purpose: the raw name is always tried, so a query that already matched
1078
+ // keeps matching exactly as before, and an alias can only ADD a match.
1075
1079
  let kind: MatchKind | null = null;
1076
1080
  let score = 0;
1077
- if (n === q) { kind = 'exact'; score = 4; }
1078
- else if (n.startsWith(`${q} `)) { kind = 'prefix'; score = 3; }
1079
- else if (n.includes(` ${q} `) || n.endsWith(` ${q}`)) { kind = 'word'; score = 2; }
1080
- else if (n.includes(q)) { kind = 'substring'; score = 1; }
1081
+ for (const spelling of [name, ...(getAliases?.(item) ?? [])]) {
1082
+ const n = normalize(spelling);
1083
+ let k: MatchKind | null = null;
1084
+ let sc = 0;
1085
+ if (n === q) { k = 'exact'; sc = 4; }
1086
+ else if (n.startsWith(`${q} `)) { k = 'prefix'; sc = 3; }
1087
+ else if (n.includes(` ${q} `) || n.endsWith(` ${q}`)) { k = 'word'; sc = 2; }
1088
+ else if (n.includes(q)) { k = 'substring'; sc = 1; }
1089
+ if (k && sc > score) { kind = k; score = sc; }
1090
+ }
1081
1091
  if (kind) scored.push({ item, kind, score, len: name.length });
1082
1092
  }
1083
1093
  scored.sort((a, b) => b.score - a.score || a.len - b.len);
1084
1094
  return scored.map(({ item, kind, score }) => ({ item, kind, score }));
1085
1095
  }
1086
1096
 
1097
+ /**
1098
+ * The trailing designators EDGAR appends to a registrant name that are NOT part
1099
+ * of the company's name: state or country of incorporation ("/DE/", "/MD",
1100
+ * "/CAN/", "/Cayman"), "/NEW", and the ADR marker. Matched case-insensitively
1101
+ * against the WHOLE segment after the last slash, so a name with a slash INSIDE
1102
+ * it ("CULLEN/FROST BANKERS", "M/I HOMES", "Quad/Graphics", "DATA I/O CORP",
1103
+ * "GENMAB A/S") is never cut. A genuine legal form that happens to look like a
1104
+ * 2-letter designator ("Anheuser-Busch InBev SA/NV") gains an extra alias
1105
+ * ("...SA"); the raw title is always tried too, so that costs nothing. Measured
1106
+ * against SEC's company_tickers.json 2026-10-26: 951 of 10,429 titles carry a
1107
+ * slash; the trailing segments are ADR (545), CAN, state codes, NEW, CAYMAN,
1108
+ * DEL(AWARE), CANADA, JAPAN, or empty ("TOYOTA MOTOR CORP/").
1109
+ */
1110
+ const EDGAR_TRAILING_DESIGNATOR =
1111
+ /\s*\/\s*(?:[A-Za-z]{2}|ADR|CAN|NEW|CAYMAN|DEL|DELAWARE|CANADA|JAPAN|UK)?\s*\/?\s*$/i;
1112
+
1113
+ /**
1114
+ * Other spellings of an EDGAR registrant title that name the same company:
1115
+ * the title with its jurisdiction/ADR designator removed ("TOYOTA MOTOR CORP/"
1116
+ * -> "TOYOTA MOTOR CORP"). Empty when there is nothing to remove. Used as
1117
+ * `rankMatches`'s aliases, never as a replacement for the title (fleet #3607).
1118
+ * Deliberately NOT a change to `normalize`: that is shared by every pack that
1119
+ * ranks its own list, and "/" is not a registrant-name artefact in those.
1120
+ */
1121
+ function edgarNameAliases(title: string): string[] {
1122
+ const stripped = title.replace(EDGAR_TRAILING_DESIGNATOR, '').trim();
1123
+ return stripped && stripped !== title.trim() && /\S/.test(stripped) ? [stripped] : [];
1124
+ }
1125
+
1087
1126
  interface SecTickerRow$shared { cik_str: number; ticker: string; title: string }
1088
1127
 
1089
1128
  interface SecEntity {
@@ -1140,7 +1179,7 @@ async function resolveSecEntity(
1140
1179
  }
1141
1180
 
1142
1181
  // 2) Company-name fallback.
1143
- const ranked = rankMatches(query, rows, (r) => r.title);
1182
+ const ranked = rankMatches(query, rows, (r) => r.title, (r) => edgarNameAliases(r.title));
1144
1183
  if (ranked.length) {
1145
1184
  const best = toEntity(ranked[0].item, 'company_name');
1146
1185
  best.matched_kind = ranked[0].kind;
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-edgar', version: '0.3.15' },
13
+ { name: '@pipeworx/mcp-edgar', version: '0.3.16' },
14
14
  { capabilities: { tools: {} } },
15
15
  );
16
16