Skip to main content
Glama
README.md
# mcp-immo-olv

**Données immobilières françaises issues de l'open data public**
À partir d'une adresse, un client MCP peut consulter les ventes notariées (DVF), obtenir une estimation par comparables, les loyers d'annonce, une indication de la taxe foncière, les DPE, les risques Géorisques et le profil INSEE de la commune — sans clé API.. 

## L'objet de ce MCP, produire des données à partir de sources fiables

Les portails immobiliers affichent parfois des prix demandés et des estimations opaques. Les données
publiques françaises offrent mieux : actes notariés DVF, diagnostics ADEME,
indicateurs de loyer, fiscalité locale REI, risques et référentiels d'adresses.
`mcp-immo-olv` les relie dans des réponses auditables.

Chaque chiffre expose sa source, sa portée et ses limites. Une estimation reste
une analyse d'open data, **pas un avis de valeur professionnel ni un conseil
financier**.

## Modalités de connexion

Prérequis unique : **Node.js 18 ou plus récent**. Aucune clé API, aucun compte.
Par défaut le serveur tourne en local, en `stdio` : rien n'est exposé sur le
réseau. Un mode `Streamable HTTP` optionnel (variable `IMMO_HTTP_PORT`) permet
de l'héberger et de le partager — voir [§ 6](#6-hébergement--streamable-http).

| Votre contexte | Connexion en une ligne |
|---|---|
| **Claude Code** | `claude mcp add immo-olv -- npx -y mcp-immo-olv@latest` |
| **Cline** | `cline mcp add immo-olv --yes -- npx -y mcp-immo-olv@latest` |
| **Autre client MCP** | copier le bloc JSON ci-dessous dans `mcpServers` |
| **Registre MCP officiel** | serveur `io.github.OlivierLAVAUD/mcp-immo` |
| **Aucun client MCP** | console web locale : `npm run dev` → http://localhost:5173 |
| **Hébergement / accès distant** | `IMMO_HTTP_PORT=8123 npx -y mcp-immo-olv@latest` → `http://127.0.0.1:8123/mcp` |

### 1. Claude Code

```bash
claude mcp add immo-olv -- npx -y mcp-immo-olv@latest
```

