Why this exists
Ask an AI agent about a Dutch address and it goes to the web. That produces an answer that looks good and is sometimes right. The underlying data is public and reliable, but it sits in nine registers each with its own key, format and quirks.
The hard part is not fetching but joining, and that is exactly where we kept getting it wrong before we noticed:
- The monument number we published turned out to be the internal object number. Prinsengracht 263 was given a number that points at a building in Zierikzee, a different province entirely.
- The monument query was not tied to a town, so an address in Asten was assigned a monument in Coevorden.
Binnenrotte 101, Amsterdamreturned the building in Rotterdam without any caveat, withmatch_verified: true.
None of the sources were broken. The joining was broken. This layer takes that work on, and says explicitly how certain it is that we found the right building.
Who it is for
Estate agents and valuers
An objective starting point for a viewing: construction year, floor area, label, protected status.
Buyers and their advisers
What is officially registered, and which points deserve a question at the building survey.
Retrofit and installation
Construction-year cohort, energy label and floor area as a starting point for insulation or heat-pump advice.
Builders of AI agents
One MCP tool an agent calls by itself the moment a Dutch address appears in the conversation.
What you get back
One JSON response, roughly 11 kB, with these blocks:
| Block | Contents |
|---|---|
identity | The building found, plus match_verified: is this really the address you asked for? |
building | Construction year, floor area, use, building identifiers |
energy | Registered energy label, validity, building type, calculated consumption |
location | Coordinates, municipality, neighbourhood and district codes |
neighbourhood | Residents, density, age profile, household composition, average property value, owner/rental split, distance to GP, supermarket, school and childcare |
environment | Environmental noise (Lden), particulates PM2.5 and nitrogen dioxide NO₂ |
heritage | Listed monument status with the actual register number |
protected_area | Located in a protected townscape, and in UNESCO World Heritage |
soil | Registrations under the Soil Protection Act, including a flag for whether the competent authority shares its files nationally |
schools | Primary and secondary schools nearby, with distance and education type |
signals | The observations, each with a recommendation and its basis |
provenance | Per source: which one, when retrieved, with what status and licence |
The signals are the point
A signal never establishes a defect. A 1921 construction year does not mean there are lead pipes — it means that is worth checking. They all work that way:
- construction_era_checks — what to check for this construction-year cohort
- conflicting_construction_year — two registers give a different year; both are shown, we do not pick
- energy_label_expiring / no_energy_label / energy_label_address_mismatch
- protected_townscape and world_heritage_area — consequences for permits
- address_match_unverified — the requested address was not found with certainty
- soil_registration_present — a soil registration exists on or near the address; this may also be completed research or a remediation already carried out
- soil_authority_does_not_share — the competent authority does not supply its soil files to the national service, so nothing can be said here
- source_unavailable — a source did not answer; the field is unknown, not empty
What it does not do
This is no valuation, no market value and no legal or structural advice. There is no asking price, no ground-lease terms, no owners-association information and no cadastral ownership history — that data is not freely available.
Watch identity.match_verified
If it is false, the requested address was not found with certainty and the rest of the answer may be about a different building. Do not present the data as fact. With match_ambiguous there are several equally good candidates, and they are all included in match_alternatives — with match_candidate_count telling you how many there really are.
Planning documents under the Dutch Environment Act are not connected; they require a separate key. That shows as not_configured in the response — a status, not an empty field.
How to use it
As an MCP server, in Claude, Cursor or another agent
Claude (web or desktop, works on every plan including free):
go to Customize → Connectors → + → Add custom connector and paste
https://property-context.tradebrite.nl/mcp. Claude cannot install this for you; that is deliberately your action, because a connector may act on your behalf.
ChatGPT: custom connectors sit behind Developer Mode and are only available on Pro, Team, Enterprise and Edu — on a Plus plan it is not possible. Use the plain HTTPS API below instead.
Claude Code:
claude mcp add --transport http property-context https://property-context.tradebrite.nl/mcp
Or by hand in your MCP configuration:
{
"mcpServers": {
"property-context": {
"type": "http",
"url": "https://property-context.tradebrite.nl/mcp"
}
}
}
After that you can simply ask: "What should I know about Grote Markt 2 in Haarlem before I view it?"
As an HTTPS API
curl "https://property-context.tradebrite.nl/v1/property/context?address=Grote%20Markt%202,%20Haarlem"
| Parameter | Meaning |
|---|---|
address | Dutch address, preferably with a town name or postcode. 2011RD 2 works too. |
depth | compact (default) or full. Full gives the complete school list and the source URLs. |
refresh | 1 bypasses the one-hour cache. |
Sources, licence and limits on use
The data comes from official Dutch registers: the buildings and addresses register (BAG), neighbourhood statistics from Statistics Netherlands, national institute measurements for noise and air quality, the energy-label register, the listed-monuments and protected-areas registers, the national soil information service, and the education addresses of the education executive agency.
Part of that is licensed CC BY 4.0, which makes attribution mandatory. That is why every response carries a provenance block with the name and status per source — including in the compact format. Pass that attribution on if you show the data to an end user; the obligation travels with the data.
Energy labels may not be redistributed in bulk. That is why there is a rate limit; it follows from the publisher's terms, not from our capacity.
Rate limit
10 requests per 10 seconds and 60 per minute, per IP address. Exceeding it returns HTTP 429 with a Retry-After header. Need more on a structural basis? Send us a mail.
Liability
This service is offered free of charge and without warranty. Decisions about buying, renovating or retrofitting remain the responsibility of the user.
Privacy
An address can be personal data once it can be linked to a resident. The registers used contain no resident data — only data about the building and its surroundings.
We log no addresses, no postcodes and no IP addresses. What we do keep, to improve the service: the municipality (coarse), which signals were issued, which sources answered, and how long the request took.
No accounts, no cookies, no trackers. The IP address is used briefly as a key for the rate limiter. Questions: info@tradebrite.nl.
Source code
The code is open on GitHub, under the MIT licence: github.com/rleefers/dutch-property-context. You can run it on your own Cloudflare account. The repository also holds the regression test we use to check that the joins are correct.
This service is also listed in the official MCP registry as
nl.tradebrite/dutch-property-context.
Questions, or something broken?
Built and maintained by Tradebrite BV. Something wrong, a source missing, or do you need more volume? Let us know — reports about a specific address are the most useful.