Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,545Letters: 14Defects: 1,324counted just now
teppi

Server definition

Hash
sha256:c0c0f3be5f09602aa74916af99b272283de43cb82524c3806f38a83ffeb85401
What it is
What a remote MCP server returned when asked what it offers: 34 tools

The blob, as servednamed by its sha256

{ "instructions": "Banking intelligence tools for AI agents. Free tools (no auth): SWIFT/BIC lookup, IBAN validation, country rules, ECB exchange rates, FX volatility, payment cutoff times, SWIFT message reference, ECCN export control lookup, sanctions screening (3/day free). Paid tools (API key required): unlimited sanctions screening. FI-tier tools (API key + FI subscription required): SWIFT payment tracking, SSI correspondent banking lookup. To get an API key, call mcp_register then mcp_verify. FI-tier tools require an FI subscription at https://ohmyfin.ai/subscription. EXPERIMENTAL: Company registry search (person/company lookups with sanctions screening) available via company_search_person and company_search_company.", "tools": [ { "description": "Get bank/public holidays for a country with payment impact analysis.\n\nReturns all public holidays plus a 'payment_impact' section that shows:\n- Whether today is a business day or holiday in this country\n- Upcoming holidays in the next 14 days\n- Recent holidays in the last 14 days — for diagnosing a payment that is\n ALREADY stuck (\"in progress for N days\", \"sent X days ago\"). A recent\n holiday only counts if BOTH hold: it falls INSIDE the payment's own\n window (on or after the send date), AND its 'costs_a_business_day' is\n true. One that predates the send date is irrelevant, and one on the\n country's banking weekend closed nothing that was open — neither may be\n subtracted or given to the user as a cause. An empty list affirmatively\n means no recent holiday explains the delay — do not invent one from\n training data.\n- Every holiday entry (upcoming, recent, and next_holiday_after_today)\n carries 'costs_a_business_day'. Roughly one holiday date in six lands on\n its own country's weekend and shortens nothing; check the flag before\n quoting a holiday as a delay, a closure or a reason a window was short.\n- elapsed_business_days_by_send_date — the AUTHORITATIVE elapsed\n business-day count keyed by send date (weekends + this country's\n holidays already excluded). Use it verbatim instead of hand-counting.\n- Next business day and how many consecutive non-business days remain\nThis context helps determine if holidays are causing payment delays.\n\nArgs:\n country_code: ISO 3166-1 alpha-2 code (e.g., \"US\", \"DE\", \"GB\")\n year: Year (default: current year). Range: 2020-2030.\n\nExamples:\n bank_holidays(\"US\")\n bank_holidays(\"DE\", 2026)\n bank_holidays(\"GB\", 2025)", "inputSchema": { "additionalProperties": false, "properties": { "country_code": { "type": "string" }, "year": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null } }, "required": [ "country_code" ], "type": "object" }, "name": "bank_holidays", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Reverse SSI lookup — find banks that use a given correspondent for a currency.\n\nGiven a correspondent BIC, currency, and origin country, returns the banks\nin that country that have a declared nostro at the correspondent for that\ncurrency. Inverse of ssi_lookup.\n\nReturns only swift + name per bank — to retrieve the account number,\nintermediary chain, or other SSI details for a specific bank from the\nresult list, call ssi_lookup(bank_swift, currency) on it.\n\nCountry and currency are required (not optional) — both bound the result\nset and the query is rejected without them.\n\nRequires an API key with an active PRO, VIP, or FI subscription.\nTight per-account daily caps apply (5/day on PRO, 10/day on VIP/FI/trial).\n\nArgs:\n correspondent_swift: BIC of the correspondent bank (e.g. \"IRVTUS3N\").\n currency: ISO 4217 (e.g. \"USD\").\n country: ISO 3166-1 alpha-2 of the client banks (e.g. \"AE\").\n name_prefix: Optional prefix on bank name (e.g. \"AL\").\n page: 1–4. Defaults to 1.\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nExamples:\n banks_using_correspondent(\"IRVTUS3N\", \"USD\", \"AE\")\n banks_using_correspondent(\"CITIUS33\", \"USD\", \"SA\", name_prefix=\"AL\")", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "correspondent_swift": { "type": "string" }, "country": { "type": "string" }, "currency": { "type": "string" }, "name_prefix": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "page": { "default": 1, "type": "integer" } }, "required": [ "correspondent_swift", "currency", "country" ], "type": "object" }, "name": "banks_using_correspondent", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "EXPERIMENTAL — List available company registries and supported jurisdictions.\n\nReturns the list of company registries that can be searched,\nalong with the jurisdiction codes you can use in\ncompany_search_person and company_search_company. This is the LIVE\nlist and outranks the codes named in those two tools' descriptions.\n\nAny country code not returned here has no registry behind it: a search\nnaming it comes back empty and \"completed\", which does not mean the\ncompany is unregistered. `XX` (GLEIF LEI) is global and is the fallback\nfor those jurisdictions.\n\nNo API key required.\n\nExamples:\n company_registries()", "inputSchema": { "additionalProperties": false, "properties": {}, "type": "object" }, "name": "company_registries", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "EXPERIMENTAL — Search company registries for a company with its officers and shareholders.\n\nFind company registrations across worldwide registries, including\ndirectors, officers, and beneficial owners (PSC/shareholders).\nEvery entity found is automatically screened against sanctions lists.\n\nYou MUST specify at least one jurisdiction. \"ALL\" is not supported.\nAvailable jurisdictions: AM, AT, AU, BR, CA, CH, CZ, DE, DK, EE, FI,\nFR, IE, IL, IS, LT, LV, NL, NO, PL, SG, UK, XX. Call\ncompany_registries() for the live list — this one can go stale.\n\nXX is GLEIF LEI, a GLOBAL registry rather than a country. Reach for it\nwhenever the company sits outside the national registries above — a\nsupplier in Hong Kong, mainland China, the US or the UAE. Hits carry an\nLEI, a registered address and a search.gleif.org URL the user can open.\n\nA jurisdiction NOT on that list is dropped silently by the backend: you\nget total_results 0 with status \"completed\" and no error. That means the\ncompany was never searched for — it is NOT evidence that it is\nunregistered or fake, and saying so to someone checking a counterparty\nbefore wiring money is the most damaging thing this tool can do. Check\n`jurisdictions_not_searched` and `coverage_warning` in the response\nbefore you report an empty result.\n\nArgs:\n name: Company name to search for.\n jurisdictions: Country codes to search (required, e.g. [\"UK\"]).\n \"ALL\" is not supported — specify individual countries.\n include_sanctions_check: Auto-screen results against sanctions DB (default: true).\n include_officers: Include directors and officers (default: true).\n include_shareholders: Include PSC/beneficial owners (default: true).\n include_only_active: Filter to active companies only (default: false).\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nExamples:\n company_search_company(\"Equinor\", jurisdictions=[\"NO\"])\n company_search_company(\"Acme Corp\", jurisdictions=[\"UK\", \"DE\"], include_only_active=True)", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "include_officers": { "default": true, "type": "boolean" }, "include_only_active": { "default": false, "type": "boolean" }, "include_sanctions_check": { "default": true, "type": "boolean" }, "include_shareholders": { "default": true, "type": "boolean" }, "jurisdictions": { "items": { "type": "string" }, "type": "array" }, "name": { "type": "string" } }, "required": [ "name", "jurisdictions" ], "type": "object" }, "name": "company_search_company", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "EXPERIMENTAL — Search company registries for a person's directorships, officer roles, and shareholdings.\n\nSearches worldwide company registries to find where a person holds\ndirector, officer, or shareholder positions. Every person and company\nfound is automatically screened against sanctions lists.\n\nYou MUST specify at least one jurisdiction. \"ALL\" is not supported.\nAvailable jurisdictions: AM, AT, AU, BR, CA, CH, CZ, DE, DK, EE, FI,\nFR, IE, IL, IS, LT, LV, NL, NO, PL, SG, UK, XX. Call\ncompany_registries() for the live list — this one can go stale.\n\nXX is GLEIF LEI, a GLOBAL registry rather than a country. Use it for\nanyone connected to a company outside the national registries above.\n\nA jurisdiction NOT on that list is dropped silently by the backend: you\nget total_results 0 with status \"completed\" and no error. That means the\nperson was never searched for — it is NOT evidence they hold no roles.\nCheck `jurisdictions_not_searched` and `coverage_warning` in the response\nbefore you report an empty result to the user.\n\nArgs:\n name: Person name to search for.\n jurisdictions: Country codes to search (required, e.g. [\"UK\", \"NO\"]).\n \"ALL\" is not supported — specify individual countries.\n include_sanctions_check: Auto-screen results against sanctions DB (default: true).\n include_inactive_roles: Include resigned/ceased roles (default: true).\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nExamples:\n company_search_person(\"John Smith\", jurisdictions=[\"UK\", \"NO\"])\n company_search_person(\"Jane Doe\", jurisdictions=[\"DE\"])", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "include_inactive_roles": { "default": true, "type": "boolean" }, "include_sanctions_check": { "default": true, "type": "boolean" }, "jurisdictions": { "items": { "type": "string" }, "type": "array" }, "name": { "type": "string" } }, "required": [ "name", "jurisdictions" ], "type": "object" }, "name": "company_search_person", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "EXPERIMENTAL — Retrieve cached company search results by search ID.\n\nEvery company_search_person and company_search_company call returns\na search_id. Use this tool to retrieve those results again without\nre-running the search.\n\nArgs:\n search_id: The search_id from a previous company search response.\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nExamples:\n company_search_result(\"abc123-def456\")", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "search_id": { "type": "string" } }, "required": [ "search_id" ], "type": "object" }, "name": "company_search_result", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get banking rules and requirements for a country.\n\nReturns IBAN requirements, SEPA membership, FATF listing status,\nnational currency, account format specifications, and country-specific\npayment requirements (mandatory codes like KNP for Kazakhstan,\nPurpose of Payment for UAE, etc.).\n\nThe `fatf_listing` block is the authoritative answer to \"is this country\ngrey-listed / black-listed / under FATF increased monitoring\". Both FATF\npublic lists are held in full, so a `not_listed` status is a positive\ndetermination and not missing data. Use it instead of training data for any\nFATF question, and note that the coarse `fatf` field is a separate, weaker\nsignal about regional-body membership that says nothing about listing.\n\nEverything here is COUNTRY-level. `currency` is the country's national\ncurrency, not the denomination of any beneficiary account — never pair it\nwith the payment currency to diagnose a currency mismatch (see\n`currency_note` in the response).\n\nUse this to check country-specific STP rules that could cause payment delays, repairs, or rejections (e.g., missing purpose codes, regulatory fields).\n\nIf a country requires special payment codes, the response includes\na payment_requirements block with field descriptions and categories.\nUse country_payment_codes to look up specific code values.\n\nArgs:\n country_code: ISO 3166-1 alpha-2 code (e.g., \"DE\", \"US\", \"KZ\")\n\nExamples:\n country_banking_rules(\"DE\")\n country_banking_rules(\"KZ\") # includes KNP requirement info\n country_banking_rules(\"AE\") # includes Purpose of Payment info", "inputSchema": { "additionalProperties": false, "properties": { "country_code": { "type": "string" } }, "required": [ "country_code" ], "type": "object" }, "name": "country_banking_rules", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Look up export control restrictions for a specific country.\n\nReturns embargo status, sanctioned programs, control reasons, and\nrestriction details across jurisdictions (US EAR, EU, UN, etc.)\nfor the given country. Response also includes a payment_jurisdiction_note\nexplaining when each listed restriction actually applies to a payment\n(US controls only bind when there's a US nexus, etc.).\n\nIMPORTANT: Each jurisdiction's controls only bind a payment when the\npayment has a nexus to that jurisdiction. Use the jurisdiction filter\nwhen you know the payment's actual jurisdictional touchpoints (sender\ncountry, clearing currency, intermediary banks). For a CHF/EUR payment\nwith no US bank in the chain, US export controls are informational only\n— do NOT cite them as compliance blockers without confirming a US nexus.\n\nArgs:\n country_code: ISO 3166-1 alpha-2 country code (e.g. \"RU\", \"CN\", \"DE\").\n jurisdiction: Optional filter by jurisdiction (e.g. \"US\", \"EU\").\n When omitted, returns restrictions from all jurisdictions.\n\nExamples:\n country_export_controls(\"RU\") # Russia — heavily embargoed\n country_export_controls(\"CN\") # China — partial restrictions\n country_export_controls(\"DE\") # Germany — minimal controls\n country_export_controls(\"RU\", \"US\") # Russia, US jurisdiction only\n\nUse case: 'What export restrictions apply to shipping to Russia?'", "inputSchema": { "additionalProperties": false, "properties": { "country_code": { "type": "string" }, "jurisdiction": { "default": "", "type": "string" } }, "required": [ "country_code" ], "type": "object" }, "name": "country_export_controls", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Look up country-specific payment codes (KNP, purpose codes, etc.).\n\nUse country_banking_rules first to see which code types a country\nrequires (in the payment_requirements block), then use this tool\nto find the right code value.\n\nArgs:\n country_code: ISO 3166-1 alpha-2 (e.g., \"KZ\", \"AE\")\n code_type: Code table to search (from payment_requirements\n required_fields[].code_type, e.g., \"knp\", \"purpose_code\")\n search: Optional keyword filter (e.g., \"transport\", \"trade\", \"insurance\")\n\nExamples:\n country_payment_codes(\"KZ\", \"knp\", \"transport\")\n country_payment_codes(\"KZ\", \"knp\", \"insurance\")\n country_payment_codes(\"AE\", \"purpose_code\", \"trade\")\n country_payment_codes(\"KZ\", \"knp\") # all codes (large response)", "inputSchema": { "additionalProperties": false, "properties": { "code_type": { "type": "string" }, "country_code": { "type": "string" }, "search": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "country_code", "code_type" ], "type": "object" }, "name": "country_payment_codes", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Look up an Export Control Classification Number (ECCN).\n\nPure reference tool — returns classification details, controlled\njurisdictions, and license requirements for the given ECCN.\n\nECCNs are alphanumeric codes (e.g. \"5A001\") used under export control\nregimes (US EAR, EU Dual-Use Regulation, Wassenaar Arrangement) to\nclassify items that may require an export license.\n\nArgs:\n eccn: The ECCN to look up (e.g. \"5A001\", \"3A001\", \"1C351\").\n\nExamples:\n eccn_lookup(\"5A001\") # Telecommunications security equipment\n eccn_lookup(\"3A001\") # Electronic components\n eccn_lookup(\"1C351\") # Human pathogens, zoonoses, toxins", "inputSchema": { "additionalProperties": false, "properties": { "eccn": { "type": "string" } }, "required": [ "eccn" ], "type": "object" }, "name": "eccn_lookup", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Screen goods for export-control restrictions to a destination country.\n\nCombines the goods classification with the destination's restriction status\nand returns whether a license is required, the risk level, applicable\nlicense policies (e.g. presumption of denial), control reasons (NS, MT, NP,\nCB, AT), and proliferation/dual-use flags. Identify the goods by ANY of:\nECCN, HS code, or a free-text description (English or Russian).\n\nIMPORTANT — jurisdiction nexus: each jurisdiction's controls only bind a\npayment/shipment when there is a nexus to that jurisdiction (US EAR binds\nUS persons, USD-clearing, and US-origin items; EU/UK/JP bind their persons,\ncurrencies, and origin). Use jurisdiction=\"ALL\" for a comprehensive\nmulti-jurisdiction view, or pick the one matching the actual touchpoints.\n\nIMPORTANT, prefer eccn or hs_code: goods_description is a fallback: the\nclassifier matches it lexically, so a vague description still returns one\nspecific HS code and it is usually the wrong one (\"industrial machinery\"\nreturns bakery and pasta machinery). When you pass a description only, the\nresult carries classification_basis and classification_confidence_note;\nread them, never quote the inferred code back to the user as their HS code\nor ECCN, and ask for the code on their invoice or export declaration. The\ndestination findings (embargo, transshipment risk, screening duties) are\nNOT affected by that doubt, so report them normally.\n\nArgs:\n destination_country: ISO 3166-1 alpha-2 destination code (e.g. \"RU\", \"CN\").\n eccn: Optional Export Control Classification Number (e.g. \"3A001\").\n hs_code: Optional Harmonized System code, 4-8 digits (e.g. \"854231\").\n goods_description: Optional free-text goods description (EN or RU).\n jurisdiction: \"US\" (default), \"EU\", \"UK\", \"JP\", \"ITAR\", or \"ALL\".\n\nProvide at least one of eccn / hs_code / goods_description.\n\nExamples:\n export_controls_screen(\"RU\", eccn=\"3A001\") # electronics → Russia\n export_controls_screen(\"CN\", eccn=\"3A090\") # advanced computing → China\n export_controls_screen(\"IR\", goods_description=\"industrial valves\")\n export_controls_screen(\"RU\", goods_description=\"drone\", jurisdiction=\"ALL\")\n export_controls_screen(\"DE\", hs_code=\"854231\") # → Germany (allied)\n\nUse case: 'Can we ship integrated circuits to Russia?'", "inputSchema": { "additionalProperties": false, "properties": { "destination_country": { "type": "string" }, "eccn": { "default": "", "type": "string" }, "goods_description": { "default": "", "type": "string" }, "hs_code": { "default": "", "type": "string" }, "jurisdiction": { "default": "US", "type": "string" } }, "required": [ "destination_country" ], "type": "object" }, "name": "export_controls_screen", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get recent US regulatory changes from BIS and OFAC.\n\nReturns Federal Register publications including entity list updates,\nrule changes, country policy shifts, and new sanctions programs.\n\nArgs:\n agency: Filter by agency — \"BIS\" (Bureau of Industry and Security)\n or \"OFAC\" (Office of Foreign Assets Control). Omit for both.\n category: Filter by change category — \"entity_list\", \"rule_change\",\n \"country_policy\", or \"sanctions\". Omit for all categories.\n severity: Filter by severity — \"critical\", \"high\", \"medium\", or\n \"low\". Omit for all severity levels.\n days: Number of days to look back (1–365). Default: 30.\n limit: Maximum number of results to return. Default: 50.\n\nExamples:\n federal_register_changes() # Last 30 days, all\n federal_register_changes(agency=\"OFAC\", days=7) # OFAC changes this week\n federal_register_changes(category=\"entity_list\", severity=\"critical\")\n\nUse case: 'Any new entity list additions affecting China?'", "inputSchema": { "additionalProperties": false, "properties": { "agency": { "default": "", "type": "string" }, "category": { "default": "", "type": "string" }, "days": { "default": 30, "type": "integer" }, "limit": { "default": 50, "type": "integer" }, "severity": { "default": "", "type": "string" } }, "type": "object" }, "name": "federal_register_changes", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get the latest available reference (mid-market) exchange rate for a pair.\n\nRates are the official ECB euro foreign-exchange reference rates where the\nECB publishes the currency; pairs whose currency the ECB does not cover\n(e.g. VND, NGN, PKR, KZT, MAD) fall back to a market data feed. ALWAYS\ncheck the `source` field before describing provenance: \"ecb\" = official\nECB reference rate; \"market\" = indicative mid-market rate, NOT an ECB\nfixing — never call it \"the ECB rate\". The `source_note` field in the\nresult states this explicitly. Coverage is wide (~60 currencies) but NOT\nuniversal — some currencies (e.g. CLP, COP, PEN) have no rate on file at\nall. When a leg is missing, the error names exactly which currency is\nuncovered: relay that we hold no rate rather than supplying one from your\nown knowledge. Non-EUR pairs are\ncomputed as cross-rates via EUR (e.g., USD/GBP = EUR/GBP / EUR/USD), so\nthey are indicative mid-rates, not dealable/executable rates.\n\nBOTH currencies are required. Always pass the exact pair you intend.\nThere is no implicit default pair: a call that omits or mis-names a\ncurrency returns a \"missing required argument\" error rather than a\nsilently-wrong rate. Never assume EUR/USD when the user asked about a\ndifferent pair such as USD/VND.\n\nArgs:\n base: Base currency (ISO 4217, e.g., \"USD\")\n target: Target currency (ISO 4217, e.g., \"VND\")\n\nExamples:\n fx_rate(\"EUR\", \"USD\")\n fx_rate(\"GBP\", \"JPY\")\n fx_rate(\"USD\", \"VND\")", "inputSchema": { "additionalProperties": false, "properties": { "base": { "type": "string" }, "target": { "type": "string" } }, "required": [ "base", "target" ], "type": "object" }, "name": "fx_rate", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get the historical reference exchange-rate series for a currency pair.\n\nReturns `series` (the daily rates) plus the metadata needed to describe it\nhonestly. READ `series_coverage` BEFORE CHARACTERISING THE PERIOD. `days`\nis the window we look back over, NOT a promise of how much history exists:\nour series start at different dates per currency, so a 365-day request\nroutinely returns five months. `series_coverage.first_date`/`last_date` are\nwhat the numbers actually span, and `series_coverage.truncated` is true\nwhen that is shorter than you asked for. Say \"the ~N months we hold\", never\n\"over the past year\", and never fill the gap from your own knowledge.\n\nCHECK `source` BEFORE ATTRIBUTING PROVENANCE. \"ecb\" = official ECB euro\nreference fixings, weekdays only. \"market\" = an indicative market data feed\nfor a currency the ECB does not publish (AED, QAR, SAR, KWD, NGN, PKR, VND,\nKZT, RUB, UAH and ~20 more). A market series is NOT an ECB series and must\nnever be described as one. Where a pair mixes the two, `series_coverage`\nreports the dates lost to aligning them.\n\n`peg_context` appears when either currency is pegged, including when the\npeg is against some third currency: it names the anchor and the pair whose\nmovement you are really looking at. Take the peg date from there rather\nthan from memory.\n\nAn uncovered pair returns an `error` naming the missing leg instead of an\nempty series. Report that we hold no history rather than describing the\nrate as stable or range-bound.\n\nBOTH currencies are required. Always pass the exact pair you intend.\nThere is no implicit EUR/USD default: an omitted or mis-named currency\nerrors rather than returning the wrong pair's history.\n\nArgs:\n base: Base currency (ISO 4217, e.g., \"EUR\")\n target: Target currency (ISO 4217, e.g., \"USD\")\n days: Lookback window in days (1-365, default 90). A ceiling on the\n window, not a guarantee of the number of points returned.\n\nExamples:\n fx_rate_history(\"EUR\", \"USD\", 30)\n fx_rate_history(\"GBP\", \"CHF\", 365)", "inputSchema": { "additionalProperties": false, "properties": { "base": { "type": "string" }, "days": { "default": 90, "type": "integer" }, "target": { "type": "string" } }, "required": [ "base", "target" ], "type": "object" }, "name": "fx_rate_history", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get FX trading windows for FX execution timing and spread / rate optimization.\n\nReturns market sessions and liquidity windows for a currency. Use this\nto understand:\n- **Rate optimization** (primary, reliable use): higher liquidity means\n tighter spreads and better rates. Execute during peak windows to minimize\n conversion costs.\n- **Delay diagnosis** (use with care): the FX market session is when a\n currency TRADES. It is NOT a guaranteed processing schedule for an inbound\n foreign-currency payment that the beneficiary bank converts on arrival.\n Conversion timing is beneficiary-bank-specific (some convert in real time\n during the session, others batch once or twice daily), so do NOT tell the\n user a payment is \"held until the next session\" and do not quote specific\n hold durations (\"adds X hours\", \"overnight delay\"); those are bank policy\n and are not in our data. For the binding delivery-side cutoff that gates the\n converted local-currency leg, call country_banking_rules(destination) and\n read local_clearing.systems. When a currency is restricted, this tool's own\n output carries an inbound_processing_note with the accurate framing to quote.\n\nPass a currency code to get its optimal window, or omit to get\nall market sessions and overlap windows.\n\nArgs:\n currency: ISO 4217 currency code (e.g., \"EUR\", \"JPY\").\n Omit to get all sessions and overlaps.\n\nExamples:\n fx_timing_advisor(\"EUR\")\n fx_timing_advisor(\"JPY\")\n fx_timing_advisor(\"INR\") # Check INR conversion windows\n fx_timing_advisor()", "inputSchema": { "additionalProperties": false, "properties": { "currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "fx_timing_advisor", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get realized FX volatility for a currency pair, and size the FX risk on an exposure held to a future date.\n\nComputes 30-day and 90-day annualized volatility from historical\nECB reference rates (standard deviation of daily log returns,\nannualized by sqrt(252)). Returns a qualitative bucket:\nLOW (<5%), MEDIUM (5-15%), HIGH (15-25%), VERY_HIGH (>25%),\nPEGGED (currency peg — near-zero volatility, e.g., USD/AED, USD/HKD).\n\nAlso returns practical daily/weekly movement estimates and a\nsettlement_risk_note explaining what the volatility means over a\ntypical T+2 settlement period — use these to advise users on FX\nrisk for their specific payment.\n\nPASS horizon_days WHENEVER THE USER'S EXPOSURE RUNS PAST SETTLEMENT.\nIt returns a `horizon` block: the volatility scaled to that horizon as an\nactual rate band at 1 and 2 sigma, which end of the band hurts a payer\nversus a receiver, and what the band does and does not tell them about\nhedging. Use it for questions shaped like:\n - \"should I hedge / lock in / take a forward for <future period>?\"\n - \"how far could <pair> move by <date>?\"\n - \"what rate should I budget for next year?\"\n - \"I have invoices in <currency> through 2027 — what is my risk?\"\n - any exposure not settling within a few days.\nCount the calendar days from today to the date the exposure ends and pass\nthat. Rough is fine — the band moves with the square root of time, so a\nmonth either way barely changes it.\n\nRead `sample_depth` before quoting any figure: this is REALISED volatility\nfrom a short history, not implied volatility, and the sample may be shorter\nthan the horizon asked about (`horizon.beyond_sample`). Say so.\n\nIMPORTANT — the band is the range of FUTURE SPOT. It is not a rate anyone\ncan transact at, and the width of the band is NOT the cost of a hedge. A\nforward is priced off the interest-rate differential between the two\ncurrencies, which we do not hold and must not guess or recall from memory.\nRelay `horizon.hedge_cost_note` rather than inventing forward points, a\ncarry figure, or a \"typical\" hedging cost. Never state a forward rate.\n\nArgs:\n base: Base currency (ISO 4217, e.g., \"EUR\")\n target: Target currency (ISO 4217, e.g., \"TRY\")\n horizon_days: Optional. Calendar days from today to the end of the\n exposure (1-1825). Omit for spot/settlement risk only.\n\nExamples:\n fx_volatility(\"EUR\", \"USD\")\n fx_volatility(\"USD\", \"TRY\")\n fx_volatility(\"GBP\", \"JPY\", 506) # exposure running to end-2027\n fx_volatility(\"EUR\", \"PLN\", 90) # invoice settling in a quarter", "inputSchema": { "additionalProperties": false, "properties": { "base": { "type": "string" }, "horizon_days": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null }, "target": { "type": "string" } }, "required": [ "base", "target" ], "type": "object" }, "name": "fx_volatility", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Classify goods for export control from a description (or HS code).\n\nBilingual (English / Russian, auto-detected) goods classifier. Returns the\nbest-matching HS code (with EN+RU descriptions), related ECCNs, control\nreasons (NS, MT, NP, CB, AT...), an export-control level (high/medium/low/\nnone), a confidence score, and alternative matches for review.\n\nThis is destination-agnostic — it identifies WHAT the goods are and whether\nthey are controlled in principle. To get the license decision FOR A SPECIFIC\ndestination, pass the result into export_controls_screen.\n\nIMPORTANT, the matcher is lexical, and confidence scores the strength of\nthe string match, not the correctness of the classification: \"equipment\"\nreturns semiconductor manufacturing equipment at confidence 1.0. Treat the\ncode as a suggestion for narrowing the question. When no hs_code was\nsupplied the result carries classification_basis and\nclassification_confidence_note; read them before quoting any code, and ask\nthe user for the HS code or ECCN on their shipping documentation.\n\nArgs:\n description: Goods description, min 2 chars (e.g. \"uranium centrifuge\",\n \"центрифуга для урана\"). Required.\n hs_code: Optional known HS code (4 or 6 digits) for a direct lookup.\n language: Optional hint — \"en\" or \"ru\" (auto-detected if omitted).\n\nExamples:\n goods_classify(\"uranium centrifuge\") # → HS 840120, ECCN 0B001\n goods_classify(\"центрифуга для обогащения урана\") # Russian query, same result\n goods_classify(\"semiconductor manufacturing equipment\")\n goods_classify(\"\", hs_code=\"840120\") # direct HS lookup\n\nUse case: 'Is a semiconductor lithography machine export-controlled?'", "inputSchema": { "additionalProperties": false, "properties": { "description": { "type": "string" }, "hs_code": { "default": "", "type": "string" }, "language": { "default": "", "type": "string" } }, "required": [ "description" ], "type": "object" }, "name": "goods_classify", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Explain SWIFT GPI tracking status codes and provide stuck-payment investigation guidance.\n\nUSE THIS TOOL FIRST whenever the user reports a payment that is stuck,\ndelayed, not arriving, held, pending, rejected, or otherwise not\nbehaving as expected. It is the primary diagnostic entrypoint for\npayment investigation — calling with a specific code returns a\nfull investigation playbook (common delay causes, recommended\nactions, GPI SLA timeframes, escalation steps).\n\nRecommended calls by scenario:\n - Payment \"stuck\" / \"in progress\" / \"pending\" / \"not arrived\":\n gpi_status_codes(\"ACSP\") → playbook for in-progress payments\n - Payment explicitly \"on hold\" / compliance review:\n gpi_status_codes(\"PDNG\") → playbook for held payments\n - Payment \"blocked\" / sanctions flag:\n gpi_status_codes(\"BLCK\") → playbook for blocked payments\n - Payment rejected by a bank in the chain (never credited):\n gpi_status_codes(\"RJCT\") → rejection investigation playbook\n - Payment returned to sender (accepted then sent back):\n gpi_status_codes(\"RTRN\") → return investigation playbook\n - Reference for ISO 20022 codes:\n gpi_status_codes() → list all codes\n\nEach code call returns:\n - Code description and meaning\n - For ACSP/PDNG/BLCK/RJCT/RTRN: investigation playbook with common\n causes, recommended actions (request gCCT tracker, request\n pacs.002/pacs.004 reason code, verify beneficiary details,\n escalate via MT199, etc.), and common ISO 20022 reason codes\n (AC01, AC04, AG01, RR01-RR04, etc.) when applicable\n - Child reason codes (e.g., G001-G004 for ACSP) that narrow the\n cause further\n\nCommon codes: ACCC (success), ACSP (in progress), RJCT (rejected),\nPDNG (on hold), BLCK (blocked). GPI reason codes (G000-G004) qualify\nACSP with more detail (e.g. G001 = cover payment sent, G002 =\nforwarded to next agent).\n\nExamples:\n gpi_status_codes(\"ACSP\") # stuck-payment diagnostic playbook\n gpi_status_codes(\"G001\") # detail on a specific reason code\n gpi_status_codes() # full reference list", "inputSchema": { "additionalProperties": false, "properties": { "code": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "gpi_status_codes", "outputSchema": { "description": "Generic wrapper for non-object return types.", "properties": { "result": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } ] } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Reverse-lookup an HS code → mapped export-control classifications (ECCNs).\n\nFor customs brokers / shippers who have an HS (Harmonized System) code and\nneed to know which export-control classifications may apply. Returns the\nmapped ECCNs with confidence levels, control reasons, sensitivity, and the\ngoverning international regime (Wassenaar, MTCR, NSG, etc.).\n\nA 4-digit HS heading is accepted, but mappings are richest at the 6-digit\nsubheading level (e.g. \"854231\" rather than \"8542\"). An empty mapping list\nmeans no export-control mapping is on file for that code — it is NOT a\nguarantee the goods are uncontrolled; confirm with goods_classify or a\nformal classification.\n\nArgs:\n hs_code: 4-6 digit HS code (e.g. \"854231\", \"8411\"). Dots/spaces are ok.\n jurisdiction: Optional filter — \"US\", \"EU\", \"UK\", or \"JP\".\n\nExamples:\n hs_code_lookup(\"854231\") # semiconductors → 3A001 / 3A090 ...\n hs_code_lookup(\"841112\") # turbojet engines → 9A001 ...\n hs_code_lookup(\"854231\", \"US\") # US mappings only\n\nUse case: 'What export controls might apply to HS code 854231?'", "inputSchema": { "additionalProperties": false, "properties": { "hs_code": { "type": "string" }, "jurisdiction": { "default": "", "type": "string" } }, "required": [ "hs_code" ], "type": "object" }, "name": "hs_code_lookup", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Validate an IBAN and identify the institution that holds the account.\n\nPerforms format check, country-specific length check, and\nISO 7064 mod-97 checksum verification. Also returns COUNTRY-level\nbanking rules for the IBAN's country prefix (national currency,\nSEPA status, expected format).\n\nCROSS-CHECKS THE BENEFICIARY BANK. Where the country's IBAN registry\nmask defines the bank identifier as four alpha characters (GB, NL, IE,\nRO, PK, MT, JO, QA, KW and others), `bank_identifier.resolved_institution`\nnames the institution that actually holds the account, read out of the\nIBAN itself. Call this whenever the user supplies an IBAN AND names a\nbeneficiary bank or BIC — if the two disagree, that mismatch is a far\nbetter explanation for a rejected or returned payment than anything you\ncan infer, and it is invisible without this call. Everywhere else the\nbank identifier is a NATIONAL bank/sort code (the German BLZ, Italian\nABI, French code banque): `bank_identifier.code` is those characters,\n`is_bic_prefix` is false, and no institution is named — quote the code\nwhen telling the user what to check, never a bank name derived from it.\n\nA FAILURE IS NOT ALWAYS A CHECKSUM FAILURE. An IBAN of the right length\nwhose characters break the country's mask (a letter where the country\nrequires a digit — O for 0, I for 1) is refused BEFORE mod-97 runs, with\n`format_violations` naming the position. Report the position and the\ncharacter; do not tell the user the check digits are wrong.\n\n`valid: true` means the check digits are right and NOTHING MORE — not\nthat the account exists, is open, or belongs to the named beneficiary or\nthe named bank. Never rule out the account details on the strength of it\nwhen diagnosing a failed payment (see `verification_note`).\n\nAn IBAN encodes country + bank + account number and carries NO\ncurrency information. `country_currency` is the country's national\ncurrency, NOT this account's denomination — never infer a currency\nmismatch or a \"resend in X\" recommendation from it (see\n`currency_note` in the response).\n\nExamples:\n iban_validate(\"DE89370400440532013000\")\n iban_validate(\"GB29 NWBK 6016 1331 9268 19\")", "inputSchema": { "additionalProperties": false, "properties": { "iban": { "type": "string" } }, "required": [ "iban" ], "type": "object" }, "name": "iban_validate", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Check if a specific date is a business day in a country.\n\nAccounts for weekends (country-specific) and public holidays.\nReturns whether the date is a business day, and if not, why\n(weekend or specific holiday name) and the next business day.\n\nThe response carries a `today` block with the server's real current date.\nResolve any relative date in the user's question (\"the 20th\", \"next\nFriday\") against that, not against your own sense of today. A check_date\nalready in the past also returns `date_anchor_warning` — heed it: a\nmis-resolved year flips the answer outright (2025-07-20 is a Sunday,\n2026-08-20 is a Thursday).\n\nArgs:\n country_code: ISO 3166-1 alpha-2 code (e.g., \"US\", \"DE\")\n check_date: Date in ISO format (YYYY-MM-DD)\n\nExamples:\n is_business_day_check(\"US\", \"2026-12-25\")\n is_business_day_check(\"DE\", \"2026-03-12\")\n is_business_day_check(\"GB\", \"2026-01-01\")", "inputSchema": { "additionalProperties": false, "properties": { "check_date": { "type": "string" }, "country_code": { "type": "string" } }, "required": [ "country_code", "check_date" ], "type": "object" }, "name": "is_business_day_check", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Register for an Ohmyfin API key to use paid tools.\n\nCreates an account and sends a 6-digit verification code to your\nemail. After receiving the code, call mcp_verify to complete\nregistration and get your API key.\n\nBy setting accept_terms to true, you confirm acceptance of the\nOhmyfin Terms & Conditions (https://ohmyfin.ai/terms) on behalf\nof your operator, including the API/MCP access terms (Section 3A),\nsanctions screening terms (Section 3B), and financial data\ndisclaimer (Section 3C).\n\nArgs:\n email: Your email address.\n organization_name: Your company or project name.\n accept_terms: Must be true. Confirms acceptance of the Ohmyfin\n Terms & Conditions at https://ohmyfin.ai/terms.\n\nExamples:\n mcp_register(\"[email protected]\", \"Acme Corp\", true)", "inputSchema": { "additionalProperties": false, "properties": { "accept_terms": { "type": "boolean" }, "email": { "type": "string" }, "organization_name": { "type": "string" } }, "required": [ "email", "organization_name", "accept_terms" ], "type": "object" }, "name": "mcp_register", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Verify your email and receive your API key.\n\nAfter calling mcp_register, check your email for the 6-digit code\nand pass it here. On success, returns your production and test\nAPI keys. You must subscribe at ohmyfin.ai/subscription to\nactivate paid tools.\n\nArgs:\n email: The email you registered with.\n code: The 6-digit verification code from your email.\n\nExamples:\n mcp_verify(\"[email protected]\", \"123456\")", "inputSchema": { "additionalProperties": false, "properties": { "code": { "type": "string" }, "email": { "type": "string" } }, "required": [ "email", "code" ], "type": "object" }, "name": "mcp_verify", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Get payment system cutoff times for major clearing systems.\n\nCovers RTGS (T2 — formerly TARGET2, CHAPS, Fedwire, BOJ-NET, SIC),\nnet settlement (CHIPS, BACS), SEPA schemes (SCT, SCT Inst, OCT Inst,\nSDD Core, SDD B2B), FX settlement (CLS, FXYCS), and other systems\n(CIPS, SPEI, FAST).\n\nFor same-day EUR guidance: filter by currency=\"EUR\" to retrieve all\nSEPA schemes plus T2 in one call — the scheme-level view is usually\nwhat treasurers need. Underlying CSMs (TIPS, RT1, EURO1, STEP2) are\nreferenced in scheme notes.\n\nDST-observing systems also carry `season_now` and `operative_cutoff_today`\nfields computed for the current date. cutoff_utc/cutoff_local are the\nSTANDARD-TIME (winter) values; summer_offset holds the DST value. Quote the\ncutoff that `operative_cutoff_today` points at for TODAY's season — do not\ndefault to the winter figure when DST is currently in force (e.g. the T2\ncustomer cutoff is 15:00 UTC in summer, not the 16:00 UTC winter value).\n\nArgs:\n system: System name (e.g., \"T2\", \"TARGET2\", \"FEDWIRE\", \"CHAPS\").\n Case-insensitive. \"TARGET2\" and \"T2\" both resolve to the\n same entry (T2 is the post-March 2023 name). Omit to list\n all or filter by currency.\n currency: ISO 4217 currency code to filter by (e.g., \"USD\", \"EUR\").\n\nExamples:\n payment_cutoff_times(system=\"T2\")\n payment_cutoff_times(currency=\"EUR\")\n payment_cutoff_times(currency=\"USD\")\n payment_cutoff_times()", "inputSchema": { "additionalProperties": false, "properties": { "currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "system": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "payment_cutoff_times", "outputSchema": { "description": "Generic wrapper for non-object return types.", "properties": { "result": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } ] } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Compare payment methods and investigate fee deductions for a country pair.\n\nEvaluates SEPA vs SWIFT vs domestic options. Also explains SWIFT charge\noptions (OUR/SHA/BEN) and fee investigation — use this when the beneficiary\nreceived less than expected to understand where the money went and which\nMT103 fields reveal each deduction. Returns cost, speed, requirements,\ncharge options, and step-by-step fee investigation guidance.\n\nArgs:\n source_country: ISO 3166-1 alpha-2 code (e.g., \"DE\", \"US\")\n dest_country: ISO 3166-1 alpha-2 code (e.g., \"GB\", \"TR\")\n\nExamples:\n payment_method_compare(\"DE\", \"FR\") # Both SEPA — will recommend SCT\n payment_method_compare(\"US\", \"TR\") # Non-SEPA — will recommend SWIFT\n payment_method_compare(\"GB\", \"GB\") # Domestic — will show CHAPS/FPS\n payment_method_compare(\"US\", \"VN\") # Fee investigation — why beneficiary got less", "inputSchema": { "additionalProperties": false, "properties": { "dest_country": { "type": "string" }, "source_country": { "type": "string" } }, "required": [ "source_country", "dest_country" ], "type": "object" }, "name": "payment_method_compare", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Screen a name against global sanctions and watchlists.\n\nFREE TIER: 3 screens per day without an API key.\nPAID: Unlimited screens with an API key.\n\nChecks the name against 300+ sanctions, designation and watchlists\nworldwide, including US OFAC (SDN and non-SDN), EU, UK OFSI, Canada,\nSwitzerland, Australia, New Zealand, Japan, Israel and national lists.\nReturns matching entities with similarity scores. The response says how\nmany lists were actually searched (lists_searched); report THAT, and do not\npresent a fixed per-jurisdiction table of \"clear\" rows, which asserts a\nper-list result the screen does not return and understates the coverage.\n\nFor a company or an individual the screen covers every list, including\nadverse media, PEP and debarment registers. For a BANK or other financial\ninstitution it returns sanctions DESIGNATIONS only: a warning-list entry\nnaming a bank is usually a clone-firm alert about fraudsters impersonating\nit, and the feed carries nothing that tells the two apart.\n\nWhen the name resolves in our bank directory, each designation is also\ncross-referenced against that institution's record (country, entity type,\nand the name or ALIAS that earned the fuzzy score) and contradicted rows are\nremoved. ALWAYS read the `verification` block, which is on every response:\n`applied: false` means nothing was cross-referenced and the rows are raw\nfeed output — either the name is not in our bank directory, or the subject\nis a company or individual, which has no directory record to check against.\nNever report an `applied: false` result as verified, and never report an\nempty one as verified-clear. Screening a bank by BIC, or calling\nswift_lookup, gets a verified answer.\n\nA row surviving that cross-reference is NOT the same as a row the\ncross-reference supported. Each verified row carries `adjudication`:\n`corroborated` means the check backed it and it is a designation against\nthis institution; `not_corroborated` means it survived the false-positive\nfloor but nothing tied it to this institution — typically\n`country_conflict: true`, the designated entity being domiciled elsewhere.\n`is_false_positive: false` is only that floor test and is never a finding;\nread `adjudication` instead. When NOTHING is corroborated the response\ncarries `verification_gate.applied: true` and `recommended_action` has been\nlowered from BLOCK to REVIEW: report a possible match needing identity\nconfirmation, do not reinstate BLOCK from the row-level `action` fields,\nand do not report the institution as clear either — every row is still in\n`matches` and the open question is which legal entity the counterparty is.\n\n`verification_gate` is on every bank response whose verdict asserts a\nfinding (BLOCK, REVIEW, MONITOR or INFORM), and it asks one question: does\nthat verdict survive the evidence this payload actually publishes. A\nREVIEW, MONITOR or INFORM over an EMPTY `matches` list is not a weaker\nBLOCK. This screen publishes designations only for a financial institution,\nso the rows that carried such a verdict are the non-designation ones\n(warning lists, adverse media, PEP, debarment) it withholds — counted in\n`non_designation_rows_withheld` and never listed. Those responses come back\n`recommended_action: CLEAR` with `verification_gate.applied: true`, meaning\nno DESIGNATION matched. Say exactly that, and keep the scope with it: it is\nnever a clean bill across every list. The gate stands down, and the verdict\nstays, when our own verification removed a designation as a false positive\n(`designations_filtered_as_false_positives`), when the directory record is\nnot clean, or when the row that set the verdict was off-page.\n\nOn an unverified response every row also carries `query_match`, listing\nwhich of the screened words appear in that row's own name or aliases and\nwhich do not. Nothing is removed on account of it. Weigh it against the\nscore: a row sharing one word out of four with the query is usually a\ndifferent entity, and its action is that entity's action, not a verdict on\nthe party screened. Absence is not proof — non-Latin aliases contribute no\nwords, and a transliterated designation of the right party can show words\nmissing — but where every query word is present, take the row at face value.\nPresent words a row holds only inside a web address, e-mail address, @handle\nor labelled channel are named again in `query_words_only_in_contact_details`:\nthey name an address or channel of the listed party, not the listed party,\nso that row is not taken at face value on their account.\n\nThe response also carries `coverage_gate`, set by the screening engine: how\nmuch of the name you screened actually appears on the rows that are\nblocking. When `applied` is true the payload-level `recommended_action` was\nlowered from BLOCK to REVIEW, because no blocking row carries more than\nhalf of the distinctive words you screened. Report a possible match that\nneeds identity confirmation, NOT a designation, and do not reinstate BLOCK\nfrom the row-level `action` fields. Nothing was removed: every row the feed\nreturned is still in `matches`, with its own score and action intact. When\n`applied` is false the verdict stands and `reason` says why. A `reason` of\n`identifier_query` means the name screened was a registration or tax\nnumber that matched a designation's own identifier: that is a match on\nidentity, not on wording, so report the BLOCK as it stands.\n\nArgs:\n name: The person or entity name to screen.\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n Optional — free tier allows 3 screens/day without a key.\n threshold: Minimum match score 0-100 (default 85).\n subject_type: What is being screened: \"bank\" for a financial\n institution, \"party\" for a company or individual, or \"auto\"\n (default). A name the bank directory resolves is treated as a\n financial institution whatever you pass here.\n\nExamples:\n sanctions_screen(\"Acme Trading Ltd\")\n sanctions_screen(\"John Smith\", threshold=90)\n sanctions_screen(\"First Abu Dhabi Bank\", subject_type=\"bank\")\n sanctions_screen(\"Acme Trading Ltd\", api_key=\"prod-abc123...\")", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "name": { "type": "string" }, "subject_type": { "default": "auto", "type": "string" }, "threshold": { "default": 85, "type": "integer" } }, "required": [ "name" ], "type": "object" }, "name": "sanctions_screen", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "BETA. Estimate when a SWIFT payment will arrive: a corpus-grounded\narrival window with an honest tail, computed from real completed payments\nwe have tracked, projected onto the currency's banking calendar.\n\nThis estimator is in BETA and still calibrating. Say so when you present a\nnumber: call it an estimate or a typical window, never a commitment, and\nnever let a user plan an irreversible decision (a cutoff, a contractual\nsettlement date) on it without that caveat. The payload carries beta=true\nwhile this holds.\n\nTwo modes:\n- Forward (default): \"when will it land\" — returns P50/P90/P95 arrival\n dates, sample size, confidence, competing non-arrival risk, delay-risk\n factors, and (where validated) the most likely correspondent route.\n- Reverse: pass arrive_by_date (YYYY-MM-DD) — returns the latest send\n date such that arrival by that day is likely (\"send by Thursday to\n land by month-end\").\n\nINPUT DISCIPLINE (important):\n- Mid-flight payment: pass ONLY the uetr (from TrackingContext or\n track_payment). The server resolves the current status, currency and\n elapsed time deterministically from the tracking record. NEVER compute\n elapsed_business_days yourself.\n- Pre-trade question (\"how long will a USD wire from X to Y take?\"):\n pass currency + sender_bic/receiver_bic (8 or 11 chars, or bank names).\n current_status / elapsed_business_days are for this path only.\n\nReading the answer honestly (relay these to the user):\n- basis.n is the sample size and confidence reflects it; when confidence\n is \"low\", present the window as a rough range, never a promise.\n- route.confirmed=false means the route is INFERRED from settlement\n instructions on file, not confirmed by GPI — say so.\n- basis.route_adjusted=true means we hold no completed payments for this\n exact pair and the window was lifted to a route-composed estimate:\n the SSI-implied correspondent chain (route.intermediaries hops) with\n typical processing time per hop. Present it as a route-based estimate,\n not as observed statistics, and never quote the faster currency-pool\n average alongside it as if corridor-specific.\n- mode=\"outlier\" means the payment is already slower than ~90% of similar\n payments: stop quoting a window, explain the usual manual causes\n (compliance review, repair/RFI, missing cover) and pivot to the\n stuck-payment diagnostic flow.\n- non_arrival.p_reject is the share of similar payments that were\n returned or rejected rather than delivered.\n- \"Delivered\" (ACCC) means delivered to the beneficiary bank per GPI;\n funds can become usable in the account slightly later.\n\nAvailable on every surface to any caller with an active subscription. The\nestimate itself costs no credits (tracking a payment does cost credits;\nnever describe tracking as free).\n\nArgs:\n uetr: UETR of a tracked payment (preferred for mid-flight questions)\n currency: 3-letter currency (pre-trade path; ignored when uetr resolves)\n sender_bic: Sender bank BIC or name (pre-trade path)\n receiver_bic: Receiver bank BIC or name (pre-trade path)\n intermediary_bic: Known intermediary BIC (optional)\n current_status: GPI status like ACSP (pre-trade/no-uetr path only)\n elapsed_business_days: Business days already in flight (pre-trade path only)\n amount: Payment amount (improves delay-risk assessment). A plain\n number is fine — 50000 and \"50,000.00\" are both accepted.\n sender_country: ISO2 country of the sender bank (optional)\n receiver_country: ISO2 country of the receiver bank (optional)\n arrive_by_date: YYYY-MM-DD — switches to reverse send-by mode. You do\n not know today's date; a deadline stated as \"the 20th\" or \"by\n month-end\" must be resolved against the `today` block returned by\n bank_holidays / value_date / is_business_day_check, not against\n your own sense of the current date. A date in the past is rejected.\n api_key: Optional API key (internal calls ride the MCP secret)", "inputSchema": { "additionalProperties": false, "properties": { "amount": { "anyOf": [ { "type": "number" }, { "type": "string" }, { "type": "null" } ], "default": null }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "arrive_by_date": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "current_status": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "elapsed_business_days": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "default": null }, "intermediary_bic": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "receiver_bic": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "receiver_country": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "sender_bic": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "sender_country": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "uetr": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "settlement_eta", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Look up correspondent banking / settlement instructions (SSI) for a bank.\n\nReturns the correspondent banks (nostro accounts) that a given bank\nuses to settle payments in a specific currency, including account\nnumbers (when available) and intermediary chains. Essential for\npayment routing and pre-validation.\n\nEach correspondent is annotated with a clearing_note indicating\nwhether it can clear the currency directly (located in a home\ncountry for that currency) or needs its own correspondent.\nIf the note suggests a further lookup, call ssi_lookup on the\ncorrespondent's SWIFT code to find the full clearing chain.\n\nIMPORTANT — known data gaps to respect:\n- Account numbers may be empty for some/all correspondents. The\n response surfaces an `account_availability_note` in those cases.\n Do NOT invent account numbers. Use swift_lookup() to find the\n bank's own published correspondent banks page when accounts\n are missing.\n- WHICH CORRESPONDENT: read `correspondent_selection`, not the array order.\n It gives the COMPLETE set of BICs for each flow (customer MT103 vs\n interbank MT202) and for whether the correspondent clears the currency\n itself, each with a count. The correspondents are returned in STORAGE\n order, which is not a ranking. Naming a subset (\"principally X and Y\",\n \"route via X\") invents a preference this feed does not hold. Name every\n BIC in the matching set, or give its count: which one is used is the\n SENDING bank's choice among the ones it can already reach, not the\n beneficiary bank's, and not ours to guess from bank size or reputation.\n `is_preferred` is `null` on almost every row because the flag is\n genuinely unrecorded (11 rows in the entire corpus carry it); where it IS\n set, `correspondent_selection.bank_flagged_preference` names it and you\n should lead with that.\n- `intermediaries` is `null` — not `[]` — when this correspondent's onward\n chain is not recorded, which is 98% of rows. `null` means NOT ESTABLISHED,\n never zero hops: do not read it as a direct chain and do not count it.\n Whether a further hop is needed is answered by each correspondent's\n `clearing_note`, which says either that it clears the currency itself or\n that a further hop is expected and gives the ssi_lookup call that resolves\n it. When the chain IS recorded the array is populated and\n `intermediaries_note` names the hops in order.\n- Asset category per correspondent is COMMERCIAL (for customer\n MT103 credit transfers) or FINANCIAL (for bank-own-account /\n interbank MT202/pacs.009 settlements). Read `asset_categories`\n (the full list) rather than the single `asset_category`, which\n shows the commercial view only: one entry is one BIC+account and\n the same account is often published under BOTH categories, so the\n single field can never establish what an account may NOT be used\n for. The `asset_category_note` summarises the split — match the\n listed correspondents to the user's flow type (customer payment\n vs treasury/interbank).\n- If `correspondents` is EMPTY, we have no SSI on file for that\n bank/currency. The response carries a `no_ssi_note` (no SSI in any\n currency) or `requested_currency_unavailable_note` (SSI on file for\n other currencies only). This is a coverage gap, NOT a finding that the\n bank has no correspondents. Do NOT name a correspondent for the missing\n currency from training data — surface the `published_ssi_document` /\n the bank's website and tell the user to confirm SSI with the bank.\n\nAlways inspect the response's top-level `next_steps` array — it\nchains the swift_lookup / country_banking_rules / bank_holidays\ncalls that complete a settlement-instruction answer.\n\nCOVERAGE IS KNOWABLE BEFORE YOU CALL, AND FOR FREE. swift_lookup returns a\n`settlement_instructions` block on every bank: `on_file: true` with a\ncurrency count means this lookup will answer, `false` means we hold none in\nany currency, null means it has not been established. Do not treat \"might be\na coverage gap\" as a reason to skip the call and describe the routing from\nmemory — ask swift_lookup, then read the answer here.\n\nRequires an API key with an active FI subscription.\nTo get started: call mcp_register → mcp_verify → subscribe to\nan FI plan at https://ohmyfin.ai/subscription.\n\nArgs:\n swift: SWIFT/BIC code of the bank (e.g., \"DEUTDEFF\", 8 or 11 chars).\n currency: ISO 4217 currency code (e.g., \"USD\", \"EUR\", \"GBP\").\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nExamples:\n ssi_lookup(\"DEUTDEFF\", \"USD\") # Deutsche Bank USD correspondents\n ssi_lookup(\"HSBCHKHH\", \"EUR\") # HSBC HK EUR correspondents\n ssi_lookup(\"DEUTDEFF\", \"USD\", api_key=\"prod-abc123...\")", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "currency": { "type": "string" }, "swift": { "type": "string" } }, "required": [ "swift", "currency" ], "type": "object" }, "name": "ssi_lookup", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Search banks and financial institutions by name, SWIFT/BIC code, or country.\n\nCovers both SWIFT-connected banks and non-SWIFT financial institutions\n(e-money issuers, payment processors, MFOs, brokerages, VASPs, etc.).\n\nReturns: SWIFT/BIC code (if any), name, city, country, institution type,\nGPI membership, a coarse sanctions FLAG across 7 hard-sanctions watchlists\n(OFAC SDN, EU, UK, CA, CH, AU, NZ — see sanctions_note; this is NOT a full\nscreen, use sanctions_screen for a compliance verdict), and enriched bank\nprofile when available.\n\nEVERY BANK COMES BACK SAYING WHETHER WE HOLD ITS CORRESPONDENT CHAIN.\nRead `settlement_instructions` on each bank: `on_file: true` with a\n`currencies_on_file` count means we hold that BIC8's actual correspondent\nBIC, nostro account number and national clearing ID, and `read_with` is the\nexact ssi_lookup call that returns them. `on_file: false` means we hold none\nin any currency — a gap in our data, not a finding about the bank. A null is\n\"not established yet\" and is neither. This is the answer to \"which\nintermediary bank do I put on the instruction?\", and it is a fact we either\nhave or do not have — never one to recall from training data.\n\nThe country parameter accepts both 2-letter ISO codes (\"ID\", \"DE\") and\nfull English names (\"Indonesia\", \"Germany\"). Names are resolved\nautomatically.\n\nA BIC IDENTIFIES AN OFFICE, NOT A BRAND, AND THE DIFFERENCE IS PRICED.\nA name search returns ONE representative office per bank, elected by BIC\nconvention rather than by relevance to the payment, and `office_note` says\nso whenever the bank holds more than one. Published tariffs, correspondent\nchains and settlement instructions are filed per BIC, so the choice changes\nthe answer: transfer_cost(\"COBADEFF\") returns Commerzbank's published 0.15%\nsending fee and transfer_cost(\"COBADEBB\") refuses for want of a filed\ntariff, and both of those are Commerzbank AG in Germany. So:\n - If the user named a CITY, put it in the query — \"Commerzbank Frankfurt\"\n resolves to the Frankfurt office, and the plain name cannot.\n - If they did not, ask which BIC is on their statement or payment\n instruction before pricing or routing, and say which office you used.\n - Never present a representative office's BIC as \"the bank's BIC\".\n\nExamples:\n swift_lookup(\"DEUTDEFF\") # exact BIC lookup\n swift_lookup(\"Deutsche Bank\") # search by name\n swift_lookup(\"Commerzbank Frankfurt\") # bank + city -> that office's BIC\n swift_lookup(\"TBC PAY\") # find non-SWIFT payment processor\n swift_lookup(\"bank\", country=\"KZ\") # explore banks in a country\n swift_lookup(\"Halyk\", country=\"KZ\") # find specific bank in country\n swift_lookup(\"Bank Mandiri\", country=\"Indonesia\") # full country name OK", "inputSchema": { "additionalProperties": false, "properties": { "country": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "limit": { "default": 20, "type": "integer" }, "query": { "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "swift_lookup", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Look up SWIFT message types — MT (FIN) and MX (ISO 20022).\n\nPass a specific type to get full details, or omit to list all types.\nCovers customer payments (MT103, pacs.008), FI transfers (MT202,\npacs.009), trade finance (MT700, MT760), cash management (MT940,\ncamt.053), and payment status (pacs.002).\n\nAlso use this tool to answer questions about where specific payment\nfields live — e.g., where the UETR sits in an MT103 (Field 121, Block 3\nheader), where charges appear (71A/71F/71G), or which fields carry\nrouting info (56/57). MT103 and pacs.008 responses include a\n`tracing_note` explaining UETR recovery for customers who only have\na reference number.\n\nArgs:\n message_type: Message type (e.g., \"MT103\", \"pacs.008\", \"MT940\").\n Case-insensitive. Omit to list all.\n\nExamples:\n swift_message_reference(\"MT103\")\n swift_message_reference(\"pacs.008\")\n swift_message_reference()", "inputSchema": { "additionalProperties": false, "properties": { "message_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "swift_message_reference", "outputSchema": { "description": "Generic wrapper for non-object return types.", "properties": { "result": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } ] } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Track a SWIFT payment by UETR or reference number.\n\nBasic SWIFT payment tracking enriched by data from certain banks in\nthe correspondent chain. Returns the overall payment status and,\nwhen available, per-bank details showing which banks reported\ninformation about this payment.\n\nIMPORTANT — every trace needs four things:\n amount, currency, date, and an identifier (uetr, or reference when\n there is no UETR). amount, currency and date are required\n parameters, on the UETR path too: there is no UETR-only lookup, so\n never tell the user the UETR alone is enough to run one. Ask for\n whatever is missing before calling, and never guess a value.\n\nIMPORTANT — UETR vs Reference:\n The UETR (Unique End-to-End Transaction Reference) is a UUID\n assigned to every SWIFT gpi payment. Tracking by UETR succeeds\n ~80% of the time. Tracking by reference number alone succeeds\n less than 1% of the time because most banks only index by UETR.\n\n → Always provide the UETR if available.\n → The reference number is Field 20 of the MT103 (or the\n equivalent <InstrId>/<EndToEndId> in pacs.008). It is the\n sender's transaction reference. Still valuable — provide it\n alongside the UETR when you have both.\n\nWHEN THE USER HAS ONLY A REFERENCE AND NO UETR\n(\"how do I find / trace my payment?\", \"I have a reference number\nbut no UETR, where is it?\"):\n This is exactly the scenario this tool can attempt — do NOT answer\n from general knowledge. A reference-based trace cannot be run from\n the reference alone; you MUST first collect three things from the user:\n 1. amount — the exact amount as sent\n 2. currency — ISO 4217 (e.g. \"USD\")\n 3. date — the send date (within the last 90 days)\n Then call track_payment(reference=..., amount=..., currency=...,\n date=...). State the expectation up front: reference-only tracing\n succeeds less than 1% of the time.\n In parallel, tell the user how to recover the UETR for a reliable\n (~80%) trace: ask the SENDING bank for the MT103 confirmation — the\n UETR is in Block 3, tag {121:} (a UUID v4), stored by every\n gpi-enabled bank against the payment. Re-run with uetr= once they\n have it. (swift_message_reference(\"MT103\") returns the full\n field/UETR-recovery reference if you need to cite specifics.)\n\nIMPORTANT — Interpreting bank details:\n Each entry in the 'details' array represents a bank that reported\n data about this payment. The bank could be the SENDER, the\n BENEFICIARY, or ANY INTERMEDIARY/CORRESPONDENT in the chain.\n Do NOT assume a bank is an intermediary just because it appears\n in the list — we only know the payment passed through that bank.\n The bank's role is only known when it self-reports via push API\n (indicated by a non-null 'role' field).\n\nRequires an API key with an active FI subscription.\nTo get started: call mcp_register → mcp_verify → subscribe to\nan FI plan at https://ohmyfin.ai/subscription.\n\nArgs:\n uetr: UETR (UUID v4 format, e.g. \"eb6305c8-0710-4e41-84ad-f58db3083e82\").\n Strongly recommended — tracking without UETR rarely returns results.\n This is the Unique End-to-End Transaction Reference assigned to every\n SWIFT gpi payment.\n reference: Sender's bank reference number (MT103 Field 20 / pacs.008\n InstrId). Useful alongside UETR for cross-referencing, but\n alone it rarely produces results. Required only if uetr is\n not provided.\n amount: REQUIRED. Transaction amount as sent (e.g. 15000.00). Must match\n the original payment amount — even small differences may prevent\n tracking from finding the payment, so ask the user for the exact\n figure rather than estimating or rounding one.\n currency: REQUIRED. ISO 4217 code of the currency the payment was SENT\n in (e.g. \"USD\", \"EUR\", \"GBP\"). Ask if you do not know it; do\n not assume the sender's or the beneficiary's home currency.\n date: REQUIRED. Transaction date. Preferred format: YYYY-MM-DD (ISO 8601).\n Also accepted: DD.MM.YYYY or DD-MM-YYYY (European format).\n Must be within the last 90 days.\n api_key: Your Ohmyfin API key (prod-...). Can also be passed\n via KEY header or Authorization: Bearer header.\n\nReturns a dict with:\n status: Overall payment status — one of:\n \"success\" — delivered to the beneficiary when the gpi code\n ACCC backs it; otherwise one bank reported its\n own leg completed (status_explanation says which)\n \"in progress\" — payment is being processed (may update)\n \"returned\" — payment was canceled/returned after processing (final)\n \"rejected\" — payment was refused (final)\n \"on hold\" — temporarily held, e.g. compliance review\n \"future\" — scheduled for a future value date\n \"unknown\" — no tracking data available yet\n status_raw: ISO 20022 status code (ACCC/ACSP/RJCT/PDNG) or null\n status_reason: ISO 20022 reason code at PAYMENT level, or null. null\n is common and does NOT mean no reason code was reported —\n most feeds report the qualifier per bank instead, see below.\n reason_codes_reported_by_banks: Present whenever any bank line reports\n a \"STATUS/REASON\" qualifier (ACSP/G003, RJCT/MS03). Each entry\n is decoded to its name and meaning. This is what answers \"is\n anything pending / held / rejected / flagged on my payment\",\n not status_reason.\n lastupdate: Date of last status change (YYYY-MM-DD) or null\n details: Array of bank-level tracking entries (see role_explanation\n in each entry for how to interpret the bank's role)\n not_found_guidance: Present only when nothing was found — concrete\n next steps (UETR recovery, exact-match checks). Relay these\n to the user instead of improvising; a miss on a\n reference-only trace is the expected outcome and does NOT\n mean the payment failed.\n\nExamples:\n track_payment(uetr=\"eb6305c8-0710-4e41-84ad-f58db3083e82\",\n amount=15000, currency=\"USD\", date=\"2026-03-10\")\n track_payment(uetr=\"eb6305c8-0710-4e41-84ad-f58db3083e82\",\n reference=\"FT2603100123\",\n amount=15000, currency=\"USD\", date=\"2026-03-10\")\n track_payment(reference=\"FT2603100123\",\n amount=5000, currency=\"EUR\", date=\"12.03.2026\")", "inputSchema": { "additionalProperties": false, "properties": { "amount": { "type": "number" }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "currency": { "type": "string" }, "date": { "type": "string" }, "reference": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "uetr": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "amount", "currency", "date" ], "type": "object" }, "name": "track_payment", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Show how a SWIFT payment's tracking results changed over time.\n\nReturns the DISTINCT tracking results recorded for a payment (by UETR or\nreference), deduplicated so ten identical re-tracks collapse to one entry\nwhile any change — a new last-update, a status change, or new bank data —\nappears as its own entry. Each entry includes what was ENTERED when the\nsearch was run (amount, currency, date) alongside the banks that reported\ndata and their confirmed amount / value date.\n\nWHEN TO USE THIS:\n - The user says the page shows different data than you see, or asks why a\n bank line (e.g. JP Morgan) \"disappeared\" or a value date differs.\n - You need to reconcile an amount discrepancy. Correspondent banks such as\n JP Morgan return their confirmation ONLY when the tracked amount exactly\n matches the payment, so a search run with the wrong amount silently drops\n their line. Comparing entries here — same UETR, different entered amounts,\n different bank data — is how you spot that the amount was the problem.\n - Before concluding \"the record was consolidated\" or \"the bank stopped\n reporting\", check the history: the earlier result you're being asked\n about is usually still here, under a different entered amount.\n\nEach bank entry's `source` names the tracking SOURCE that reported it (e.g.\n\"Standard Chartered\"), not the bank at a step of the payment; track_payment\nnames the same data by the bank at each step, so the two names differ.\n\nOnly results for the current user (plus system tracks with no owner) are\nreturned; other users' searches of the same UETR are never shown.\n\nRequires an API key with an active FI subscription.\n\nArgs:\n uetr: UETR (UUID v4) of the payment. Strongly preferred.\n reference: Sender's reference (MT103 Field 20) — used when no UETR.", "inputSchema": { "additionalProperties": false, "properties": { "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "reference": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "uetr": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "tracking_history", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "BETA. Estimate what a cross-border payment will COST, split by WHO\nPAYS: the sending bank's published fee (the sender's side), what\ncorrespondents deduct in transit and what the beneficiary's own bank\ncharges to credit it (the beneficiary's side), and what actually lands.\n\nThis estimator is in BETA. Present every number as a typical case and a\nhigh case, never as a quote, and never let a user commit to a contractual\namount on it. The payload carries beta=true while this holds.\n\nHOW TO READ THE ANSWER (relay these honestly):\n- `answered=false` means we REFUSED. The most common reason is that we\n hold no published tariff rule for the sending bank, in which case there\n is deliberately no total and no \"recipient receives\" figure. Say we do\n not know what that bank charges. Do NOT add up the parts yourself and\n present a total: treating the unknown fee as zero is the exact defect\n this tool was built to remove.\n- The correspondent fee is a RANGE (`p50` typical, `p90` high case), not a\n point. The spread is real: SWIFT tracking never reveals whether a\n payment was sent OUR, SHA or BEN, so a single cohort mixes all three.\n- THREE FEES, THREE DIFFERENT PAYERS, AND THEY ARE NOT INTERCHANGEABLE.\n `sending_fee` is billed to the SENDER by their own bank.\n `correspondent_fee` comes out of the payment in transit, so the\n BENEFICIARY bears it. `beneficiary_fee` is what the RECEIVING bank\n charges its own customer to credit the payment, so the beneficiary bears\n that too - and it is frequently the largest of the three (measured\n 2026-08-22 on one live corridor: 35.26 USD of sender-side cost against a\n 245.68 USD beneficiary bank fee). Never quote one of them as \"the cost\",\n and never call the beneficiary bank's fee a correspondent charge.\n `total` is the sending fee plus the transit deduction; `total_both_sides`\n adds the beneficiary bank's fee and is the all-in figure.\n- WHERE EACH NUMBER COMES FROM. The correspondent fee is OBSERVED, from\n payments we have tracked. `beneficiary_fee.source` is `tariff` (or\n `tariff_fallback`, see below) and never `observed`: a beneficiary bank\n deducts after the last bank that reports to GPI, so no tracking data can\n see it, and we read it off that bank's published incoming tariff\n instead. Say which is which when the user leans on a figure.\n- `beneficiary_fee.known=false` means WE HOLD NO INCOMING TARIFF for that\n bank (we hold one for roughly two thirds of beneficiary banks). Its\n charge is then missing from every figure, `total_both_sides` is null,\n and `recipient_receives.typical` is an UPPER BOUND -\n `recipient_receives.beneficiary_fee_known` says so. Do not fill that gap\n with a zero, a guess or a typical figure; say the receiving bank's own\n charge is not included and point the user at that bank's tariff.\n- `beneficiary_fee.applies=false` under OUR / OUR-OUR: the instruction says\n the sender covers every downstream charge, so the bank claims it back\n rather than taking it off the credit. The figure is reported but NOT\n subtracted. Our data ends before the account is credited, so we can\n neither confirm nor refute that it was honoured on a given payment.\n- `beneficiary_fee.segment` says which of the bank's incoming price lists\n was read. `segment_fallback=true` means the account type asked for had\n no usable schedule so the other one answered - which can only happen\n when `beneficiary_segment` was NOT supplied, i.e. when we were assuming\n the beneficiary matches the sender. Say that you assumed it.\n- `beneficiary_fee.reason='other_segment_only'` means you DID supply\n `beneficiary_segment`, and that bank publishes an incoming tariff for\n the other account type only (`beneficiary_fee.other_segment` names it).\n We decline to quote it. Do NOT report this as \"we hold no tariff for\n that bank\": we hold one, for a different kind of account. Tell the user\n which, because it is often the useful half of the answer.\n- `basis.n` is how many observed payments back the correspondent figure and\n `confidence` reflects it. At \"low\", present the range as rough.\n- `basis.level` says how specific the evidence is: `corridor` is this\n correspondent into this destination country, `correspondent` is that\n bank overall, and `currency` or `global` mean we hold nothing specific\n and are quoting a pool. Say so when it is a pool.\n- ON A REFUSAL `basis` IS NULL, and the same two figures are still on each\n entry of `correspondent_fee.legs[]` as `level` and `n`. Read them there.\n Do not read a missing `basis` as corridor-specific evidence: on a\n measured DE->AM screen the legs said `level: \"currency\", n: 146`, a\n currency-wide pool, and the answer described it as a single well-priced\n hop because the top-level key was absent.\n- `assumptions` is a list of plain sentences explaining what shaped the\n number (SEPA, OUR honoured, PSD2, a modelled BEN uplift, a stale\n tariff). Relay the ones that matter to the user's question.\n- under OUR the correspondent leg carries `our_breach`: the measured share\n of OUR payments that lose a charge in transit anyway, and what that\n costs. p50 is 0 and p90 is that loss. Quote BOTH - \"the beneficiary\n should receive the full amount, and in about 7% of the OUR payments we\n can follow end to end they do not\" - never the p50 alone as a promise.\n- `chain.status` = `no_chain` means the pair settles on local rails (SEPA,\n domestic, same banking group) with NO correspondent deduction at all.\n\nIMPORTANT ON CHARGE TYPE: charge_type is an INPUT and is never inferred\nfrom tracking. OUR is a real instruction and usually holds - of 150\npayments whose own MT103 declared OUR and which we could follow from the\ninstructed amount to the settled one, 139 reached the beneficiary intact,\nagainst 6 of 52 under SHA. It is NOT a guarantee: the other 11 lost a flat\ncorrespondent charge in transit, and we find no evidence that this depends\non the destination country or on a US correspondent being in the chain, so\ndo not tell a user that OUR is safe everywhere except the US. BEN is\nmaterially more expensive than SHA and our high case models it rather than\nmeasuring it. If the user has not said which they will use, ask, or state\nwhich one you assumed.\n\nPass `beneficiary_bic` whenever the user knows the receiving bank: without\nit there is no correspondent chain to price and no beneficiary bank to\nread a tariff from, so the answer is the sending fee alone and no total.\n\n`customer_segment` selects which side of the SENDING bank's published price\nlist is read. It is not cosmetic: of 30 banks publishing both schedules, 9\nof the 17 that answered on both quote a different fee, one of them 220 PLN\nfor a company against free for a person. It defaults to `individual` here;\npass `business` when the payer is a company, and say which you assumed.\n\n`beneficiary_segment` does the same for the RECEIVING side, which is a\ndifferent bank's price list and not a restatement of the sender's. Of 120\nbanks publishing both schedules, 28 quote a different incoming fee\n(measured 2026-08-24), and it runs both ways: Hipotekarna banka (HBBAMEPG)\ncredits a 100,000 EUR payment free of charge to a company and takes 0.1%\nof it from a person, while Nordea charges a person 60 SEK and a company\n250. Omit it and we assume the beneficiary matches the sender, which is\nwhat this tool did before 2026-08-24 - so if you omit it, say you assumed\nit. Supply it when the user has told you who is being paid, and prefer\nasking over guessing when the amount makes the difference material.\n\nAvailable to any caller with an active subscription. The estimate itself\ncosts no credits (tracking a payment does cost credits; never describe\ntracking as free).\n\nArgs:\n bank_swift: Sending bank BIC (8 or 11 chars)\n amount: Transfer amount\n currency: 3-letter transfer currency\n charge_type: SHA (default), OUR or BEN. Ask the user rather than guessing\n beneficiary_bic: Receiving bank BIC; needed for a total\n channel: online | branch | mobile_app | any\n customer_segment: individual | business | financial_institution - the SENDER\n beneficiary_segment: individual | business | financial_institution - the\n party being PAID. Omitted, it mirrors customer_segment\n customer_sub_segment: standard | premium | private_banking | vip\n api_key: Optional API key (internal calls ride the MCP secret)", "inputSchema": { "additionalProperties": false, "properties": { "amount": { "type": "number" }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "bank_swift": { "type": "string" }, "beneficiary_bic": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "beneficiary_segment": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "channel": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "charge_type": { "default": "SHA", "type": "string" }, "currency": { "type": "string" }, "customer_segment": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "customer_sub_segment": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "bank_swift", "amount", "currency" ], "type": "object" }, "name": "transfer_cost", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Calculate the value/settlement date for a payment.\n\nDetermines when a payment will settle based on:\n- Source and destination country holiday calendars\n- Weekend conventions (Sat/Sun or Fri/Sat)\n- Currency center holidays (if FX conversion involved)\n- Settlement convention (T+0, T+1, T+2)\n\nArgs:\n source_country: Sender's country (ISO 3166-1 alpha-2, e.g., \"US\")\n dest_country: Receiver's country (ISO 3166-1 alpha-2, e.g., \"DE\")\n settlement_type: One of \"wire\" (T+0 domestic / T+1 international),\n \"fx_spot\" (T+1 or T+2 based on pair),\n \"sepa\" (D+1), \"sepa_instant\" (T+0)\n base_currency: Base currency for FX (ISO 4217, e.g., \"USD\").\n Required when settlement_type is \"fx_spot\".\n target_currency: Target currency for FX (ISO 4217, e.g., \"EUR\").\n Required when settlement_type is \"fx_spot\".\n from_date: Start date in ISO format (YYYY-MM-DD). Default: today.\n You do not know today's date — omit this argument unless the\n user named a specific send date. If the user's date is\n relative (\"the 20th\", \"next Friday\", \"month-end\"), read the\n `today` block in any response from this tool, bank_holidays\n or is_business_day_check and resolve against that.\n\nExamples:\n value_date(\"US\", \"DE\")\n value_date(\"US\", \"DE\", \"fx_spot\", \"USD\", \"EUR\")\n value_date(\"DE\", \"FR\", \"sepa\")\n value_date(\"US\", \"US\", \"wire\", from_date=\"2026-07-03\")", "inputSchema": { "additionalProperties": false, "properties": { "base_currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "dest_country": { "type": "string" }, "from_date": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "settlement_type": { "default": "wire", "type": "string" }, "source_country": { "type": "string" }, "target_currency": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "source_country", "dest_country" ], "type": "object" }, "name": "value_date", "outputSchema": { "additionalProperties": true, "type": "object" } } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:c0c0f3be5f09602aa74916af99b272283de43cb82524c3806f38a83ffeb85401 | sha256sum