{"serverId":"mcp-registry/io.github.gabrielkasmi/deeppvmapper","tools":[{"name":"count_detections","fixed":{"name":"count_detections","description":"Count detections matching a set of filters, exactly, without downloading rows (fast, no row cap). Use this for \"how many ...\" questions, e.g. \"how many installations have an RNB id?\" -> has_rnb_id=true; \"how many are identified by 2+ sources?\" -> quality_filter=true; \"how many come from OpenStreetMap?\" -> sources_include=[2]. Returns the matching count, the unfiltered registry total and the percentage. Counts are DETECTED systems, not an inventory. Data quality note: this is a detection dataset,","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["quality_filter","breakdown_rnb_id"],"properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\"."},"insee":{"type":"string","description":"INSEE commune code."},"max_kwp":{"type":"number","description":"Maximum estimated installed capacity, in kWp."},"min_kwp":{"type":"number","description":"Minimum estimated installed capacity, in kWp."},"max_tilt":{"type":"number","description":"Maximum estimated tilt from horizontal, in degrees."},"min_tilt":{"type":"number","description":"Minimum estimated tilt from horizontal, in degrees."},"has_rnb_id":{"type":"boolean","description":"true = only detections matched to an RNB building identifier (rnb_id not null); false = only detections without one."},"max_azimuth":{"type":"number","description":"Maximum estimated azimuth, degrees clockwise from true north (180 = south)."},"max_surface":{"type":"number","description":"Maximum estimated PV array area, in m²."},"min_azimuth":{"type":"number","description":"Minimum estimated azimuth, degrees clockwise from true north (180 = south)."},"min_surface":{"type":"number","description":"Minimum estimated PV array area, in m²."},"max_vintages":{"type":"integer","maximum":9007199254740991,"description":"Maximum number of imagery vintages (e.g. 1 = seen in a single year only).","exclusiveMinimum":0},"min_vintages":{"type":"integer","maximum":9007199254740991,"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.","exclusiveMinimum":0},"max_last_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Upper bound on last_seen imagery year."},"min_last_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Lower bound on last_seen imagery year."},"has_frpv_proba":{"type":"boolean","description":"true = only detections that have an FRPV comparison (frpv_proba not null); false = only those without one. A null frpv_proba means \"no comparison available\", not probability 0."},"max_first_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Upper bound on first_seen imagery year."},"min_first_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Earliest imagery year of first detection, lower bound (e.g. 2018). Not an installation date."},"min_frpv_proba":{"type":"number","maximum":1,"minimum":0,"description":"Minimum frpv_proba. The data contract recommends 0.1 as a precision/recall trade-off. Note: detections with a null frpv_proba (no FRPV comparison available) are excluded when this is set; null does not mean probability 0."},"quality_filter":{"type":"boolean","default":false,"description":"If true, only include detections identified by 2 OR MORE sources(the `sources` field lists at least two codes, e.g. \"0,1\" = DeepPVMapper pipeline + FRPV reference, \"0,2\" = pipeline + OpenStreetMap). Default false: all detections are included, including those found by a single source (typically the automated pipeline alone)."},"cross_validated":{"type":"boolean","description":"Alias of quality_filter, kept for backward compatibility."},"sources_include":{"type":"array","items":{"anyOf":[{"type":"integer","maximum":4,"minimum":0},{"type":"string"}]},"description":"Only include detections present in ALL of these sources. Accepts names or codes, case-insensitive: dpvm/deeppvmapper/kasmi (0), frpv/thebault (1), osm/openstreetmap (2), manual/annotation (3), recall (4). Examples: [\"osm\"] = detections that are in OpenStreetMap; [\"dpvm\",\"frpv\"] = present in both DeepPVMapper and FRPV. See get_source_reference for what each source is and where it comes from."},"breakdown_rnb_id":{"type":"boolean","default":false,"description":"If true, also return how many of the matching detections do / do not have an rnb_id (ignores has_rnb_id for this breakdown)."},"false_positive_status":{"enum":["flagged","not_flagged","unrecorded"],"type":"string","description":"flagged = false_positive is true; not_flagged = false_positive is false; unrecorded = false_positive is null (no status recorded — NOT a confirmed true positive)."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":1391,"tokensAfter":1391},{"name":"get_community_activity","fixed":{"name":"get_community_activity","description":"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.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["recent_limit"],"properties":{"recent_limit":{"type":"integer","default":15,"maximum":50,"description":"How many of the most recent pending contributions to list.","exclusiveMinimum":0}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":224,"tokensAfter":224},{"name":"get_community_activity_in_area","fixed":{"name":"get_community_activity_in_area","description":"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 /","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["scan_limit","recent_limit"],"properties":{"dpt":{"type":"string","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."},"max_lat":{"type":"number"},"max_lon":{"type":"number"},"min_lat":{"type":"number"},"min_lon":{"type":"number"},"scan_limit":{"type":"integer","default":500,"maximum":2000,"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.","exclusiveMinimum":0},"recent_limit":{"type":"integer","default":30,"maximum":100,"description":"Maximum number of matching items to return per category.","exclusiveMinimum":0}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":470,"tokensAfter":470},{"name":"get_data_quality_reference","fixed":{"name":"get_data_quality_reference","description":"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 se","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":192,"tokensAfter":192},{"name":"get_department_capacity_stats","fixed":{"name":"get_department_capacity_stats","description":"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 the","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\" for Gironde. Omit for all départements."},"top_n":{"type":"integer","maximum":96,"description":"If set and dpt is omitted, return only the top N départements by installed capacity.","exclusiveMinimum":0}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":270,"tokensAfter":270},{"name":"get_department_profile","fixed":{"name":"get_department_profile","description":"One-call profile of a département: installed capacity and national rank, yearly trend (by first-seen imagery year), source mix, share identified by 2+ sources, and share matched to an RNB building id. Cross-references the pre-computed department statistics with live counts. 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 s","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["dpt"],"properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\"."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":217,"tokensAfter":217},{"name":"get_department_yearly_stats","fixed":{"name":"get_department_yearly_stats","description":"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. In this server, quality_filter=true keeps only detections identified by 2 or more sources (see source_encoding","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\". Omit for all départements."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":221,"tokensAfter":221},{"name":"get_detection_details","fixed":{"name":"get_detection_details","description":"Get the full record of one detection by id: technical characteristics (surface, kwp, tilt, azimuth — model estimates), imagery years, sources decoded into plain labels, frpv_proba, false-positive flag, rnb_id and location codes, plus simple confidence signals. 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","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["id"],"properties":{"id":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Registry identifier of the detection (the `id` field)."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":237,"tokensAfter":237},{"name":"get_detections_in_bbox","fixed":{"name":"get_detections_in_bbox","description":"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. In this server, quality_filter=true keeps only detections identified by 2 or more sources (see ","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["min_lon","min_lat","max_lon","max_lat","max_count"],"properties":{"max_lat":{"type":"number"},"max_lon":{"type":"number"},"min_lat":{"type":"number"},"min_lon":{"type":"number"},"max_count":{"type":"integer","default":100,"maximum":500,"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).","exclusiveMinimum":0}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":307,"tokensAfter":307},{"name":"get_field_coverage","fixed":{"name":"get_field_coverage","description":"Completeness report: for each optional field of the registry (rnb_id, frpv_proba, false_positive, false_positive_source), how many detections have it filled in and what percentage. Answers \"how many installations have an RNB id / an FRPV comparison / a false-positive flag?\" in one call, for France or one département. For a single filtered count use count_detections instead. Null means \"not available/recorded\", never \"0\" or \"confirmed ok\". Data quality note: this is a detection dataset, not an ex","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"dpt":{"type":"string","description":"French département code. Omit for all of France."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":216,"tokensAfter":216},{"name":"get_field_distribution","fixed":{"name":"get_field_distribution","description":"Histogram of a numeric field (kwp, surface, tilt, azimuth, n_vintages, first_seen, last_seen) with exact counts per bin, for France or one département. Answers \"how are installations distributed by size / tilt / orientation / year?\". kwp, surface, tilt and azimuth are model estimates. first_seen/last_seen are imagery years, not installation dates. Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection does not mean no PV installat","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["field","quality_filter"],"properties":{"dpt":{"type":"string","description":"French département code. Omit for all of France."},"field":{"enum":["kwp","surface","tilt","azimuth","n_vintages","first_seen","last_seen"],"type":"string","description":"Numeric field to describe."},"max_year":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"For first_seen / last_seen: last year to count."},"min_year":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"For first_seen / last_seen: first year to count."},"bin_edges":{"type":"array","items":{"type":"number"},"maxItems":25,"minItems":2,"description":"Custom ascending bin edges; each bin is [edge_i, edge_i+1) and the last is closed. Ignored for first_seen / last_seen, which are counted per year (use min_year / max_year)."},"quality_filter":{"type":"boolean","default":false,"description":"If true, restrict to detections identified by 2+ sources."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":461,"tokensAfter":461},{"name":"get_field_reference","fixed":{"name":"get_field_reference","description":"Field-by-field documentation of a detection record: type, unit, nullability, whether it is observed or a model estimate, how to read it, and which tool filters or reports it. Call this when the user asks what a field means or how reliable it is.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":119,"tokensAfter":119},{"name":"get_source_breakdown","fixed":{"name":"get_source_breakdown","description":"Break down detections by source code (0=DPVM pipeline, 1=FRPV reference, 2=OSM, 3=manual correction, 4=recall sample), for one département or all of France, with human-readable labels. A detection can carry several sources, so per-source counts overlap and do not add up to the total. Also returns how many detections are identified by 2+ sources (the meaning of quality_filter). Data quality note: this is a detection dataset, not an exhaustive inventory (estimated recall ~0.6). A missing detection","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\". Omit for all of France."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":218,"tokensAfter":218},{"name":"get_source_reference","fixed":{"name":"get_source_reference","description":"Explain the data sources behind the registry's `sources` field: for each source, its code, short key, name, accepted aliases, and where the data comes from (with references: code, thesis, papers). Use it for questions like \"what is FRPV?\", \"where does the OSM data come from?\", \"what is a manual correction?\". The `sources` field answers \"where do we have this installation?\": each listed code is a dataset or process that contains it. Example: \"0,1\" = present in both DeepPVMapper (DPVM) and FRPV; \"","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"source":{"type":"string","description":"A source name, alias or code (e.g. \"frpv\", \"OpenStreetMap\", \"kasmi\", \"3\"). Omit to list all."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":233,"tokensAfter":233},{"name":"get_started","fixed":{"name":"get_started","description":"START HERE. Call this first when the user is new, asks what this server can do, or asks a vague question about DeepPVMapper. Returns a plain-language introduction, example questions, which tool answers which kind of question, a glossary and the main caveats. Reply to the user in their own language.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":132,"tokensAfter":132},{"name":"search_detections","fixed":{"name":"search_detections","description":"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 ","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["quality_filter","limit"],"properties":{"dpt":{"type":"string","description":"French département code, e.g. \"33\"."},"insee":{"type":"string","description":"INSEE commune code."},"limit":{"type":"integer","default":20,"maximum":200,"description":"Maximum number of records to return (max 200).","exclusiveMinimum":0},"max_kwp":{"type":"number","description":"Maximum estimated installed capacity, in kWp."},"min_kwp":{"type":"number","description":"Minimum estimated installed capacity, in kWp."},"max_tilt":{"type":"number","description":"Maximum estimated tilt from horizontal, in degrees."},"min_tilt":{"type":"number","description":"Minimum estimated tilt from horizontal, in degrees."},"has_rnb_id":{"type":"boolean","description":"true = only detections matched to an RNB building identifier (rnb_id not null); false = only detections without one."},"max_azimuth":{"type":"number","description":"Maximum estimated azimuth, degrees clockwise from true north (180 = south)."},"max_surface":{"type":"number","description":"Maximum estimated PV array area, in m²."},"min_azimuth":{"type":"number","description":"Minimum estimated azimuth, degrees clockwise from true north (180 = south)."},"min_surface":{"type":"number","description":"Minimum estimated PV array area, in m²."},"max_vintages":{"type":"integer","maximum":9007199254740991,"description":"Maximum number of imagery vintages (e.g. 1 = seen in a single year only).","exclusiveMinimum":0},"min_vintages":{"type":"integer","maximum":9007199254740991,"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.","exclusiveMinimum":0},"max_last_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Upper bound on last_seen imagery year."},"min_last_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Lower bound on last_seen imagery year."},"has_frpv_proba":{"type":"boolean","description":"true = only detections that have an FRPV comparison (frpv_proba not null); false = only those without one. A null frpv_proba means \"no comparison available\", not probability 0."},"max_first_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Upper bound on first_seen imagery year."},"min_first_seen":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991,"description":"Earliest imagery year of first detection, lower bound (e.g. 2018). Not an installation date."},"min_frpv_proba":{"type":"number","maximum":1,"minimum":0,"description":"Minimum frpv_proba. The data contract recommends 0.1 as a precision/recall trade-off. Note: detections with a null frpv_proba (no FRPV comparison available) are excluded when this is set; null does not mean probability 0."},"quality_filter":{"type":"boolean","default":false,"description":"If true, only include detections identified by 2 OR MORE sources(the `sources` field lists at least two codes, e.g. \"0,1\" = DeepPVMapper pipeline + FRPV reference, \"0,2\" = pipeline + OpenStreetMap). Default false: all detections are included, including those found by a single source (typically the automated pipeline alone)."},"cross_validated":{"type":"boolean","description":"Alias of quality_filter, kept for backward compatibility."},"sources_include":{"type":"array","items":{"anyOf":[{"type":"integer","maximum":4,"minimum":0},{"type":"string"}]},"description":"Only include detections present in ALL of these sources. Accepts names or codes, case-insensitive: dpvm/deeppvmapper/kasmi (0), frpv/thebault (1), osm/openstreetmap (2), manual/annotation (3), recall (4). Examples: [\"osm\"] = detections that are in OpenStreetMap; [\"dpvm\",\"frpv\"] = present in both DeepPVMapper and FRPV. See get_source_reference for what each source is and where it comes from."},"false_positive_status":{"enum":["flagged","not_flagged","unrecorded"],"type":"string","description":"flagged = false_positive is true; not_flagged = false_positive is false; unrecorded = false_positive is null (no status recorded — NOT a confirmed true positive)."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":1370,"tokensAfter":1370}],"toolsChanged":16,"tokensSaved":0,"todo":[{"tool":"get_community_activity_in_area","params":["max_lat","max_lon","min_lat","min_lon"]},{"tool":"get_detections_in_bbox","params":["max_lat","max_lon","min_lat","min_lon"]}],"note":"Deterministic fixes. Changes marked verify need a human look before shipping (renames, inferred annotations, inferred types, removed text). Parameter descriptions in `todo` need to be written by someone who knows the API."}