Bancadia

MCP Reference

This page is a complete reference for the Bancadia MCP server — every JSON-RPC method it accepts, the two tools it currently routes, and every error it can return. It's written to be equally useful to a human integrating by hand and to an AI agent parsing this page to decide how to call the server.

In short: everything happens through a single endpoint — https://mcp.bancadia.com/. Most calls are a POST whose JSON-RPC method field determines behavior; the same endpoint also accepts GET (a standalone server-push stream) and DELETE (session termination) — see Session management below.

Transport

Every JSON-RPC interaction is sent as POST to https://mcp.bancadia.com/ (root path, trailing slash) with Content-Type: application/json and Accept: application/json, text/event-stream. The server may respond with either a plain application/json body (the common case, and the only mode documented in detail below) or a text/event-stream response carrying the same JSON-RPC object as a single SSE event — spec-compliant clients may request the latter by default, but no tool here emits intermediate progress events, so the two modes are equivalent in practice.

methodAuth requiredSession requiredDescription
initializeNoNo — this call creates the sessionMCP lifecycle handshake — protocol/capability negotiation. Must be called first; every other method depends on the session it issues.
tools/listNoYesReturns the manifest of callable tools with their JSON Schema.
tools/callYes (Bearer)YesInvokes a tool by name with arguments.
notifications/*n/aYesClient→server notifications (e.g. notifications/initialized). Any request that omits id entirely is treated as a notification.

Any other method value, or an unrecognized tool name passed to tools/call, returns a JSON-RPC error with HTTP status 404 and code -32601.

Calling initializefirst is now required. It's the only method that doesn't need an Mcp-Session-Id header — every other method (including notifications) does, since initialize is what issues that session ID in the first place. A request that skips straight to tools/list or tools/call without ever calling initialize fails with 400. See Session management below for the full lifecycle.

Session management

A session is created only by a successful initialize call, returned via the Mcp-Session-Id response header. Every subsequent request on the MCP endpoint — tools/list, tools/call, notifications, GET, DELETE — must echo that same value back as an Mcp-Session-Id request header:

Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

Sessions idle-expire after ~30 minutes of inactivity by default (a sliding window — every valid request resets the clock). This is a housekeeping window, not a held-open connection: each call is an ordinary independent HTTP request, and nothing stays open for 30 minutes.

A request missing the Mcp-Session-Id header (on any method other than initialize) gets 400. A request whose session has expired, or was never valid, gets 404 — call initialize again to get a new session. This is the expected, normal way a long-idle client resumes, not an error state to alarm on. See Errors below for the exact status/code combinations.

A client that wants to end its session immediately (e.g. explicit logout) rather than waiting for idle expiry can send DELETE — see below.

Authentication

tools/call requires a bearer token in the Authorization header. Tokens are obtained by registering at bancadia.com/developer/signup.

Authorization: Bearer bcd_YOUR_TOKEN_HERE

A missing header, a header without the Bearer prefix, or an unknown/revoked token all return HTTP 401 with JSON-RPC error code -32001:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Unauthorized. Register at bancadia.com/developer/signup to obtain an API token."
  }
}

initialize and tools/list do not require a token.

Rate limiting

Successful tools/call requests are subject to a per-token sliding-window rate limit (100 requests / 60s by default). Rate-limit headers are present on every tools/call response, success or 429 — never on initialize, tools/list, /health, or /.well-known/mcp, since only tools/call is rate-limited.

HeaderDescription
X-RateLimit-LimitMax requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp (seconds) when the window resets

Exceeding the limit returns HTTP 429 with JSON-RPC error code -32029:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32029, "message": "Rate limit exceeded." }
}

initialize

The standard MCP lifecycle handshake, and now the mandatory first call — no auth required, but every other method depends on the Mcp-Session-Id it issues. See Session management above.

Request

{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": { "name": "example-client", "version": "1.0.0" }
  }
}

Response

{
  "jsonrpc": "2.0",
  "id": 0,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": { "tools": {} },
    "serverInfo": { "name": "Bancadia MCP", "version": "2.0.0" }
  }
}

The HTTP response also carries an Mcp-Session-Id header — save it, you must send it back on every subsequent request:

Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

protocolVersionin the response is the client's requested version if this server supports it (currently 2025-06-18, 2025-03-26, or 2024-11-05), otherwise it falls back to the latest version this server supports rather than rejecting the request. capabilities only ever advertises tools — no resources, prompts, logging, or sampling, and the tool set is static per deployment (no tools.listChanged notifications).

MCP clients typically follow a successful initialize with a notifications/initialized notification — see below.

tools/list

Returns the manifest of callable tools, each with a JSON Schema inputSchema describing its arguments. No bearer token required, but the Mcp-Session-Id from your last initialize call is. Currently returns exactly two tools.

Request

POST https://mcp.bancadia.com/
Content-Type: application/json
Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "query_business_checking",
        "description": "Query the Bancadia registry for business checking account products using compound filter criteria. Returns active, verified listings from financial institutions. Optionally accepts target_industries/target_business_profiles to soft-rank results toward listings built for a given business type or stage — non-matching but eligible listings are still returned, just ranked lower.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "monthly_fee_max": { "type": "number", "description": "Maximum monthly fee" },
            "minimum_opening_deposit_max": { "type": "number", "description": "Maximum minimum opening deposit" },
            "entity_types_accepted": { "type": "array", "items": { "type": "string" }, "description": "Returns listings accepting all specified entity types (e.g. llc, s_corp)" },
            "available_states": { "type": "array", "items": { "type": "string" }, "description": "Returns listings available in all specified states" },
            "target_industries": { "type": "array", "items": { "type": "string", "enum": ["ecommerce", "retail_storefront", "restaurant_food_service", "content_creator_solopreneur", "professional_services", "real_estate", "healthcare_practice", "construction_trades", "trucking_logistics", "agriculture", "saas_tech", "nonprofit", "small_business_digital_first"] }, "description": "Soft-ranks results toward listings built for these business types. Does not exclude non-matching but otherwise-eligible listings." },
            "target_business_profiles": { "type": "array", "items": { "type": "string", "enum": ["early_stage_startup", "vc_backed", "bootstrapped_solopreneur", "established_smb", "high_growth", "side_hustle"] }, "description": "Soft-ranks results toward listings built for this business stage/shape. Does not exclude non-matching but otherwise-eligible listings." },
            "insurance_type": { "type": "string", "enum": ["fdic", "ncua", "uninsured"], "description": "Deposit insurance type" },
            "cash_deposit_available": { "type": "boolean", "description": "Whether cash deposits are supported" },
            "sub_accounts_supported": { "type": "boolean", "description": "Whether sub-accounts are supported" },
            "free_transactions_min": { "type": "number", "description": "Minimum free transactions per month" },
            "rtp_supported": { "type": "boolean", "description": "Whether real-time payments (any rail) are supported at all" },
            "rtp_network": { "type": "string", "enum": ["fednow", "rtp_network", "both", "none"], "description": "Which real-time payment rail is supported" },
            "accounting_integration_available": { "type": "boolean", "description": "Whether the account connects to any accounting software (e.g. QuickBooks, Xero)" },
            "tax_integration_available": { "type": "boolean", "description": "Whether the account connects to any tax-prep or tax-filing software/service" },
            "expense_integration_available": { "type": "boolean", "description": "Whether the account connects to any expense/spend-management software" },
            "interest_bearing": { "type": "boolean", "description": "Whether the account earns interest" },
            "apy_min": { "type": "number", "description": "Minimum APY (inclusive), for interest-bearing accounts" }
          },
          "additionalProperties": false
        }
      },
      {
        "name": "get_business_checking_listing",
        "description": "Get full detail on one specific business checking listing, including gotcha fees (business_deposit_fees, e.g. overdraft, NSF, dormancy) and feature narrative (business_deposit_account_features) not returned by query_business_checking's broad list results. Fees/features that apply to only one plan tier (e.g. a Standard/Plus/Premier ladder) are nested under that tier in plan_tiers[].fees / plan_tiers[].features; tier-agnostic ones are in the top-level general_fees / general_features. Use this as a follow-up after query_business_checking to dig deeper on one listing the caller already identified by its listing_slug.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "listing_slug": { "type": "string", "description": "The stable public identifier for the listing, as returned by query_business_checking" }
          },
          "required": ["listing_slug"],
          "additionalProperties": false
        }
      }
    ]
  }
}

A handful of other tool names — query_hysa, query_personal_savings, query_personal_checking, query_personal_cd, query_business_savings, query_business_cd — existed historically and may still be referenced in older material, but they are not currently routed. They don't appear in tools/list or /.well-known/mcp, and calling any of them returns the -32601 Unknown tool error described below. query_business_checking and get_business_checking_listing are the only tools available today.

notifications/initialized and other notifications

Per JSON-RPC 2.0, a request that omits id entirely is a notification and never receives a response body — the server acknowledges it with an empty HTTP 202. This applies to any id-less request, not just notifications/initialized (e.g. notifications/cancelled is handled identically). If your client sends this after a successful initialize, expect a bare 202 with no JSON body — don't try to parse one.

Like every method except initialize, notifications must also include the Mcp-Session-Id header from your last initialize call — omitting it returns 400 instead of 202.

// Request (no "id" field, session header required)
POST https://mcp.bancadia.com/
Content-Type: application/json
Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

{ "jsonrpc": "2.0", "method": "notifications/initialized" }

// Response: HTTP 202, empty body

tools/callquery_business_checking

Queries active, verified business checking account listings using compound filter criteria. Requires a bearer token and a valid Mcp-Session-Id header from your last initialize call.

When a user asks to "dig deeper" or "tell me more" about one named result from this tool, prefer calling get_business_checking_listing with that result's listing_slugrather than re-running this broader query — it's cheaper and returns strictly more detail than this tool provides. See below.

Arguments

All filters are optional and combine with AND semantics — every filter you supply must match for a listing to be returned. Array filters (entity_types_accepted, available_states) require every requested value to be present on a listing (i.e. "all of", not "any of"). Unrecognized argument names are rejected (additionalProperties: false).

Two exceptions to that AND-and-exclude model: target_industries and target_business_profiles are soft-rankingsignals, not filters — a listing that doesn't match either one is still returned as long as it passes every other (real, hard) filter. Matching listings are simply reordered ahead of non-matching ones; nothing is excluded on account of these two arguments. See the worked example below the response fields.

ParameterTypeDescription
monthly_fee_maxnumberMaximum monthly fee.
minimum_opening_deposit_maxnumberMaximum minimum opening deposit.
entity_types_acceptedstring[]Returns listings accepting all specified entity types. Valid values: llc, s_corp, c_corp, sole_prop, partnership, nonprofit. Not enforced server-side — unrecognized values simply never match.
available_statesstring[]Returns listings available in all specified states (two-letter codes). A listing whose available_states includes the literal value ALL always matches, regardless of which states are requested.
target_industriesstring[]Soft-ranking, not a filter — see the note above. Reorders matching listings ahead of non-matching ones; never excludes. Valid values: ecommerce, retail_storefront, restaurant_food_service, content_creator_solopreneur, professional_services, real_estate, healthcare_practice, construction_trades, trucking_logistics, agriculture, saas_tech, nonprofit, small_business_digital_first.
target_business_profilesstring[]Soft-ranking, not a filter — see the note above. Reorders matching listings ahead of non-matching ones; never excludes. Valid values: early_stage_startup, vc_backed, bootstrapped_solopreneur, established_smb, high_growth, side_hustle.
insurance_typestringDeposit insurance type. One of fdic, ncua, uninsured.
cash_deposit_availablebooleanWhether cash deposits are supported.
sub_accounts_supportedbooleanWhether sub-accounts are supported.
free_transactions_minnumberMinimum free transactions per month.
rtp_supportedbooleanWhether real-time payments (any rail) are supported at all.
rtp_networkstringWhich real-time payment rail is supported. One of fednow, rtp_network, both, none.
accounting_integration_availablebooleanWhether the account connects to any accounting software (e.g. QuickBooks, Xero). Category-level only — specific products aren’t filterable.
tax_integration_availablebooleanWhether the account connects to any tax-prep or tax-filing software/service.
expense_integration_availablebooleanWhether the account connects to any expense/spend-management software.
interest_bearingbooleanWhether the account earns interest.
apy_minnumberMinimum APY (inclusive), for interest-bearing accounts.

Request

POST https://mcp.bancadia.com/
Authorization: Bearer bcd_YOUR_TOKEN_HERE
Content-Type: application/json
Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "query_business_checking",
    "arguments": {
      "monthly_fee_max": 0,
      "rtp_supported": true,
      "rtp_network": "both",
      "accounting_integration_available": true,
      "entity_types_accepted": ["llc", "s_corp"],
      "available_states": ["CA", "NY"],
      "target_industries": ["professional_services"]
    }
  }
}

Response

Per the MCP spec, results are wrapped in a content: [{ type: "text", text: "<json-string>" }] block rather than returned as native JSON. text is a JSON-encoded string — your client must JSON.parse(text) to get the actual array of results.

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[{\"listing_slug\":\"example-bank-business-checking-pro\",\"institution_name\":\"Example Bank\",\"institution\":{\"display_name\":\"Example Bank\",\"website_url\":\"https://examplebank.com\",\"logo_url\":\"https://examplebank.com/logo.png\",\"institution_type\":\"regional_bank\",\"support_email\":\"[email protected]\"},\"product_name\":\"Business Checking Pro\",\"monthly_fee\":0,\"monthly_fee_waiver_condition\":null,\"minimum_opening_deposit\":0,\"entity_types_accepted\":[\"llc\",\"s_corp\"],\"available_states\":[\"ALL\"],\"target_industries\":[\"professional_services\"],\"target_business_profiles\":[\"established_smb\"],\"insurance_type\":\"fdic\",\"free_transactions_per_month\":100,\"cash_deposit_available\":true,\"cash_deposit_fee_per_100\":2.5,\"monthly_cash_deposit_limit\":5000,\"sub_accounts_supported\":true,\"rtp_supported\":true,\"rtp_network\":\"both\",\"accounting_integration_available\":true,\"tax_integration_available\":false,\"expense_integration_available\":true,\"interest_bearing\":true,\"apy\":1.25,\"apy_tiers\":null,\"outgoing_domestic_wire_fee\":15,\"incoming_domestic_wire_fee\":0,\"outgoing_international_wire_fee\":45,\"incoming_international_wire_fee\":15,\"multicurrency_support\":false,\"free_domestic_wires_per_month\":2,\"per_transaction_fee_after_limit\":0.5,\"atm_fee_reimbursement\":true,\"atm_fee_reimbursement_limit\":10,\"atm_network\":\"Allpoint\",\"overdraft_protection_available\":true,\"overdraft_line_of_credit_available\":false,\"daily_debit_limit\":5000,\"ach_debit_block_available\":true,\"positive_pay_available\":true,\"remote_deposit_capture\":true,\"bill_pay_available\":true,\"check_writing_available\":true,\"corporate_card_available\":true,\"virtual_cards_available\":true,\"physical_debit_card_available\":true,\"plan_tiers\":[{\"plan_name\":\"Standard\",\"monthly_fee\":0,\"monthly_fee_waiver_condition\":null,\"apy\":1.25,\"apy_max_balance_eligible\":null,\"apy_condition\":null,\"is_default\":true,\"sort_order\":0}],\"promotions\":[{\"bonus_amount\":300,\"condition_description\":\"Deposit $2,500 within 30 days\",\"minimum_deposit\":2500,\"expiry_date\":null,\"promo_url\":\"https://example.com/promo\"}],\"application_url\":\"https://example.com/apply\",\"last_modified\":\"2026-01-01T00:00:00Z\",\"is_verified\":true}]"
      }
    ]
  }
}

JSON.parse(text)yields an array of results (empty array if nothing matched, or if the underlying query errored — errors are not surfaced to the caller). The wire format above is intentionally compact — here's that same content[0].text, decoded and pretty-printed for readability:

[
  {
    "listing_slug": "example-bank-business-checking-pro",
    "institution_name": "Example Bank",
    "institution": {
      "display_name": "Example Bank",
      "website_url": "https://examplebank.com",
      "logo_url": "https://examplebank.com/logo.png",
      "institution_type": "regional_bank",
      "support_email": "[email protected]"
    },
    "product_name": "Business Checking Pro",
    "monthly_fee": 0,
    "monthly_fee_waiver_condition": null,
    "minimum_opening_deposit": 0,
    "entity_types_accepted": ["llc", "s_corp"],
    "available_states": ["ALL"],
    "target_industries": ["professional_services"],
    "target_business_profiles": ["established_smb"],
    "insurance_type": "fdic",
    "free_transactions_per_month": 100,
    "cash_deposit_available": true,
    "cash_deposit_fee_per_100": 2.5,
    "monthly_cash_deposit_limit": 5000,
    "sub_accounts_supported": true,
    "rtp_supported": true,
    "rtp_network": "both",
    "accounting_integration_available": true,
    "tax_integration_available": false,
    "expense_integration_available": true,
    "interest_bearing": true,
    "apy": 1.25,
    "apy_tiers": null,
    "outgoing_domestic_wire_fee": 15,
    "incoming_domestic_wire_fee": 0,
    "outgoing_international_wire_fee": 45,
    "incoming_international_wire_fee": 15,
    "multicurrency_support": false,
    "free_domestic_wires_per_month": 2,
    "per_transaction_fee_after_limit": 0.5,
    "atm_fee_reimbursement": true,
    "atm_fee_reimbursement_limit": 10,
    "atm_network": "Allpoint",
    "overdraft_protection_available": true,
    "overdraft_line_of_credit_available": false,
    "daily_debit_limit": 5000,
    "ach_debit_block_available": true,
    "positive_pay_available": true,
    "remote_deposit_capture": true,
    "bill_pay_available": true,
    "check_writing_available": true,
    "corporate_card_available": true,
    "virtual_cards_available": true,
    "physical_debit_card_available": true,
    "plan_tiers": [
      {
        "plan_name": "Standard",
        "monthly_fee": 0,
        "monthly_fee_waiver_condition": null,
        "apy": 1.25,
        "apy_max_balance_eligible": null,
        "apy_condition": null,
        "is_default": true,
        "sort_order": 0
      }
    ],
    "promotions": [
      {
        "bonus_amount": 300,
        "condition_description": "Deposit $2,500 within 30 days",
        "minimum_deposit": 2500,
        "expiry_date": null,
        "promo_url": "https://example.com/promo"
      }
    ],
    "application_url": "https://example.com/apply",
    "last_modified": "2026-01-01T00:00:00Z",
    "is_verified": true
  }
]

Each result object has this shape:

ParameterTypeDescription
institution_namestring | nullName of the financial institution. Kept for backward compatibility — see the nested institution object below for more detail.
institutionobject | nullNested detail on the institution — see the Institutionshape below. Null only if the listing's institution join unexpectedly failed to resolve.
product_namestringName of the product.
listing_slugstringStable, public identifier for this listing (e.g. found-business-checking) — pass this to get_business_checking_listing for a follow-up query on this specific result.
monthly_feenumberBase monthly fee in USD.
monthly_fee_waiver_conditionstring | nullCondition to waive the monthly fee, if any.
minimum_opening_depositnumberMinimum deposit required to open.
entity_types_acceptedstring[]Enum values from entity_type_enum (llc, s_corp, c_corp, sole_prop, partnership, nonprofit).
available_statesstring[]["ALL"] indicates nationwide availability.
target_industriesstring[]Which industry_vertical segment(s) this listing is tagged with — a soft-ranking signal only, not an eligibility requirement. Empty array [] for an untagged listing, never null.
target_business_profilesstring[]Which business_profile segment(s) this listing is tagged with — a soft-ranking signal only, not an eligibility requirement. Empty array [] for an untagged listing, never null.
insurance_typestringOne of fdic, ncua, uninsured.
free_transactions_per_monthinteger | nullFree transactions included per month.
cash_deposit_availableboolean | nullWhether cash deposits are supported.
sub_accounts_supportedboolean | nullWhether sub-accounts are supported.
rtp_supportedboolean | nullWhether real-time payments (any rail) are supported.
rtp_networkstring | nullOne of fednow, rtp_network, both, none; null when rtp_supported is false.
accounting_integration_availableboolean | nullConnects to accounting software.
tax_integration_availableboolean | nullConnects to tax-prep/filing software.
expense_integration_availableboolean | nullConnects to expense/spend-management software.
interest_bearingboolean | nullWhether the account earns interest.
apynumber | nullBest available APY for indexing — mirrors the highest APY across plan_tiers if the product has multiple.
apy_tiersobject | nullCanonical balance-tiered rate schema — see ApyTiers below. Only populated when interest_bearing is true and the rate varies by balance; null for flat-rate or non-interest accounts. The flat apy field above always holds the best available rate regardless of this structure.
outgoing_domestic_wire_feenumber | nullFee for outgoing domestic wires.
incoming_domestic_wire_feenumber | nullFee for incoming domestic wires.
incoming_international_wire_feenumber | nullFee for incoming international wires.
outgoing_international_wire_feenumber | nullFee for outgoing international wires.
multicurrency_supportboolean | nullWhether the account supports holding or transacting in multiple currencies.
cash_deposit_fee_per_100number | nullFee charged per $100 of cash deposited.
monthly_cash_deposit_limitnumber | nullMonthly cash deposit limit before fees or restrictions apply.
free_domestic_wires_per_monthinteger | nullNumber of domestic wires included free per month.
per_transaction_fee_after_limitnumber | nullFee per transaction once the included free-transaction limit is exceeded.
atm_fee_reimbursementboolean | nullWhether out-of-network ATM fees are reimbursed.
atm_fee_reimbursement_limitnumber | nullMonthly cap on reimbursed ATM fees, if reimbursement is offered.
atm_networkstring | nullName of the fee-free ATM network, if any.
overdraft_protection_availableboolean | nullWhether overdraft protection (e.g. linked-account transfer) is available.
overdraft_line_of_credit_availableboolean | nullWhether an overdraft line of credit is available.
daily_debit_limitnumber | nullDaily debit card spending limit.
ach_debit_block_availableboolean | nullWhether ACH debit blocking is available.
positive_pay_availableboolean | nullWhether positive pay fraud protection is available.
remote_deposit_captureboolean | nullWhether remote (mobile/desktop) check deposit is available.
bill_pay_availableboolean | nullWhether bill pay is available.
check_writing_availableboolean | nullWhether paper check writing is available.
corporate_card_availableboolean | nullWhether corporate charge/credit cards are available.
virtual_cards_availableboolean | nullWhether virtual debit/charge cards are available.
physical_debit_card_availableboolean | nullWhether a physical debit card is available.
plan_tiersPlanTier[]One row per paid subscription plan (e.g. a Bluevine-style Standard/Plus/Premier ladder) whose pricing/APY differs from the listing's flat default. Empty array for products with a single, unconditional pricing tier. See PlanTier below — note that its features and fees arrays are only present in get_business_checking_listing's response, not here.
promotionsPromotion[]One-to-many welcome/bonus offers for this listing. Empty array if none. See Promotion below.
application_urlstring (uri)Where to apply for this product.
last_modifiedstring (date-time)When the listing was last updated.
is_verifiedbooleanWhether this listing has been verified by Bancadia.

All of the fields above besides the identifiers, flags with an explicit default, and plan_tiers/promotions are nullable — nullmeans "not applicable / not populated for this listing," the same convention already used by fields like apy and rtp_network. Most of these are not filterable — this section only covers what each result object includes, not what you can query on. target_industries/target_business_profilesare the one exception: they're both a response field and a request argument (see Arguments above), because the request-side values are used to soft-rank, and the response echoes back what a listing is actually tagged with.

Worked example: calling with { "target_industries": ["content_creator_solopreneur"] } ranks listings tagged content_creator_solopreneurfirst, followed by listings tagged with zero matching industries, in the same relative (monthly-fee-ascending) order they'd have appeared in without the argument. A listing that's eligible but simply hasn't been tagged with that industry is not removed from the results — it just ranks lower. This is why target_industries/target_business_profiles are documented separately from the "every filter must match" semantics that govern every other argument on this tool.

Institution

The nested object at institution on every result.

ParameterTypeDescription
display_namestring | nullInstitution’s public-facing name.
website_urlstring (uri) | nullInstitution’s marketing website.
logo_urlstring (uri) | nullInstitution’s logo image.
institution_typestringOne of national_bank, regional_bank, community_bank, credit_union, neobank, fintech.
support_emailstring (email) | nullInstitution’s support contact address.

PlanTier

One row per paid subscription plan whose pricing or APY differs from the listing's flat default (e.g. a Standard/Plus/Premier ladder). At most one tier per listing has is_default: true — that tier's values seed the listing's flat monthly_fee / apy fields above.

ParameterTypeDescription
plan_namestringDisplay name of the plan (e.g. "Standard", "Plus").
monthly_feenumberMonthly fee for this plan.
monthly_fee_waiver_conditionstring | nullCondition to waive this plan’s monthly fee, if any.
apynumber | nullAPY on this plan, or null if this plan does not earn interest.
apy_max_balance_eligiblenumber | nullMaximum balance eligible to earn interest on this plan; null = no cap.
apy_conditionstring | nullActivity/eligibility requirement to earn this plan’s stated APY.
is_defaultbooleanMarks the plan whose values seed the listing’s flat monthly_fee / apy fields. At most one true per listing.
sort_orderintegerDisplay order, cheapest to priciest (0 = cheapest).
featuresFeature[]Feature rows scoped to this plan tier only. Tier-agnostic features are returned separately in general_features. Only present in get_business_checking_listing's response — absent from query_business_checking's plan_tiers.
feesAdditionalFee[]Fee rows scoped to this plan tier only. Tier-agnostic fees are returned separately in general_fees. Only present in get_business_checking_listing's response — absent from query_business_checking's plan_tiers.

Promotion

One-to-many welcome/bonus offers for this listing. Empty array if none.

ParameterTypeDescription
bonus_amountintegerDollar amount of the bonus.
condition_descriptionstringHuman-readable description of how to earn the bonus.
minimum_depositinteger | nullMinimum deposit required to qualify, if any.
expiry_datestring (date) | nullDate the promotion expires, if any.
promo_urlstring (uri) | nullLink with more detail on the promotion, if any.

ApyTiers

The shape of apy_tiers when populated — a canonical balance-tiered rate schema (bancadia-db migration 037, sharing its contract with migration 034) enforced across every business checking listing that has one, not a per-listing free-form shape. Object or null; null for flat-rate or non-interest accounts, or when the rate doesn't vary by balance.

ParameterTypeDescription
effective_datestring (date)Date this rate schedule took effect.
relationship_conditionstring | nullQualifying criteria for the relationship rate, or null if this product has no relationship rate.
tiersApyTier[]The balance ladder itself — one or more ApyTier objects, ordered from lowest to highest min_balance. See ApyTier below.

ApyTier (each element of tiers)

One balance band and the rate(s) that apply within it.

ParameterTypeDescription
min_balanceintegerWhole-dollar amount — the lower bound of this tier, inclusive.
max_balanceinteger | nullWhole-dollar amount — the upper bound of this tier, inclusive. Null = no upper bound (this is the top tier).
standard{ interest_rate: number, apy: number }The rate every customer in this balance tier earns. Both interest_rate and apy are decimals (e.g. 0.0130 = 1.30%) — kept as two separate fields because compounding frequency makes them differ slightly.
relationship{ interest_rate: number, apy: number }A higher rate available to customers who meet the relationship_condition above (e.g. holding a linked account, or a minimum combined relationship balance). Omitted entirely from this tier's object — not present as null — when the product has no relationship rate for this tier.

Putting it together, a fully populated apy_tiers looks like this:

{
  "effective_date": "2026-01-01",
  "relationship_condition": "Maintain a linked Bancadia Business Checking account",
  "tiers": [
    {
      "min_balance": 0,
      "max_balance": 24999,
      "standard": { "interest_rate": 0.0100, "apy": 0.0100 },
      "relationship": { "interest_rate": 0.0130, "apy": 0.0130 }
    },
    {
      "min_balance": 25000,
      "max_balance": null,
      "standard": { "interest_rate": 0.0150, "apy": 0.0151 },
      "relationship": { "interest_rate": 0.0180, "apy": 0.0182 }
    }
  ]
}

In this example, a customer with a $10,000 balance who doesn't meet the relationship condition earns 1.00% APY; a customer with $30,000 who does meet it earns 1.82% APY. If a product has no relationship rate at all, every tier simply omits the relationship key and relationship_condition is null. The flat apyfield on the base result always mirrors the single best (highest) rate across this whole structure, for indexing — it's redundant with apy_tiers, not a separate figure.

tools/callget_business_checking_listing

Returns full detail on a single business checking listing. Same auth and session requirements as query_business_checking — a bearer token and a valid Mcp-Session-Id header from your last initialize call. Rate limiting and every error code behave identically to query_business_checking too — nothing special about this tool on that front.

This is the tool to call for follow-up questions like "tell me more about X" or "what are the gotcha fees on X" after a query_business_checking result — pass the listing_slug from that result rather than re-running the broader query. It returns everything query_business_checking returns for a listing, plus general_fees and general_features — the two one-to-many tables (business_deposit_fees, business_deposit_account_features) deliberately excluded from query_business_checking's broader list response to keep multi-listing payloads bounded in size. general_fees/general_features hold only the rows with no plan_tier_id— fees or features scoped to one specific plan tier (e.g. a sub-account limit that only applies on the "Plus" plan) are nested instead under that tier, as plan_tiers[].fees / plan_tiers[].features (see the PlanTiershape above). Returns an empty array (not an error) if the slug doesn't match an active listing.

Arguments

ParameterTypeDescription
listing_slugstringThe stable public identifier for the listing (e.g. found-business-checking), as returned by query_business_checking. Not the internal database id, which is never exposed. Unrecognized argument names are rejected (additionalProperties: false).

Request

POST https://mcp.bancadia.com/
Authorization: Bearer bcd_YOUR_TOKEN_HERE
Content-Type: application/json
Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_business_checking_listing",
    "arguments": { "listing_slug": "found-business-checking" }
  }
}

Response

Same envelope as every other tool — JSON.parse(result.content[0].text) yields an array with either one element (a match was found) or zero elements (no active listing has that listing_slug, or the argument was missing/malformed). There is no dedicated "not found" error — an empty array covers both cases.

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[{\"listing_slug\":\"example-bank-business-checking-pro\",\"institution_name\":\"Example Bank\",\"institution\":{\"display_name\":\"Example Bank\",\"website_url\":\"https://examplebank.com\",\"logo_url\":\"https://examplebank.com/logo.png\",\"institution_type\":\"regional_bank\",\"support_email\":\"[email protected]\"},\"product_name\":\"Business Checking Pro\",\"monthly_fee\":0,\"monthly_fee_waiver_condition\":null,\"minimum_opening_deposit\":0,\"entity_types_accepted\":[\"llc\",\"s_corp\"],\"available_states\":[\"ALL\"],\"target_industries\":[\"professional_services\"],\"target_business_profiles\":[\"established_smb\"],\"insurance_type\":\"fdic\",\"free_transactions_per_month\":100,\"cash_deposit_available\":true,\"cash_deposit_fee_per_100\":2.5,\"monthly_cash_deposit_limit\":5000,\"sub_accounts_supported\":true,\"rtp_supported\":true,\"rtp_network\":\"both\",\"accounting_integration_available\":true,\"tax_integration_available\":false,\"expense_integration_available\":true,\"interest_bearing\":true,\"apy\":1.25,\"apy_tiers\":null,\"outgoing_domestic_wire_fee\":15,\"incoming_domestic_wire_fee\":0,\"outgoing_international_wire_fee\":45,\"incoming_international_wire_fee\":15,\"multicurrency_support\":false,\"free_domestic_wires_per_month\":2,\"per_transaction_fee_after_limit\":0.5,\"atm_fee_reimbursement\":true,\"atm_fee_reimbursement_limit\":10,\"atm_network\":\"Allpoint\",\"overdraft_protection_available\":true,\"overdraft_line_of_credit_available\":false,\"daily_debit_limit\":5000,\"ach_debit_block_available\":true,\"positive_pay_available\":true,\"remote_deposit_capture\":true,\"bill_pay_available\":true,\"check_writing_available\":true,\"corporate_card_available\":true,\"virtual_cards_available\":true,\"physical_debit_card_available\":true,\"plan_tiers\":[{\"plan_name\":\"Standard\",\"monthly_fee\":0,\"monthly_fee_waiver_condition\":null,\"apy\":1.25,\"apy_max_balance_eligible\":null,\"apy_condition\":null,\"is_default\":true,\"sort_order\":0,\"features\":[],\"fees\":[]},{\"plan_name\":\"Plus\",\"monthly_fee\":15,\"monthly_fee_waiver_condition\":\"Waived with $10,000 average daily balance\",\"apy\":1.75,\"apy_max_balance_eligible\":null,\"apy_condition\":null,\"is_default\":false,\"sort_order\":1,\"features\":[{\"category\":\"account_management\",\"description\":\"Maximum number of sub-accounts included with this plan.\",\"value\":10}],\"fees\":[]}],\"promotions\":[{\"bonus_amount\":300,\"condition_description\":\"Deposit $2,500 within 30 days\",\"minimum_deposit\":2500,\"expiry_date\":null,\"promo_url\":\"https://example.com/promo\"}],\"application_url\":\"https://example.com/apply\",\"last_modified\":\"2026-01-01T00:00:00Z\",\"is_verified\":true,\"general_fees\":[{\"fee_type\":\"overdraft\",\"amount\":35,\"amount_description\":null,\"eligibility_criteria\":null,\"tiers\":null,\"waivable\":false,\"waiver_condition\":null}],\"general_features\":[{\"category\":\"cash_handling\",\"description\":\"Free cash deposits up to $2,000/mo\",\"value\":2000},{\"category\":\"fraud_protection\",\"description\":\"Instant card freeze\",\"value\":null}]}]"
      }
    ]
  }
}

The wire format above is intentionally compact — here's that same content[0].text, decoded and pretty-printed for readability:

[
  {
    "listing_slug": "example-bank-business-checking-pro",
    "institution_name": "Example Bank",
    "institution": {
      "display_name": "Example Bank",
      "website_url": "https://examplebank.com",
      "logo_url": "https://examplebank.com/logo.png",
      "institution_type": "regional_bank",
      "support_email": "[email protected]"
    },
    "product_name": "Business Checking Pro",
    "monthly_fee": 0,
    "monthly_fee_waiver_condition": null,
    "minimum_opening_deposit": 0,
    "entity_types_accepted": ["llc", "s_corp"],
    "available_states": ["ALL"],
    "target_industries": ["professional_services"],
    "target_business_profiles": ["established_smb"],
    "insurance_type": "fdic",
    "free_transactions_per_month": 100,
    "cash_deposit_available": true,
    "cash_deposit_fee_per_100": 2.5,
    "monthly_cash_deposit_limit": 5000,
    "sub_accounts_supported": true,
    "rtp_supported": true,
    "rtp_network": "both",
    "accounting_integration_available": true,
    "tax_integration_available": false,
    "expense_integration_available": true,
    "interest_bearing": true,
    "apy": 1.25,
    "apy_tiers": null,
    "outgoing_domestic_wire_fee": 15,
    "incoming_domestic_wire_fee": 0,
    "outgoing_international_wire_fee": 45,
    "incoming_international_wire_fee": 15,
    "multicurrency_support": false,
    "free_domestic_wires_per_month": 2,
    "per_transaction_fee_after_limit": 0.5,
    "atm_fee_reimbursement": true,
    "atm_fee_reimbursement_limit": 10,
    "atm_network": "Allpoint",
    "overdraft_protection_available": true,
    "overdraft_line_of_credit_available": false,
    "daily_debit_limit": 5000,
    "ach_debit_block_available": true,
    "positive_pay_available": true,
    "remote_deposit_capture": true,
    "bill_pay_available": true,
    "check_writing_available": true,
    "corporate_card_available": true,
    "virtual_cards_available": true,
    "physical_debit_card_available": true,
    "plan_tiers": [
      {
        "plan_name": "Standard",
        "monthly_fee": 0,
        "monthly_fee_waiver_condition": null,
        "apy": 1.25,
        "apy_max_balance_eligible": null,
        "apy_condition": null,
        "is_default": true,
        "sort_order": 0,
        "features": [],
        "fees": []
      },
      {
        "plan_name": "Plus",
        "monthly_fee": 15,
        "monthly_fee_waiver_condition": "Waived with $10,000 average daily balance",
        "apy": 1.75,
        "apy_max_balance_eligible": null,
        "apy_condition": null,
        "is_default": false,
        "sort_order": 1,
        "features": [
          {
            "category": "account_management",
            "description": "Maximum number of sub-accounts included with this plan.",
            "value": 10
          }
        ],
        "fees": []
      }
    ],
    "promotions": [
      {
        "bonus_amount": 300,
        "condition_description": "Deposit $2,500 within 30 days",
        "minimum_deposit": 2500,
        "expiry_date": null,
        "promo_url": "https://example.com/promo"
      }
    ],
    "application_url": "https://example.com/apply",
    "last_modified": "2026-01-01T00:00:00Z",
    "is_verified": true,
    "general_fees": [
      {
        "fee_type": "overdraft",
        "amount": 35,
        "amount_description": null,
        "eligibility_criteria": null,
        "tiers": null,
        "waivable": false,
        "waiver_condition": null
      }
    ],
    "general_features": [
      {
        "category": "cash_handling",
        "description": "Free cash deposits up to $2,000/mo",
        "value": 2000
      },
      {
        "category": "fraud_protection",
        "description": "Instant card freeze",
        "value": null
      }
    ]
  }
]

Note in the decoded example above that the "Standard" tier has empty fees/featuresarrays while "Plus" has a tier-scoped feature, and the account-wide overdraft fee and two account-wide features are surfaced separately in general_fees / general_features rather than under any one tier. Each result object has this shape:

ParameterTypeDescription
listing_slugstringStable, public identifier for this listing — the same value you passed in as the listing_slug argument.
institution_namestring | nullName of the financial institution. Kept for backward compatibility — see the nested institution object below for more detail.
institutionInstitution | nullNested detail on the institution — see Institutionbelow. Null only if the listing's institution join unexpectedly failed to resolve.
product_namestringName of the product.
monthly_feenumberBase monthly fee in USD.
monthly_fee_waiver_conditionstring | nullCondition to waive the monthly fee, if any.
minimum_opening_depositnumberMinimum deposit required to open.
entity_types_acceptedstring[]Enum values from entity_type_enum (llc, s_corp, c_corp, sole_prop, partnership, nonprofit).
available_statesstring[]["ALL"] indicates nationwide availability.
target_industriesstring[]Which industry_vertical segment(s) this listing is tagged with — a soft-ranking signal only, not an eligibility requirement. Empty array [] for an untagged listing, never null.
target_business_profilesstring[]Which business_profile segment(s) this listing is tagged with — a soft-ranking signal only, not an eligibility requirement. Empty array [] for an untagged listing, never null.
insurance_typestringOne of fdic, ncua, uninsured.
free_transactions_per_monthinteger | nullFree transactions included per month.
cash_deposit_availableboolean | nullWhether cash deposits are supported.
cash_deposit_fee_per_100number | nullFee charged per $100 of cash deposited, above monthly_cash_deposit_limit (if any).
monthly_cash_deposit_limitnumber | nullAmount of cash deposits per month before cash_deposit_fee_per_100 applies. Null = no limit.
sub_accounts_supportedboolean | nullWhether sub-accounts are supported.
rtp_supportedboolean | nullWhether real-time payments (any rail) are supported.
rtp_networkstring | nullOne of fednow, rtp_network, both, none; null when rtp_supported is false.
accounting_integration_availableboolean | nullConnects to accounting software.
tax_integration_availableboolean | nullConnects to tax-prep/filing software.
expense_integration_availableboolean | nullConnects to expense/spend-management software.
interest_bearingboolean | nullWhether the account earns interest.
apynumber | nullBest available APY for indexing — mirrors the highest APY across plan_tiers if the product has multiple.
apy_tiersApyTiers | nullCanonical balance-tiered rate schema — see ApyTiers below. Only populated when interest_bearing is true and the rate varies by balance; null for flat-rate or non-interest accounts.
outgoing_domestic_wire_feenumber | nullFee for outgoing domestic wires.
incoming_domestic_wire_feenumber | nullFee for incoming domestic wires.
outgoing_international_wire_feenumber | nullFee for outgoing international wires.
incoming_international_wire_feenumber | nullFee for incoming international wires.
multicurrency_supportboolean | nullWhether the account supports holding or transacting in multiple currencies.
free_domestic_wires_per_monthinteger | nullNumber of domestic wires included free per month.
per_transaction_fee_after_limitnumber | nullFee per transaction once the included free-transaction limit is exceeded.
atm_fee_reimbursementboolean | nullWhether out-of-network ATM fees are reimbursed.
atm_fee_reimbursement_limitnumber | nullMonthly cap on reimbursed ATM fees, if reimbursement is offered.
atm_networkstring | nullName of the fee-free ATM network, if any.
overdraft_protection_availableboolean | nullWhether overdraft protection (e.g. linked-account transfer) is available.
overdraft_line_of_credit_availableboolean | nullWhether an overdraft line of credit is available.
daily_debit_limitnumber | nullDaily debit card spending limit.
ach_debit_block_availableboolean | nullWhether ACH debit blocking is available.
positive_pay_availableboolean | nullWhether positive pay fraud protection is available.
remote_deposit_captureboolean | nullWhether remote (mobile/desktop) check deposit is available.
bill_pay_availableboolean | nullWhether bill pay is available.
check_writing_availableboolean | nullWhether paper check writing is available.
corporate_card_availableboolean | nullWhether corporate charge/credit cards are available.
virtual_cards_availableboolean | nullWhether virtual debit/charge cards are available.
physical_debit_card_availableboolean | nullWhether a physical debit card is available.
plan_tiersPlanTier[]One row per paid subscription plan (e.g. a Bluevine-style Standard/Plus/Premier ladder). Empty array for products with a single, unconditional pricing tier. See PlanTier below — unlike query_business_checking, each tier here includes its own features and fees arrays.
promotionsPromotion[]One-to-many welcome/bonus offers for this listing. Empty array if none. See Promotion below.
application_urlstring (uri)Where to apply for this product.
last_modifiedstring (date-time)When the listing was last updated.
is_verifiedbooleanWhether this listing has been verified by Bancadia.
general_feesAdditionalFee[]Fees with no plan_tier_id — apply account-wide rather than to one specific plan tier. See AdditionalFee below, including the override note — a tier-specific fee of the same fee_type in plan_tiers[].feessupersedes the matching row here for that plan, it doesn't add to it. Not present in query_business_checking's response.
general_featuresFeature[]Features with no plan_tier_id — apply account-wide rather than to one specific plan tier. See Feature below. Not present in query_business_checking's response.

Institution

The nested object at institution. Identical shape to the Institution documented under query_business_checking above.

ParameterTypeDescription
display_namestring | nullInstitution’s public-facing name.
website_urlstring (uri) | nullInstitution’s marketing website.
logo_urlstring (uri) | nullInstitution’s logo image.
institution_typestringOne of national_bank, regional_bank, community_bank, credit_union, neobank, fintech.
support_emailstring (email) | nullInstitution’s support contact address.

PlanTier

One row per paid subscription plan whose pricing or APY differs from the listing's flat default (e.g. a Standard/Plus/Premier ladder). At most one tier per listing has is_default: true — that tier's values seed the listing's flat monthly_fee / apy fields above. Unlike query_business_checking, every tier here carries its own features and feesarrays (both may be empty, as with the "Standard" tier in the example above).

ParameterTypeDescription
plan_namestringDisplay name of the plan (e.g. "Standard", "Plus").
monthly_feenumberMonthly fee for this plan.
monthly_fee_waiver_conditionstring | nullCondition to waive this plan’s monthly fee, if any.
apynumber | nullAPY on this plan, or null if this plan does not earn interest.
apy_max_balance_eligiblenumber | nullMaximum balance eligible to earn interest on this plan; null = no cap.
apy_conditionstring | nullActivity/eligibility requirement to earn this plan’s stated APY.
is_defaultbooleanMarks the plan whose values seed the listing’s flat monthly_fee / apy fields. At most one true per listing.
sort_orderintegerDisplay order, cheapest to priciest (0 = cheapest).
featuresFeature[]Feature rows scoped to this plan tier only (rows from business_deposit_account_features whose plan_tier_id matches this tier). Tier-agnostic features are returned separately in the top-level general_features. See Feature below.
feesAdditionalFee[]Fee rows scoped to this plan tier only (rows from business_deposit_fees whose plan_tier_id matches this tier). A row here overrides — rather than adds to — any row of the same fee_type in the top-level general_fees; see the override note under AdditionalFee below.

Promotion

One-to-many welcome/bonus offers for this listing. Empty array if none. Identical shape to the Promotion documented under query_business_checking above.

ParameterTypeDescription
bonus_amountintegerDollar amount of the bonus.
condition_descriptionstringHuman-readable description of how to earn the bonus.
minimum_depositinteger | nullMinimum deposit required to qualify, if any.
expiry_datestring (date) | nullDate the promotion expires, if any.
promo_urlstring (uri) | nullLink with more detail on the promotion, if any.

ApyTiers

The shape of apy_tiers when populated — a canonical balance-tiered rate schema (bancadia-db migration 037, sharing its contract with migration 034) enforced across every business checking listing that has one, not a per-listing free-form shape. Object or null; null for flat-rate or non-interest accounts, or when the rate doesn't vary by balance. Identical shape to the ApyTiers documented under query_business_checking above.

ParameterTypeDescription
effective_datestring (date)Date this rate schedule took effect.
relationship_conditionstring | nullQualifying criteria for the relationship rate, or null if this product has no relationship rate.
tiersApyTier[]The balance ladder itself — one or more ApyTier objects, ordered from lowest to highest min_balance. See ApyTier below.

ApyTier (each element of tiers)

One balance band and the rate(s) that apply within it.

ParameterTypeDescription
min_balanceintegerWhole-dollar amount — the lower bound of this tier, inclusive.
max_balanceinteger | nullWhole-dollar amount — the upper bound of this tier, inclusive. Null = no upper bound (this is the top tier).
standard{ interest_rate: number, apy: number }The rate every customer in this balance tier earns. Both interest_rate and apy are decimals (e.g. 0.0130 = 1.30%) — kept as two separate fields because compounding frequency makes them differ slightly.
relationship{ interest_rate: number, apy: number }A higher rate available to customers who meet the relationship_condition above (e.g. holding a linked account, or a minimum combined relationship balance). Omitted entirely from this tier's object — not present as null — when the product has no relationship rate for this tier.

Putting it together, a fully populated apy_tiers looks like this:

{
  "effective_date": "2026-01-01",
  "relationship_condition": "Maintain a linked Bancadia Business Checking account",
  "tiers": [
    {
      "min_balance": 0,
      "max_balance": 24999,
      "standard": { "interest_rate": 0.0100, "apy": 0.0100 },
      "relationship": { "interest_rate": 0.0130, "apy": 0.0130 }
    },
    {
      "min_balance": 25000,
      "max_balance": null,
      "standard": { "interest_rate": 0.0150, "apy": 0.0151 },
      "relationship": { "interest_rate": 0.0180, "apy": 0.0182 }
    }
  ]
}

In this example, a customer with a $10,000 balance who doesn't meet the relationship condition earns 1.00% APY; a customer with $30,000 who does meet it earns 1.82% APY. If a product has no relationship rate at all, every tier simply omits the relationship key and relationship_condition is null. The flat apyfield on the base result always mirrors the single best (highest) rate across this whole structure, for indexing — it's redundant with apy_tiers, not a separate figure.

AdditionalFee

One row from business_deposit_fees, only for fee_type values that have no dedicated flat column on the top-level result shape (e.g. overdraft, non_sufficient_funds, dormancy — not wire_domestic_outgoing etc., which are already covered by outgoing_domestic_wire_fee and friends above; this split avoids the same fee ever being represented twice by two sources that could disagree). This is the shape of both the top-level general_fees array and every plan_tiers[].fees array.

Plan-tier fees override, they don't add. If the same fee_type appears both in the top-level general_fees (a row with no plan_tier_id) and in one specific tier's plan_tiers[].fees, the tier-specific row is that plan's effective fee for that fee_type — it supersedes the general one rather than stacking with it. To find what a given plan actually pays for a fee_type: look for it in that plan's plan_tiers[].fees first; only fall back to general_feesif it's not there. This API does not pre-resolve that for you — it returns both rows as-is, so a caller that naively sums or lists every fee it sees will double-count any overridden ones. (This mirrors the resolution contract documented on business_deposit_fees.plan_tier_id in bancadia-db migration 040 — e.g. a plan that discounts wire fees is modeled as one override row for that plan, not an additional fee.)

ParameterTypeDescription
fee_typestringOne of monthly_maintenance, overdraft, non_sufficient_funds, account_opening, account_closing, minimum_balance, excess_transaction, atm_foreign, paper_statement, dormancy, returned_item, stop_payment, card_replacement, foreign_transaction, other.
amountnumber | nullFlat fee amount in USD, if applicable — the standard/lowest rate when tiers is populated.
amount_descriptionstring | nullFree-text description of the amount, used when the fee isn’t a simple flat number.
eligibility_criteriastring | nullFree-text description of when this fee applies.
tiersFeeVariant[] | nullPopulated only when a single fee_type has multiple rates that differ by channel or condition (e.g. online vs. branch wire fees) — not a balance-tiered structure like ApyTiers above, despite the similar name. Null if the fee is a single flat amount. See FeeVariant below.
waivablebooleanWhether this fee can be waived.
waiver_conditionstring | nullCondition under which the fee is waived, if waivable.

FeeVariant (each element of tiers)

One rate variant for a fee that differs by channel or condition (bancadia-db migration 032's canonical schema for business_deposit_fees.tiers — every listing that populates this field follows the same fixed shape).

ParameterTypeDescription
channelstringHow/where the transaction is initiated, e.g. "online", "branch", "waived".
amountnumberFee in dollars for this channel.
descriptionstringHuman-readable condition or context for this variant.

Example — an outgoing domestic wire fee that's cheaper online and waived when sent by a banker on the caller's behalf:

[
  { "channel": "online", "amount": 25.00, "description": "Via online banking or mobile app" },
  { "channel": "branch", "amount": 35.00, "description": "With the help of a banker" },
  { "channel": "waived", "amount": 0.00, "description": "If originally sent via a banker referral" }
]

Feature

One row from business_deposit_account_features — narrative/marketing feature callouts, richer than the raw booleans on the top-level result shape, sorted by display order. This is the shape of both the top-level general_features array and every plan_tiers[].features array.

Unlike AdditionalFee, plan-tier features are additive, not an override— a feature row scoped to one plan tier is an extra fact about that plan (e.g. a Premier-only capability, or that plan's specific sub-account limit via value), not a replacement for some general-features row of the same description. There is no fallback to resolve here: a plan's full feature set is simply general_features plus that plan's own plan_tiers[].features, taken together (per bancadia-db migration 041).

ParameterTypeDescription
categorystringOne of payment_rails, cash_handling, cards_and_atm, online_banking, fraud_protection, account_management, platform_integrations, other.
descriptionstringHuman-readable description of the feature.
valuenumber | nullNullable quantified value for the feature (e.g. a dollar limit or a count).

GET — standalone SSE stream

GET https://mcp.bancadia.com/ with Accept: text/event-stream and a valid Mcp-Session-Id header opens a stream for messages the server initiates outside of a specific tools/call response (e.g. a future progress or sampling push). No tool currently sends anything on it — the stream exists so that MCP client libraries which open it unconditionally after initialize don't fail.

The server sends periodic keep-alive pingevents and closes the stream itself after roughly a minute; well-behaved clients reconnect automatically. This is handled by spec-compliant client libraries, if at all — if you're integrating by hand (Option B in the Quickstart), you never need to call this.

GET without an Accept: text/event-stream header returns 405 with no body.

DELETE — session termination

A client that's done with a session (e.g. the user closes a chat or tab) can end it immediately rather than waiting for idle expiry:

DELETE https://mcp.bancadia.com/
Mcp-Session-Id: 7e93bc81-b832-4c8b-9834-1bac55106e22

Returns 204 No Content with an empty body. This is a courtesy, not something a caller must remember to do — an unterminated session simply idle-expires (see Session management above).

Errors

HTTP statusJSON-RPC codeMeaning
400-32600Missing Mcp-Session-Id header on any request other than initialize, or an MCP-Protocol-Versionheader value this server doesn't support. No JSON-RPC body if the request was a notification (no id).
401-32001Unauthorized — missing, malformed, or unknown/revoked bearer token on tools/call.
403The Originrequest header is present but not on the server's allowlist. No JSON-RPC body — a plain text/empty response. Only relevant to browser-based callers; curl/SDK/CLI clients don't send Origin and are unaffected in practice.
404-32601Unknown method (anything other than initialize, tools/list, tools/call) or unknown/unrouted tool name passed to tools/call.
404-32600Different case, same status. The Mcp-Session-Id header doesn't match a known, unexpired session. Call initialize again to get a new one — this is the normal way a long-idle client resumes, not an error state to alarm on.
405GET request whose Accept header doesn't include text/event-stream. No body.
429-32029Per-token rate limit exceeded.

The two 404 rows share an HTTP status but mean different things and need different fixes — fix the tool/method name for -32601, re-initialize for -32600. 403 and 405 are also worth noting specially: unlike every other error case here, they return no JSON-RPC body at all — just a bare HTTP status with a plain-text or empty body. A client that assumes every non-2xx response has a parseable error.code will break on these two.

Example — missing session header, and an unknown/expired session (both an id-bearing request would get):

// 400 — missing Mcp-Session-Id
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32600, "message": "Missing Mcp-Session-Id header." } }

// 404 — unknown/expired session
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32600, "message": "Session not found or expired. Re-initialize." } }

Example — calling an unrouted or unknown tool name:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32601, "message": "Unknown tool: query_hysa" }
}

Discovery & health endpoints

Two unauthenticated GET endpoints exist alongside the JSON-RPC endpoint:

ParameterTypeDescription
GET /healthLiveness check. Returns { "status": "ok" }.
GET /.well-known/mcpPublic discovery document — advertises the JSON-RPC endpoint URL and a summary (name + description, no inputSchema) of every currently-routed tool. Useful for agents that discover capabilities by URL convention rather than a JSON-RPC handshake. Bancadia's main site mirrors this at bancadia.com/.well-known/mcp.