@ignfab/geocontext 0.9.3 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +62 -31
  2. package/dist/gpf/adminexpress.js +7 -27
  3. package/dist/gpf/adminexpress.js.map +1 -1
  4. package/dist/gpf/parcellaire-express.js +13 -33
  5. package/dist/gpf/parcellaire-express.js.map +1 -1
  6. package/dist/gpf/urbanisme.d.ts +4 -2
  7. package/dist/gpf/urbanisme.js +20 -61
  8. package/dist/gpf/urbanisme.js.map +1 -1
  9. package/dist/gpf/wfs.d.ts +2 -2
  10. package/dist/gpf/wfs.js +17 -71
  11. package/dist/gpf/wfs.js.map +1 -1
  12. package/dist/helpers/distance.d.ts +4 -2
  13. package/dist/helpers/distance.js +20 -5
  14. package/dist/helpers/distance.js.map +1 -1
  15. package/dist/helpers/http.d.ts +4 -0
  16. package/dist/helpers/http.js +103 -1
  17. package/dist/helpers/http.js.map +1 -1
  18. package/dist/helpers/jsonSchema.d.ts +9 -0
  19. package/dist/helpers/jsonSchema.js +14 -0
  20. package/dist/helpers/jsonSchema.js.map +1 -0
  21. package/dist/helpers/schemas.d.ts +13 -0
  22. package/dist/helpers/schemas.js +18 -0
  23. package/dist/helpers/schemas.js.map +1 -0
  24. package/dist/helpers/wfs.d.ts +27 -0
  25. package/dist/helpers/wfs.js +55 -0
  26. package/dist/helpers/wfs.js.map +1 -0
  27. package/dist/helpers/wfs_internal/compile.d.ts +55 -0
  28. package/dist/helpers/wfs_internal/compile.js +596 -0
  29. package/dist/helpers/wfs_internal/compile.js.map +1 -0
  30. package/dist/helpers/wfs_internal/request.d.ts +47 -0
  31. package/dist/helpers/wfs_internal/request.js +121 -0
  32. package/dist/helpers/wfs_internal/request.js.map +1 -0
  33. package/dist/helpers/wfs_internal/response.d.ts +29 -0
  34. package/dist/helpers/wfs_internal/response.js +59 -0
  35. package/dist/helpers/wfs_internal/response.js.map +1 -0
  36. package/dist/helpers/wfs_internal/schema.d.ts +167 -0
  37. package/dist/helpers/wfs_internal/schema.js +81 -0
  38. package/dist/helpers/wfs_internal/schema.js.map +1 -0
  39. package/dist/index.js +47 -25
  40. package/dist/index.js.map +1 -1
  41. package/dist/tools/AdminexpressTool.d.ts +52 -2
  42. package/dist/tools/AdminexpressTool.js +12 -14
  43. package/dist/tools/AdminexpressTool.js.map +1 -1
  44. package/dist/tools/AltitudeTool.d.ts +2 -2
  45. package/dist/tools/AltitudeTool.js +4 -13
  46. package/dist/tools/AltitudeTool.js.map +1 -1
  47. package/dist/tools/AssietteSupTool.d.ts +55 -3
  48. package/dist/tools/AssietteSupTool.js +13 -15
  49. package/dist/tools/AssietteSupTool.js.map +1 -1
  50. package/dist/tools/CadastreTool.d.ts +52 -2
  51. package/dist/tools/CadastreTool.js +14 -15
  52. package/dist/tools/CadastreTool.js.map +1 -1
  53. package/dist/tools/GeocodeTool.d.ts +2 -2
  54. package/dist/tools/GeocodeTool.js +6 -4
  55. package/dist/tools/GeocodeTool.js.map +1 -1
  56. package/dist/tools/GpfWfsDescribeTypeTool.d.ts +16 -16
  57. package/dist/tools/GpfWfsDescribeTypeTool.js +4 -3
  58. package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
  59. package/dist/tools/GpfWfsGetFeatureByIdTool.d.ts +110 -0
  60. package/dist/tools/GpfWfsGetFeatureByIdTool.js +156 -0
  61. package/dist/tools/GpfWfsGetFeatureByIdTool.js.map +1 -0
  62. package/dist/tools/GpfWfsGetFeaturesTool.d.ts +161 -44
  63. package/dist/tools/GpfWfsGetFeaturesTool.js +139 -114
  64. package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
  65. package/dist/tools/GpfWfsSearchTypesTool.d.ts +8 -2
  66. package/dist/tools/GpfWfsSearchTypesTool.js +12 -9
  67. package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
  68. package/dist/tools/UrbanismeTool.d.ts +53 -3
  69. package/dist/tools/UrbanismeTool.js +10 -15
  70. package/dist/tools/UrbanismeTool.js.map +1 -1
  71. package/package.json +8 -7
  72. package/dist/resources/WfsCqlFilterResource.d.ts +0 -10
  73. package/dist/resources/WfsCqlFilterResource.js +0 -23
  74. package/dist/resources/WfsCqlFilterResource.js.map +0 -1
  75. package/dist/resources/content/wfs-cql-filter.md +0 -215
  76. package/dist/tools/GpfWfsListTypesTool.d.ts +0 -22
  77. package/dist/tools/GpfWfsListTypesTool.js +0 -26
  78. package/dist/tools/GpfWfsListTypesTool.js.map +0 -1
@@ -1,76 +1,43 @@
1
1
  import { MCPTool } from "mcp-framework";
