fdic-mcp-server 1.16.0 → 1.17.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/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
32
32
  var import_express2 = __toESM(require("express"));
33
33
 
34
34
  // src/constants.ts
35
- var VERSION = true ? "1.16.0" : process.env.npm_package_version ?? "0.0.0-dev";
35
+ var VERSION = true ? "1.17.0" : process.env.npm_package_version ?? "0.0.0-dev";
36
36
  var FDIC_API_BASE_URL = "https://banks.data.fdic.gov/api";
37
37
  var CHARACTER_LIMIT = 5e4;
38
38
  var DEFAULT_FDIC_MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
@@ -32687,19 +32687,16 @@ Common filter examples:
32687
32687
  - Branches in a state: STALPBR:CA
32688
32688
  - Branches in a city: CITYBR:"Austin"
32689
32689
  - High-deposit branches: DEPSUMBR:[1000000 TO *]
32690
- - By metro area: MSANAMEBR:"Dallas-Fort Worth-Arlington"
32690
+ - By metro area (MSA code): MSABR:19100
32691
32691
 
32692
32692
  Key returned fields:
32693
32693
  - YEAR: Report year (as of June 30)
32694
32694
  - CERT: FDIC Certificate Number
32695
32695
  - BRNUM: Branch number (0 = main office)
32696
- - UNINAME: Institution name
32697
- - NAMEFULL: Full branch name
32696
+ - NAMEFULL: Branch or institution name
32698
32697
  - ADDRESBR, CITYBR, STALPBR, ZIPBR: Branch address
32699
- - CNTYBR: County
32700
32698
  - DEPSUMBR: Total deposits at branch ($thousands)
32701
- - MSABR: Metropolitan Statistical Area code
32702
- - MSANAMEBR: MSA name
32699
+ - MSABR: Metropolitan Statistical Area code (numeric; 0 = non-MSA)
32703
32700
  - LATITUDE, LONGITUDE: Coordinates
32704
32701
 
32705
32702
  Args:
@@ -34640,7 +34637,7 @@ var CANONICAL_FIELDS = [
34640
34637
  "SC",
34641
34638
  "ASSTLT",
34642
34639
  "VOLIAB",
34643
- "BRWDMONY"
34640
+ "OTHBRF"
34644
34641
  ].join(",");
