Check MTD VAT Status
hmrc_check_mtd_statusCheck whether a UK business is mandated for Making Tax Digital (MTD) for VAT by providing its VAT Registration Number. Returns mandate status, effective date, and trading name.
Instructions
Check a business's Making Tax Digital VAT mandate status via the HMRC API.
NOTE: Connects to the HMRC sandbox by default. Set HMRC_API_BASE env var to 'https://api.service.hmrc.gov.uk' for production. Requires HMRC_CLIENT_ID and HMRC_CLIENT_SECRET environment variables (OAuth 2.0). Returns whether the business is mandated for MTD, effective date, and trading name.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | HMRCMTDStatusInput with the 9-digit VAT Registration Number. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| vrn | Yes | VAT Registration Number queried | |
| mandated | Yes | Whether this business is mandated for MTD VAT | |
| effective_date | No | Date from which MTD obligation applies | |
| trading_name | No | Registered trading name if available |
Implementation Reference
- src/modules/hmrc/tools.py:121-171 (handler)The main handler function for 'hmrc_check_mtd_status'. It checks a business's Making Tax Digital VAT mandate status via the HMRC API. It obtains an OAuth2 bearer token using client credentials, then calls the HMRC organisations/vat/{vrn}/obligations endpoint to determine if the business is mandated for MTD, returning an MTDStatus model with vrn, mandated flag, effective_date, and trading_name.
@mcp.tool( name="check_mtd_status", annotations={"title": "Check MTD VAT Status", "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, "openWorldHint": True}, ) async def hmrc_check_mtd_status(params: HMRCMTDStatusInput, ctx: Context) -> MTDStatus: """Check a business's Making Tax Digital VAT mandate status via the HMRC API. NOTE: Connects to the HMRC sandbox by default. Set HMRC_API_BASE env var to 'https://api.service.hmrc.gov.uk' for production. Requires HMRC_CLIENT_ID and HMRC_CLIENT_SECRET environment variables (OAuth 2.0). Returns whether the business is mandated for MTD, effective date, and trading name. Args: params: HMRCMTDStatusInput with the 9-digit VAT Registration Number. """ client_id = os.getenv("HMRC_CLIENT_ID") client_secret = os.getenv("HMRC_CLIENT_SECRET") if not client_id or not client_secret: raise RuntimeError( "HMRC OAuth credentials not configured. " "Set HMRC_CLIENT_ID and HMRC_CLIENT_SECRET. " "Register at https://developer.service.hmrc.gov.uk" ) client: httpx.AsyncClient = ctx.lifespan_context["http"] token_resp = await client.post( f"{HMRC_API_BASE}/oauth/token", data={"grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret, "scope": "read:vat"}, ) token_resp.raise_for_status() access_token = token_resp.json().get("access_token") vrn = params.vrn.strip().lstrip("GB").lstrip("gb") resp = await client.get( f"{HMRC_API_BASE}/organisations/vat/{vrn}/obligations", headers={"Authorization": f"Bearer {access_token}"}, params={"status": "O"}, ) resp.raise_for_status() data = resp.json() obligations = data.get("obligations", []) effective_date = None if obligations: start = obligations[0].get("start") if start: effective_date = date.fromisoformat(start) return MTDStatus( vrn=vrn, mandated=len(obligations) > 0, effective_date=effective_date, trading_name=data.get("tradingName"), ) - src/modules/hmrc/tools.py:90-93 (schema)Input schema (HMRCMTDStatusInput) for the check_mtd_status tool: a Pydantic model with a single 'vrn' field (VAT Registration Number).
class HMRCMTDStatusInput(BaseModel): model_config = ConfigDict(str_strip_whitespace=True, extra="forbid") vrn: str = Field(..., description="VAT Registration Number: 9 digits, e.g. '123456789'. GB prefix accepted and stripped automatically.", min_length=9, max_length=12) - src/modules/hmrc/models.py:25-33 (schema)Output schema (MTDStatus) returned by the check_mtd_status handler: a Pydantic model with fields vrn, mandated, effective_date, and trading_name.
class MTDStatus(BaseModel): """Making Tax Digital VAT status for a VAT registration number.""" model_config = ConfigDict(str_strip_whitespace=True) vrn: str = Field(..., description="VAT Registration Number queried") mandated: bool = Field(..., description="Whether this business is mandated for MTD VAT") effective_date: date | None = Field(None, description="Date from which MTD obligation applies") trading_name: str | None = Field(None, description="Registered trading name if available") - src/modules/hmrc/__init__.py:8-22 (registration)Registration of the hmrc MCP server using FastMCP. The module creates 'hmrc_mcp' and calls register_tools(hmrc_mcp) which internally decorates the hmrc_check_mtd_status function as a tool.
hmrc_mcp = FastMCP( name="hmrc", instructions=( "Look up UK tax information via HMRC APIs and GOV.UK. " "Use hmrc_get_vat_rate to find the VAT rate for any commodity or service type. " "Use hmrc_check_mtd_status to check Making Tax Digital VAT status (requires HMRC OAuth credentials). " "Use hmrc_search_guidance to find HMRC guidance documents on GOV.UK." ), ) hmrc_mcp.add_middleware(ResponseCachingMiddleware(call_tool_settings=CallToolSettings(ttl=7776000))) register_tools(hmrc_mcp) __all__ = ["hmrc_mcp"] - src/modules/hmrc/tools.py:102-104 (registration)The register_tools function that registers the tool via the @mcp.tool decorator. Line 121-124 show the @mcp.tool decorator with name='check_mtd_status' and annotations.
def register_tools(mcp: FastMCP) -> None: @mcp.tool(