Skip to main content
Glama
paulieb89

UK Legal Research MCP Server

Get VAT Rate for Commodity

hmrc_get_vat_rate
Read-onlyIdempotent

Look up the UK VAT rate for any commodity or service, receiving the rate category, effective date, and any conditions or exceptions.

Instructions

Look up the UK VAT rate for a commodity or service type.

Returns the rate category (standard 20%, reduced 5%, zero 0%, exempt), effective date, and any relevant conditions or exceptions. Uses a static lookup table current as of 22 Nov 2023 (Autumn Statement). Rates may have changed — always verify against GOV.UK for recent Budgets.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYesHMRCVATRateInput with the commodity_code (description of goods or service).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
commodity_codeYesCommodity code or description queried
rateYesVAT rate category
rate_percentageYesApplicable rate as percentage: 20.0 (standard), 5.0 (reduced), 0.0 (zero/exempt)
effective_fromYesDate from which this rate applies
notesNoAny additional notes or conditions on this rate

Implementation Reference

  • The hmrc_get_vat_rate async function is the tool handler. It takes an HMRCVATRateInput (commodity_code string) and returns a VATRate by delegating to the _lookup_vat helper function.
    async def hmrc_get_vat_rate(params: HMRCVATRateInput) -> VATRate:
        """Look up the UK VAT rate for a commodity or service type.
    
        Returns the rate category (standard 20%, reduced 5%, zero 0%, exempt),
        effective date, and any relevant conditions or exceptions.
        Uses a static lookup table current as of 22 Nov 2023 (Autumn Statement).
        Rates may have changed — always verify against GOV.UK for recent Budgets.
    
        Args:
            params: HMRCVATRateInput with the commodity_code (description of goods or service).
        """
        return _lookup_vat(params.commodity_code)
  • HMRCVATRateInput Pydantic model — the input schema for the tool. Accepts a commodity_code string (2-200 chars) describing the goods or service.
    class HMRCVATRateInput(BaseModel):
        model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")
    
        commodity_code: str = Field(
            ...,
            description="Commodity code or plain-English description. E.g. 'food', 'domestic fuel', 'software', 'financial services', 'new build residential'",
            min_length=2, max_length=200,
        )
  • VATRate Pydantic model — the output schema for the tool. Contains commodity_code, rate (standard/reduced/zero/exempt/outside_scope), rate_percentage, effective_from date, and notes.
    class VATRate(BaseModel):
        """VAT rate for a commodity or service."""
    
        model_config = ConfigDict(str_strip_whitespace=True)
    
        commodity_code: str = Field(..., description="Commodity code or description queried")
        rate: Literal["standard", "reduced", "zero", "exempt", "outside_scope"] = Field(
            ..., description="VAT rate category"
        )
        rate_percentage: float = Field(
            ..., description="Applicable rate as percentage: 20.0 (standard), 5.0 (reduced), 0.0 (zero/exempt)"
        )
        effective_from: date = Field(..., description="Date from which this rate applies")
        notes: str | None = Field(None, description="Any additional notes or conditions on this rate")
  • The register_tools function registers the tool via @mcp.tool decorator with name='get_vat_rate'. The gateway mounts the hmrc_mcp (from __init__.py) under namespace 'hmrc', making the full tool name 'hmrc_get_vat_rate'.
    def register_tools(mcp: FastMCP) -> None:
    
        @mcp.tool(
            name="get_vat_rate",
            annotations={"title": "Get VAT Rate for Commodity", "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, "openWorldHint": False},
        )
        async def hmrc_get_vat_rate(params: HMRCVATRateInput) -> VATRate:
            """Look up the UK VAT rate for a commodity or service type.
    
            Returns the rate category (standard 20%, reduced 5%, zero 0%, exempt),
            effective date, and any relevant conditions or exceptions.
            Uses a static lookup table current as of 22 Nov 2023 (Autumn Statement).
            Rates may have changed — always verify against GOV.UK for recent Budgets.
    
            Args:
                params: HMRCVATRateInput with the commodity_code (description of goods or service).
            """
            return _lookup_vat(params.commodity_code)
  • _lookup_vat helper function — looks up the commodity code in the static _VAT_LOOKUP dictionary, performing fuzzy matching. Falls back to standard 20% rate if no match found. The lookup table (lines 26-57) has ~30 entries with rate categories, percentages, and explanatory notes.
    def _lookup_vat(commodity_code: str) -> VATRate:
        key = commodity_code.strip().lower()
        for k, (rate_name, percentage, notes) in _VAT_LOOKUP.items():
            if k in key or key in k:
                return VATRate(
                    commodity_code=commodity_code, rate=rate_name,  # type: ignore[arg-type]
                    rate_percentage=percentage, effective_from=_EFFECTIVE_DATE, notes=notes,
                )
        return VATRate(
            commodity_code=commodity_code, rate="standard", rate_percentage=20.0,
            effective_from=_EFFECTIVE_DATE,
            notes=(
                f"No specific exemption found for '{commodity_code}'. "
                "Standard 20% rate assumed. Verify at https://www.gov.uk/guidance/rates-of-vat-on-different-goods-and-services"
            ),
        )
Behavior5/5

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

The description adds significant context beyond the annotations: it reveals the data source (static lookup), currency date, return fields (rate category, effective date, conditions), and the need for external verification. No contradictions with annotations.

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?

Three well-structured sentences, each adding value. The purpose is front-loaded, and every sentence is justified without unnecessary elaboration.

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

Completeness5/5

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

Given the tool's simplicity (one parameter) and the presence of an output schema, the description provides sufficient context about what the tool does, what it returns, and its limitations. No gaps.

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

Parameters3/5

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

Schema coverage is 100%, so baseline is 3. The description does not add parameter-specific details beyond what the schema provides, though it contextualizes the parameter as 'commodity or service type'. No significant added value.

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 specifies the action ('Look up') and the resource ('UK VAT rate for a commodity or service type'). It effectively distinguishes from sibling tools like hmrc_check_mtd_status and hmrc_search_guidance, which serve different purposes.

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

Usage Guidelines4/5

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

The description provides usage context by noting the static lookup table's date and advising verification against GOV.UK for recent updates. While it does not explicitly list alternatives or exclusion criteria, the caution about staleness guides appropriate use.

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/paulieb89/uk-legal-mcp'

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