DeepPVMapper

Open registry of 1.14M+ rooftop-solar detections across France, queryable by natural language.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
85%
Naming quality
100%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~2,457Tokens (tool definitions)
~2.1 KBTypical response size
Moderate attention impact (1.92% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "deeppvmapper": {
      "url": "https://zelhliylrlktnasircwp.supabase.co/functions/v1/mcp/mcp"
    }
  }
}

Remote endpoints

https://zelhliylrlktnasircwp.supabase.co/functions/v1/mcp/mcpstreamable-http

What it can do

Tool inventory

Tools (8)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢get_data_quality_reference

Return the DeepPVMapper/OpenPVMapper registry's documented data-quality characteristics: estimated detection recall, which fields are model-derived estimates vs. structural/observed fields, the source-encoding table, the recommended confidence threshold, confidence signals, and licensing/liability terms. Call this before advising how much to trust a result for a specific use case (e.g. exploratory research vs. a commercial or regulatory decision) — pair it with the quality_summary attached to search_detections / aggregate_detection_capacity results, which reflects the specific query rather than the registry as a whole.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢get_department_capacity_stats(dpt, top_n)

Get installed rooftop-PV capacity (total kWp) and system counts for one or all French départements, from the DeepPVMapper/OpenPVMapper registry. This is a fixed, pre-computed department-wide aggregate with no other filters — use aggregate_detection_capacity instead if you need a filtered subset (e.g. only cross-validated detections). Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installation exists there. kwp, surface, tilt and azimuth are model estimates, not surveyed values. Call get_data_quality_reference for the full picture before assessing fitness for a specific use case.

Input Schema

