@pipeworx/mcp-fed-nic 0.1.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/LICENSE +21 -0
- package/README.md +229 -0
- package/bin/cli.js +17 -0
- package/package.json +32 -0
- package/server.json +18 -0
- package/src/index.ts +1050 -0
- package/src/server.ts +45 -0
- package/tsconfig.json +18 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mojibake Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# @pipeworx/fed-nic
|
|
2
|
+
|
|
3
|
+
Institution search, corporate ownership hierarchy, and merger/acquisition history
|
|
4
|
+
for US banks and bank/financial holding companies, sourced from the Federal
|
|
5
|
+
Reserve System's National Information Center (NIC, ffiec.gov/npw).
|
|
6
|
+
|
|
7
|
+
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1679+ live data sources.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
- `nic_search_institutions(query, status?, state?, limit?)` — find institutions
|
|
12
|
+
by name. Returns RSSD ID, FDIC certificate, LEI, institution type, location,
|
|
13
|
+
active/closed status. RANKED via `nic_search_ranked` (migration 212): exact
|
|
14
|
+
match, then prefix match on an active FDIC-cert institution, then any
|
|
15
|
+
prefix match, then other active FDIC-cert institutions, then the rest —
|
|
16
|
+
not alphabetical (see "Coverage / accuracy notes").
|
|
17
|
+
- `nic_get_institution(rssd_id? | fdic_cert? | lei?)` — full NIC record for
|
|
18
|
+
one institution, looked up by exactly one of RSSD ID, FDIC certificate
|
|
19
|
+
number (chains to the `fdic` pack), or LEI (chains to the `gleif` pack).
|
|
20
|
+
- `nic_get_hierarchy(rssd_id, direction?, limit?, offset?)` — `direction="up"`
|
|
21
|
+
(default) walks the ownership chain to its top holder ("which holding
|
|
22
|
+
company owns this bank?"); `direction="down"` lists entities owned by the
|
|
23
|
+
given RSSD ID, paged via `limit`/`offset`, with `total_subsidiary_count`
|
|
24
|
+
computed as a DISTINCT count in SQL (migration 212's `nic_descendant_count`)
|
|
25
|
+
— see "Coverage / accuracy notes" for why the previous count was wrong.
|
|
26
|
+
- `nic_get_history(rssd_id)` — mergers, acquisitions, failures and
|
|
27
|
+
transformations the institution was party to ("what predecessor
|
|
28
|
+
institutions merged into this bank?").
|
|
29
|
+
|
|
30
|
+
## Auth
|
|
31
|
+
|
|
32
|
+
Keyless — no caller-facing credential. The gateway supplies the store
|
|
33
|
+
credential automatically.
|
|
34
|
+
|
|
35
|
+
## Data sources
|
|
36
|
+
|
|
37
|
+
- <https://www.ffiec.gov/npw/FinancialReport/DataDownload> — NIC's public
|
|
38
|
+
bulk CSV files: Attributes-Active, Attributes-Closed, Relationships,
|
|
39
|
+
Transformations. US federal government data; no reuse restriction found on
|
|
40
|
+
the download page or the NPW site (public-domain by default for federal
|
|
41
|
+
data — see "Reuse terms" below).
|
|
42
|
+
|
|
43
|
+
## Why this pack reads from a mirror, not a live proxy
|
|
44
|
+
|
|
45
|
+
`www.ffiec.gov` sits behind a Cloudflare Managed Challenge
|
|
46
|
+
(`cf-mitigated: challenge`) that returns a 403 "CAPTCHA Error" page to every
|
|
47
|
+
non-browser HTTP client — confirmed on both:
|
|
48
|
+
|
|
49
|
+
- the interactive NPW pages the live site itself uses per-query
|
|
50
|
+
(`Institution/Profile/{rssd_id}`, POST `Institution/BuildTier`, POST
|
|
51
|
+
`Institution/LoadHistory`), and
|
|
52
|
+
- the bulk CSV download endpoints (`FinancialReport/Return*ZipFileCSV`)
|
|
53
|
+
themselves,
|
|
54
|
+
|
|
55
|
+
with a full Chrome header set (User-Agent, Accept, Accept-Language,
|
|
56
|
+
`sec-ch-ua*`). A Cloudflare Worker's `fetch()` hits the identical wall — there
|
|
57
|
+
is no header or cookie fix, it is a JS/TLS-fingerprint challenge, not a UA
|
|
58
|
+
check — so there is no live per-query route this gateway can reach. Per
|
|
59
|
+
Bruce's 2026-09-23 ruling ("build a copy when live doesn't serve"), this pack
|
|
60
|
+
is instead backed by a periodically-refreshed copy of NIC's own public bulk
|
|
61
|
+
files (migration `supabase/migrations/209_fed_nic.sql`), refreshed by
|
|
62
|
+
`scripts/ingest-fed-nic.mjs` — see that script's header for exactly why the
|
|
63
|
+
refresh cannot be a Worker cron and what running it manually requires. It is
|
|
64
|
+
registered in `workers/data-pipeline/src/datasets/fed-nic.ts` for freshness
|
|
65
|
+
visibility only (no scheduled run), the same pattern
|
|
66
|
+
`workers/data-pipeline/src/datasets/ffiec.ts` uses for `cdr.ffiec.gov`.
|
|
67
|
+
|
|
68
|
+
## Reuse terms
|
|
69
|
+
|
|
70
|
+
NIC's Data Download page (`/npw/FinancialReport/DataDownload`, "About the
|
|
71
|
+
Files") documents the file contents and how to use them but states no
|
|
72
|
+
copyright, license, or reuse restriction. The NIC Data Dictionary PDF (linked
|
|
73
|
+
from that page) sits behind the same Cloudflare wall as the rest of
|
|
74
|
+
`ffiec.gov`, so it could not be checked directly. This is data produced by a
|
|
75
|
+
US federal agency (the Federal Reserve System) about a supervisory/regulatory
|
|
76
|
+
function; US federal government works are public domain by default (17 U.S.C.
|
|
77
|
+
§ 105) absent a specific notice to the contrary, and none was found.
|
|
78
|
+
|
|
79
|
+
## Coverage / accuracy notes
|
|
80
|
+
|
|
81
|
+
- **Branches are not ingested.** NIC's Attributes-Branches file (~174k rows,
|
|
82
|
+
95MB) is out of scope for the hierarchy/history use case this pack ships;
|
|
83
|
+
the NIC UI's own "Branches" tab covers it and this could be added later.
|
|
84
|
+
- **`nic_get_hierarchy` is our own computed closure**, not a copy of NIC's own
|
|
85
|
+
tiering algorithm. It recursively walks currently-active
|
|
86
|
+
(`dt_end IS NULL`) edges in NIC's public Relationships file. Spot-checked
|
|
87
|
+
live on 2026-09-23 against JPMorgan Chase Bank, N.A. (RSSD 852218):
|
|
88
|
+
`direction="up"` matched the live UI exactly (top holder JPMorgan Chase &
|
|
89
|
+
Co., RSSD 1039502); `direction="down"` from the top tier returned 877
|
|
90
|
+
subsidiaries by our closure versus 1,025 on the live UI. The discrepancy is
|
|
91
|
+
not reconstructable from the public bulk file alone (the live UI's tiering
|
|
92
|
+
algorithm likely applies rules — e.g. non-equity control bases, branch/agent
|
|
93
|
+
relationships — that the public Relationships export does not fully carry).
|
|
94
|
+
Treat the down-direction count as a lower bound computed from NIC's own
|
|
95
|
+
published data, not NIC's official figure.
|
|
96
|
+
**Migration 212 fixes a separate bug in how that 877 reached the tool.**
|
|
97
|
+
The Relationships closure emits one row per ownership PATH, not one per
|
|
98
|
+
distinct subsidiary — a subsidiary reachable through more than one parent
|
|
99
|
+
chain appears more than once (1,672 raw rows for JPMorgan vs. 877 distinct
|
|
100
|
+
RSSD ids). The tool originally called the raw closure RPC directly and used
|
|
101
|
+
the returned row count as `total_subsidiary_count`; PostgREST caps a single
|
|
102
|
+
RPC response at 1,000 rows, so the count silently landed on 1,000 instead of
|
|
103
|
+
877 whenever the raw closure exceeded that cap. `nic_descendant_count` (a
|
|
104
|
+
single-row scalar, immune to the row cap) and `nic_descendants_page`
|
|
105
|
+
(deduped + paged in SQL) fix this — see `src/index.ts`'s top-of-file
|
|
106
|
+
comment and `supabase/migrations/212_fed_nic_hierarchy_and_search_fix.sql`.
|
|
107
|
+
- **`nic_search_institutions` ranking (migration 212, `nic_search_ranked`).**
|
|
108
|
+
Plain alphabetical order put same-family entities ahead of the institution
|
|
109
|
+
most callers mean — e.g. query "Wells Fargo Bank" returned "WELLS FARGO
|
|
110
|
+
BANK INTERNATIONAL UNLIMITED COMPANY" (an Ireland entity, no FDIC cert)
|
|
111
|
+
ahead of "WELLS FARGO BANK, NATIONAL ASSOCIATION" (RSSD 451965) purely
|
|
112
|
+
because `' '` sorts before `','` in ASCII. Ranking now tiers by exact
|
|
113
|
+
match, then prefix-match-with-FDIC-cert, then any prefix match, then
|
|
114
|
+
other cert-holding active institutions, then the rest; ties within a tier
|
|
115
|
+
break on shortest `legal_name` (closest in length to the query), then
|
|
116
|
+
trigram similarity.
|
|
117
|
+
- **`entity_type_code` labels are partial.** `ENTITY_TYPE_LABELS` in
|
|
118
|
+
`src/index.ts` only carries codes verified live against the NIC UI (NAT,
|
|
119
|
+
FHD, EDI, IBK, INB, DEO). Any other code is returned raw rather than
|
|
120
|
+
guessed — the NIC Data Dictionary that would confirm the rest is itself
|
|
121
|
+
behind the Cloudflare wall.
|
|
122
|
+
- **`trnsfm_cd` (transformation type) is a raw NIC code**, not a label, for
|
|
123
|
+
the same reason. Code 50 is corroborated against a live example (First
|
|
124
|
+
Republic Bank, RSSD 4114567 → JPMorgan Chase Bank N.A., RSSD 852218,
|
|
125
|
+
2023-05-01, "failed and ceased to exist" on the live NIC History tab).
|
|
126
|
+
|
|
127
|
+
## Quick Start
|
|
128
|
+
|
|
129
|
+
Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"mcpServers": {
|
|
134
|
+
"fed-nic": {
|
|
135
|
+
"url": "https://gateway.pipeworx.io/fed-nic/mcp"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### What this endpoint actually serves
|
|
142
|
+
|
|
143
|
+
`tools/list` at `https://gateway.pipeworx.io/fed-nic/mcp` returns the tools in the table
|
|
144
|
+
above **plus the shared Pipeworx meta-tools** — `ask_pipeworx`,
|
|
145
|
+
`discover_tools`, `search_within`, `remember`/`recall` and the rest of the
|
|
146
|
+
gateway-wide set. So the tool count you see is larger than this table: a
|
|
147
|
+
single-pack endpoint currently lists roughly 30 shared tools alongside the
|
|
148
|
+
pack's own. The connection's `initialize` response states its exact scope, and
|
|
149
|
+
is the authoritative answer for a given day.
|
|
150
|
+
|
|
151
|
+
This is deliberate, not multiplexing by accident. The meta-tools are what let a
|
|
152
|
+
scoped connection answer a question this pack does not cover — via
|
|
153
|
+
`ask_pipeworx`, which routes across the whole catalog — without you adding a
|
|
154
|
+
second MCP server. There is currently no way to mount a pack endpoint without
|
|
155
|
+
them; if the extra schemas cost you more context than the routing is worth,
|
|
156
|
+
connect to the full gateway once rather than to several pack endpoints.
|
|
157
|
+
|
|
158
|
+
Or connect to the full Pipeworx gateway to get every pack's tools listed
|
|
159
|
+
directly, instead of just this one's:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"mcpServers": {
|
|
164
|
+
"pipeworx": {
|
|
165
|
+
"url": "https://gateway.pipeworx.io/mcp"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Both URLs reach the same gateway and the same 1679+ data sources. The
|
|
172
|
+
only difference is which pack's tools are listed **directly**; `ask_pipeworx`
|
|
173
|
+
reaches all of them from either one.
|
|
174
|
+
|
|
175
|
+
## No MCP client? Call it over HTTP
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
curl -X POST https://gateway.pipeworx.io/v1/tools/nic_search_institutions \
|
|
179
|
+
-H 'Content-Type: application/json' \
|
|
180
|
+
-d '{"query":"JPMorgan Chase Bank"}'
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
No account needed for the first calls. Inspect any tool: `GET https://gateway.pipeworx.io/v1/tools/nic_search_institutions`. Find one: `POST https://gateway.pipeworx.io/v1/tools/search_packs` with `{"query":"..."}`.
|
|
184
|
+
|
|
185
|
+
## Standalone (no gateway account)
|
|
186
|
+
|
|
187
|
+
This package also runs as a local stdio MCP server — no Pipeworx account, no
|
|
188
|
+
gateway round-trip:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"mcpServers": {
|
|
193
|
+
"fed-nic": {
|
|
194
|
+
"command": "npx",
|
|
195
|
+
"args": ["-y", "@pipeworx/mcp-fed-nic"]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Or run it directly to confirm it starts:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npx -y @pipeworx/mcp-fed-nic
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
It speaks MCP over stdin/stdout and answers `initialize`/`tools/list`/`tools/call`
|
|
208
|
+
for **only** this pack's tools — none of the shared meta-tools the gateway
|
|
209
|
+
connection above adds. Same source, same tools, no ask_pipeworx routing.
|
|
210
|
+
|
|
211
|
+
## Using with ask_pipeworx
|
|
212
|
+
|
|
213
|
+
Instead of calling tools directly, you can ask questions in plain English —
|
|
214
|
+
this works on the pack endpoint above as well as on the full gateway:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
ask_pipeworx({ question: "your question about Fed Nic data" })
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The gateway picks the right tool and fills the arguments automatically.
|
|
221
|
+
|
|
222
|
+
## More
|
|
223
|
+
|
|
224
|
+
- [Docs and guides](https://pipeworx.io/docs)
|
|
225
|
+
- [pipeworx.io](https://pipeworx.io)
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//
|
|
3
|
+
// Entry point for `npx @pipeworx/mcp-<slug>`.
|
|
4
|
+
//
|
|
5
|
+
// Packs ship as raw TypeScript (no build step — see publish-pack.sh for why:
|
|
6
|
+
// tsx sidesteps every extensionless-import / bare-JSON-import edge case a
|
|
7
|
+
// per-pack tsc build would have to solve one pack at a time). This file
|
|
8
|
+
// registers tsx's ESM loader programmatically, then hands off to src/server.ts,
|
|
9
|
+
// which wraps the pack's {tools, callTool} export in a stdio MCP server.
|
|
10
|
+
//
|
|
11
|
+
// Copied verbatim into every published pack repo by scripts/publish-pack.sh —
|
|
12
|
+
// edit this file, not a per-pack copy.
|
|
13
|
+
import { register } from 'tsx/esm/api';
|
|
14
|
+
|
|
15
|
+
register();
|
|
16
|
+
|
|
17
|
+
await import('../src/server.ts');
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pipeworx/mcp-fed-nic",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Federal Reserve National Information Center (NIC, ffiec.gov/npw)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mcp-fed-nic": "bin/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": ["mcp", "mcp-server", "model-context-protocol", "pipeworx", "fed-nic"],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/pipeworx-io/mcp-fed-nic.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"typecheck": "tsc --noEmit"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
22
|
+
"tsx": "^4.19.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.9.3",
|
|
26
|
+
"@cloudflare/workers-types": "^4.20260405.1"
|
|
27
|
+
},
|
|
28
|
+
"pipeworx": {
|
|
29
|
+
"sourceHash": "v1-1878eaf82a7becc9bebdf083ac9ecba382d75d5e813076b8c73828ab8ecc884d",
|
|
30
|
+
"sourceCommit": "b0fb3c31386cf0256dcf1e2f1b3440435a87ec35"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.pipeworx-io/fed-nic",
|
|
4
|
+
"title": "Fed Nic",
|
|
5
|
+
"description": "Federal Reserve National Information Center (NIC, ffiec.gov/npw)",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"websiteUrl": "https://pipeworx.io/packs/fed-nic",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/pipeworx-io/mcp-fed-nic",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"remotes": [
|
|
13
|
+
{
|
|
14
|
+
"type": "streamable-http",
|
|
15
|
+
"url": "https://gateway.pipeworx.io/fed-nic/mcp"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|