A supplier in another EU country sends you an invoice and a VAT number. Before you zero-rate that cross-border invoice, you are supposed to confirm the number is valid on the day you invoice and that it belongs to the counterparty you think it does. Ask Claude "is FR40303265045 a valid VAT number and whose is it?" and the model will answer from training data that is stale, or it will simply make something up. For a tax position you may have to defend in an audit, "probably valid" is not good enough.
In this guide we fix that. We connect Claude to the official Apify MCP server, expose a single Actor that checks a VAT number against the European Commission's VIES service, and turn "is this VAT number real?" from a guess into a live lookup against the source of record. By the end you will have a working validation tool that Claude, Cursor, or any MCP client can call mid-conversation, and you will know exactly where in the run the tool fires and what it returns.
Everything below is a real setup with real output. No mocked responses.
What is the Apify MCP server?
Model Context Protocol (MCP) is an open standard that lets AI clients call external tools. The Apify MCP server (https://mcp.apify.com) implements that standard on top of the Apify platform, which means every one of the thousands of Actors in the Apify Store becomes a tool an agent can invoke.
Why route an Actor through MCP instead of hard-coding an API call?
- The agent decides when to fetch. Claude reads the conversation, notices it needs a fact it does not have, and calls the tool on its own. You do not write glue code for every question.
- Structured input and output. The MCP server hands Claude the Actor's input schema, so the model fills in the parameters correctly, and returns a clean dataset it can reason over.
-
One connection, many tools. The same MCP endpoint exposes
search-actors,fetch-actor-details, andcall-actor, so an agent can discover and run any Actor without new configuration. - No infrastructure. The server is hosted. You add a few lines to a config file and you are done.
The Actor we will use
We will expose the EU VAT Number Validation Scraper (VIES). Give it one or more EU VAT numbers and it checks each against the European Commission's VIES service, returning a validity flag, the country code and local number, the exact request date, and, where the member state provides them, the registered company name and address.
That field set is exactly what an accounts-payable, invoicing, or tax-compliance check needs. VIES is the authoritative EU-wide source for confirming that a VAT number is currently registered for cross-border trade, and it carries no login wall.
Step 1: Get your Apify API token
Sign in to the Apify Console, open Settings → Integrations, and copy your personal API token. The MCP server uses it to authenticate and to bill Actor runs to your account.
📌 Note: the token is a secret. Keep it in the client config only, never in a prompt or a committed file.
Step 2: Point Claude Desktop at the Apify MCP server
Open Claude Desktop's config file (Settings → Developer → Edit Config, or ~/Library/Application Support/Claude/claude_desktop_config.json on macOS) and add the Apify server. The tools query parameter is the important part: it tells the server which Actor to expose, so Claude gets one focused tool instead of the entire Store.
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=scrapers_lat/eu-vat-vies-validation-scraper",
"headers": {
"Authorization": "Bearer YOUR_APIFY_TOKEN"
}
}
}
}
Cursor uses the same JSON in .cursor/mcp.json. If you prefer to run it locally over stdio instead of the hosted endpoint:
{
"mcpServers": {
"apify": {
"command": "npx",
"args": ["-y", "@apify/actors-mcp-server", "--tools", "scrapers_lat/eu-vat-vies-validation-scraper"],
"env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
}
}
}
Restart Claude Desktop so it picks up the new server.
Step 3: Confirm the tool is loaded
After the restart, the Actor shows up as a callable tool. If you list the tools the Apify server exposes, you will see the storage helpers plus the Actor itself, named after its Store handle:
get-actor-run, get-dataset-items, get-key-value-store-record,
abort-actor-run, scrapers_lat--eu-vat-vies-validation-scraper
That last entry, scrapers_lat--eu-vat-vies-validation-scraper, is our validation tool. Claude now knows it exists, what it does (from the Actor's README), and what inputs it takes (from the input schema the server passes along).
Step 4: Ask Claude to validate a VAT number
Now the payoff. In a normal chat, ask a question that requires ground truth:
"We're about to invoice a new French supplier that gave us VAT number FR40303265045. Before I zero-rate the invoice, is that VAT number actually valid, and what registered company and address does it belong to?"
Claude recognizes it cannot answer this reliably from memory, selects the VIES tool, and fills in the input from your question. Under the hood the client sends a tools/call with the Actor's parameters:
{
"name": "scrapers_lat--eu-vat-vies-validation-scraper",
"arguments": {
"vatNumbers": ["FR40303265045"]
}
}
The Apify MCP server starts the Actor, waits for it to finish, and returns the dataset. Here is the real run metadata it produced:
{
"runId": "WpKTbwMoyDcF0hZSA",
"actorName": "scrapers_lat/eu-vat-vies-validation-scraper",
"status": "SUCCEEDED",
"startedAt": "2026-07-30T17:43:42.144Z",
"finishedAt": "2026-07-30T17:43:46.203Z",
"stats": { "runTimeSecs": 3.9 }
}
Under four seconds, live against VIES.
Step 5: Read the real output
The dataset the tool returns is structured validation data, one record per VAT number. This is an actual record from the run:
{
"countryCode": "FR",
"vatNumber": "FR40303265045",
"vatNumberLocal": "40303265045",
"valid": true,
"traderName": "SA SODIMAS",
"traderAddress": "11 RUE AMPERE\n26600 PONT DE L ISERE",
"requestDate": "2026-07-30T17:43:45.858Z",
"source": "EU VIES"
}
Claude reads that and answers in plain language: yes, the number is valid, it is registered to SA SODIMAS at 11 Rue Ampere, 26600 Pont de l'Isere, and the check was run today against VIES. Every one of those facts is traceable to the official EU service, not the model's memory, and the record itself is your evidence that the check happened.
The counter-example is just as important. In the same run we passed DE143593636 and it came back valid: false with userError: "INVALID". A number that looks well-formed can still be unregistered or deregistered, and an AP clerk about to zero-rate an invoice needs to see that before the money moves. There is also a quieter nuance the tool surfaces honestly: some member states, Germany among them, confirm validity but do not return the trader name or address, so those rows come back valid: true with the name fields empty. The tool tells you which is which; the model alone would not.
A real use case: an invoice-validation agent
Put this in context. An accounts-payable or tax analyst is processing a batch of cross-border EU invoices at month-end and must confirm, before releasing payment and filing the return, that:
- each supplier's VAT number is valid in VIES on the invoice date,
- the registered name on VIES matches the name on the invoice, and
- no number has quietly been deregistered since it was last used.
Without a tool, the analyst opens the VIES website, types each number, solves the occasional interstitial, and copies the result into a spreadsheet, once per line. With the tool wired into Claude, the analyst pastes the supplier list into the chat and asks the agent to validate each one. Claude calls the Actor per number, flags every valid: false, compares each returned traderName against the invoice, and produces a short exceptions list with the request date as the timestamped proof of validation. The mechanical lookup disappears; the judgment stays with the human.
This is the shape of every good agent tool: it removes the mechanical fetch, not the decision.
Going further: chain a second tool
VAT validation rarely stops at "is the number valid." Once you know a UK supplier's registered name, you often want to confirm the company itself is real and active. The same MCP connection can expose more Actors by extending the tools parameter:
https://mcp.apify.com?tools=scrapers_lat/eu-vat-vies-validation-scraper,scrapers_lat/uk-companies-house-scraper
Now the agent can validate a VAT number and, using the name it gets back, look the company up in the UK Companies House Scraper to confirm it is active with matching officers and address, then combine both results into one onboarding summary. Because each Actor is a separate tool, the agent picks the right one for each step on its own.
🏹 Troubleshooting: if the tool does not appear in Claude, the two usual causes are a missing or misspelled Actor handle in the tools parameter (it must be the exact username/actor-name from the Store URL) and a config that was edited while Claude was running. Fix the handle, save, and fully restart the client.
📌 Note: each tool call is a real Actor run billed to your Apify account (this Actor is pay-per-result). For one-off validation the cost is a fraction of a cent; if you plan to check thousands of VAT numbers on a schedule, run the Actor directly through the Apify API or a scheduled task with the full batch in vatNumbers instead of one call per chat message.
Wrapping up
You now have an AI agent that can validate an EU VAT number against the authoritative VIES service, on demand, mid-conversation, with the registered name and address a compliance check actually needs. The pattern is reusable: pick an Actor that returns authoritative structured data, expose it through the Apify MCP server with the tools parameter, and let the agent decide when to call it.
To take it further:
- Pass a whole
vatNumbersarray to validate an entire supplier ledger in one run. - Chain company-registry, sanctions, or licensing Actors to build a full supplier-onboarding agent.
- Read the Apify MCP server docs for OAuth setup, resource reads, and the
search-actors/call-actortools that let an agent discover Actors it was not preconfigured with.
The Actor used in this guide: EU VAT Number Validation Scraper (VIES).


Top comments (0)