{
  "type": "object",
  "properties": {
    "dpt": {
      "description": "French département code, e.g. \"33\" for Gironde. Omit for all départements.",
      "type": "string"
    },
    "top_n": {
      "description": "If set and dpt is omitted, return only the top N départements by installed capacity.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 96
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢get_department_yearly_stats(dpt)

Get yearly system counts and capacity by département, based on first-seen imagery year. Useful for tracking apparent PV deployment growth over time. Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installation exists there. kwp, surface, tilt and azimuth are model estimates, not surveyed values. Call get_data_quality_reference for the full picture before assessing fitness for a specific use case.

Input Schema

{
  "type": "object",
  "properties": {
    "dpt": {
      "description": "French département code, e.g. \"33\". Omit for all départements.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢search_detections(dpt, insee, min_kwp, max_kwp, min_vintages, ...)

Search individual rooftop-PV detections by département, commune (INSEE code), estimated capacity range, and/or cross-validation confidence (min_vintages, cross_validated). Returns a bounded list of detection records plus a quality_summary for the returned sample (use get_detections_in_bbox instead for map/spatial queries with geometry). Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installation exists there. kwp, surface, tilt and azimuth are model estimates, not surveyed values. Call get_data_quality_reference for the full picture before assessing fitness for a specific use case.

Input Schema

{
  "type": "object",
  "properties": {
    "dpt": {
      "description": "French département code, e.g. \"33\".",
      "type": "string"
    },
    "insee": {
      "description": "INSEE commune code.",
      "type": "string"
    },
    "min_kwp": {
      "description": "Minimum estimated installed capacity, in kWp.",
      "type": "number"
    },
    "max_kwp": {
      "description": "Maximum estimated installed capacity, in kWp.",
      "type": "number"
    },
    "min_vintages": {
      "description": "Minimum number of distinct imagery vintages (years) the installation was independently detected in. Use 2+ as a persistence/confidence signal, since a one-off detection in a single vintage is more likely to be a transient artifact.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "cross_validated": {
      "description": "If true, only include detections confirmed by at least two independent sources (e.g. the automated DeepPVMapper pipeline plus OpenStreetMap or the FRPV reference dataset), not just a single pipeline. This is a stronger confidence signal than min_vintages.",
      "type": "boolean"
    },
    "quality_filter": {
      "default": true,
      "description": "If true (default), only include detections with frpv_proba >= 0.1, the threshold recommended in the data contract for a good precision/recall trade-off.",
      "type": "boolean"
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of records to return (max 200).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 200
    }
  },
  "required": [
    "quality_filter",
    "limit"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟡aggregate_detection_capacity(dpt, insee, min_kwp, max_kwp, min_vintages, ...)

Compute the total estimated installed capacity (kWp) and count of detections matching a set of filters — département, commune, capacity range, and cross-validation across sources (cross_validated) or imagery vintages (min_vintages) — plus a quality_summary for the summed sample. Unlike get_department_capacity_stats, which is a fixed pre-computed département-wide aggregate with no other filters, this tool sums a live filtered subset, up to max_rows detections. Example: "installed capacity in Gironde confirmed by at least two sources" -> dpt="33", cross_validated=true. Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installation exists there. kwp, surface, tilt and azimuth are model estimates, not surveyed values. Call get_data_quality_reference for the full picture before assessing fitness for a specific use case.

Input Schema

{
  "type": "object",
  "properties": {
    "dpt": {
      "description": "French département code, e.g. \"33\".",
      "type": "string"
    },
    "insee": {
      "description": "INSEE commune code.",
      "type": "string"
    },
    "min_kwp": {
      "description": "Minimum estimated installed capacity, in kWp.",
      "type": "number"
    },
    "max_kwp": {
      "description": "Maximum estimated installed capacity, in kWp.",
      "type": "number"
    },
    "min_vintages": {
      "description": "Minimum number of distinct imagery vintages (years) the installation was independently detected in. Use 2+ as a persistence/confidence signal, since a one-off detection in a single vintage is more likely to be a transient artifact.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "cross_validated": {
      "description": "If true, only include detections confirmed by at least two independent sources (e.g. the automated DeepPVMapper pipeline plus OpenStreetMap or the FRPV reference dataset), not just a single pipeline. This is a stronger confidence signal than min_vintages.",
      "type": "boolean"
    },
    "quality_filter": {
      "default": true,
      "description": "If true (default), only include detections with frpv_proba >= 0.1, the threshold recommended in the data contract for a good precision/recall trade-off.",
      "type": "boolean"
    },
    "max_rows": {
      "default": 5000,
      "description": "Cap on the number of matching detection rows fetched to compute the capacity sum. If the true match count exceeds this, total_kwp is a partial lower bound and `truncated` is true — increase max_rows or narrow the filters (e.g. add dpt or insee) for an exact total.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 20000
    }
  },
  "required": [
    "quality_filter",
    "max_rows"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢get_detections_in_bbox(min_lon, min_lat, max_lon, max_lat, max_count)

Get rooftop-PV detections within a geographic bounding box (WGS84 lon/lat), including footprint geometry. Intended for map-style spatial queries over a small area. Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installation exists there. kwp, surface, tilt and azimuth are model estimates, not surveyed values. Call get_data_quality_reference for the full picture before assessing fitness for a specific use case.

Input Schema

{
  "type": "object",
  "properties": {
    "min_lon": {
      "type": "number"
    },
    "min_lat": {
      "type": "number"
    },
    "max_lon": {
      "type": "number"
    },
    "max_lat": {
      "type": "number"
    },
    "max_count": {
      "default": 100,
      "description": "Maximum number of detections to return (max 500 here; the underlying API defaults to 2000, capped lower to keep responses manageable for an LLM).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 500
    }
  },
  "required": [
    "min_lon",
    "min_lat",
    "max_lon",
    "max_lat",
    "max_count"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟡get_community_activity(recent_limit)

Get a snapshot of ongoing community contribution activity on the map: how many corrections are currently pending moderation, their breakdown by action type (add / modify / delete), and the most recent submissions (timestamp, action, target). Submitted free-text comments are intentionally excluded from this tool. This reflects unmoderated, unverified user activity, not the registry itself — do not present it as confirmed detection data.

Input Schema

{
  "type": "object",
  "properties": {
    "recent_limit": {
      "default": 15,
      "description": "How many of the most recent pending contributions to list.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 50
    }
  },
  "required": [
    "recent_limit"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢get_community_activity_in_area(dpt, min_lon, min_lat, max_lon, max_lat, ...)

Find pending, unmoderated community contributions relevant to a specific area, to answer "has anyone flagged anything here that is not in the registry yet?" Two independent filters: dpt finds pending edits/deletions (action=modify/delete) targeting existing detections in that département; a full bounding box (min_lon/min_lat/max_lon/max_lat) finds pending new additions (action=add) whose proposed footprint centroid falls inside it. Combine with get_department_capacity_stats / search_detections / get_detections_in_bbox for the confirmed registry picture, and present this separately and clearly as unverified, pending community input — not confirmed detection data. Free-text comments are never included.

Input Schema

{
  "type": "object",
  "properties": {
    "dpt": {
      "description": "Filter pending edits/deletions of EXISTING detections (action=modify or delete) to this département. Does not apply to proposed new additions (action=add), which have no département recorded on the pending item itself — use the bbox parameters for those.",
      "type": "string"
    },
    "min_lon": {
      "type": "number"
    },
    "min_lat": {
      "type": "number"
    },
    "max_lon": {
      "type": "number"
    },
    "max_lat": {
      "type": "number"
    },
    "scan_limit": {
      "default": 500,
      "description": "How many recent proposed additions (action=add) to scan for a bbox match. Only relevant when all four bbox parameters are given — there is no server-side spatial index on pending items, so matching is done by fetching this many of the most recent ones and checking their centroid against the box.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2000
    },
    "recent_limit": {
      "default": 30,
      "description": "Maximum number of matching items to return per category.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "required": [
    "scan_limit",
    "recent_limit"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded8 tools