2
- import { z } from "zod";
3
- import { GPF_WFS_URL } from "../gpf/wfs.js";
4
- import { fetchJSON } from "../helpers/http.js";
2
+ import { wfsClient } from "../gpf/wfs.js";
3
+ import { fetchJSONPost } from "../helpers/http.js";
5
4
  import logger from "../logger.js";
6
5
  import { READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS } from "../helpers/toolAnnotations.js";
7
- // This tool intentionally does not expose a single outputSchemaShape.
8
- // - `result_type="results"` can return a large FeatureCollection, and we
9
- // avoid duplicating that payload into structuredContent.
10
- // - Compact modes (`hits`, `url`) are handled explicitly in createSuccessResponse().
11
- const gpfWfsGetFeaturesInputSchema = z.object({
12
- typename: z
13
- .string()
14
- .trim()
15
- .min(1, "le nom du type ne doit pas être vide")
16
- .describe("L'identifiant exact du type WFS à interroger (ex : `BDTOPO_V3:batiment`). Ce paramètre détermine la collection interrogée et doit correspondre à un type valide. Utiliser `gpf_wfs_search_types` pour trouver un `typename` pertinent, puis `gpf_wfs_describe_type` pour inspecter ses propriétés avant la requête."),
17
- property_names: z
18
- .string()
19
- .optional()
20
- .describe("La liste des propriétés à inclure dans chaque objet renvoyé, séparées par des virgules (ex : \"code_insee,nom_officiel,geometrie\"). Ce paramètre limite les champs présents dans la réponse, sans filtrer les objets eux-mêmes. Les noms doivent correspondre exactement aux propriétés du type WFS ; utiliser `gpf_wfs_describe_type` pour les connaître."),
21
- sort_by: z
22
- .string()
23
- .optional()
24
- .describe("Les propriétés à utiliser pour trier les objets renvoyés, avec la syntaxe `field [A|D]` où `A` signifie tri ascendant et `D` tri descendant. Plusieurs critères peuvent être séparés par des virgules (ex : `nom_officiel A, population D`). Les noms doivent correspondre exactement aux propriétés du type WFS ; utiliser `gpf_wfs_describe_type` pour les connaître."),
25
- count: z
26
- .number()
27
- .int()
28
- .min(1)
29
- .max(1000)
30
- .optional()
31
- .describe("Le nombre maximum d'objets à retourner dans la réponse (entre 1 et 1000). Ce paramètre limite les résultats renvoyés, sans modifier le nombre total d'objets correspondant à la requête. Il est surtout utile avec `result_type=\"results\"`."),
32
- cql_filter: z
33
- .string()
34
- .optional()
35
- .describe([
36
- "Un filtre `cql_filter` GeoServer pour restreindre les objets renvoyés par la requête.",
37
- "Il faut utiliser les noms exacts des propriétés du type WFS ; utiliser `gpf_wfs_describe_type` pour les connaître.",
38
- "Attention : en `EPSG:4326`, les coordonnées des géométries doivent être exprimées en `lat lon` (y x), y compris pour les points, lignes et polygones.",
39
- "Exemples :",
40
- "- filtre attributaire : `code_insee = '75056'`",
41
- "- filtre spatial point : `DWITHIN(geom,Point(48.8566 2.3522),100,meters)`",
42
- "- filtre spatial polygone : `INTERSECTS(geom,POLYGON((48.85 2.34,48.86 2.34,48.86 2.36,48.85 2.36,48.85 2.34)))`",
43
- ].join("\r\n")),
44
- result_type: z
45
- .enum(["results", "hits", "url"])
46
- .optional()
47
- .describe([
48
- "Choisit le type de résultat renvoyé par le tool :",
49
- "- `results` : retourne les objets trouvés sous forme de `FeatureCollection` GeoJSON complète (défaut)",
50
- "- `hits` : retourne uniquement le nombre total d'objets correspondant à la requête",
51
- "- `url` : retourne uniquement l'URL WFS construite pour la requête, utile pour inspection, débogage ou réutilisation côté client",
52
- ].join("\r\n"))
53
- });
54
- const gpfWfsGetFeaturesHitsOutputSchema = z.object({
55
- result_type: z.literal("hits").describe("Indique que la réponse contient uniquement un comptage."),
56
- totalFeatures: z.number().describe("Le nombre total d'objets correspondant à la requête."),
57
- });
58
- const gpfWfsGetFeaturesUrlOutputSchema = z.object({
59
- result_type: z.literal("url").describe("Indique que la réponse contient uniquement l'URL de la requête."),
60
- url: z.string().describe("L'URL WFS générée pour la requête."),
61
- });
6
+ import { compileQueryParts, geometryToEwkt, getGeometryProperty, getSpatialFilter } from "../helpers/wfs_internal/compile.js";
7
+ import { buildMainRequest, buildReferenceGeometryRequest } from "../helpers/wfs_internal/request.js";
8
+ import { attachFeatureRefs } from "../helpers/wfs_internal/response.js";
9
+ import { gpfWfsGetFeaturesHitsOutputSchema, gpfWfsGetFeaturesInputSchema, gpfWfsGetFeaturesPublishedInputSchema, gpfWfsGetFeaturesRequestOutputSchema, } from "../helpers/wfs_internal/schema.js";
62
10
  class GpfWfsGetFeaturesTool extends MCPTool {
63
11
  name = "gpf_wfs_get_features";
64
12
  title = "Lecture d’objets WFS";
65
13
  annotations = READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS;
66
14
  description = [
67
- "Récupère les objets d'un type WFS à partir d'un `typename` valide, avec filtres, tri et sélection de propriétés optionnels.",
68
- "Exécute une requête WFS sur un type connu (`typename`) et renvoie soit les objets trouvés, soit leur nombre total, soit l'URL WFS correspondante.",
69
- "Utiliser `gpf_wfs_search_types` puis `gpf_wfs_describe_type` avant ce tool lorsque le type ou ses propriétés ne sont pas connus.",
70
- "Le paramètre `result_type` permet de récupérer soit les données complètes (`results`), soit uniquement le comptage (`hits`), soit l'URL WFS générée (`url`).",
71
- "Les paramètres optionnels permettent de filtrer, trier ou restreindre les champs et le nombre d'objets renvoyés.",
72
- ].join("\r\n");
15
+ "Interroge un type WFS et renvoie des résultats structurés sans demander au modèle d'écrire du CQL ou du WFS.",
16
+ "Utiliser `select` pour choisir les propriétés, `where` pour filtrer, `order_by` pour trier et `spatial_operator` avec ses paramètres dédiés pour le spatial. Avec `result_type=\"request\"`, la géométrie est automatiquement ajoutée aux propriétés sélectionnées pour garantir une requête cartographiable.",
17
+ "Exemple attributaire : `where=[{ property: \"code_insee\", operator: \"eq\", value: \"75056\" }]`.",
18
+ "Exemple bbox : `spatial_operator=\"bbox\"` avec `bbox_west`, `bbox_south`, `bbox_east`, `bbox_north` en `lon/lat`.",
19
+ "Exemple distance : `spatial_operator=\"dwithin_point\"` avec `dwithin_lon`, `dwithin_lat`, `dwithin_distance_m`.",
20
+ "Exemple réutilisation : `spatial_operator=\"intersects_feature\"` avec `intersects_feature_typename` et `intersects_feature_id` issus d'une `feature_ref`.",
21
+ "⚠️ Quand `typename` et `intersects_feature_typename` sont identiques, utiliser `gpf_wfs_get_feature_by_id` pour récupérer exactement l'objet ciblé.",
22
+ "**OBLIGATOIRE : toujours appeler `gpf_wfs_describe_type` avant ce tool, sauf si `gpf_wfs_describe_type` a déjà été appelé pour ce même typename dans la conversation en cours.**",
23
+ "Les noms de propriétés **ne peuvent pas être devinés** : ils sont spécifiques à chaque typename et diffèrent systématiquement des conventions habituelles (ex : pas de nom_officiel, navigabilite sans accent, etc.). Toute tentative sans appel préalable à `gpf_wfs_describe_type` **provoquera une erreur.**"
24
+ ].join("\n");
73
25
  schema = gpfWfsGetFeaturesInputSchema;
