get_bin_data_tool
Retrieve Bank Identification Number data for payment cards to verify issuer details and payment card information using the Pagos Data MCP Server.
Instructions
Get BIN data for a given BIN number.
Args: bin (str): The BIN number to get data for. Returns: str: A formatted string containing the BIN data (enhanced or basic based on ENHANCED_BIN_DATA config).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| bin | Yes |
Implementation Reference
- main.py:192-206 (handler)The core handler function implementing the tool logic: retrieves API key, creates PagosClient, fetches data asynchronously, handles empty response, and formats output.async def get_bin_data_tool(bin: str) -> str: """ Get BIN data for a given BIN number. Args: bin (str): The BIN number to get data for. Returns: str: A formatted string containing the BIN data (enhanced or basic based on ENHANCED_BIN_DATA config). """ api_key = os.getenv("PAGOS_API_KEY") pagos_client = PagosClient(api_key=api_key) data = await pagos_client.get_bin_data(bin) if not data: return "Unable to retrieve BIN data or no BIN data found" return format_bin_data(data)
- main.py:191-191 (registration)Registers the get_bin_data_tool using the FastMCP tool decorator (@mcp.tool()).@mcp.tool()
- main.py:12-189 (helper)Supporting function that formats the EnhancedBinApiResponse object into a detailed human-readable string, covering all aspects like card details, product, bank, country, authentication, features, costs, etc.def format_bin_data(bin_data: Optional[EnhancedBinApiResponse]) -> str: if not bin_data or not bin_data.card: return "No BIN data available" card = bin_data.card result = [] # Basic card information result.append("Card Details:") result.append("-------------") if card.card_brand: result.append(f"Brand: {card.card_brand}") if card.type: result.append(f"Type: {card.type}") if card.prepaid is not None: result.append(f"Prepaid: {'Yes' if card.prepaid else 'No'}") if card.virtual_card is not None: result.append(f"Virtual Card: {'Yes' if card.virtual_card else 'No'}") if card.funding_source: result.append(f"Funding Source: {card.funding_source}") if card.card_segment_type: result.append(f"Card Segment Type: {card.card_segment_type}") if card.combo_card: result.append(f"Combo Card: {card.combo_card}") # Product information if card.product: result.append("") result.append("Product Information:") result.append("-------------------") if card.product.product_name: result.append(f"Product: {card.product.product_name}") if card.product.product_id: result.append(f"Product ID: {card.product.product_id}") # Bank information if card.bank: result.append("") result.append("Bank Information:") result.append("----------------") if card.bank.name: result.append(f"Bank: {card.bank.name}") if card.bank.clean_name: result.append(f"Clean Name: {card.bank.clean_name}") if card.bank.phone: result.append(f"Phone: {card.bank.phone}") if card.bank.url: result.append(f"URL: {card.bank.url}") # Country information if card.country: result.append("") result.append("Country Information:") result.append("-------------------") if card.country.name: result.append(f"Country: {card.country.name}") if card.country.alpha2: result.append(f"Country Code: {card.country.alpha2}") if card.country.numeric: result.append(f"Numeric Code: {card.country.numeric}") # Authentication information if card.authentication: result.append("") result.append("Authentication:") result.append("---------------") result.append( f"Authentication Required: {'Yes' if card.authentication.authentication_required else 'No'}" ) if card.authentication.authentication_name: result.append( f"Authentication Name: {card.authentication.authentication_name}" ) # Technical details result.append("") result.append("Technical Details:") result.append("-----------------") if card.bin_min and card.bin_max: result.append(f"BIN Range: {card.bin_min} - {card.bin_max}") if card.bin_length: result.append(f"BIN Length: {card.bin_length}") if card.pagos_bin_length: result.append(f"Pagos BIN Length: {card.pagos_bin_length}") if card.number and card.number.length: result.append(f"Card Number Length: {card.number.length}") if card.pan_or_token: result.append(f"PAN or Token: {card.pan_or_token}") if card.correlation_id: result.append(f"Correlation ID: {card.correlation_id}") # Additional features if any( [ card.level2, card.level3, card.alm, card.account_updater, card.domestic_only, card.gambling_blocked, card.reloadable, card.issuer_supports_tokenization, card.shared_bin, ] ): result.append("") result.append("Additional Features:") result.append("-------------------") if card.level2 is not None: result.append(f"Level 2: {'Yes' if card.level2 else 'No'}") if card.level3 is not None: result.append(f"Level 3: {'Yes' if card.level3 else 'No'}") if card.alm is not None: result.append(f"ALM: {'Yes' if card.alm else 'No'}") if card.account_updater is not None: result.append(f"Account Updater: {'Yes' if card.account_updater else 'No'}") if card.domestic_only is not None: result.append(f"Domestic Only: {'Yes' if card.domestic_only else 'No'}") if card.gambling_blocked is not None: result.append( f"Gambling Blocked: {'Yes' if card.gambling_blocked else 'No'}" ) if card.reloadable is not None: result.append(f"Reloadable: {'Yes' if card.reloadable else 'No'}") if card.issuer_supports_tokenization is not None: result.append( f"Issuer Supports Tokenization: {'Yes' if card.issuer_supports_tokenization else 'No'}" ) if card.shared_bin is not None: result.append(f"Shared BIN: {'Yes' if card.shared_bin else 'No'}") # Currency and access information if card.issuer_currency or card.multi_account_access_indicator: result.append("") result.append("Currency & Access:") result.append("------------------") if card.issuer_currency: result.append(f"Issuer Currency: {card.issuer_currency}") if card.multi_account_access_indicator: result.append( f"Multi Account Access: {card.multi_account_access_indicator}" ) # Additional card brands if card.additional_card_brands: result.append("") result.append("Additional Card Brands:") result.append("----------------------") for brand in card.additional_card_brands: if brand.card_brand: result.append(f"- {brand.card_brand}") if brand.card_brand_product: result.append(f" Product: {brand.card_brand_product}") if brand.card_brand_bank_name: result.append(f" Bank: {brand.card_brand_bank_name}") if brand.ecom_enabled is not None: result.append( f" E-commerce Enabled: {'Yes' if brand.ecom_enabled else 'No'}" ) if brand.billpay_enabled is not None: result.append( f" Bill Pay Enabled: {'Yes' if brand.billpay_enabled else 'No'}" ) # Cost information if card.cost and card.cost.interchange: result.append("") result.append("Cost Information:") result.append("-----------------") interchange = card.cost.interchange result.append(f"Regulated: {'Yes' if interchange.regulated else 'No'}") if interchange.regulated_name: result.append(f"Regulated Name: {interchange.regulated_name}") if interchange.notes: result.append(f"Notes: {interchange.notes}") return "\n".join(result)
- pagos_client.py:141-145 (schema)Dataclass schema defining the EnhancedBinApiResponse structure used internally for typing and parsing the Pagos API response data.class EnhancedBinApiResponse: """Enhanced BIN API response from the Pagos Parrot API.""" card: Optional[EnhancedCard] = None
- pagos_client.py:180-321 (helper)PagosClient.get_bin_data async method: constructs API request to Pagos Parrot (/bins), handles HTTP, parses complex nested JSON into dataclasses (EnhancedCard, Bank, etc.), returns typed response or None on error.async def get_bin_data( self, bin: str, enhanced: Optional[bool] = None ) -> Optional[EnhancedBinApiResponse]: """ Get BIN data for a given BIN number. Based on the GET /bins endpoint from the Pagos Parrot API. Args: bin: The BIN number to lookup (Bank Identification Number) enhanced: Whether to return enhanced data (default: True) Returns: EnhancedBinApiResponse if successful, None if not found or error occurs Raises: httpx.HTTPStatusError: For HTTP errors (4xx, 5xx) httpx.RequestError: For network/connection errors """ # Use instance setting if enhanced parameter is None enhanced_value = enhanced if enhanced is not None else self.enhanced params = {"bin": bin, "enhanced": str(enhanced_value).lower()} async with httpx.AsyncClient() as client: try: response = await client.get( self.base_url, params=params, headers=self.headers ) response.raise_for_status() data = response.json() # Parse the card data with all enhanced fields card_data = data.get("card", {}) # Parse nested objects number_data = card_data.get("number", {}) number = Number(**number_data) if number_data else None product_data = card_data.get("product", {}) product = Product(**product_data) if product_data else None bank_data = card_data.get("bank", {}) bank = Bank(**bank_data) if bank_data else None country_data = card_data.get("country", {}) country = Country(**country_data) if country_data else None auth_data = card_data.get("authentication", {}) authentication = Authentication(**auth_data) if auth_data else None # Parse cost structure cost_data = card_data.get("cost", {}) cost = None if cost_data: interchange_data = cost_data.get("interchange", {}) interchange = None if interchange_data: domestic_data = interchange_data.get("domestic", {}) domestic = CostDto(**domestic_data) if domestic_data else None inter_data = interchange_data.get("inter", {}) inter = CostDto(**inter_data) if inter_data else None intra_data = interchange_data.get("intra", {}) intra = CostDto(**intra_data) if intra_data else None interchange = Interchange( regulated=interchange_data.get("regulated", False), regulated_name=interchange_data.get("regulated_name"), domestic=domestic, inter=inter, intra=intra, notes=interchange_data.get("notes"), ) cost = Cost(interchange=interchange) # Parse additional card brands additional_brands_data = card_data.get("additional_card_brands", []) additional_card_brands = None if additional_brands_data: additional_card_brands = [ AdditionalNetwork(**brand) for brand in additional_brands_data ] # Parse networkfees networkfees_data = card_data.get("networkfees", {}) networkfees = Networkfees() if networkfees_data else None enhanced_card = EnhancedCard( number=number, bin_length=card_data.get("bin_length"), pagos_bin_length=card_data.get("pagos_bin_length"), bin_min=card_data.get("bin_min"), bin_max=card_data.get("bin_max"), pan_or_token=card_data.get("pan_or_token"), virtual_card=card_data.get("virtual_card"), level2=card_data.get("level2"), level3=card_data.get("level3"), alm=card_data.get("alm"), account_updater=card_data.get("account_updater"), domestic_only=card_data.get("domestic_only"), gambling_blocked=card_data.get("gambling_blocked"), issuer_currency=card_data.get("issuer_currency"), reloadable=card_data.get("reloadable"), additional_card_brands=additional_card_brands, card_brand=card_data.get("card_brand"), card_segment_type=card_data.get("card_segment_type"), combo_card=card_data.get("combo_card"), type=card_data.get("type"), funding_source=card_data.get("funding_source"), prepaid=card_data.get("prepaid"), product=product, bank=bank, country=country, authentication=authentication, cost=cost, networkfees=networkfees, correlation_id=card_data.get("correlation_id"), issuer_supports_tokenization=card_data.get( "issuer_supports_tokenization" ), multi_account_access_indicator=card_data.get( "multi_account_access_indicator" ), shared_bin=card_data.get("shared_bin"), ) return EnhancedBinApiResponse(card=enhanced_card) except httpx.HTTPStatusError as e: # Log the error for debugging print(f"HTTP error {e.response.status_code}: {e.response.text}") return None except httpx.RequestError as e: # Log network/connection errors print(f"Request error: {e}") return None except KeyError as e: # Log data parsing errors print(f"Data parsing error: {e}") return None