normi
Server Details
French property market data — 17M+ DVF sales, 22M+ DPE energy ratings, 20M+ building records.
- Status
- Healthy
- Uptime
- 100.0% over the last 24 hours
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- ChatGPT
- –
- Claude
- Normi
TDQS
Scored across 36 tools
Most tools have distinct resource/action targets, and several descriptions explicitly explain when to use one tool versus another. However, there is real overlap among market-analysis tools (statistics vs. overview, activity vs. health) and between the two DPE price tools, so agents must read descriptions carefully.
All tools use snake_case with a predictable verb_noun structure: analyze_*, get_*, list_*, create_*, update_*, delete_*, search_*, score_*, and resolve/show/submit. The convention is consistent throughout, even across portfolio, alert, and analytics tools.
With 36 tools, the surface is very large for an MCP server, exceeding the 25-tool threshold where selection cost becomes significant. Some consolidation is possible because get_market_overview already bundles stats/trend/health, and multiple DPE analyses overlap.
The tool set covers full portfolio and alert CRUD, location resolution, market statistics/trends/health, transaction search, comparables and AVM, DPE, building stock, risk signals, rental yield, business lookup, credits, and feedback. No obvious dead ends appear for the stated French real-estate analytics domain.
Available Tools
36 toolsadd_property_to_portfolioAdd Property to PortfolioAInspect
Add a property to your portfolio. For Maison/Appartement, an estimate is automatically computed (10 credits). For other types, only metadata is stored (2 credits).
REQUIRED: latitude, longitude, type_local, surface
Optional: label, address, code_postal, commune, pieces, purchase_price
Returns the created property record with estimate fields (if applicable).
Cost: 10 credits (Maison/Appartement) or 2 credits (other types)
Inputs: surface (required), latitude (required), longitude (required), type_local (required), +6 more.
analyze_building_age_price_impactAnalyze Building Age Price Impact (BDNB)ARead-onlyInspect
Get median prix/m² grouped by construction decade for a location.
Shows how building age affects price — the premium or discount of each era vs. the area median. Useful for advising whether older buildings trade at a discount and how much.
Construction decade buckets: avant_1919, 1919_1945, 1946_1970, 1971_1990, 1991_2005, 2006_plus
REQUIRED: at least one location — code_postal, commune, or code_departement OPTIONAL: type_local (Maison|Appartement)
Example output: { tranche: "1946_1970", nb: 312, prix_m2_median: 3800, vs_zone_pct: -12 } → buildings from 1946-1970 sell 12% below the area median
Cost: 10 credits
Inputs: commune, type_local, code_postal, code_departement.
analyze_building_stockAnalyze Building Stock (BDNB)ARead-onlyInspect
Get aggregate building stock characteristics for a location from the BDNB national database.
Counts ALL buildings (not just those with DVF transactions). Returns totals by construction decade, usage type, total housing units, and percentage of pre-1975 buildings (renovation indicator). par_usage (BDNB usage_principal): residentiel (= residentiel_collectif + residentiel_individuel), tertiaire, dependance, secondaire, non_renseigne; mixte and autre are kept for compatibility.
REQUIRED: at least one location — code_commune_insee, commune, or code_departement
code_commune_insee: 5-digit INSEE code (most precise, no ambiguity between same-name communes)
commune: city name (uppercase, e.g. "LYON")
code_departement: department code (e.g. "69")
Example output: { nb_batiments: 12500, annee_construction_median: 1968, pct_vieux: 42, par_tranche: { avant_1919: 800, "1946_1970": 4200, ... }, par_usage: { residentiel: 4440, residentiel_collectif: 2740, residentiel_individuel: 1700, tertiaire: 623, dependance: 38, secondaire: 11, non_renseigne: 986, mixte: 0, autre: 0 } }
Cost: 5 credits
Inputs: commune, code_postal, code_departement, code_commune_insee.
analyze_dpe_distributionAnalyze DPE DistributionARead-onlyInspect
Get the DPE (energy performance) class distribution for a location.
Returns the count and share of A–G energy ratings across all diagnosed properties.
REQUIRED: at least one location — code_postal, commune, or code_departement OPTIONAL: type_batiment (maison|appartement|immeuble), date_debut
Example: code_postal: "75011" → { count: 42300, distribution: { A: 812, B: 3100, ... }, pct: { A: 1.9, B: 7.3, ... } }
Cost: 10 credits
Inputs: commune, date_debut, code_postal, type_batiment, +1 more.
analyze_dpe_price_and_thermal_riskAnalyze DPE Price & Thermal RiskARead-onlyInspect
Combined DPE market analysis — price per energy class AND thermal sieve stock. Use when you need the full DPE picture in a single call.
Returns TWO distinct analyses:
Median price/m² per energy class (A–G) with taux_couverture_dpe (share of sales with a DPE within 200m)
prime_verte: each class's median vs class D (descriptive gap, see limitations in the response)
Thermal sieves (passoires thermiques): share of F/G transactions since 2022 with annual trend
WHEN TO USE THIS vs analyze_dpe_price_premium:
Use analyze_dpe_price_and_thermal_risk for a full DPE snapshot (prices + sieve stock + trend)
Use analyze_dpe_price_premium when you only need "how much more is an A vs the local median?"
REQUIRED: at least one location — code_postal, commune (e.g., "PARIS 11"), or code_departement OPTIONAL: type_local (Maison|Appartement)
Note: Alsace (dept. 67, 68) returns zero results — DVF does not cover Alsace-Moselle (Livre foncier). Matching: nearest DPE within 200m of each sale; it is often a neighbouring building, so class gaps are indicative.
Cost: 10 credits
Inputs: commune, annee_min, type_local, code_postal, +1 more.
analyze_market_activityAnalyze Market ActivityARead-onlyInspect
Monthly transaction volume time series — use when you need to show how activity has changed over time, not when you need a single comparable number.
WHEN TO USE THIS vs score_market_health:
Use analyze_market_activity when the question is "show me how volume has evolved" or "is there seasonality?"
Use score_market_health when the question is "is this market good or bad?" or "compare two markets"
REQUIRED: At least one location filter:
code_postal, commune (e.g., "PARIS 11"), or code_departement
Optional:
type_local: Property type filter
months: Analysis period (default: 24, max: 60)
Returns:
Monthly transaction volumes with YoY changes
Trend direction: "increasing", "decreasing", or "stable"
Activity level: "hot", "normal", or "slow"
Seasonality: peak and low months
Market signal with description
Example: Lyon market activity: {commune: "LYON", type_local: "Appartement", months: 24}
Note: DVF data covers 2014–2025 (annual cadence). Use months ≥ 12 for reliable results.
Cost: 10 credits per call
Inputs: months, commune, type_local, code_postal, +1 more.
analyze_market_statisticsAnalyze Market StatisticsARead-onlyInspect
Get market statistics: avg/median prices, price per m², surface areas.
REQUIRED: You MUST provide at least one location filter:
code_postal (e.g., "75011")
commune (e.g., "PARIS 11" - uppercase; Paris uses "PARIS 01"–"PARIS 20")
code_departement (e.g., "75")
latitude + longitude for radius search
Examples:
Paris 11e market: {commune: "PARIS 11", type_local: "Appartement"}
500m radius: {latitude: 48.8566, longitude: 2.3522, radius_m: 500}
Department stats: {code_departement: "69", type_local: "Maison"}
Returns: count, price (min/max/avg/median), surface stats, price_per_m2. The figures leave out the scope's lowest and highest 1% price per m² (outliers_excluded, 20+ sales); count is every matching sale.
Note: radius_m > 1000m is automatically restricted to the last 12 months of data.
Cost: 5 credits per call
Inputs: commune, date_fin, latitude, radius_m, +10 more.
analyze_price_trendsAnalyze Price TrendsARead-onlyInspect
Analyze price evolution over time - essential for market timing and investment decisions.
REQUIRED: At least one location filter:
code_postal, commune (e.g., "PARIS 11"), or code_departement
No coordinates or radius: for a point, pass its code_postal or commune (find_property_comparables covers a radius)
Optional:
type_local: "Maison", "Appartement", "Terrain", "Local commercial"
granularity: "month", "quarter" (default), or "year"
date_debut/date_fin: Date range (default: last 5 years)
Returns:
Time series with median/avg prices per period
Year-over-year changes (%)
Overall trend: "increasing", "decreasing", or "stable" (±5%), on the median price per m² (summary.change_basis)
Total change over the period
Example: Paris 11e apartment price trends: {commune: "PARIS 11", type_local: "Appartement", granularity: "quarter"}
Note: DVF data covers 2014–2025 (annual cadence). Use date windows ≥ 12 months for reliable results.
Cost: 10 credits per call
Inputs: commune, date_fin, date_debut, type_local, +5 more.
analyze_purchasing_powerAnalyze Purchasing PowerARead-onlyInspect
Price-to-income ratio: how many years of median income to buy the median property here. Median sale price (same sales as analyze_market_statistics: no VEFA, 1 % €/m² trim) over INSEE Filosofi commune-level median income.
REQUIRED: You MUST provide one of:
code_postal (e.g., "75011")
commune (e.g., "LYON", "PARIS 11" - uppercase)
code_commune: explicit 5-digit INSEE code (e.g., "75111")
NOT SUPPORTED: code_departement alone, or latitude+longitude — a department spans hundreds of communes with no single meaningful income figure, and radius circles cross commune boundaries. Use analyze_market_statistics or find_property_comparables for those scopes instead.
Returns: ratio_prix_revenu (years of income), prix_bien_median, revenu_median_annuel_uc, annee_reference, vintage_gap_years (sale year minus income year: older income inflates the ratio). ratio_prix_revenu is null when INSEE suppresses the commune's income figure (small population).
Cost: 5 credits per call
Inputs: commune, date_fin, date_debut, type_local, +2 more.
analyze_rental_yieldAnalyze Rental YieldARead-onlyInspect
Estimate gross rental yield for one French commune using ANIL asking-rent indicators and clean DVF sale prices.
REQUIRED:
code_insee: French 5-character INSEE commune code (e.g., "33063" for Bordeaux; Corsica codes such as "2A004" are supported)
OPTIONAL:
type_local: "Appartement" (default) or "Maison"
appartement_profile: "all" (default), "t1_t2", or "t3_plus" — apartments only
Returns the latest available 24-month DVF sale window, median sale price/m², ANIL's charges-included rent/m², estimated gross yield, confidence interval, and data-quality flags.
Important: this is a commune-level estimate, not a property valuation. It excludes taxes, financing, vacancy, maintenance, and management costs. ANIL rents are unfurnished advertised rents including charges.
Cost: 10 credits per call
Inputs: code_insee (required), type_local, appartement_profile.
compare_locationsCompare LocationsARead-onlyInspect
Compare 2-5 neighborhoods side-by-side - perfect for investment location decisions.
REQUIRED:
locations: Array of 2-5 objects with {code_postal} or {commune}
Optional:
type_local: "Maison" or "Appartement" (default: Appartement)
date_debut: Start date (default: 1 year ago)
Returns per location:
Transaction count, median price/m², median price
Year-over-year price change
Rankings (cheapest, most expensive, highest volume, fastest growing)
Example: Compare Paris arrondissements by postal code: {locations: [{code_postal: "75011"}, {code_postal: "75020"}, {code_postal: "75019"}]}
Example: Compare cities by commune: {locations: [{commune: "LYON"}, {commune: "BORDEAUX"}, {commune: "NANTES"}]}
Note: DVF data covers 2014–2025 (annual cadence). Use date windows ≥ 12 months for reliable results.
Cost: 10 credits per call
Inputs: locations (required), date_debut, type_local.
create_market_alertCreate Market AlertAInspect
Create a webhook alert for new DVF transactions matching your criteria. Requires Pro or Enterprise plan. Max 20 active alerts per API key.
REQUIRED: webhook_url + at least one location filter (code_postal, commune, or code_departement)
Optional: type_local, prix_min, prix_max, surface_min, surface_max
When a matching transaction is added to DVF, a POST request is sent to your webhook_url with the transaction details.
Cost: 0 credits (Pro/Enterprise plan required)
Inputs: webhook_url (required), commune, prix_max, prix_min, +5 more.
delete_market_alertDelete Market AlertADestructiveIdempotentInspect
Permanently delete a webhook alert. Requires Pro or Enterprise plan.
REQUIRED: id (alert ID)
Returns: { deleted: true } on success.
Cost: 0 credits (Pro/Enterprise plan required)
Inputs: id (required).
delete_portfolio_propertyDelete Portfolio PropertyADestructiveIdempotentInspect
Permanently delete a property from your portfolio.
REQUIRED: id (property ID)
Returns: { deleted: true } on success.
Cost: 0 credits
Inputs: id (required).
detect_flipsDetect Property FlipsARead-onlyInspect
Detects short-hold resales ("flips") in one French commune.
REQUIRED:
code_insee: 5-digit INSEE commune code (e.g., "33063" for Bordeaux) code_commune is accepted as a compatibility alias.
OPTIONAL:
type_local: "Maison" (default). "Appartement" returns available: false and is not charged: DVF parcel/address matching can't tell flats in the same building apart, so apartment flips aren't published until matching on the copropriete lot is available.
A flip is a clean DVF sale followed by a resale of the same house 18 to 24 months later. Matching uses cadastral section + plan first, then a conservative normalized-address + surface fallback.
Returns aggregate-only indicators: flip rate, median gross margin, median margin percentage, median holding period, and matching-method counts. It never returns transaction addresses or owners. The 24-month window is anchored to the latest DVF mutation available in the requested commune.
Cost: 10 credits per call
Inputs: code_insee, type_local, code_commune.
estimate_property_valueEstimate Property ValueARead-onlyInspect
Get an automated valuation (AVM) for a property — low / mid / high price range.
Use find_property_comparables instead if you want the raw comparable transactions with similarity scores. estimate_property_value returns only the AVM summary (low/mid/high range).
REQUIRED: latitude, longitude, surface
Optional:
type_local: "Maison" or "Appartement" (default: Appartement)
pieces: Number of rooms
code_postal, commune: Optional administrative fallback when GPS comparables are sparse
radius_m: Search radius (100–2000m, default: 500)
max_age_months: Max transaction age (1–24, default: 18)
Returns:
price_range: { low, mid, high } in euros
price_per_m2: { median, used_surface }
confidence: "high", "medium" or "low": how much the retained comparables agree on price/m² (dispersion (P75-P25)/median: high <15%, medium 15-50%, low >=50%). Measured on 1,957 masked DVF sales: median error 12% / 20% / 30%. It is not a probability of accuracy: even at "high", half of the outcomes fall outside price_range.
confidence_basis: "comparable_agreement" — names what confidence measures.
based_on_count: number of comparables used
interval: { method, coverage_label, basis, cohort, cohort_eligible_n, ratio_low, ratio_high, contract_version, calibration_generated_at } — how price_range was derived.
confidence_factors: { comparable_count, average_similarity, fallback_used, positive_factors[], limiting_factors[] } — what strengthens or limits the estimate.
Returns estimate: null with a message if fewer than 3 comparables are found. Tip: increase radius_m or max_age_months to get more data.
Note: the low/high range is a data-calibrated 50% interquartile interval (P25/P75 of observed-price / published-mid, backtest-measured on 2,000 masked DVF sales), not a fixed percentage. Its width is driven first by how much the retained comparables agree on price/m² — the dispersion cohort, (P75-P25) / median, e.g. interval.cohort = "dispersion=<15%" — then by comparable density, property type and surface band, and it widens to the global cohort when a segment lacks enough measured data (interval.basis). Agreeing or contradicting comparables also surface as confidence_factors comparables_agree / comparables_disagree. The mid value is unaffected by any of this. DVF data covers 2014–2025 (annual cadence). Use max_age_months ≥ 12 for reliable results.
Cost: 10 credits per call
Inputs: surface (required), latitude (required), longitude (required), pieces, +5 more.
find_property_comparablesFind Property ComparablesARead-onlyInspect
Find comparable recorded sales around a property, for valuation.
REQUIRED parameters:
latitude, longitude: Target property coordinates
type_local: "Maison" or "Appartement"
surface_min, surface_max: Surface range in m² (typically ±20% of target)
Optional:
pieces: Number of rooms (±1 tolerance applied)
code_postal, commune: Optional administrative fallback when GPS comparables are sparse
radius_m: Search radius (default: 500m, max: 2000m)
max_age_months: Transaction age limit (default: 18, same as estimate_property_value; max: 36) When fewer than 3 comps match, the search first extends to 36 months at the same radius, then to 2 km.
limit: Max comparables (default: 10, max: 20)
Returns:
Comparable properties with similarity scores (0-1)
Distance from target, age of transaction
Adjustment suggestions, to apply to the comparable's €/m² (e.g., "+2% for 10m² larger": smaller units sell dearer per m²)
excluded_comparables: sales left out (Carrez/built surface mismatch, €/m² over 2× from the median)
Valuation estimate with comparable-agreement confidence, plus a data-calibrated 50% interval (interval.*) and traceable confidence_factors — see estimate_property_value's description for the full field reference
Example: Find comps for a 75m² apartment near Tour Eiffel: {latitude: 48.858, longitude: 2.294, type_local: "Appartement", surface_min: 60, surface_max: 90}
Cost: 10 credits per call
Inputs: latitude (required), longitude (required), type_local (required), surface_max (required), +8 more.
get_building_characteristicsGet Building Characteristics (BDNB)ARead-onlyInspect
Get physical building characteristics for a DVF transaction from the BDNB national building database.
Returns: construction year, number of units, number of floors, wall material, roof material, primary usage, and median price/m² from BDNB's pre-2022 DVF aggregate stats.
REQUIRED: transaction_id (DVF transaction ID — get this from the "id" field in search_property_transactions results)
Match method: spatial proximity (nearest BDNB building within 200m). Returns null + refunds credits if no building found within 200m.
Workflow: call search_property_transactions first → use an "id" from the results as transaction_id here.
Example: transaction_id: "12345678" → { building: { annee_construction: 1967, nb_logements: 48, mat_mur: "beton", ... } }
Cost: 2 credits
Inputs: transaction_id (required).
get_market_overviewGet Market OverviewARead-onlyInspect
Get a complete market brief for a location in one call — stats + trend + health score.
Bundles three queries in parallel: market statistics (prices, volume), annual price trend (1-year change %), and health score (0–100).
Use this as the first tool for any "how is the market in X?" question. It replaces calling analyze_market_statistics + analyze_price_trends + score_market_health separately (saves 15–25 credits).
REQUIRED: At least one location filter:
code_postal (e.g., "75011")
commune (e.g., "PARIS 11" — uppercase; Paris uses "PARIS 01"–"PARIS 20")
code_departement (e.g., "69")
latitude + longitude for radius search
Optional:
type_local: "Maison", "Appartement", "Terrain", "Local commercial"
radius_m: search radius in meters (default: 500)
Returns:
stats: count, median/avg price, price/m², median surface
trend: direction (increasing/stable/decreasing), 1-year change %, overall change %
health: score (0–100), label (Calme/Modéré/Dynamique/Très actif), data quality Note: health score requires code_postal/commune/code_departement (not available for lat+lon only searches)
Score interpretation: 0–30 Calme · 31–60 Modéré · 61–80 Dynamique · 81–100 Très actif
Cost: 10 credits per call
Inputs: commune, latitude, radius_m, longitude, +3 more.
get_portfolio_propertyGet Portfolio PropertyAIdempotentInspect
Get a single portfolio property by ID. If the estimate is older than 30 days and the property is a Maison or Appartement, the estimate is automatically refreshed (10 credits).
REQUIRED: id (property ID from list_portfolio_properties or add_property_to_portfolio)
Returns: property record + estimate_refreshed boolean.
Cost: 0 credits (10 if estimate is refreshed)
Inputs: id (required).
get_property_risk_signalsGet Property Risk Signals (Géorisques)ARead-onlyInspect
Get observed public geographic risk signals for a coordinate from Géorisques V2.
Returns four separate signals, each with status (available | no_match | unavailable), spatial_scope (coordinate or commune, as published by the provider), the provider classification and label, and a source URL:
clay_shrink_swell: RGA clay shrink-swell exposure at the point
radon: commune radon potential (category 1–3)
seismic_zoning: commune seismic zone (1 very low – 5 strong)
recorded_risk_procedures: GASPAR risk procedures and hazards recorded for the commune
Indicative public geographic information only: not a property diagnosis, not a regulatory risk statement (état des risques), no composite score. It never adjusts a valuation. Always show source.attribution and source.update_date to the user.
REQUIRED: latitude, longitude (WGS84, metropolitan France, Corsica or an overseas department). Tip: use resolve_location or the coordinates of a transaction first.
Cost: 10 credits per call (refunded if Géorisques is unavailable)
Inputs: latitude, longitude.
get_real_estate_business_detailsGet Real Estate Business Details (SIRENE)ARead-onlyInspect
Get full details for a French business by SIREN number via the INSEE open API.
Returns the main establishment (siège): legal name, NAF code, address, creation date, and administrative status.
REQUIRED: siren (9-digit SIREN number)
Example: siren: "123456789" → { denomination: "ORPI CENTRE", naf_code: "6831Z", commune: "PARIS", ... }
Note: Requires INSEE_API_TOKEN to be configured on the server.
Cost: 2 credits
Inputs: siren (required).
get_zonal_price_distributionGet Zonal Price DistributionARead-onlyInspect
Map and rank median price per m² by postal code or commune across a city or department, from recorded DVF sales. Hosts with MCP Apps support (such as ChatGPT and Claude) render the result as an interactive price map; other clients get the same data as JSON.
REQUIRED: At least one scope filter:
code_departement: Department code (e.g., "75" for Paris)
commune: Major city (e.g., "PARIS" - returns all arrondissements)
Optional:
type_local: "Maison" or "Appartement"
group_by: "code_postal" (default) or "commune"
min_transactions: Minimum transactions to include zone (default: 10)
date_debut/date_fin: Date range (default: last year)
Returns per zone:
Centroid coordinates (lat/lon) for map plotting
Median and average price/m²
Transaction count
Relative position: "expensive", "average", or "affordable"
Use this when the user wants to: map or compare prices across arrondissements, postal codes or communes, or find the most/least expensive zones.
Example: Paris zones by postal code: {commune: "PARIS", type_local: "Appartement"}
Cost: 15 credits per call
Inputs: commune, date_fin, group_by, date_debut, +3 more.
list_market_alertsList Market AlertsARead-onlyInspect
List all webhook alerts (active and inactive) for this API key. Requires Pro or Enterprise plan.
Cost: 0 credits (Pro/Enterprise plan required)
Inputs: no named parameters.
list_portfolio_propertiesList Portfolio PropertiesARead-onlyInspect
List all properties in your portfolio with their cached estimates.
Returns an array of property records ordered by creation date (newest first). Estimates shown are cached — use get_portfolio_property for a specific property to trigger a refresh if stale.
Cost: 0 credits
Inputs: no named parameters.
lookup_property_historyLook Up Property HistoryARead-onlyInspect
Get transaction history for a specific address - essential for due diligence.
REQUIRED: One of these combinations:
address + code_postal: "49 cours Richard Vitton" → sales at that number (one building). Without a number ("cours Richard Vitton") → the 50 most recent sales on the whole street. Full street types (cours, avenue, boulevard…) and bis/ter are understood.
section + no_plan + code_commune: Cadastral parcel lookup
Returns:
Transactions, newest first (max 50), with scope = address | street | parcel
Each transaction includes an id field — pass it to get_building_characteristics for BDNB building data
Price, surface, type, rooms for each
price_evolution: only for a repeat sale of the same property (same type, surface within 5%), otherwise null
No sale at the number: the numbers on that street that do have sales
Workflow: lookup_property_history → use transaction id → get_building_characteristics
Example by address: {address: "49 cours Richard Vitton", code_postal: "69003"}
Example by cadastral: {section: "AB", no_plan: "123", code_commune: "101"}
Cost: 20 credits per call, refunded when nothing is found
Inputs: address, no_plan, section, code_postal, +1 more.
resolve_locationResolve LocationARead-onlyInspect
Resolve free-form French administrative locations to the canonical Normi filters.
Use this before another Normi tool when the location is informal, accented, abbreviated, or ambiguous. It accepts postal codes, communes and arrondissements such as "Paris 11e", "75011", "Saint-Étienne" or "st etienne".
It returns ranked canonical commune, postal-code, department and INSEE filters. "Paris" intentionally returns all 20 arrondissements rather than silently choosing one.
Cost: 1 credit per call
Inputs: query (required).
score_market_healthScore Market HealthARead-onlyInspect
Instant 0–100 composite score for comparing markets or making go/no-go decisions.
WHEN TO USE THIS vs analyze_market_activity:
Use score_market_health when you need a single comparable number ("rank these markets", "is this worth investing in?")
Use analyze_market_activity when you need volume trends over time or seasonal patterns
REQUIRED: At least one of code_postal, commune, or code_departement. Note: latitude+longitude is NOT supported — use code_postal, commune, or code_departement only.
Optional:
type_local: "Maison", "Appartement", "Terrain", "Local commercial"
Score interpretation:
0–30: Low activity — weak volume, stagnant/declining prices
31–60: Moderate — decent activity, neutral trends
61–80: Active — good volume, slight price increase
81–100: Very dynamic — strong demand, fast-rising prices
Returns: score (0–100), label, components (volume, price_trend, dispersion), data_quality. Windows end on the latest DVF sale. Volume compares the latest 12 months with the 36 before. Returns score: null if fewer than 10 transactions in the latest 12 months (data_quality.count_6m, name kept for compatibility).
Cost: 10 credits per call
Inputs: commune, type_local, code_postal, code_departement.
score_renovation_potentialScore Renovation Potential (BDNB)ARead-onlyInspect
Identify renovation opportunities: pre-1975 buildings priced below the area median.
Returns a score 0-100 (higher = more potential: bigger discount + older stock), the count of such properties, median price/m² for old buildings vs. area median, average construction year, and dominant wall material.
REQUIRED: at least one location — code_postal, commune, or code_departement OPTIONAL: type_local (Maison|Appartement)
Example output: { score: 72, nb_opportunites: 145, decote_vs_zone_pct: 18, annee_construction_moy: 1958, materiaux_murs_principal: "brique" } → Old buildings trade 18% below market; renovation potential score 72/100
Note: Score is null if fewer than 10 pre-1975 transactions found (statistically unreliable).
Cost: 10 credits
Inputs: commune, type_local, code_postal, code_departement.
search_property_transactionsSearch Property TransactionsARead-onlyInspect
Search French property transactions (Demandes de Valeurs Foncières).
REQUIRED: You MUST provide at least one location filter:
code_postal (e.g., "75011" for Paris 11e)
commune (e.g., "PARIS 11", "LYON", "MARSEILLE" - uppercase; Paris uses arrondissements: "PARIS 01"–"PARIS 20")
code_departement (e.g., "75" for Paris, "69" for Rhône)
latitude + longitude for radius search (e.g., 48.8566, 2.3522 for Paris center)
address + code_postal for automatic geocoding (e.g., address: "12 rue de Rivoli", code_postal: "75001")
Common examples:
Paris 11e apartments: {commune: "PARIS 11", type_local: "Appartement"}
Near a location: {latitude: 48.8566, longitude: 2.3522, radius_m: 500}
By postal code: {code_postal: "69001", type_local: "Maison"}
By address: {address: "12 rue de Rivoli", code_postal: "75001", radius_m: 300}
Options:
summary_only=true: Get stats + 3 samples (~500 tokens vs ~3500 for full results) — use this for overviews. The stats cover every matching sale, identical to analyze_market_statistics (same date cap), unless prix_*/surface_*/pieces_min filters are set: then summary.basis = "sample" and they describe the returned page only.
limit: 1-100 results (default: 5)
type_local: "Appartement", "Maison", "Terrain", "Local commercial"
Note: radius_m > 1000m is automatically restricted to the last 12 months of data.
Cost: 5 credits per call
Inputs: limit, offset, address, commune, +18 more.
search_real_estate_businessesSearch Real Estate Businesses (SIRENE)ARead-onlyInspect
Find real estate businesses near a location using the INSEE SIRENE registry.
Returns businesses within the specified radius, sorted by distance. Optionally enriches results with DVF transaction volume for each business's area (last 24 months) — useful for competitive intelligence.
REQUIRED: latitude + longitude (search center) OPTIONAL:
radius_m: 100–5000m (default 1000)
type: filter by business type (default "all")
"agence" — real estate agency
"notaire" — notary
"promoteur" — property developer
"gestionnaire" — property manager
"marchand" — marchand de biens
"courtier" — mortgage broker
"bailleur" — landlord / rental operator
"all" — all types
limit: 1–50 (default 20)
include_dvf_stats: boolean
Tip: use get_real_estate_business_details with the siren field from results to get full company info.
Example: latitude: 48.8566, longitude: 2.3522, radius_m: 500, type: "agence" → Returns agencies within 500m of Paris centre, sorted by distance
Cost: 5 credits
Inputs: latitude (required), longitude (required), type, limit, +2 more.
show_credit_optionsShow Credit OptionsARead-onlyInspect
Show the user their Normi credit balance and the credit packs and plans they can buy, in an interactive view.
ONLY call this right after a Normi tool was refused with "Insufficient credits", passing that tool as refused_tool and its exact arguments as refused_arguments. Never call it otherwise, and never suggest buying credits on your own initiative.
The user buys on Normi's website in their browser; nothing is bought from this tool. Once they have added credits, the view lets them run the refused call again.
Cost: 0 credits
Inputs: refresh, refused_tool, refused_arguments.
submit_feedbackSubmit FeedbackAInspect
Send a message from the user to the Normi team: a wrong number, a missing commune, a confusing result, a feature request.
ONLY call this when the user asks to send feedback, or after they explicitly approve the exact message you propose. Never send on your own initiative. After a failed or surprising Normi result you may OFFER to send feedback; then show the user the message and wait for their yes.
Do not include personal data or the user's conversation beyond what they approved. Use tool_name and query_params to attach the Normi call the feedback is about.
Max 10 per hour. Cost: 0 credits
Inputs: message (required), category, tool_name, query_params.
update_market_alertUpdate Market AlertADestructiveIdempotentInspect
Update an existing webhook alert. Requires Pro or Enterprise plan.
REQUIRED: id (alert ID from list_market_alerts)
All other fields are optional. Use is_active: false to pause without deleting.
Cost: 0 credits (Pro/Enterprise plan required)
Inputs: id (required), commune, prix_max, prix_min, +7 more.
update_portfolio_propertyUpdate Portfolio PropertyADestructiveIdempotentInspect
Update metadata for a portfolio property.
REQUIRED: id (property ID)
Optional: label, address, code_postal, commune, latitude, longitude, type_local, surface, pieces, purchase_price
Note: Changing latitude, longitude, surface, or type_local invalidates the cached estimate — it will be refreshed on the next get_portfolio_property call.
Cost: 0 credits
Inputs: id (required), label, pieces, address, +7 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
French real estate data: cadastre, DVF sales, DPE energy ratings, price estimates, parcel context
French address intelligence: 18.6M sold prices, energy, risk, crime and schools — each sourced.
French property data: cadastral parcels, DVF sales, DPE, PLU zoning, permits, legal owners
French public registers: companies (SIRENE, BODACC) and real estate (cadastre, DVF, DPE, risks).
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAccess 17M+ geocoded French property transactions (DVF), 22M+ DPE energy ratings, and 20M+ building records via MCP or REST API. Search transactions, market stats, comparables, price trends, rental yield, flip detection, and more.MIT
- AlicenseNot gradedqualityDmaintenanceAnalyzes French real-estate market using open data sources like DVF transactions, DPE certificates, and risk data.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query France's official DVF property-transfer price records, listing recorded sales filtered by commune, postcode, date range and property type, retrieving a single transaction with all its bundled parcels and lots, and computing median and average price per m² statistics by commune and year. Every response carries data-as-of, source and licence metadata.104 npmMIT
- FlicenseNot gradedqualityDmaintenanceFrench real estate data platform for AI agents. Identifies property owners likely to sell and tracks behavioral signals on active listings. Coverage: metropolitan France.-
Glama MCP Gateway
Add one secure layer between your agents and this server.