34645
34642
  var FIELD_ALIASES = {
34646
34643
  IDT1CER: ["REPTE9"],
@@ -34717,7 +34714,7 @@ function extractCanonicalMetrics(raw) {
34717
34714
  const sc = asNumber(raw.SC);
34718
34715
  const asstlt = asNumber(raw.ASSTLT);
34719
34716
  const voliab = asNumber(raw.VOLIAB);
34720
- const brwdmony = asNumber(raw.BRWDMONY);
34717
+ const othbrf = asNumber(raw.OTHBRF);
34721
34718
  const metrics = {
34722
34719
  // Amounts
34723
34720
  totalAssets: direct("totalAssets", "ASSET"),
@@ -34786,8 +34783,8 @@ function extractCanonicalMetrics(raw) {
34786
34783
  ),
34787
34784
  borrowedFundsToAssetsPct: derived(
34788
34785
  "borrowedFundsToAssetsPct",
34789
- () => safeDivPct(brwdmony, asset),
34790
- "BRWDMONY / ASSET * 100"
34786
+ () => safeDivPct(othbrf, asset),
34787
+ "OTHBRF / ASSET * 100"
34791
34788
  )
34792
34789
  };
34793
34790
  for (const [key, value] of Object.entries(metrics)) {
@@ -36678,7 +36675,6 @@ var CREDIT_FIELDS = [
36678
36675
  "LNCI",
36679
36676
  "LNCON",
36680
36677
  "LNAG",
36681
- "LNOTH",
36682
36678
  "LNREDOM",
36683
36679
  "LNREFOR"
36684
36680
  ].join(",");
@@ -37571,7 +37567,7 @@ function buildMarketConcentration(participants) {
37571
37567
  }
37572
37568
 
37573
37569
  // src/tools/marketShareAnalysis.ts
37574
- var SOD_FIELDS = "CERT,UNINAME,DEPSUMBR,BRNUM,MSANAMEBR,CNTYBR,STALPBR,YEAR";
37570
+ var SOD_FIELDS = "CERT,NAMEFULL,DEPSUMBR,BRNUM,MSABR,STALPBR,YEAR";
37575
37571
  var SOD_FETCH_LIMIT = 1e4;
37576
37572
  function fmtNum(val) {
37577
37573
  return Math.round(val).toLocaleString("en-US");
@@ -37624,12 +37620,12 @@ function getDefaultSodYear() {
37624
37620
  return (/* @__PURE__ */ new Date()).getFullYear() - 1;
37625
37621
  }
37626
37622
  var MarketShareInputSchema = import_zod16.z.object({
37627
- msa: import_zod16.z.string().optional().describe(
37628
- 'MSA name to filter (e.g., "Dallas-Fort Worth-Arlington"). Use MSANAMEBR field.'
37623
+ msa: import_zod16.z.number().int().positive().optional().describe(
37624
+ "FDIC MSABR numeric code for the Metropolitan Statistical Area (e.g., 19100 for Dallas-Fort Worth-Arlington, 42660 for Seattle-Tacoma-Bellevue). Use fdic_search_sod with MSABR to look up codes."
37629
37625
  ),
37630
- county: import_zod16.z.string().optional().describe('County name (e.g., "Travis"). Requires state.'),
37626
+ city: import_zod16.z.string().optional().describe('City name (e.g., "Austin"). Requires state.'),
37631
37627
  state: import_zod16.z.string().length(2).optional().describe(
37632
- "Two-letter state abbreviation (e.g., TX). Required when using county filter."
37628
+ "Two-letter state abbreviation (e.g., TX). Required when using city filter."
37633
37629
  ),
37634
37630
  year: import_zod16.z.number().int().min(1994).optional().describe("SOD report year (1994-present). Defaults to most recent."),
37635
37631
  cert: import_zod16.z.number().int().positive().optional().describe("Highlight a specific institution in the results.")
@@ -37639,17 +37635,21 @@ function registerMarketShareAnalysisTools(server) {
37639
37635
  "fdic_market_share_analysis",
37640
37636
  {
37641
37637
  title: "Deposit Market Share Analysis",
37642
- description: `Analyze deposit market share and concentration for an MSA or county market using FDIC Summary of Deposits (SOD) data.
37638
+ description: `Analyze deposit market share and concentration for an MSA or city market using FDIC Summary of Deposits (SOD) data.
37643
37639
 
37644
37640
  Computes market share for all institutions in a geographic market, ranks them by deposits, and calculates the Herfindahl-Hirschman Index (HHI) for market concentration analysis per DOJ/FTC merger guidelines.
37645
37641
 
37642
+ Two entry modes:
37643
+ - MSA market: provide msa as the numeric MSABR code (e.g., msa: 19100 for Dallas-Fort Worth-Arlington, msa: 42660 for Seattle-Tacoma-Bellevue). Use fdic_search_sod to look up MSABR codes.
37644
+ - City market: provide city (branch city name, e.g., "Austin") and state (two-letter code, e.g., "TX").
37645
+
37646
37646
  Output includes:
37647
37647
  - Market overview with total deposits, institution count, and HHI classification
37648
- - Optional highlighted institution showing rank and share
37648
+ - Optional highlighted institution showing rank and share (provide cert)
37649
37649
  - Top institutions ranked by deposit market share
37650
37650
  - Structured JSON for programmatic consumption
37651
37651
 
37652
- Requires at least one of: msa, or county + state.`,
37652
+ Requires at least one of: msa (numeric MSABR code), or city + state.`,
37653
37653
  inputSchema: MarketShareInputSchema,
37654
37654
  annotations: {
37655
37655
  readOnlyHint: true,
@@ -37663,17 +37663,17 @@ Requires at least one of: msa, or county + state.`,
37663
37663
  const timeoutId = setTimeout(() => controller.abort(), ANALYSIS_TIMEOUT_MS);
37664
37664
  const progressToken = extra._meta?.progressToken;
37665
37665
  try {
37666
- if (!rawParams.msa && !rawParams.county) {
37666
+ if (!rawParams.msa && !rawParams.city) {
37667
37667
  return formatToolError(
37668
37668
  new Error(
37669
- "At least one of 'msa' or 'county' (with 'state') must be provided."
37669
+ "At least one of 'msa' (numeric MSABR code) or 'city' (with 'state') must be provided."
37670
37670
  )
37671
37671
  );
37672
37672
  }
37673
- if (rawParams.county && !rawParams.state) {
37673
+ if (rawParams.city && !rawParams.state) {
37674
37674
  return formatToolError(
37675
37675
  new Error(
37676
- "'state' is required when using 'county' filter."
37676
+ "'state' is required when using 'city' filter."
37677
37677
  )
37678
37678
  );
37679
37679
  }
@@ -37681,11 +37681,11 @@ Requires at least one of: msa, or county + state.`,
37681
37681
  let filterStr;
37682
37682
  let marketName;
37683
37683
  if (rawParams.msa) {
37684
- filterStr = `MSANAMEBR:"${rawParams.msa}" AND YEAR:${year}`;
37685
- marketName = rawParams.msa;
37684
+ filterStr = `MSABR:${rawParams.msa} AND YEAR:${year}`;
37685
+ marketName = `MSA ${rawParams.msa}`;
37686
37686
  } else {
37687
- filterStr = `CNTYBR:"${rawParams.county}" AND STALPBR:${rawParams.state} AND YEAR:${year}`;
37688
- marketName = `${rawParams.county} County, ${rawParams.state}`;
37687
+ filterStr = `CITYBR:"${rawParams.city}" AND STALPBR:${rawParams.state} AND YEAR:${year}`;
37688
+ marketName = `${rawParams.city}, ${rawParams.state}`;
37689
37689
  }
37690
37690
  await sendProgressNotification(
37691
37691
  server.server,
@@ -37720,7 +37720,7 @@ Requires at least one of: msa, or county + state.`,
37720
37720
  );
37721
37721
  const branches = records.map((r) => ({
37722
37722
  cert: Number(r.CERT),
37723
- name: String(r.UNINAME ?? ""),
37723
+ name: String(r.NAMEFULL ?? ""),
37724
37724
  deposits: typeof r.DEPSUMBR === "number" ? r.DEPSUMBR : 0
37725
37725
  }));
37726
37726
  const participants = computeMarketShare(branches);
@@ -37767,7 +37767,7 @@ Requires at least one of: msa, or county + state.`,
37767
37767
 
37768
37768
  // src/tools/franchiseFootprint.ts
37769
37769
  var import_zod17 = require("zod");
37770
- var SOD_BRANCH_FIELDS = "CERT,UNINAME,DEPSUMBR,BRNUM,MSANAMEBR,CNTYBR,STALPBR,YEAR";
37770
+ var SOD_BRANCH_FIELDS = "CERT,NAMEFULL,DEPSUMBR,BRNUM,MSABR,STALPBR,YEAR";
37771
37771
  var SOD_FETCH_LIMIT2 = 1e4;
37772
37772
  var NON_MSA_LABEL = "Non-MSA / Rural";
37773
37773
  function fmtNum2(val) {
@@ -37889,7 +37889,7 @@ Branches outside MSAs are grouped under "Non-MSA / Rural".`,
37889
37889
  );
37890
37890
  const byMarket = /* @__PURE__ */ new Map();
37891
37891
  for (const rec of branchRecords) {
37892
- const msaName = typeof rec.MSANAMEBR === "string" && rec.MSANAMEBR.trim() !== "" ? rec.MSANAMEBR.trim() : NON_MSA_LABEL;
37892
+ const msaName = typeof rec.MSABR === "number" && rec.MSABR !== 0 ? `MSA ${rec.MSABR}` : NON_MSA_LABEL;
37893
37893
  const deposits = typeof rec.DEPSUMBR === "number" ? rec.DEPSUMBR : 0;
37894
37894
  const existing = byMarket.get(msaName);
37895
37895
  if (existing) {
package/dist/server.js CHANGED
@@ -46,7 +46,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
46
46
  var import_express2 = __toESM(require("express"));
47
47
 
48
48
  // src/constants.ts
49
- var VERSION = true ? "1.16.0" : process.env.npm_package_version ?? "0.0.0-dev";
49
+ var VERSION = true ? "1.17.0" : process.env.npm_package_version ?? "0.0.0-dev";
50
50
  var FDIC_API_BASE_URL = "https://banks.data.fdic.gov/api";
51
51
  var CHARACTER_LIMIT = 5e4;
52
52
  var DEFAULT_FDIC_MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
@@ -32701,19 +32701,16 @@ Common filter examples:
32701
32701
  - Branches in a state: STALPBR:CA
32702
32702
  - Branches in a city: CITYBR:"Austin"
32703
32703
  - High-deposit branches: DEPSUMBR:[1000000 TO *]
32704
- - By metro area: MSANAMEBR:"Dallas-Fort Worth-Arlington"
32704
+ - By metro area (MSA code): MSABR:19100
32705
32705
 
32706
32706
  Key returned fields:
32707
32707
  - YEAR: Report year (as of June 30)
32708
32708
  - CERT: FDIC Certificate Number
32709
32709
  - BRNUM: Branch number (0 = main office)
32710
- - UNINAME: Institution name
32711
- - NAMEFULL: Full branch name
32710
+ - NAMEFULL: Branch or institution name
32712
32711
  - ADDRESBR, CITYBR, STALPBR, ZIPBR: Branch address
32713
- - CNTYBR: County
32714
32712
  - DEPSUMBR: Total deposits at branch ($thousands)
32715
- - MSABR: Metropolitan Statistical Area code
32716
- - MSANAMEBR: MSA name
32713
+ - MSABR: Metropolitan Statistical Area code (numeric; 0 = non-MSA)
32717
32714
  - LATITUDE, LONGITUDE: Coordinates
32718
32715
 
32719
32716
  Args:
@@ -34654,7 +34651,7 @@ var CANONICAL_FIELDS = [
34654
34651
  "SC",
34655
34652
  "ASSTLT",
34656
34653
  "VOLIAB",
34657
- "BRWDMONY"
34654
+ "OTHBRF"
34658
34655
  ].join(",");
34659
34656
  var FIELD_ALIASES = {
34660
34657
  IDT1CER: ["REPTE9"],
@@ -34731,7 +34728,7 @@ function extractCanonicalMetrics(raw) {
34731
34728
  const sc = asNumber(raw.SC);
34732
34729
  const asstlt = asNumber(raw.ASSTLT);
34733
34730
  const voliab = asNumber(raw.VOLIAB);
34734
- const brwdmony = asNumber(raw.BRWDMONY);
34731
+ const othbrf = asNumber(raw.OTHBRF);
34735
34732
  const metrics = {
34736
34733
  // Amounts
34737
34734
  totalAssets: direct("totalAssets", "ASSET"),
@@ -34800,8 +34797,8 @@ function extractCanonicalMetrics(raw) {
34800
34797
  ),
34801
34798
  borrowedFundsToAssetsPct: derived(
34802
34799
  "borrowedFundsToAssetsPct",
34803
- () => safeDivPct(brwdmony, asset),
34804
- "BRWDMONY / ASSET * 100"
34800
+ () => safeDivPct(othbrf, asset),
34801
+ "OTHBRF / ASSET * 100"
34805
34802
  )
34806
34803
  };
34807
34804
  for (const [key, value] of Object.entries(metrics)) {
@@ -36692,7 +36689,6 @@ var CREDIT_FIELDS = [
36692
36689
  "LNCI",
36693
36690
  "LNCON",
36694
36691
  "LNAG",
36695
- "LNOTH",
36696
36692
  "LNREDOM",
36697
36693
  "LNREFOR"
36698
36694
  ].join(",");
@@ -37585,7 +37581,7 @@ function buildMarketConcentration(participants) {
37585
37581
  }
37586
37582
 
37587
37583
  // src/tools/marketShareAnalysis.ts
37588
- var SOD_FIELDS = "CERT,UNINAME,DEPSUMBR,BRNUM,MSANAMEBR,CNTYBR,STALPBR,YEAR";
37584
+ var SOD_FIELDS = "CERT,NAMEFULL,DEPSUMBR,BRNUM,MSABR,STALPBR,YEAR";
37589
37585
  var SOD_FETCH_LIMIT = 1e4;
37590
37586
  function fmtNum(val) {
37591
37587
  return Math.round(val).toLocaleString("en-US");
@@ -37638,12 +37634,12 @@ function getDefaultSodYear() {
37638
37634
  return (/* @__PURE__ */ new Date()).getFullYear() - 1;
37639
37635
  }
37640
37636
  var MarketShareInputSchema = import_zod16.z.object({
37641
- msa: import_zod16.z.string().optional().describe(
37642
- 'MSA name to filter (e.g., "Dallas-Fort Worth-Arlington"). Use MSANAMEBR field.'
37637
+ msa: import_zod16.z.number().int().positive().optional().describe(
37638
+ "FDIC MSABR numeric code for the Metropolitan Statistical Area (e.g., 19100 for Dallas-Fort Worth-Arlington, 42660 for Seattle-Tacoma-Bellevue). Use fdic_search_sod with MSABR to look up codes."
37643
37639
  ),
37644
- county: import_zod16.z.string().optional().describe('County name (e.g., "Travis"). Requires state.'),
37640
+ city: import_zod16.z.string().optional().describe('City name (e.g., "Austin"). Requires state.'),
37645
37641
  state: import_zod16.z.string().length(2).optional().describe(
37646
- "Two-letter state abbreviation (e.g., TX). Required when using county filter."
37642
+ "Two-letter state abbreviation (e.g., TX). Required when using city filter."
37647
37643
  ),
37648
37644
  year: import_zod16.z.number().int().min(1994).optional().describe("SOD report year (1994-present). Defaults to most recent."),
37649
37645
  cert: import_zod16.z.number().int().positive().optional().describe("Highlight a specific institution in the results.")
@@ -37653,17 +37649,21 @@ function registerMarketShareAnalysisTools(server) {
37653
37649
  "fdic_market_share_analysis",
37654
37650
  {
37655
37651
  title: "Deposit Market Share Analysis",
37656
- description: `Analyze deposit market share and concentration for an MSA or county market using FDIC Summary of Deposits (SOD) data.
37652
+ description: `Analyze deposit market share and concentration for an MSA or city market using FDIC Summary of Deposits (SOD) data.
37657
37653
 
37658
37654
  Computes market share for all institutions in a geographic market, ranks them by deposits, and calculates the Herfindahl-Hirschman Index (HHI) for market concentration analysis per DOJ/FTC merger guidelines.
37659
37655
 
37656
+ Two entry modes:
37657
+ - MSA market: provide msa as the numeric MSABR code (e.g., msa: 19100 for Dallas-Fort Worth-Arlington, msa: 42660 for Seattle-Tacoma-Bellevue). Use fdic_search_sod to look up MSABR codes.
37658
+ - City market: provide city (branch city name, e.g., "Austin") and state (two-letter code, e.g., "TX").
37659
+
37660
37660
  Output includes:
37661
37661
  - Market overview with total deposits, institution count, and HHI classification
37662
- - Optional highlighted institution showing rank and share
37662
+ - Optional highlighted institution showing rank and share (provide cert)
37663
37663
  - Top institutions ranked by deposit market share
37664
37664
  - Structured JSON for programmatic consumption
37665
37665
 
37666
- Requires at least one of: msa, or county + state.`,
37666
+ Requires at least one of: msa (numeric MSABR code), or city + state.`,
37667
37667
  inputSchema: MarketShareInputSchema,
37668
37668
  annotations: {
37669
37669
  readOnlyHint: true,
@@ -37677,17 +37677,17 @@ Requires at least one of: msa, or county + state.`,
37677
37677
  const timeoutId = setTimeout(() => controller.abort(), ANALYSIS_TIMEOUT_MS);
37678
37678
  const progressToken = extra._meta?.progressToken;
37679
37679
  try {
37680
- if (!rawParams.msa && !rawParams.county) {
37680
+ if (!rawParams.msa && !rawParams.city) {
37681
37681
  return formatToolError(
37682
37682
  new Error(
37683
- "At least one of 'msa' or 'county' (with 'state') must be provided."
37683
+ "At least one of 'msa' (numeric MSABR code) or 'city' (with 'state') must be provided."
37684
37684
  )
37685
37685
  );
37686
37686
  }
37687
- if (rawParams.county && !rawParams.state) {
37687
+ if (rawParams.city && !rawParams.state) {
37688
37688
  return formatToolError(
37689
37689
  new Error(
37690
- "'state' is required when using 'county' filter."
37690
+ "'state' is required when using 'city' filter."
37691
37691
  )
37692
37692
  );
37693
37693
  }
@@ -37695,11 +37695,11 @@ Requires at least one of: msa, or county + state.`,
37695
37695
  let filterStr;
37696
37696
  let marketName;
37697
37697
  if (rawParams.msa) {
37698
- filterStr = `MSANAMEBR:"${rawParams.msa}" AND YEAR:${year}`;
37699
- marketName = rawParams.msa;
37698
+ filterStr = `MSABR:${rawParams.msa} AND YEAR:${year}`;
37699
+ marketName = `MSA ${rawParams.msa}`;
37700
37700
  } else {
37701
- filterStr = `CNTYBR:"${rawParams.county}" AND STALPBR:${rawParams.state} AND YEAR:${year}`;
37702
- marketName = `${rawParams.county} County, ${rawParams.state}`;
37701
+ filterStr = `CITYBR:"${rawParams.city}" AND STALPBR:${rawParams.state} AND YEAR:${year}`;
37702
+ marketName = `${rawParams.city}, ${rawParams.state}`;
37703
37703
  }
37704
37704
  await sendProgressNotification(
37705
37705
  server.server,
@@ -37734,7 +37734,7 @@ Requires at least one of: msa, or county + state.`,
37734
37734
  );
37735
37735
  const branches = records.map((r) => ({
37736
37736
  cert: Number(r.CERT),
37737
- name: String(r.UNINAME ?? ""),
37737
+ name: String(r.NAMEFULL ?? ""),
37738
37738
  deposits: typeof r.DEPSUMBR === "number" ? r.DEPSUMBR : 0
37739
37739
  }));
37740
37740
  const participants = computeMarketShare(branches);
@@ -37781,7 +37781,7 @@ Requires at least one of: msa, or county + state.`,
37781
37781
 
37782
37782
  // src/tools/franchiseFootprint.ts
37783
37783
  var import_zod17 = require("zod");
37784
- var SOD_BRANCH_FIELDS = "CERT,UNINAME,DEPSUMBR,BRNUM,MSANAMEBR,CNTYBR,STALPBR,YEAR";
37784
+ var SOD_BRANCH_FIELDS = "CERT,NAMEFULL,DEPSUMBR,BRNUM,MSABR,STALPBR,YEAR";
37785
37785
  var SOD_FETCH_LIMIT2 = 1e4;
37786
37786
  var NON_MSA_LABEL = "Non-MSA / Rural";
37787
37787
  function fmtNum2(val) {
@@ -37903,7 +37903,7 @@ Branches outside MSAs are grouped under "Non-MSA / Rural".`,
37903
37903
  );
37904
37904
  const byMarket = /* @__PURE__ */ new Map();
37905
37905
  for (const rec of branchRecords) {
37906
- const msaName = typeof rec.MSANAMEBR === "string" && rec.MSANAMEBR.trim() !== "" ? rec.MSANAMEBR.trim() : NON_MSA_LABEL;
37906
+ const msaName = typeof rec.MSABR === "number" && rec.MSABR !== 0 ? `MSA ${rec.MSABR}` : NON_MSA_LABEL;
37907
37907
  const deposits = typeof rec.DEPSUMBR === "number" ? rec.DEPSUMBR : 0;
37908
37908
  const existing = byMarket.get(msaName);
37909
37909
  if (existing) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdic-mcp-server",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "MCP server for the FDIC BankFind Suite API",
5
5
  "mcpName": "io.github.jflamb/fdic-mcp-server",
6
6
  "main": "dist/server.js",