26
+ /**
27
+ * Exposes an input schema variant that stays compatible with most MCP integrations.
28
+ *
29
+ * @returns The published input schema exposed through the MCP tool definition.
30
+ */
31
+ get inputSchema() {
32
+ return gpfWfsGetFeaturesPublishedInputSchema;
33
+ }
34
+ /**
35
+ * Formats compact responses (`hits`, `request`) into `structuredContent`.
36
+ * Full result sets are still delegated to the framework default behavior.
37
+ *
38
+ * @param data Raw execution result returned by the tool implementation.
39
+ * @returns An MCP success response, optionally enriched with structured content.
40
+ */
74
41
  createSuccessResponse(data) {
75
42
  if (typeof data === "object" &&
76
43
  data !== null &&
@@ -79,80 +46,138 @@ class GpfWfsGetFeaturesTool extends MCPTool {
79
46
  "totalFeatures" in data &&
80
47
  typeof data.totalFeatures === "number") {
81
48
  return {
82
- content: [
83
- {
84
- type: "text",
85
- text: JSON.stringify(data.totalFeatures),
86
- },
87
- ],
49
+ content: [{ type: "text", text: JSON.stringify(data.totalFeatures) }],
88
50
  structuredContent: gpfWfsGetFeaturesHitsOutputSchema.parse(data),
89
51
  };
90
52
  }
91
53
  if (typeof data === "object" &&
92
54
  data !== null &&
93
55
  "result_type" in data &&
94
- data.result_type === "url" &&
95
- "url" in data &&
96
- typeof data.url === "string") {
56
+ data.result_type === "request") {
97
57
  return {
98
- content: [
99
- {
100
- type: "text",
101
- text: data.url,
102
- },
103
- ],
104
- structuredContent: gpfWfsGetFeaturesUrlOutputSchema.parse(data),
58
+ content: [{ type: "text", text: JSON.stringify(data) }],
59
+ structuredContent: gpfWfsGetFeaturesRequestOutputSchema.parse(data),
105
60
  };
106
61
  }
107
62
  return super.createSuccessResponse(data);
108
63
  }
109
- async execute(input) {
110
- const params = {
111
- service: 'WFS',
112
- request: 'GetFeature',
113
- typeName: input.typename,
114
- outputFormat: 'application/json'
115
- };
116
- // Only add optional parameters if they are defined
117
- if (input.cql_filter) {
118
- params.cql_filter = input.cql_filter;
64
+ /**
65
+ * Loads a WFS feature type description from the embedded catalog.
66
+ *
67
+ * @param typename Exact WFS typename to load from the embedded schema store.
68
+ * @returns The matching feature type description.
69
+ */
70
+ async getFeatureType(typename) {
71
+ return wfsClient.getFeatureType(typename);
72
+ }
73
+ /**
74
+ * Executes a compiled WFS request as POST and returns the JSON FeatureCollection.
75
+ *
76
+ * @param request Compiled request split into query-string parameters and POST body.
77
+ * @returns The parsed JSON response returned by the WFS endpoint.
78
+ */
79
+ async fetchFeatureCollection(request) {
80
+ const url = `${request.url}?${new URLSearchParams(request.query).toString()}`;
81
+ return fetchJSONPost(url, request.body, {
82
+ "Content-Type": "application/x-www-form-urlencoded",
83
+ "Accept": "application/json",
84
+ });
85
+ }
86
+ /**
87
+ * Extracts a result count from a WFS response, preferring `numberMatched`.
88
+ * Explicitly rejects responses that do not provide a usable total.
89
+ *
90
+ * @param featureCollection Parsed WFS response object.
91
+ * @returns The total number of matching features.
92
+ */
93
+ getMatchedFeatureCount(featureCollection) {
94
+ if (typeof featureCollection.numberMatched === "number") {
95
+ return featureCollection.numberMatched;
96
+ }
97
+ if (featureCollection.numberMatched === "unknown") {
98
+ throw new Error("Le service WFS a renvoyé un comptage indéterminé (numberMatched=\"unknown\").");
119
99
  }
120
- if (input.count) {
121
- params.count = String(input.count);
100
+ if (typeof featureCollection.totalFeatures === "number") {
101
+ return featureCollection.totalFeatures;
122
102
  }
123
- if (input.sort_by) {
124
- params.sortBy = input.sort_by;
103
+ throw new Error("Le service WFS n'a pas retourné de comptage exploitable");
104
+ }
105
+ /**
106
+ * Resolves the geometry of a reference feature when `intersects_feature` is used,
107
+ * then converts it to EWKT for CQL compilation.
108
+ *
109
+ * @param input Normalized tool input.
110
+ * @returns The resolved reference geometry, or `undefined` when no reference feature is needed.
111
+ */
112
+ async resolveIntersectsFeatureGeometry(input) {
113
+ const spatialFilter = getSpatialFilter(input);
114
+ if (!spatialFilter || spatialFilter.operator !== "intersects_feature") {
115
+ return undefined;
125
116
  }
126
- if (input.property_names && input.property_names.length > 0) {
127
- params.propertyName = input.property_names;
117
+ const referenceFeatureType = await this.getFeatureType(spatialFilter.typename);
118
+ const referenceGeometryProperty = getGeometryProperty(referenceFeatureType);
119
+ const request = buildReferenceGeometryRequest(spatialFilter.typename, spatialFilter.feature_id, referenceGeometryProperty.name);
120
+ const featureCollection = await this.fetchFeatureCollection(request);
121
+ const referenceFeature = Array.isArray(featureCollection?.features) ? featureCollection.features[0] : undefined;
122
+ if (!referenceFeature) {
123
+ throw new Error(`Le feature de référence '${spatialFilter.feature_id}' est introuvable dans '${spatialFilter.typename}'.`);
128
124
  }
129
- // Si result_type est 'hits', on utilise count=1 pour récupérer juste le totalFeatures
130
- // On fait cela parce que Geoserver ne renvoie pas de json avec resultType=hits
131
- // On est obligé de faire une requete getfeature pour récupérer le totalFeatures...
132
- if (input.result_type === 'hits') {
133
- params.count = "1";
134
- // On n'a pas besoin des propriétés détaillées pour un comptage
135
- delete params.propertyName;
125
+ if (!referenceFeature?.geometry) {
126
+ throw new Error(`Le feature de référence '${spatialFilter.feature_id}' n'a pas de géométrie exploitable.`);
136
127
  }
137
- const url = `${GPF_WFS_URL}?` + new URLSearchParams(params).toString();
138
- logger.info(`[gpf_wfs_get_features] ${url}`);
139
- if (input.result_type === 'url') {
128
+ return {
129
+ typename: spatialFilter.typename,
130
+ feature_id: spatialFilter.feature_id,
131
+ geometry_ewkt: geometryToEwkt(referenceFeature.geometry),
132
+ };
133
+ }
134
+ /**
135
+ * Orchestrates the full tool execution flow:
136
+ * catalog lookup -> compilation -> WFS request -> response post-processing.
137
+ *
138
+ * @param input Normalized tool input.
139
+ * @returns Either a compiled request, a hit count, or a transformed FeatureCollection.
140
+ */
141
+ async execute(input) {
142
+ if (input.spatial_operator === "intersects_feature" &&
143
+ input.intersects_feature_typename !== undefined &&
144
+ input.typename === input.intersects_feature_typename) {
145
+ throw new Error("Le filtre `intersects_feature` sur le même `typename` retourne potentiellement plusieurs objets. " +
146
+ "Utiliser `gpf_wfs_get_feature_by_id` avec `{ typename, feature_id: intersects_feature_id }` pour cibler exactement un objet.");
147
+ }
148
+ const featureType = await this.getFeatureType(input.typename);
149
+ const resolvedGeometryRef = await this.resolveIntersectsFeatureGeometry(input);
150
+ const compiled = compileQueryParts(input, featureType, resolvedGeometryRef);
151
+ const request = buildMainRequest(input, compiled);
152
+ if (input.result_type === "request") {
140
153
  return {
141
- result_type: "url",
142
- url,
154
+ result_type: "request",
155
+ method: request.method,
156
+ url: request.url,
157
+ query: request.query,
158
+ body: request.body,
159
+ get_url: request.get_url ?? null,
143
160
  };
144
161
  }
145
- const featureCollection = await fetchJSON(url);
146
- if (input.result_type === 'hits') {
147
- if (typeof featureCollection?.totalFeatures !== "number") {
148
- throw new Error("Le service WFS n'a pas retourné de comptage exploitable");
162
+ let featureCollection;
163
+ try {
164
+ logger.info(`[gpf_wfs_get_features] POST ${request.url}?${new URLSearchParams(request.query).toString()}`);
165
+ featureCollection = await this.fetchFeatureCollection(request);
166
+ }
167
+ catch (error) {
168
+ const message = error instanceof Error ? error.message : String(error);
169
+ if (message.includes(`Illegal property name: ${compiled.geometryProperty.name}`)) {
170
+ throw new Error(`Le champ géométrique '${compiled.geometryProperty.name}' issu du catalogue embarqué est rejeté par le WFS live pour '${input.typename}'. Le catalogue embarqué est probablement désynchronisé. Détail : ${message}`);
149
171
  }
172
+ throw error;
173
+ }
174
+ if (input.result_type === "hits") {
150
175
  return {
151
176
  result_type: "hits",
152
- totalFeatures: featureCollection.totalFeatures,
177
+ totalFeatures: this.getMatchedFeatureCount(featureCollection),
153
178
  };
154
179
  }
155
- return featureCollection;
180
+ return attachFeatureRefs(featureCollection, input.typename);
156
181
  }
157
182
  }
158
183
  export default GpfWfsGetFeaturesTool;
@@ -1 +1 @@
1
- {"version":3,"file":"GpfWfsGetFeaturesTool.js","sourceRoot":"","sources":["../../src/tools/GpfWfsGetFeaturesTool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GpfWfsGetFeaturesTool.js","sourceRoot":"","sources":["../../src/tools/GpfWfsGetFeaturesTool.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  declare const gpfWfsSearchTypesInputSchema: z.ZodObject<{
4
4
  query: z.ZodString;
5
5
  max_results: z.ZodOptional<z.ZodNumber>;
6
- }, "strip", z.ZodTypeAny, {
6
+ }, "strict", z.ZodTypeAny, {
7
7
  query?: string;
8
8
  max_results?: number;
9
9
  }, {
@@ -26,32 +26,37 @@ declare class GpfWfsSearchTypesTool extends MCPTool<GpfWfsSearchTypesInput> {
26
26
  id: z.ZodString;
27
27
  title: z.ZodString;
28
28
  description: z.ZodString;
29
+ score: z.ZodOptional<z.ZodNumber>;
29
30
  }, "strip", z.ZodTypeAny, {
30
31
  id?: string;
31
32
  title?: string;
32
33
  description?: string;
34
+ score?: number;
33
35
  }, {
34
36
  id?: string;
35
37
  title?: string;
36
38
  description?: string;
39
+ score?: number;
37
40
  }>, "many">;
38
41
  }, "strip", z.ZodTypeAny, {
39
42
  results?: {
40
43
  id?: string;
41
44
  title?: string;
42
45
  description?: string;
46
+ score?: number;
43
47
  }[];
44
48
  }, {
45
49
  results?: {
46
50
  id?: string;
47
51
  title?: string;
48
52
  description?: string;
53
+ score?: number;
49
54
  }[];
50
55
  }>;
51
56
  schema: z.ZodObject<{
52
57
  query: z.ZodString;
53
58
  max_results: z.ZodOptional<z.ZodNumber>;
54
- }, "strip", z.ZodTypeAny, {
59
+ }, "strict", z.ZodTypeAny, {
55
60
  query?: string;
56
61
  max_results?: number;
57
62
  }, {
@@ -60,6 +65,7 @@ declare class GpfWfsSearchTypesTool extends MCPTool<GpfWfsSearchTypesInput> {
60
65
  }>;
61
66
  execute(input: GpfWfsSearchTypesInput): Promise<{
62
67
  results: {
68
+ score?: number;
63
69
  id: string;
64
70
  title: string;
65
71
  description: string;
@@ -15,11 +15,12 @@ const gpfWfsSearchTypesInputSchema = z.object({
15
15
  .max(50)
16
16
  .optional()
17
17
  .describe("Le nombre maximum de résultats à retourner (entre 1 et 50). Défaut : 10."),
18
- });
18
+ }).strict();
19
19
  const gpfWfsSearchTypeResultSchema = z.object({
20
20
  id: z.string().describe("L'identifiant complet du type WFS."),
21
21
  title: z.string().describe("Le titre lisible du type WFS."),
22
22
  description: z.string().describe("La description du type WFS."),
23
+ score: z.number().describe("Le score de pertinence de la recherche.").optional(),
23
24
  });
24
25
  const gpfWfsSearchTypesOutputSchema = z.object({
25
26
  results: z.array(gpfWfsSearchTypeResultSchema).describe("La liste ordonnée des types WFS trouvés."),
@@ -30,20 +31,22 @@ class GpfWfsSearchTypesTool extends MCPTool {
30
31
  annotations = READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS;
31
32
  description = [
32
33
  "Recherche des types WFS de la Géoplateforme (GPF) à partir de mots-clés afin de trouver un identifiant de type (`typename`) valide.",
33
- "Utiliser ce tool avant `gpf_wfs_describe_type` ou `gpf_wfs_get_features` lorsque le nom exact du type n'est pas connu.",
34
- "La recherche est textuelle (mini-search) et retourne une liste ordonnée de candidats avec leur identifiant, leur titre et leur description.",
34
+ "La recherche est textuelle (mini-search) et retourne une liste ordonnée de candidats avec leur identifiant, leur titre, leur description et un score de pertinence éventuel.",
35
35
  "Le paramètre `max_results` permet d'élargir le nombre de candidats retournés (10 par défaut).",
36
- ].join("\r\n");
36
+ "**Important** : Utiliser ce tool avant `gpf_wfs_describe_type` ou `gpf_wfs_get_features` lorsque le nom exact du type n'est pas connu.",
37
+ "**Important** : Privilégier des termes métier en français pour la recherche."
38
+ ].join("\n");
37
39
  outputSchemaShape = gpfWfsSearchTypesOutputSchema;
38
40
  schema = gpfWfsSearchTypesInputSchema;
39
41
  async execute(input) {
40
42
  const maxResults = input.max_results || 10;
41
- const featureTypes = await wfsClient.searchFeatureTypes(input.query, maxResults);
43
+ const featureTypes = await wfsClient.searchFeatureTypesWithScores(input.query, maxResults);
42
44
  return {
43
- results: featureTypes.map((featureType) => ({
44
- id: featureType.id,
45
- title: featureType.title,
46
- description: featureType.description,
45
+ results: featureTypes.map(({ collection, score }) => ({
46
+ id: collection.id,
47
+ title: collection.title,
48
+ description: collection.description,
49
+ ...(score !== undefined ? { score } : {}),
47
50
  })),
48
51
  };
49
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GpfWfsSearchTypesTool.js","sourceRoot":"","sources":["../../src/tools/GpfWfsSearchTypesTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,EAAE,+CAA+C,CAAC;SACvD,QAAQ,CAAC,yBAAyB,CAAC;IACtC,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,0EAA0E,CAAC;CACxF,CAAC,CAAC;AAIH,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC7D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;CAChE,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;CACpG,CAAC,CAAC;AAEH,MAAM,qBAAsB,SAAQ,OAA+B;IACjE,IAAI,GAAG,sBAAsB,CAAC;IAC9B,KAAK,GAAG,wBAAwB,CAAC;IACjC,WAAW,GAAG,qCAAqC,CAAC;IACpD,WAAW,GAAG;QACZ,qIAAqI;QACrI,wHAAwH;QACxH,6IAA6I;QAC7I,+FAA+F;KAChG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACL,iBAAiB,GAAG,6BAA6B,CAAC;IAE5D,MAAM,GAAG,4BAA4B,CAAC;IAEtC,KAAK,CAAC,OAAO,CAAC,KAA6B;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACjF,OAAO;YACL,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBAC1C,EAAE,EAAE,WAAW,CAAC,EAAE;gBAClB,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,WAAW,EAAE,WAAW,CAAC,WAAW;aACrC,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF;AAED,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"GpfWfsSearchTypesTool.js","sourceRoot":"","sources":["../../src/tools/GpfWfsSearchTypesTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,EAAE,+CAA+C,CAAC;SACvD,QAAQ,CAAC,yBAAyB,CAAC;IACtC,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,0EAA0E,CAAC;CACxF,CAAC,CAAC,MAAM,EAAE,CAAC;AAIZ,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC7D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAAC,QAAQ,EAAE;CACjF,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;CACpG,CAAC,CAAC;AAEH,MAAM,qBAAsB,SAAQ,OAA+B;IACjE,IAAI,GAAG,sBAAsB,CAAC;IAC9B,KAAK,GAAG,wBAAwB,CAAC;IACjC,WAAW,GAAG,qCAAqC,CAAC;IACpD,WAAW,GAAG;QACZ,qIAAqI;QACrI,8KAA8K;QAC9K,+FAA+F;QAC/F,wIAAwI;QACxI,8EAA8E;KAC/E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACH,iBAAiB,GAAG,6BAA6B,CAAC;IAE5D,MAAM,GAAG,4BAA4B,CAAC;IAEtC,KAAK,CAAC,OAAO,CAAC,KAA6B;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,4BAA4B,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC3F,OAAO;YACL,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;gBACpD,EAAE,EAAE,UAAU,CAAC,EAAE;gBACjB,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1C,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF;AAED,eAAe,qBAAqB,CAAC"}
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  declare const urbanismeInputSchema: z.ZodObject<{
4
4
  lon: z.ZodNumber;
5
5
  lat: z.ZodNumber;
6
- }, "strip", z.ZodTypeAny, {
6
+ }, "strict", z.ZodTypeAny, {
7
7
  lon?: number;
8
8
  lat?: number;
9
9
  }, {
@@ -26,16 +26,46 @@ declare class UrbanismeTool extends MCPTool<UrbanismeInput> {
26
26
  type: z.ZodString;
27
27
  id: z.ZodString;
28
28
  bbox: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
29
+ feature_ref: z.ZodOptional<z.ZodObject<{
30
+ typename: z.ZodString;
31
+ feature_id: z.ZodString;
32
+ }, "strip", z.ZodTypeAny, {
33
+ typename?: string;
34
+ feature_id?: string;
35
+ }, {
36
+ typename?: string;
37
+ feature_id?: string;
38
+ }>>;
29
39
  distance: z.ZodNumber;
30
40
  }, "strip", z.ZodUnknown, z.objectOutputType<{
31
41
  type: z.ZodString;
32
42
  id: z.ZodString;
33
43
  bbox: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
44
+ feature_ref: z.ZodOptional<z.ZodObject<{
45
+ typename: z.ZodString;
46
+ feature_id: z.ZodString;
47
+ }, "strip", z.ZodTypeAny, {
48
+ typename?: string;
49
+ feature_id?: string;
50
+ }, {
51
+ typename?: string;
52
+ feature_id?: string;
53
+ }>>;
34
54
  distance: z.ZodNumber;
35
55
  }, z.ZodUnknown, "strip">, z.objectInputType<{
36
56
  type: z.ZodString;
37
57
  id: z.ZodString;
38
58
  bbox: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
59
+ feature_ref: z.ZodOptional<z.ZodObject<{
60
+ typename: z.ZodString;
61
+ feature_id: z.ZodString;
62
+ }, "strip", z.ZodTypeAny, {
63
+ typename?: string;
64
+ feature_id?: string;
65
+ }, {
66
+ typename?: string;
67
+ feature_id?: string;
68
+ }>>;
39
69
  distance: z.ZodNumber;
40
70
  }, z.ZodUnknown, "strip">>, "many">;
41
71
  }, "strip", z.ZodTypeAny, {
@@ -43,6 +73,16 @@ declare class UrbanismeTool extends MCPTool<UrbanismeInput> {
43
73
  type: z.ZodString;
44
74
  id: z.ZodString;
45
75
  bbox: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
76
+ feature_ref: z.ZodOptional<z.ZodObject<{
77
+ typename: z.ZodString;
78
+ feature_id: z.ZodString;
79
+ }, "strip", z.ZodTypeAny, {
80
+ typename?: string;
81
+ feature_id?: string;
82
+ }, {
83
+ typename?: string;
84
+ feature_id?: string;
85
+ }>>;
46
86
  distance: z.ZodNumber;
47
87
  }, z.ZodUnknown, "strip">[];
48
88
  }, {
@@ -50,13 +90,23 @@ declare class UrbanismeTool extends MCPTool<UrbanismeInput> {
50
90
  type: z.ZodString;
51
91
  id: z.ZodString;
52
92
  bbox: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
93
+ feature_ref: z.ZodOptional<z.ZodObject<{
94
+ typename: z.ZodString;
95
+ feature_id: z.ZodString;
96
+ }, "strip", z.ZodTypeAny, {
97
+ typename?: string;
98
+ feature_id?: string;
99
+ }, {
100
+ typename?: string;
101
+ feature_id?: string;
102
+ }>>;
53
103
  distance: z.ZodNumber;
54
104
  }, z.ZodUnknown, "strip">[];
55
105
  }>;
56
106
  schema: z.ZodObject<{
57
107
  lon: z.ZodNumber;
58
108
  lat: z.ZodNumber;
59
- }, "strip", z.ZodTypeAny, {
109
+ }, "strict", z.ZodTypeAny, {
60
110
  lon?: number;
61
111
  lat?: number;
62
112
  }, {
@@ -64,7 +114,7 @@ declare class UrbanismeTool extends MCPTool<UrbanismeInput> {
64
114
  lat?: number;
65
115
  }>;
66
116
  execute(input: UrbanismeInput): Promise<{
67
- results: any;
117
+ results: {}[];
68
118
  }>;
69
119
  }
70
120
  export default UrbanismeTool;
@@ -1,34 +1,30 @@
1
1
  import { MCPTool } from "mcp-framework";
2
2
  import { z } from "zod";
3
3
  import { getUrbanisme, URBANISME_SOURCE } from "../gpf/urbanisme.js";
4
- import logger from "../logger.js";
5
4
  import { READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS } from "../helpers/toolAnnotations.js";
5
+ import { featureRefSchema, lonSchema, latSchema } from "../helpers/schemas.js";
6
6
  const urbanismeInputSchema = z.object({
7
- lon: z
8
- .number()
9
- .min(-180)
10
- .max(180)
11
- .describe("La longitude du point."),
12
- lat: z
13
- .number()
14
- .min(-90)
15
- .max(90)
16
- .describe("La latitude du point."),
17
- });
7
+ lon: lonSchema,
8
+ lat: latSchema,
9
+ }).strict();
18
10
  const urbanismeResultSchema = z
19
11
  .object({
20
12
  type: z.string().describe("Le type d'objet d'urbanisme renvoyé."),
21
13
  id: z.string().describe("L'identifiant de l'objet d'urbanisme."),
22
14
  bbox: z.array(z.number()).describe("La boîte englobante de l'objet d'urbanisme.").optional(),
23
- distance: z.number().describe("La distance entre le point demandé et l'objet d'urbanisme retenu."),
15
+ feature_ref: featureRefSchema.describe("Référence WFS réutilisable, notamment avec `gpf_wfs_get_features` et `spatial_operator = \"intersects_feature\"`.").optional(),
16
+ distance: z.number().describe("La distance en mètres entre le point demandé et l'objet d'urbanisme retenu."),
24
17
  })
25
18
  .catchall(z.unknown());
26
19
  const urbanismeOutputSchema = z.object({
27
20
  results: z.array(urbanismeResultSchema).describe("La liste des objets d'urbanisme pertinents pour le point demandé."),
28
21
  });
29
22
  const URBANISME_TOOL_DESCRIPTION = [
30
- `Renvoie, pour un point donné par sa longitude et sa latitude, la liste des objets d'urbanisme pertinents du Géoportail de l'Urbanisme (document, zones, prescriptions, informations, etc.), avec leurs propriétés associées. (source : ${URBANISME_SOURCE}).`,
23
+ `Renvoie, pour un point donné par sa \`longitude\` et sa \`latitude\`, la liste des objets d'urbanisme pertinents du Géoportail de l'Urbanisme (document, zones, prescriptions, informations, etc.), avec leurs propriétés associées. (source : ${URBANISME_SOURCE}).`,
31
24
  "Les résultats peuvent notamment inclure le document d'urbanisme applicable ainsi que des éléments réglementaires associés à proximité du point.",
25
+ "Quand un objet correspond à une couche WFS réutilisable, il expose aussi un `feature_ref` compatible avec `gpf_wfs_get_features` et `spatial_operator=\"intersects_feature\"`.",
26
+ "Le zonage PLU (zone U, AU, A, N...) est inclus dans les zones retournées et constitue souvent l'information principale recherchée.",
27
+ "Pour récupérer exactement l'objet correspondant au `feature_ref`, utiliser `gpf_wfs_get_feature_by_id`.",
32
28
  "Modèles d'URL Géoportail de l'Urbanisme :",
33
29
  "- fiche document: https://www.geoportail-urbanisme.gouv.fr/document/by-id/{gpu_doc_id}",
34
30
  "- carte: https://www.geoportail-urbanisme.gouv.fr/map/?documentId={gpu_doc_id}",
@@ -42,7 +38,6 @@ class UrbanismeTool extends MCPTool {
42
38
  outputSchemaShape = urbanismeOutputSchema;
43
39
  schema = urbanismeInputSchema;
44
40
  async execute(input) {
45
- logger.info(`urbanisme(${input.lon},${input.lat})...`);
46
41
  return {
47
42
  results: await getUrbanisme(input.lon, input.lat),
48
43
  };
@@ -1 +1 @@
1
- {"version":3,"file":"UrbanismeTool.js","sourceRoot":"","sources":["../../src/tools/UrbanismeTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AAEtF,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,GAAG,CAAC;SACT,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CAAC,wBAAwB,CAAC;IACrC,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,CAAC,uBAAuB,CAAC;CACrC,CAAC,CAAC;AAIH,MAAM,qBAAqB,GAAG,CAAC;KAC5B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACjE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IAChE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAAC,QAAQ,EAAE;IAC5F,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;CACnG,CAAC;KACD,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEzB,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,mEAAmE,CAAC;CACtH,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG;IACjC,0OAA0O,gBAAgB,IAAI;IAC9P,iJAAiJ;IACjJ,2CAA2C;IAC3C,wFAAwF;IACxF,gFAAgF;IAChF,8FAA8F;CAC/F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAGb,MAAM,aAAc,SAAQ,OAAuB;IACjD,IAAI,GAAG,WAAW,CAAC;IACnB,KAAK,GAAG,0BAA0B,CAAC;IACnC,WAAW,GAAG,qCAAqC,CAAC;IACpD,WAAW,GAAG,0BAA0B,CAAC;IAC/B,iBAAiB,GAAG,qBAAqB,CAAC;IAEpD,MAAM,GAAG,oBAAoB,CAAC;IAE9B,KAAK,CAAC,OAAO,CAAC,KAAqB;QACjC,MAAM,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;QACvD,OAAO;YACL,OAAO,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;SAClD,CAAC;IACJ,CAAC;CACF;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"UrbanismeTool.js","sourceRoot":"","sources":["../../src/tools/UrbanismeTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE/E,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;CACf,CAAC,CAAC,MAAM,EAAE,CAAC;AAIZ,MAAM,qBAAqB,GAAG,CAAC;KAC5B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACjE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IAChE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAAC,QAAQ,EAAE;IAC5F,WAAW,EAAE,gBAAgB,CAAC,QAAQ,CAAC,mHAAmH,CAAC,CAAC,QAAQ,EAAE;IACtK,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;CAC7G,CAAC;KACD,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEzB,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,mEAAmE,CAAC;CACtH,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG;IACjC,kPAAkP,gBAAgB,IAAI;IACtQ,iJAAiJ;IACjJ,gLAAgL;IAChL,oIAAoI;IACpI,yGAAyG;IACzG,2CAA2C;IAC3C,wFAAwF;IACxF,gFAAgF;IAChF,8FAA8F;CAC/F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAGb,MAAM,aAAc,SAAQ,OAAuB;IACjD,IAAI,GAAG,WAAW,CAAC;IACnB,KAAK,GAAG,0BAA0B,CAAC;IACnC,WAAW,GAAG,qCAAqC,CAAC;IACpD,WAAW,GAAG,0BAA0B,CAAC;IAC/B,iBAAiB,GAAG,qBAAqB,CAAC;IAEpD,MAAM,GAAG,oBAAoB,CAAC;IAE9B,KAAK,CAAC,OAAO,CAAC,KAAqB;QACjC,OAAO;YACL,OAAO,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;SAClD,CAAC;IACJ,CAAC;CACF;AAED,eAAe,aAAa,CAAC"}