Skip to main content
Glama
ampcome-mcps

Pagos Data MCP Server

by ampcome-mcps

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
NameRequiredDescriptionDefault
binYes

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()
  • 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)
  • 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
  • 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
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions that the output format depends on an 'ENHANCED_BIN_DATA config,' hinting at variability, but fails to detail critical aspects like authentication needs, rate limits, error handling, or whether the operation is read-only or has side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and appropriately sized, with a clear purpose statement followed by 'Args' and 'Returns' sections. Every sentence adds value, though the formatting could be more integrated into natural language for better front-loading.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (one parameter, no output schema, no annotations), the description is minimally adequate. It covers the basic purpose and parameter semantics but lacks details on behavioral traits and usage context, leaving gaps for an agent to operate effectively without additional information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema, which has 0% coverage. It explains that the 'bin' parameter is a 'BIN number to get data for,' clarifying its purpose. With only one parameter and no schema descriptions, this compensation is effective, though it could specify format constraints (e.g., length, allowed characters).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get BIN data for a given BIN number.' It specifies the verb ('Get') and resource ('BIN data'), making the function unambiguous. However, with no sibling tools mentioned, there's no opportunity to distinguish from alternatives, preventing a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or exclusions. It only states what the tool does without context for its application, leaving usage entirely implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ampcome-mcps/pagos-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server