Skip to main content
Glama
cmendezs

mcp-einvoicing-be

lookup_vat_be

Retrieve legal name, registered address, legal form, status, and NACE activity codes for any Belgian enterprise number using the BCE/KBO public database. Accepts numbers with or without the BE prefix.

Instructions

Look up a Belgian enterprise number against the BCE/KBO public database.

Accepts the number with or without the 'BE' prefix and with or without dots/spaces. Returns the enterprise's legal name, registered address, legal form, status, and NACE activity codes.

Optionally set the BCE_API_KEY environment variable for authenticated access to the full BCE dataset.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
vat_numberYesBelgian VAT/enterprise number, e.g. 'BE0123456789' or '0123456789'

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The async function lookup_vat_be that implements the tool logic. It normalizes a Belgian VAT number, calls the BCE/KBO API at /enterprises/{digits}, and returns legal name, address, legal form, status, NACE codes, and start date. Handles 404 with a structured not-found response.
    async def lookup_vat_be(
        vat_number: Annotated[
            str,
            "Belgian VAT/enterprise number, e.g. 'BE0123456789' or '0123456789'",
        ],
    ) -> dict[str, object]:
        """Look up a Belgian enterprise number against the BCE/KBO public database.
    
        Accepts the number with or without the 'BE' prefix and with or without
        dots/spaces. Returns the enterprise's legal name, registered address,
        legal form, status, and NACE activity codes.
    
        Optionally set the ``BCE_API_KEY`` environment variable for authenticated
        access to the full BCE dataset.
        """
        normalized = normalize_vat_be(vat_number)
        digits = normalized[2:]  # strip 'BE' for the path segment
    
        client = _bce_client()
        try:
            response = await client._request("GET", f"/enterprises/{digits}")
        except PlatformError as exc:
            if exc.status_code == 404:
                return {
                    "found": False,
                    "vat_number": normalized,
                    "error": "Enterprise number not found",
                }  # noqa: E501
            raise
    
        data: dict[str, object] = response.json()
        return {
            "found": True,
            "vat_number": normalized,
            "name": data.get("name"),
            "legal_form": data.get("legalForm"),
            "status": data.get("status"),
            "address": data.get("address"),
            "nace_codes": data.get("activities", []),
            "start_date": data.get("startDate"),
        }
  • Module-level imports and constants, including the BCE API base URL and type annotations. The input schema is defined inline via Annotated[str, ...] on the vat_number parameter (lines 31-34).
    """Lookup tools: lookup_vat_be, check_peppol_participant_be, get_invoice_types_be."""
    
    import os
    from typing import Annotated
    
    from mcp_einvoicing_core import AuthMode, BaseEInvoicingClient, PlatformError
    
    from mcp_einvoicing_be.standards.peppol_bis_3 import INVOICE_TYPES
    from mcp_einvoicing_be.utils.helpers import normalize_vat_be
    
    _BCE_API_BASE = "https://api.kbo-bce.be/v1"
    _PEPPOL_SML_BASE = "https://edelivery.tech.ec.europa.eu/edelivery-smp"
  • Registration of lookup_vat_be on the MCP server via mcp.tool()(lookup_vat_be) at line 26. The function is imported from tools.lookup at line 11.
    def _register_be_tools(mcp: Any) -> None:
        """Register all Belgian e-invoicing tools onto the shared FastMCP instance."""
        mcp.tool()(_validator.validate_invoice_be)
        mcp.tool()(_validator.validate_pint_be)
        mcp.tool()(_generator.generate_invoice_be)
        mcp.tool()(transform_to_ubl)
        mcp.tool()(lookup_vat_be)
        mcp.tool()(check_peppol_participant_be)
        mcp.tool()(get_invoice_types_be)
  • Helper function normalize_vat_be used by lookup_vat_be. Normalizes a Belgian VAT number to 'BE' + 10 digits, stripping spaces, dots, dashes and optional BE prefix.
    def normalize_vat_be(vat_number: str) -> str:
        """Normalize a Belgian VAT/enterprise number to 'BE' + 10-digit format.
    
        Accepts:
        - ``BE0123456789``
        - ``0123456789``
        - ``BE 0123.456.789``
        - ``0123.456.789``
    
        Raises ``ValueError`` if the result is not exactly 10 digits.
        """
        cleaned = re.sub(r"[\s.\-]", "", vat_number.upper())
        digits = cleaned[2:] if cleaned.startswith("BE") else cleaned
    
        if not re.fullmatch(r"\d{10}", digits):
            raise ValueError(
                f"Invalid Belgian VAT/enterprise number: {vat_number!r}. "
                "Expected 10 digits (with optional 'BE' prefix)."
            )
    
        return f"BE{digits}"
  • Helper _bce_client() that constructs an HTTP client for the BCE API, optionally using a BEARER_TOKEN auth mode if BCE_API_KEY environment variable is set.
    def _bce_client() -> BaseEInvoicingClient:
        api_key = os.environ.get("BCE_API_KEY", "")
        if api_key:
            return BaseEInvoicingClient(
                base_url=_BCE_API_BASE,
                auth_mode=AuthMode.BEARER_TOKEN,
                static_bearer_token=api_key,
            )
        return BaseEInvoicingClient(base_url=_BCE_API_BASE, auth_mode=AuthMode.NONE)
Behavior4/5

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

The description discloses returns (legal name, address, etc.) and optional authenticated access via environment variable. However, no information about error handling, rate limits, or any destructive behavior is included.

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

Conciseness5/5

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

The description is concise with two focused paragraphs: one for core function and one for optional auth. Every sentence is useful and front-loaded.

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

Completeness4/5

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

Given the simple single-parameter tool and presence of an output schema (not shown), the description adequately covers input format, return fields, and optional configuration. Missing details on failure cases but overall complete.

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 sole parameter is described in both schema and description. The description adds clarification about acceptable formats (with/without prefix and dots/spaces) not fully covered in the schema example.

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

Purpose5/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: lookup a Belgian enterprise number against the BCE/KBO public database. It distinguishes from sibling tools which focus on invoices and validation.

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

Usage Guidelines3/5

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

The description implies usage for looking up Belgian enterprises but does not explicitly state when to use this tool vs alternatives like 'check_peppol_participant_be'. No when-not-to-use or exclusion criteria are provided.

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/cmendezs/mcp-einvoicing-be'

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