Vérifier avec `claude mcp list` : `immo-olv` doit y figurer. Pour les commandes
`/immo-olv:rapport`, `/immo-olv:estimation` et `/immo-olv:risques`, installez le
plugin (voir [Installer en plugin Claude Code](#installer-en-plugin-claude-code)).

### 2. Cline

**En une commande** (CLI `cline`) :

```bash
cline mcp add immo-olv --yes -- npx -y mcp-immo-olv@latest
```

Sans `--yes`, la commande ouvre l'assistant d'ajout avec ces champs pré-remplis.
Vérifier avec `cline config mcp` : `immo-olv` doit y figurer, actif.

**Depuis l'IDE** : dans le panneau Cline, icône *MCP Servers* (barre d'outils) →
onglet *Configure* → bouton *Configure MCP Servers*, puis ajouter dans `mcpServers` :

```json
{
  "mcpServers": {
    "immo-olv": {
      "command": "npx",
      "args": ["-y", "mcp-immo-olv@latest"],
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

L'extension ouvre son propre fichier de réglages MCP ; la CLI, elle, lit
`~/.cline/data/settings/cline_mcp_settings.json` (surcharge possible avec la
variable `CLINE_MCP_SETTINGS_PATH`). Ensuite, redémarrer Cline : les 21 outils
apparaissent dans la liste MCP.

### 3. Tout autre client MCP

Copier ce bloc dans la configuration du client (`mcpServers`) :

```json
{
  "mcpServers": {
    "immo-olv": {
      "command": "npx",
      "args": ["-y", "mcp-immo-olv"]
    }
  }
}
```

Redémarrer le client : les 21 outils apparaissent dans sa liste d'outils MCP.

### 4. Depuis ce dépôt (développement)

```bash
npm install
npm run build
```

Pointer ensuite le client sur le build local au lieu du paquet publié :

```json
{
  "mcpServers": {
    "immo-olv": {
      "command": "node",
      "args": ["/chemin/vers/mcp-immo-olv/dist/index.js"]
    }
  }
}
```

Équivalent en une commande avec Claude Code :

```bash
claude mcp add immo-olv -- node /chemin/vers/mcp-immo-olv/dist/index.js
```

Le serveur se lance aussi seul, mais il attend un client sur stdin :

```bash
node dist/index.js
```

### 5. Console web (sans client MCP)

```bash
npm --prefix ui install
npm run build        # le pont a besoin de dist/index.js
npm run dev          # console : http://localhost:5173
```

Sans rien installer, un client compatible résout le serveur depuis le registre
MCP officiel sous le nom `io.github.OlivierLAVAUD/mcp-immo` — voir
[Installer depuis le registre MCP](#installer-depuis-le-registre-mcp).

### 6. Hébergement / Streamable HTTP

Par défaut le serveur est un processus `stdio` lancé par un client MCP. En
définissant `IMMO_HTTP_PORT`, ce **même registre d'outils** bascule sur le
transport MCP *Streamable HTTP*, pour l'héberger, le partager en équipe ou le
joindre depuis un client qui ne sait pas lancer un sous-processus.

```bash
IMMO_HTTP_PORT=8123 npx -y mcp-immo-olv@latest
# → mcp-immo-olv listening on Streamable HTTP: http://127.0.0.1:8123/mcp
```

Point un client MCP « remote » sur l'URL de l'endpoint :

```json
{
  "mcpServers": {
    "immo-olv": { "url": "http://127.0.0.1:8123/mcp" }
  }
}
```

| Variable | Défaut | Rôle |
|---|---|---|
| `IMMO_HTTP_PORT` | *(absente = stdio)* | Port d'écoute ; sa présence bascule le serveur en mode HTTP |
| `IMMO_HTTP_HOST` | `127.0.0.1` | Adresse de liaison |
| `IMMO_CACHE_DIR` | *(absente = mémoire seule)* | Dossier de cache disque persistant pour les DVF : accélère le cold start d'un ordre de grandeur |

À savoir avant d'exposer le serveur :

- **Bouclage local par défaut.** Il n'écoute que sur `127.0.0.1` : un serveur
  MCP sans authentification donne accès à tout le surface d'outils. Pour le
  partager au-delà de la machine, liez-le délibérément (`IMMO_HTTP_HOST`) et
  protégez l'accès (reverse proxy avec authentification, pare-feu…). Aucune
  authentification n'est implémentée côté serveur.
- **Sessions.** Chaque session MCP (`initialize`) reçoit son propre couple
  serveur/transport, routé par l'en-tête `Mcp-Session-Id`. Une session
  inconnue répond `404`, une méthode non autorisée `405`.
- **Réponses JSON.** Chaque outil est une requête/réponse unique (pas de flux
  serveur-initié), donc le serveur répond en JSON direct — compatible curl et
  tout client Streamable HTTP (qui doit accepter `application/json` **et**
  `text/event-stream`, comme le veut la spécification).
- **stdio reste la voie par défaut.** Rien ne change pour Claude Code, Cline ou
  tout client qui lance le paquet : sans `IMMO_HTTP_PORT`, c'est exactement le
  même comportement qu'avant.

## Installer depuis le registre MCP

Le serveur est référencé dans le registre officiel MCP sous le nom :

**`io.github.OlivierLAVAUD/mcp-immo`**

Un client capable de résoudre un serveur depuis le registre le trouve par ce
nom, sans clé API ni compte à créer. Le registre ne stocke que les métadonnées :
le serveur tourne en local, en `stdio`, et se lance depuis le paquet npm
`mcp-immo-olv`. La configuration manuelle ci-dessus reste équivalente.

```bash
# Vérifier la fiche publiée
curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.OlivierLAVAUD%2Fmcp-immo"
```

## Installer en plugin Claude Code

Le dépôt est aussi un marketplace de plugins Claude Code. Deux commandes
suffisent, sans clé API :

```bash
claude plugin marketplace add OlivierLAVAUD/mcp-immo-olv
claude plugin install immo-olv@mcp-immo-olv
```

Le plugin `immo-olv` lance le serveur MCP en `stdio` via
`npx -y mcp-immo-olv@latest`, et ajoute trois commandes qui pré-câblent les
appels d'outils :

| Commande | Ce qu'elle produit |
|---|---|
| `/immo-olv:rapport <adresse>` | Dossier complet sur une adresse |
| `/immo-olv:estimation <adresse> <type> <surface>` | Estimation par comparables et fiabilité mesurée du modèle |
| `/immo-olv:risques <adresse>` | Risques, urbanisme et cadastre |

Un skill de cadrage (`immobilier-france`) accompagne les outils : il impose de
citer la source de chaque chiffre, de ne jamais inventer une donnée, et de
traiter un risque `available: false` comme **inconnu** et non comme absent.

Sous Windows natif, si `npx` n'est pas résolu, déclare le serveur à la main :

```bash
claude mcp add immo-olv -- cmd /c npx -y mcp-immo-olv@latest
```

## Outils

| Outil | Résultat | Source |
|---|---|---|
| `property_report` | Dossier complet : marché, ventes, estimation, loyers, taxe, DPE, risques, commune, cadastre, PLU, IRIS, encadrement ; option `format: "markdown"` pour une fiche partageable, ou `addresses` (2–5) pour un dossier par adresse | Toutes les sources ci-dessous |
| `compare_properties` | Comparaison côte à côte de 2 à 5 adresses : marché, estimation, loyers, DPE, classements | DVF + Carte des loyers + ADEME |
| `acquisition_costs` | Simulation des frais d'acquisition (droits de mutation, émoluments, taxe foncière moyenne) et rendements brut/net | Barème officiel + REI + Carte des loyers |
| `search_by_budget` | Recherche inversée : quelles communes un budget donné peut atteindre, surfaces et rendements | DVF + Carte des loyers + geo.api.gouv.fr |
| `estimate_property` | Estimation pondérée par comparables, fourchette, échantillon effectif, loyer et rendements | DVF + Carte des loyers + REI pour la taxe moyenne |
| `backtest_estimator` | Backtest walk-forward du modèle : MAPE, biais, couverture des intervalles, par bande de surface et par année | DVF (DGFiP / Etalab) |
| `property_sales` | Ventes notariées réelles autour d'une adresse ou dans une commune | DVF (DGFiP / Etalab) |
| `price_per_m2` | Médiane, quartiles, évolution annuelle et fenêtre 12 mois | DVF (DGFiP / Etalab) |
| `rent_estimate` | Indicateurs de loyer d'annonce par segment | Carte des loyers (Ministère du Logement / ANIL) |
| `rent_control` | Loyer de référence, plafond légal (majoré) et minoré | Encadrement des loyers (Ville de Paris, Métropole de Lyon, Montpellier) |
| `property_tax_estimate` | Charge annuelle moyenne par article taxable, ventilée par composante | REI (DGFiP), via API publique OFGL |
| `dpe_lookup` | Diagnostics de performance énergétique à l'adresse, logements existants **et** neufs, avec statut légal de location par étiquette (décret n° 2024-501) et coût énergétique annuel estimé | ADEME (`dpe03existant`, `dpe02neuf`) |
| `cadastral_parcel` | Parcelle cadastrale : identifiant `idu`, section, numéro, contenance officielle | PCI, IGN / DGFiP (API Carto) |
| `urbanism_zoning` | Zone PLU (U / AU / A / N), règlement et prescriptions d'urbanisme | Géoportail de l'urbanisme (DGALN / IGN) |
| `iris_lookup` | IRIS INSEE d'une adresse : code, nom, type, commune | CONTOURS-IRIS / ADMINEXPRESS, IGN |
| `nearby_amenities` | Ce qu'il y a autour d'une adresse : transports, écoles, commerces, santé, espaces verts — nombre dans le rayon et distance à vol d'oiseau des plus proches, avec un détail train / métro / tram / bus pour les transports | OpenStreetMap (ODbL), API Overpass |
| `natural_risks` | Risques naturels et technologiques officiels | Géorisques |
| `risk_summary` | Digest des risques : une phrase par risque (inondation, argile, radon, ICPE, DPE), explicite sur les inconnus | Géorisques + ADEME |
| `commune_info` | Population (recensement + population légale INSEE pmun/pcap/ptot), code postal, département, région, surface, centre | geo.api.gouv.fr / INSEE |
| `geocode_address` / `reverse_geocode` | Adresse ↔ coordonnées, code INSEE et identifiant BAN | Base Adresse Nationale |

### Sortie structurée

Les 21 outils déclarent le schéma de leur résultat (`outputSchema`, spécification
MCP 2025-06-18). Chaque appel renvoie donc la même charge utile deux fois :
`structuredContent`, l'objet validé par le SDK avant envoi, et le bloc texte JSON
historique, conservé pour les clients antérieurs à cette révision. Un client peut
typer le résultat, le rendre sans le reparser, et faire confiance à la forme
annoncée — `estimate_property` promet `estimate.per_m2.estimate`,
`estimate.confidence`, `estimate.top_comps[]`, et le serveur échoue plutôt que de
livrer autre chose.

Les schémas sont volontairement **ouverts** (`additionalProperties: true`) : un
champ ajouté par une source en amont ne peut pas invalider un outil. Ils sont
vérifiés à deux niveaux — `test/output-schemas.test.ts` les confronte à un
payload réel capturé (`ui/fixtures/property-report-lyon.json`), et `npm run smoke`
valide les réponses live contre les mêmes schémas.

### Taxe foncière et rendement « net »

`property_tax_estimate` ne prétend **jamais** connaître l'avis de taxe foncière
d'un bien. Le REI publie des montants agrégés et nombres d'articles imposés par
commune : le serveur calcule leur charge moyenne, avec les composantes publiées
(part communale, intercommunale, syndicats, GEMAPI, TEOM). L'avis réel dépend de
la valeur locative cadastrale, des exonérations, du propriétaire et de
l'imposition : demandez-le avant tout achat.

Le rendement après taxe moyenne retire cette seule moyenne au loyer annuel. Il
ne déduit ni charges de copropriété, assurance, gestion, vacance, travaux ni
impôt sur les revenus : ce n'est pas un rendement net-net.

## Exemples

Les sorties réelles des outils — digest de risques, proximité, comparaison,
recherche par budget, fiche Markdown, lots d'adresses et messages d'erreur — sont
dans **[EXAMPLES.md](EXAMPLES.md)**, rejouables avec `npm run examples`.

Des **prompts d'exemple pour les 21 outils** (à copier dans votre client),
classés par besoin et par parcours, sont dans **[Prompts.md](Prompts.md)**. Ils
incluent des prompts qui vérifient les garde-fous : source injoignable →
`inconnu`, estimation refusée sous trois comparables, adresse inexistante.

## Méthodologie d'estimation

L'estimation est une médiane pondérée des ventes comparables : même type de
bien, surface 40–250 % de la cible, un seul logement par acte, valeurs extrêmes
écartées. Les prix anciens sont ramenés au niveau du dernier millésime de marché
par commune (coefficient borné 0,7–1,6). Les poids combinent distance,
similarité de surface et ancienneté ; les quartiles pondérés donnent la
fourchette. Chaque comparable, son ajustement et son poids sont restitués.

Le moteur refuse une estimation sous trois comparables. Il ne connaît ni l'état,
ni l'étage, ni la vue, ni les travaux, ni les contraintes juridiques.

### Backtesting du moteur

`backtest_estimator` rejoue le moteur sur les ventes de la commune : chaque vente
est estimée en n'utilisant **que les ventes enregistrées avant sa propre date**
(découpe `asOf`, acte exclu), puis comparée au prix réellement payé. Aucun
comparable futur, aucun niveau de marché futur ne peut fuiter.

Il publie la MAPE, l'erreur médiane et le 90ᵉ centile, le biais signé (positif =
le modèle surestime) et la couverture de l'intervalle P25–P75 — à lire près de
**50 %**, pas 95 % : un intervalle P25–P75 bien calibré contient la moitié des
ventes réalisées. Le tout est ventilé par bande de surface et par année, avec
les dix plus grosses erreurs pour audit. Une exécution de contrôle sur Lyon
donne une MAPE d'environ 21 %, un biais de +8 % et une couverture de 52,5 %.

## Sources, licences et limites

Chaque jeu renvoie à sa page de référence officielle (le nom du jeu est un lien) ;
les URL que le serveur renvoie dans une réponse — `source_url`, `officialReportUrl`,
`unavailable.portal_url` — sont vérifiées en direct par `npm run smoke`.

| Jeu | Producteur | Usage dans le serveur |
|---|---|---|
| [DVF géolocalisées](https://www.data.gouv.fr/fr/datasets/demandes-de-valeurs-foncieres-geolocalisees/) | DGFiP / Etalab | Ventes 2021 → présent ; **aucune source géolocalisée avant 2021** ; pas d'Alsace-Moselle ni Mayotte ; délai de publication |
| [Carte des loyers](https://www.data.gouv.fr/fr/datasets/carte-des-loyers-indicateurs-de-loyers-dannonce-par-commune-en-2025/) | Ministère du Logement / ANIL | Loyer d'annonce modélisé, charges comprises ; pas un loyer de référence réglementé |
| Encadrement des loyers | [Ville de Paris](https://www.paris.fr/pages/l-encadrement-des-loyers-parisiens-en-vigueur-le-1er-aout-2712), [Métropole de Lyon](https://www.grandlyon.com/mes-services-au-quotidien/se-loger-ameliorer-ou-louer-son-logement/sinformer-sur-lencadrement-des-loyers) et [Montpellier](https://www.montpellier.fr/vie-quotidienne/vivre-ici/se-loger/lencadrement-des-loyers) | Loyers de référence des zones couvertes uniquement ; « non couvert » est renvoyé explicitement ailleurs |
| [REI](https://data.ofgl.fr/explore/dataset/rei/) | DGFiP, exposé par OFGL | Fiscalité locale agrégée ; moyenne par article, jamais taxe individuelle |
| [DPE logements existants](https://data.ademe.fr/datasets/dpe-v2-logements-existants) et [neufs](https://data.ademe.fr/datasets/dpe-v2-logements-neufs) | ADEME | Diagnostics `dpe03existant` et `dpe02neuf`, chacun étiqueté par registre |
| [Cadastre (PCI)](https://cadastre.data.gouv.fr/) | IGN / DGFiP ([API Carto](https://apicarto.ign.fr/api/doc/cadastre)) | Parcelle, `idu` et contenance ; jamais la propriété ni le droit de construire |
| [Géoportail de l'urbanisme](https://www.geoportail-urbanisme.gouv.fr/) | DGALN / IGN ([API Carto](https://apicarto.ign.fr/api/doc/gpu)) | Zonage et prescriptions opposables ; les communes sans PLU en sont absentes |
| [CONTOURS-IRIS / ADMINEXPRESS](https://geoservices.ign.fr/adminexpress) | IGN (source INSEE) | Identité de l'IRIS ; aucune donnée socio-démographique dans cette couche |
| [Géorisques](https://www.georisques.gouv.fr/) | Ministère de la Transition écologique | Rapport de risques officiel ; si leur API ne répond pas, la réponse porte `available: false` et le dit explicitement au lieu de renvoyer une liste vide |
| [OpenStreetMap](https://www.openstreetmap.org/copyright) (via [Overpass](https://wiki.openstreetmap.org/wiki/Overpass_API)) | Contributeurs OSM, ODbL | Points d'intérêt autour d'une adresse ; couverture communautaire, donc inégale, et un `count` nul quand Overpass ne répond pas signifie **inconnu**, jamais « rien autour » |
| [BAN](https://adresse.data.gouv.fr/) / [geo.api.gouv.fr](https://geo.api.gouv.fr/) | IGN / DINUM / INSEE | Adresses et unités administratives |

Licences : Licence Ouverte / Open Licence (Etalab) pour les jeux de l'État cités
ici, ODbL pour OpenStreetMap ; certains jeux de collectivités ont leur propre
licence, à vérifier sur la fiche du jeu avant réutilisation. La source doit être
citée dès qu'une réponse est reprise. Les jeux publics sont interrogés en direct,
sans clé API. Le cache mémoire réduit la latence et les appels répétés, mais
est vidé au redémarrage ; définir `IMMO_CACHE_DIR` (un dossier inscriptible)
persiste les lignes DVF lues sur disque — un redémarrage réhydrate depuis le
fichier au lieu de tout re-télécharger, sans changer les données servies.

## Développement

```bash
npm install
npm run build
npm test          # tests unitaires, sans réseau
npm run smoke     # vérification live des API publiques
npm run examples  # exemples live, commentés dans EXAMPLES.md

cd ui
npm install
npm run dev       # console avec hot reload : http://localhost:5173
npm run build
npm start         # console compilée + pont MCP : http://localhost:8787
npm run smoke     # test de rendu avec fixtures réelles
```

Depuis la racine, les mêmes commandes sont accessibles sans changer de dossier
(`npm run dev` délègue à `ui/`) :

```bash
npm --prefix ui install
npm run dev       # console avec hot reload
npm run ui:build  # compile l'interface
npm run ui:start  # console compilée + pont MCP sur un seul port
```

## Licence

MIT. Copyright **© 2026 Olivier LAVAUD** (voir `LICENSE`).

TDQS

A3.7/5.0

Scored across 16 tools

Disambiguation3/5

Most tools target distinct official data sources (DPE, risks, cadastre, IRIS), but property_report is an umbrella that overlaps with estimate_property, property_tax_estimate, price_per_m2, dpe_lookup, and natural_risks, and rent_estimate vs rent_control both return rent figures in €/m². Detailed descriptions help, but an agent must read carefully to avoid picking a redundant or wrong tool.

Naming Consistency3/5

All names are readable lowercase snake_case, but there is no consistent verb_noun pattern: geocode_address, estimate_property, and reverse_geocode are actions, while property_sales, natural_risks, commune_info, and cadastral_parcel are noun phrases, and dpe_lookup/iris_lookup put the noun first. The mixed conventions are understandable but not predictable.

Tool Count4/5

16 tools is one over the typical 3-15 well-scoped range, but each tool mostly maps to a distinct official data source (DVF, ADEME, Géorisques, cadastre, urbanism, INSEE) for a broad French real-estate domain. property_report makes some tools redundant, yet the count remains reasonable for the server's comprehensive purpose.

Completeness4/5

The surface covers geocoding, sales, price statistics, comparables-based valuation with backtesting, rents, rent control, tax proxies, energy diagnostics, natural risks, cadastre, urbanism zoning, and commune/IRIS demographics. Minor gaps include aggregate-only tax estimates, no ownership records, and no school or amenity data, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues