@honua/mcp-server 0.0.10-alpha.0 → 0.1.0-beta.0

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 (176) hide show
  1. package/README.md +259 -15
  2. package/certification/geospatial-mcp-schemas/PROVENANCE.md +41 -0
  3. package/certification/geospatial-mcp-schemas/README.md +90 -0
  4. package/certification/geospatial-mcp-schemas/common/geoprocessing-error.schema.json +45 -0
  5. package/certification/geospatial-mcp-schemas/conformance/manifest.schema.json +79 -0
  6. package/certification/geospatial-mcp-schemas/index.json +390 -0
  7. package/certification/geospatial-mcp-schemas/resources/app-package.schema.json +20 -0
  8. package/certification/geospatial-mcp-schemas/resources/app-template.schema.json +15 -0
  9. package/certification/geospatial-mcp-schemas/resources/artifact.schema.json +69 -0
  10. package/certification/geospatial-mcp-schemas/resources/deployment.schema.json +27 -0
  11. package/certification/geospatial-mcp-schemas/resources/map-package.schema.json +21 -0
  12. package/certification/geospatial-mcp-schemas/resources/map-template.schema.json +15 -0
  13. package/certification/geospatial-mcp-schemas/resources/provenance.schema.json +50 -0
  14. package/certification/geospatial-mcp-schemas/resources/published-service.schema.json +21 -0
  15. package/certification/geospatial-mcp-schemas/resources/result-package.schema.json +64 -0
  16. package/certification/geospatial-mcp-schemas/resources/style.schema.json +12 -0
  17. package/certification/geospatial-mcp-schemas/resources/theme.schema.json +12 -0
  18. package/certification/geospatial-mcp-schemas/resources/workspace.schema.json +63 -0
  19. package/certification/geospatial-mcp-schemas/tools/apply_style_preset.schema.json +27 -0
  20. package/certification/geospatial-mcp-schemas/tools/buffer_features.schema.json +60 -0
  21. package/certification/geospatial-mcp-schemas/tools/cancel_job.schema.json +15 -0
  22. package/certification/geospatial-mcp-schemas/tools/clarify_intent.schema.json +69 -0
  23. package/certification/geospatial-mcp-schemas/tools/compose_mixed_protocol_map.schema.json +21 -0
  24. package/certification/geospatial-mcp-schemas/tools/create_app_package.schema.json +33 -0
  25. package/certification/geospatial-mcp-schemas/tools/create_map_package.schema.json +41 -0
  26. package/certification/geospatial-mcp-schemas/tools/edit_features.schema.json +74 -0
  27. package/certification/geospatial-mcp-schemas/tools/execute_plan.schema.json +64 -0
  28. package/certification/geospatial-mcp-schemas/tools/export_dataset.schema.json +60 -0
  29. package/certification/geospatial-mcp-schemas/tools/geocode_address.schema.json +36 -0
  30. package/certification/geospatial-mcp-schemas/tools/geocode_addresses.schema.json +34 -0
  31. package/certification/geospatial-mcp-schemas/tools/get_style.schema.json +40 -0
  32. package/certification/geospatial-mcp-schemas/tools/ground_candidates.schema.json +66 -0
  33. package/certification/geospatial-mcp-schemas/tools/ingest_dataset.schema.json +45 -0
  34. package/certification/geospatial-mcp-schemas/tools/join_features.schema.json +73 -0
  35. package/certification/geospatial-mcp-schemas/tools/list_capabilities.schema.json +21 -0
  36. package/certification/geospatial-mcp-schemas/tools/list_layers.schema.json +14 -0
  37. package/certification/geospatial-mcp-schemas/tools/overlay_features.schema.json +53 -0
  38. package/certification/geospatial-mcp-schemas/tools/plan_analysis.schema.json +19 -0
  39. package/certification/geospatial-mcp-schemas/tools/preview_app_package.schema.json +15 -0
  40. package/certification/geospatial-mcp-schemas/tools/preview_map_package.schema.json +17 -0
  41. package/certification/geospatial-mcp-schemas/tools/preview_package.schema.json +40 -0
  42. package/certification/geospatial-mcp-schemas/tools/propose_operation.schema.json +28 -0
  43. package/certification/geospatial-mcp-schemas/tools/publish_result.schema.json +29 -0
  44. package/certification/geospatial-mcp-schemas/tools/publish_service.schema.json +59 -0
  45. package/certification/geospatial-mcp-schemas/tools/query_features.schema.json +74 -0
  46. package/certification/geospatial-mcp-schemas/tools/refine_map_package.schema.json +22 -0
  47. package/certification/geospatial-mcp-schemas/tools/render_map.schema.json +60 -0
  48. package/certification/geospatial-mcp-schemas/tools/reproject_features.schema.json +49 -0
  49. package/certification/geospatial-mcp-schemas/tools/resolve_entity.schema.json +30 -0
  50. package/certification/geospatial-mcp-schemas/tools/solve_route.schema.json +39 -0
  51. package/certification/geospatial-mcp-schemas/tools/summarize_statistics.schema.json +71 -0
  52. package/certification/geospatial-mcp-schemas/tools/validate_package.schema.json +35 -0
  53. package/certification/geospatial-mcp-schemas/tools/validate_plan.schema.json +61 -0
  54. package/dist/src/capability.d.ts +48 -0
  55. package/dist/src/capability.d.ts.map +1 -0
  56. package/dist/src/capability.js +44 -0
  57. package/dist/src/certification/census-data.d.ts +33 -0
  58. package/dist/src/certification/census-data.d.ts.map +1 -0
  59. package/dist/src/certification/census-data.js +506 -0
  60. package/dist/src/certification/census-fixture-client.d.ts +7 -0
  61. package/dist/src/certification/census-fixture-client.d.ts.map +1 -0
  62. package/dist/src/certification/census-fixture-client.js +226 -0
  63. package/dist/src/certification/certifier.d.ts +125 -0
  64. package/dist/src/certification/certifier.d.ts.map +1 -0
  65. package/dist/src/certification/certifier.js +455 -0
  66. package/dist/src/certification/cli.d.ts +3 -0
  67. package/dist/src/certification/cli.d.ts.map +1 -0
  68. package/dist/src/certification/cli.js +63 -0
  69. package/dist/src/certification/contracts.d.ts +103 -0
  70. package/dist/src/certification/contracts.d.ts.map +1 -0
  71. package/dist/src/certification/contracts.js +245 -0
  72. package/dist/src/certification/fixture-client.d.ts +4 -0
  73. package/dist/src/certification/fixture-client.d.ts.map +1 -0
  74. package/dist/src/certification/fixture-client.js +113 -0
  75. package/dist/src/certification/fixtures.d.ts +45 -0
  76. package/dist/src/certification/fixtures.d.ts.map +1 -0
  77. package/dist/src/certification/fixtures.js +92 -0
  78. package/dist/src/certification/json-schema.d.ts +71 -0
  79. package/dist/src/certification/json-schema.d.ts.map +1 -0
  80. package/dist/src/certification/json-schema.js +172 -0
  81. package/dist/src/certification/lifecycle.d.ts +14 -0
  82. package/dist/src/certification/lifecycle.d.ts.map +1 -0
  83. package/dist/src/certification/lifecycle.js +326 -0
  84. package/dist/src/certification/mock-upstream.d.ts +29 -0
  85. package/dist/src/certification/mock-upstream.d.ts.map +1 -0
  86. package/dist/src/certification/mock-upstream.js +96 -0
  87. package/dist/src/certification/operator-catalog.d.ts +90 -0
  88. package/dist/src/certification/operator-catalog.d.ts.map +1 -0
  89. package/dist/src/certification/operator-catalog.js +650 -0
  90. package/dist/src/certification/report.d.ts +4 -0
  91. package/dist/src/certification/report.d.ts.map +1 -0
  92. package/dist/src/certification/report.js +103 -0
  93. package/dist/src/certification/run.d.ts +28 -0
  94. package/dist/src/certification/run.d.ts.map +1 -0
  95. package/dist/src/certification/run.js +32 -0
  96. package/dist/src/certification/schema-index.d.ts +94 -0
  97. package/dist/src/certification/schema-index.d.ts.map +1 -0
  98. package/dist/src/certification/schema-index.js +109 -0
  99. package/dist/src/certification/target.d.ts +48 -0
  100. package/dist/src/certification/target.d.ts.map +1 -0
  101. package/dist/src/certification/target.js +219 -0
  102. package/dist/src/eval/cli.d.ts +3 -0
  103. package/dist/src/eval/cli.d.ts.map +1 -0
  104. package/dist/src/eval/cli.js +118 -0
  105. package/dist/src/eval/corpus.d.ts +34 -0
  106. package/dist/src/eval/corpus.d.ts.map +1 -0
  107. package/dist/src/eval/corpus.js +150 -0
  108. package/dist/src/eval/drivers/anthropic.d.ts +14 -0
  109. package/dist/src/eval/drivers/anthropic.d.ts.map +1 -0
  110. package/dist/src/eval/drivers/anthropic.js +120 -0
  111. package/dist/src/eval/drivers/bedrock.d.ts +54 -0
  112. package/dist/src/eval/drivers/bedrock.d.ts.map +1 -0
  113. package/dist/src/eval/drivers/bedrock.js +178 -0
  114. package/dist/src/eval/drivers/deterministic.d.ts +17 -0
  115. package/dist/src/eval/drivers/deterministic.d.ts.map +1 -0
  116. package/dist/src/eval/drivers/deterministic.js +64 -0
  117. package/dist/src/eval/drivers/index.d.ts +34 -0
  118. package/dist/src/eval/drivers/index.d.ts.map +1 -0
  119. package/dist/src/eval/drivers/index.js +74 -0
  120. package/dist/src/eval/drivers/openai.d.ts +14 -0
  121. package/dist/src/eval/drivers/openai.d.ts.map +1 -0
  122. package/dist/src/eval/drivers/openai.js +136 -0
  123. package/dist/src/eval/grade.d.ts +14 -0
  124. package/dist/src/eval/grade.d.ts.map +1 -0
  125. package/dist/src/eval/grade.js +75 -0
  126. package/dist/src/eval/northstar-corpus.d.ts +3 -0
  127. package/dist/src/eval/northstar-corpus.d.ts.map +1 -0
  128. package/dist/src/eval/northstar-corpus.js +194 -0
  129. package/dist/src/eval/operator-corpus.d.ts +3 -0
  130. package/dist/src/eval/operator-corpus.d.ts.map +1 -0
  131. package/dist/src/eval/operator-corpus.js +193 -0
  132. package/dist/src/eval/report.d.ts +109 -0
  133. package/dist/src/eval/report.d.ts.map +1 -0
  134. package/dist/src/eval/report.js +133 -0
  135. package/dist/src/eval/runner.d.ts +28 -0
  136. package/dist/src/eval/runner.d.ts.map +1 -0
  137. package/dist/src/eval/runner.js +130 -0
  138. package/dist/src/eval/standalone-corpus.d.ts +3 -0
  139. package/dist/src/eval/standalone-corpus.d.ts.map +1 -0
  140. package/dist/src/eval/standalone-corpus.js +699 -0
  141. package/dist/src/eval/types.d.ts +118 -0
  142. package/dist/src/eval/types.d.ts.map +1 -0
  143. package/dist/src/eval/types.js +10 -0
  144. package/dist/src/helpers.d.ts +11 -0
  145. package/dist/src/helpers.d.ts.map +1 -1
  146. package/dist/src/helpers.js +22 -0
  147. package/dist/src/index.d.ts +31 -0
  148. package/dist/src/index.d.ts.map +1 -1
  149. package/dist/src/index.js +50 -4
  150. package/dist/src/provenance.d.ts +44 -0
  151. package/dist/src/provenance.d.ts.map +1 -0
  152. package/dist/src/provenance.js +37 -0
  153. package/dist/src/proxy.d.ts +46 -0
  154. package/dist/src/proxy.d.ts.map +1 -0
  155. package/dist/src/proxy.js +124 -0
  156. package/dist/src/resources/styles.d.ts +29 -0
  157. package/dist/src/resources/styles.d.ts.map +1 -0
  158. package/dist/src/resources/styles.js +76 -0
  159. package/dist/src/styles.d.ts +112 -0
  160. package/dist/src/styles.d.ts.map +1 -0
  161. package/dist/src/styles.js +144 -0
  162. package/dist/src/tools/apply-style-preset.d.ts +27 -0
  163. package/dist/src/tools/apply-style-preset.d.ts.map +1 -0
  164. package/dist/src/tools/apply-style-preset.js +41 -0
  165. package/dist/src/tools/count-features.d.ts.map +1 -1
  166. package/dist/src/tools/count-features.js +5 -4
  167. package/dist/src/tools/get-extent.d.ts.map +1 -1
  168. package/dist/src/tools/get-extent.js +6 -4
  169. package/dist/src/tools/get-style.d.ts +24 -0
  170. package/dist/src/tools/get-style.d.ts.map +1 -0
  171. package/dist/src/tools/get-style.js +39 -0
  172. package/dist/src/tools/list-services.d.ts.map +1 -1
  173. package/dist/src/tools/list-services.js +16 -1
  174. package/dist/src/tools/query-features.d.ts.map +1 -1
  175. package/dist/src/tools/query-features.js +4 -1
  176. package/package.json +28 -4
@@ -0,0 +1,76 @@
1
+ import { CapabilityUnavailableError, capabilityUnavailablePayload } from "../capability.js";
2
+ import { STYLE_SURFACE, listStyles, resolveStyleRef } from "../styles.js";
3
+ const STYLE_GUIDANCE = "This target is a plain FeatureServer/OGC endpoint with no OGC API - Styles surface. " +
4
+ "Build a MapLibre style client-side, or point honua-mcp at a Honua deployment for managed styles.";
5
+ /** URI for the styles catalog resource (`honua://styles`). */
6
+ export const uri = "honua://styles";
7
+ /** URI template for a single style resource (`honua://styles/{styleId}`). */
8
+ export const uriTemplate = "honua://styles/{styleId}";
9
+ /**
10
+ * Read the styles catalog: the list of styles available on the server, each
11
+ * with its stable styleId, title, and canonical URI (`honua://styles/{id}`).
12
+ */
13
+ export async function readCatalog(client) {
14
+ let list;
15
+ try {
16
+ list = await listStyles(client);
17
+ }
18
+ catch (err) {
19
+ if (err instanceof CapabilityUnavailableError) {
20
+ return unavailableContents(uri, err.reason);
21
+ }
22
+ throw err;
23
+ }
24
+ const styles = list.styles.map((entry) => ({
25
+ styleId: entry.id,
26
+ title: entry.title ?? entry.id,
27
+ uri: `honua://styles/${encodeURIComponent(entry.id)}`,
28
+ }));
29
+ return {
30
+ contents: [
31
+ {
32
+ uri,
33
+ mimeType: "application/json",
34
+ text: JSON.stringify({ styles, default: list.default ?? null }, null, 2),
35
+ },
36
+ ],
37
+ };
38
+ }
39
+ /** Structured "not available on this target" resource body (platform-free mode). */
40
+ function unavailableContents(resourceUri, reason) {
41
+ return {
42
+ contents: [
43
+ {
44
+ uri: resourceUri,
45
+ mimeType: "application/json",
46
+ text: JSON.stringify(capabilityUnavailablePayload(STYLE_SURFACE, reason, STYLE_GUIDANCE), null, 2),
47
+ },
48
+ ],
49
+ };
50
+ }
51
+ /**
52
+ * Read a single style as a `StyleRef` projection (style_id / title /
53
+ * description / style_version / encodings / legend_url), resolved against the
54
+ * server's `/ogc/styles/{styleId}` surface.
55
+ */
56
+ export async function read(client, styleId) {
57
+ let styleRef;
58
+ try {
59
+ styleRef = await resolveStyleRef(client, styleId);
60
+ }
61
+ catch (err) {
62
+ if (err instanceof CapabilityUnavailableError) {
63
+ return unavailableContents(`honua://styles/${encodeURIComponent(styleId)}`, err.reason);
64
+ }
65
+ throw err;
66
+ }
67
+ return {
68
+ contents: [
69
+ {
70
+ uri: `honua://styles/${encodeURIComponent(styleId)}`,
71
+ mimeType: "application/json",
72
+ text: JSON.stringify(styleRef, null, 2),
73
+ },
74
+ ],
75
+ };
76
+ }
@@ -0,0 +1,112 @@
1
+ import type { HonuaClient } from "@honua/sdk-js";
2
+ /** Human label for the Honua-only styling surface (capability degradation). */
3
+ export declare const STYLE_SURFACE = "OGC API - Styles";
4
+ /**
5
+ * Thin read-only client over the server's OGC API – Styles surface
6
+ * (honua-server, ADR-0048):
7
+ *
8
+ * GET /ogc/styles -> styles list ({ styles: [{ id, title, links }], default? })
9
+ * GET /ogc/styles/{styleId}/metadata -> style metadata ({ id, title, description, keywords, license, version, links })
10
+ * GET /ogc/styles/{styleId} -> stylesheet body (MapLibre/Mapbox JSON by default; SLD via Accept)
11
+ *
12
+ * These helpers project the server responses into the geospatial-grpc
13
+ * `StyleRef` / `StyleEncoding` shape (style_id / title / encodings) so the MCP
14
+ * resource + `get_style` tool surface a single canonical style object.
15
+ *
16
+ * The MCP package only consumes the public {@link HonuaClient.pipelineFetch}
17
+ * request pipeline (auth / retry / timeout / interceptors) rather than a
18
+ * private route, matching the other `/ogc/*` consumers in the SDK.
19
+ *
20
+ * @module
21
+ */
22
+ /** Default path prefix for the server's OGC API – Styles surface. */
23
+ export declare const OGC_STYLES_PATH = "/ogc/styles";
24
+ /** MapLibre / Mapbox style media type (server default stylesheet encoding). */
25
+ export declare const MAPLIBRE_STYLE_MEDIA_TYPE = "application/vnd.mapbox.style+json";
26
+ /** SLD 1.0 stylesheet media type. */
27
+ export declare const SLD_10_MEDIA_TYPE = "application/vnd.ogc.sld+xml;version=1.0";
28
+ /** SLD 1.1 stylesheet media type. */
29
+ export declare const SLD_11_MEDIA_TYPE = "application/vnd.ogc.sld+xml;version=1.1";
30
+ /**
31
+ * Stylesheet encodings the MCP surface understands, keyed by the canonical
32
+ * geospatial-grpc `StyleEncoding.encoding` identifier. The server
33
+ * content-negotiates these via the `Accept` header.
34
+ */
35
+ export declare const STYLE_ENCODINGS: {
36
+ readonly "mapbox-style": "application/vnd.mapbox.style+json";
37
+ readonly "sld-1.0.0": "application/vnd.ogc.sld+xml;version=1.0";
38
+ readonly "sld-1.1.0": "application/vnd.ogc.sld+xml;version=1.1";
39
+ };
40
+ /** A geospatial-grpc `StyleEncoding`-aligned encoding identifier. */
41
+ export type StyleEncodingId = keyof typeof STYLE_ENCODINGS;
42
+ /** Hypermedia link entry on an OGC styles document. */
43
+ export interface OgcStyleLink {
44
+ href: string;
45
+ rel?: string;
46
+ type?: string;
47
+ title?: string;
48
+ }
49
+ /** One entry in the `GET /ogc/styles` styles list. */
50
+ export interface OgcStyleListEntry {
51
+ id: string;
52
+ title?: string;
53
+ links?: OgcStyleLink[];
54
+ }
55
+ /** Response body of `GET /ogc/styles`. */
56
+ export interface OgcStyleList {
57
+ styles: OgcStyleListEntry[];
58
+ default?: string;
59
+ links?: OgcStyleLink[];
60
+ }
61
+ /** Response body of `GET /ogc/styles/{styleId}/metadata`. */
62
+ export interface OgcStyleMetadata {
63
+ id: string;
64
+ title?: string;
65
+ description?: string;
66
+ keywords?: string[];
67
+ license?: string;
68
+ version?: string;
69
+ links?: OgcStyleLink[];
70
+ }
71
+ /**
72
+ * A single encoded representation of a style, aligned with the geospatial-grpc
73
+ * `StyleEncoding` message. The MCP surface carries the inline body for the
74
+ * MapLibre encoding (the default the server serves) and exposes the alternate
75
+ * SLD encodings by reference (`storageRef` = the stylesheet URL).
76
+ */
77
+ export interface StyleEncoding {
78
+ encoding: StyleEncodingId | string;
79
+ contentType?: string;
80
+ inlineBody?: unknown;
81
+ storageRef?: string;
82
+ }
83
+ /**
84
+ * Canonical style projection aligned with the geospatial-grpc `StyleRef`
85
+ * message (`style_id` / `title` / `description` / `style_version` /
86
+ * `encodings` / `legend_url`).
87
+ */
88
+ export interface StyleRef {
89
+ styleId: string;
90
+ title: string;
91
+ description: string | null;
92
+ styleVersion: number | null;
93
+ legendUrl: string | null;
94
+ encodings: StyleEncoding[];
95
+ }
96
+ /** List available styles via `GET /ogc/styles`. */
97
+ export declare function listStyles(client: HonuaClient): Promise<OgcStyleList>;
98
+ /** Fetch style metadata via `GET /ogc/styles/{styleId}/metadata`. */
99
+ export declare function getStyleMetadata(client: HonuaClient, styleId: string): Promise<OgcStyleMetadata>;
100
+ /**
101
+ * Fetch the MapLibre/Mapbox stylesheet body via `GET /ogc/styles/{styleId}`
102
+ * (content-negotiated to {@link MAPLIBRE_STYLE_MEDIA_TYPE}).
103
+ */
104
+ export declare function getMapLibreStylesheet(client: HonuaClient, styleId: string): Promise<unknown>;
105
+ /**
106
+ * Resolve a single style into a `StyleRef` projection: fetch metadata and the
107
+ * canonical MapLibre stylesheet, and advertise the alternate SLD encodings by
108
+ * reference. The stylesheet base URL (`{baseUrl}/ogc/styles/{styleId}`) backs
109
+ * the `storageRef` for the by-reference encodings.
110
+ */
111
+ export declare function resolveStyleRef(client: HonuaClient, styleId: string): Promise<StyleRef>;
112
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjD,+EAA+E;AAC/E,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AAEH,qEAAqE;AACrE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,sCAAsC,CAAC;AAE7E,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,4CAA4C,CAAC;AAE3E,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,4CAA4C,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,eAAe,CAAC;AAE3D,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,eAAe,GAAG,MAAM,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAqCD,mDAAmD;AACnD,wBAAsB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAuB3E;AAED,qEAAqE;AACrE,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGtG;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAElG;AASD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4B7F"}
@@ -0,0 +1,144 @@
1
+ import { CapabilityUnavailableError } from "./capability.js";
2
+ /** Human label for the Honua-only styling surface (capability degradation). */
3
+ export const STYLE_SURFACE = "OGC API - Styles";
4
+ /**
5
+ * Thin read-only client over the server's OGC API – Styles surface
6
+ * (honua-server, ADR-0048):
7
+ *
8
+ * GET /ogc/styles -> styles list ({ styles: [{ id, title, links }], default? })
9
+ * GET /ogc/styles/{styleId}/metadata -> style metadata ({ id, title, description, keywords, license, version, links })
10
+ * GET /ogc/styles/{styleId} -> stylesheet body (MapLibre/Mapbox JSON by default; SLD via Accept)
11
+ *
12
+ * These helpers project the server responses into the geospatial-grpc
13
+ * `StyleRef` / `StyleEncoding` shape (style_id / title / encodings) so the MCP
14
+ * resource + `get_style` tool surface a single canonical style object.
15
+ *
16
+ * The MCP package only consumes the public {@link HonuaClient.pipelineFetch}
17
+ * request pipeline (auth / retry / timeout / interceptors) rather than a
18
+ * private route, matching the other `/ogc/*` consumers in the SDK.
19
+ *
20
+ * @module
21
+ */
22
+ /** Default path prefix for the server's OGC API – Styles surface. */
23
+ export const OGC_STYLES_PATH = "/ogc/styles";
24
+ /** MapLibre / Mapbox style media type (server default stylesheet encoding). */
25
+ export const MAPLIBRE_STYLE_MEDIA_TYPE = "application/vnd.mapbox.style+json";
26
+ /** SLD 1.0 stylesheet media type. */
27
+ export const SLD_10_MEDIA_TYPE = "application/vnd.ogc.sld+xml;version=1.0";
28
+ /** SLD 1.1 stylesheet media type. */
29
+ export const SLD_11_MEDIA_TYPE = "application/vnd.ogc.sld+xml;version=1.1";
30
+ /**
31
+ * Stylesheet encodings the MCP surface understands, keyed by the canonical
32
+ * geospatial-grpc `StyleEncoding.encoding` identifier. The server
33
+ * content-negotiates these via the `Accept` header.
34
+ */
35
+ export const STYLE_ENCODINGS = {
36
+ "mapbox-style": MAPLIBRE_STYLE_MEDIA_TYPE,
37
+ "sld-1.0.0": SLD_10_MEDIA_TYPE,
38
+ "sld-1.1.0": SLD_11_MEDIA_TYPE,
39
+ };
40
+ function isRecord(value) {
41
+ return typeof value === "object" && value !== null && !Array.isArray(value);
42
+ }
43
+ async function getJson(client, path, accept) {
44
+ let response;
45
+ try {
46
+ response = await client.pipelineFetch("GET", path, { headers: { Accept: accept } });
47
+ }
48
+ catch (err) {
49
+ // A plain FeatureServer / OGC-Features endpoint has no styling surface, so
50
+ // `GET /ogc/styles*` fails (404, network error, or the SDK's non-2xx throw).
51
+ // Degrade gracefully rather than surfacing a raw crash.
52
+ throw new CapabilityUnavailableError(STYLE_SURFACE, `request to ${path} failed: ${errorMessage(err)}`);
53
+ }
54
+ if (!response.ok) {
55
+ throw new CapabilityUnavailableError(STYLE_SURFACE, `${path} returned HTTP ${response.status}`);
56
+ }
57
+ try {
58
+ return (await response.json());
59
+ }
60
+ catch {
61
+ throw new CapabilityUnavailableError(STYLE_SURFACE, `${path} did not return JSON (target has no OGC API - Styles surface)`);
62
+ }
63
+ }
64
+ function errorMessage(err) {
65
+ return err instanceof Error ? err.message : String(err);
66
+ }
67
+ function stylePath(styleId) {
68
+ return `${OGC_STYLES_PATH}/${encodeURIComponent(styleId)}`;
69
+ }
70
+ /** List available styles via `GET /ogc/styles`. */
71
+ export async function listStyles(client) {
72
+ const body = await getJson(client, OGC_STYLES_PATH, "application/json");
73
+ if (!isRecord(body) || !Array.isArray(body.styles)) {
74
+ // A well-formed styles document always carries a `styles` array (possibly
75
+ // empty). Anything else means the target is not an OGC API - Styles surface;
76
+ // report that honestly instead of returning a misleading empty catalog.
77
+ throw new CapabilityUnavailableError(STYLE_SURFACE, `${OGC_STYLES_PATH} response is not a styles document`);
78
+ }
79
+ const styles = [];
80
+ for (const entry of body.styles) {
81
+ if (isRecord(entry) && typeof entry.id === "string") {
82
+ styles.push({
83
+ id: entry.id,
84
+ ...(typeof entry.title === "string" ? { title: entry.title } : {}),
85
+ ...(Array.isArray(entry.links) ? { links: entry.links } : {}),
86
+ });
87
+ }
88
+ }
89
+ return {
90
+ styles,
91
+ ...(typeof body.default === "string" ? { default: body.default } : {}),
92
+ ...(Array.isArray(body.links) ? { links: body.links } : {}),
93
+ };
94
+ }
95
+ /** Fetch style metadata via `GET /ogc/styles/{styleId}/metadata`. */
96
+ export async function getStyleMetadata(client, styleId) {
97
+ const body = await getJson(client, `${stylePath(styleId)}/metadata`, "application/json");
98
+ return body;
99
+ }
100
+ /**
101
+ * Fetch the MapLibre/Mapbox stylesheet body via `GET /ogc/styles/{styleId}`
102
+ * (content-negotiated to {@link MAPLIBRE_STYLE_MEDIA_TYPE}).
103
+ */
104
+ export async function getMapLibreStylesheet(client, styleId) {
105
+ return getJson(client, stylePath(styleId), `${MAPLIBRE_STYLE_MEDIA_TYPE}, application/json;q=0.9`);
106
+ }
107
+ /** Coerce a free-form metadata `version` (string) into the numeric style_version, when possible. */
108
+ function parseStyleVersion(version) {
109
+ if (version === undefined)
110
+ return null;
111
+ const parsed = Number.parseInt(version, 10);
112
+ return Number.isFinite(parsed) ? parsed : null;
113
+ }
114
+ /**
115
+ * Resolve a single style into a `StyleRef` projection: fetch metadata and the
116
+ * canonical MapLibre stylesheet, and advertise the alternate SLD encodings by
117
+ * reference. The stylesheet base URL (`{baseUrl}/ogc/styles/{styleId}`) backs
118
+ * the `storageRef` for the by-reference encodings.
119
+ */
120
+ export async function resolveStyleRef(client, styleId) {
121
+ const [metadata, maplibre] = await Promise.all([
122
+ getStyleMetadata(client, styleId).catch(() => null),
123
+ getMapLibreStylesheet(client, styleId),
124
+ ]);
125
+ const stylesheetUrl = `${client.serverBaseUrl}${stylePath(styleId)}`;
126
+ const encodings = [
127
+ {
128
+ encoding: "mapbox-style",
129
+ contentType: MAPLIBRE_STYLE_MEDIA_TYPE,
130
+ inlineBody: maplibre,
131
+ },
132
+ { encoding: "sld-1.0.0", contentType: SLD_10_MEDIA_TYPE, storageRef: stylesheetUrl },
133
+ { encoding: "sld-1.1.0", contentType: SLD_11_MEDIA_TYPE, storageRef: stylesheetUrl },
134
+ ];
135
+ const legendUrl = metadata?.links?.find((l) => l.rel === "preview")?.href ?? null;
136
+ return {
137
+ styleId,
138
+ title: metadata?.title ?? styleId,
139
+ description: metadata?.description ?? null,
140
+ styleVersion: parseStyleVersion(metadata?.version),
141
+ legendUrl,
142
+ encodings,
143
+ };
144
+ }
@@ -0,0 +1,27 @@
1
+ import type { HonuaClient } from "@honua/sdk-js";
2
+ import { z } from "zod";
3
+ export declare const schema: z.ZodObject<{
4
+ styleId: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ styleId: string;
7
+ }, {
8
+ styleId: string;
9
+ }>;
10
+ export type Input = z.infer<typeof schema>;
11
+ /**
12
+ * Resolve a style preset for client-side application. Returns the canonical
13
+ * `StyleRef` plus the MapLibre/Mapbox stylesheet body so an agent or downstream
14
+ * runtime can apply the preset to a map.
15
+ *
16
+ * This is a read-only inspection projection: it resolves and returns the
17
+ * preset's stylesheet but never mutates server state. Persisting a preset onto
18
+ * a map or published service stays with the typed gRPC execution layer per the
19
+ * MCP boundary (geospatial-mcp taxonomy / ADR-0028).
20
+ */
21
+ export declare function execute(client: HonuaClient, input: Input): Promise<{
22
+ content: Array<{
23
+ type: "text";
24
+ text: string;
25
+ }>;
26
+ }>;
27
+ //# sourceMappingURL=apply-style-preset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-style-preset.d.ts","sourceRoot":"","sources":["../../../src/tools/apply-style-preset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,MAAM;;;;;;EAEjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAqB9D"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { CapabilityUnavailableError, capabilityUnavailable } from "../capability.js";
3
+ import { jsonText } from "../helpers.js";
4
+ import { STYLE_SURFACE, resolveStyleRef } from "../styles.js";
5
+ const STYLE_GUIDANCE = "This target is a plain FeatureServer/OGC endpoint with no style presets. " +
6
+ "Build a MapLibre style client-side from the layer's fields, or use a Honua deployment for managed presets.";
7
+ export const schema = z.object({
8
+ styleId: z.string().describe("Stable style identifier of the preset to resolve."),
9
+ });
10
+ /**
11
+ * Resolve a style preset for client-side application. Returns the canonical
12
+ * `StyleRef` plus the MapLibre/Mapbox stylesheet body so an agent or downstream
13
+ * runtime can apply the preset to a map.
14
+ *
15
+ * This is a read-only inspection projection: it resolves and returns the
16
+ * preset's stylesheet but never mutates server state. Persisting a preset onto
17
+ * a map or published service stays with the typed gRPC execution layer per the
18
+ * MCP boundary (geospatial-mcp taxonomy / ADR-0028).
19
+ */
20
+ export async function execute(client, input) {
21
+ // `resolveStyleRef` already fetches the MapLibre stylesheet and inlines it on
22
+ // the `mapbox-style` encoding, so reuse that body instead of issuing a second
23
+ // identical GET /ogc/styles/{id}.
24
+ let styleRef;
25
+ try {
26
+ styleRef = await resolveStyleRef(client, input.styleId);
27
+ }
28
+ catch (err) {
29
+ if (err instanceof CapabilityUnavailableError) {
30
+ return capabilityUnavailable(STYLE_SURFACE, err.reason, STYLE_GUIDANCE);
31
+ }
32
+ throw err;
33
+ }
34
+ const stylesheet = styleRef.encodings.find((e) => e.encoding === "mapbox-style")?.inlineBody ?? null;
35
+ return jsonText({
36
+ style: styleRef,
37
+ stylesheet,
38
+ application: "client-side",
39
+ note: "Apply this MapLibre stylesheet client-side. MCP does not mutate server state; persisting a preset to a map or service uses the gRPC execution layer.",
40
+ });
41
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"count-features.d.ts","sourceRoot":"","sources":["../../../src/tools/count-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;EAajB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAoB9D"}
1
+ {"version":3,"file":"count-features.d.ts","sourceRoot":"","sources":["../../../src/tools/count-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;EAajB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAqB9D"}
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { GEOMETRY_TYPES, jsonText, mapSpatialRel, resolveGeometryType } from "../helpers.js";
2
+ import { GEOMETRY_TYPES, coerceCount, jsonText, mapSpatialRel, resolveGeometryType } from "../helpers.js";
3
3
  export const schema = z.object({
4
4
  serviceId: z.string().describe("The feature service ID"),
5
5
  layerId: z.number().int().nonnegative().describe("The layer ID within the service"),
@@ -26,9 +26,10 @@ export async function execute(client, input) {
26
26
  outFields: "OBJECTID",
27
27
  extraParams: { returnCountOnly: true },
28
28
  }));
29
- const hasCount = Object.prototype.hasOwnProperty.call(response, "count");
30
- const count = response.count;
31
- if (!hasCount || typeof count !== "number" || !Number.isFinite(count)) {
29
+ // The default grpc-web transport returns very large counts as a string to
30
+ // preserve precision beyond Number.MAX_SAFE_INTEGER; accept both forms.
31
+ const count = coerceCount(response.count);
32
+ if (count === undefined) {
32
33
  throw new Error("Count query did not return a numeric count.");
33
34
  }
34
35
  return jsonText({ count });
@@ -1 +1 @@
1
- {"version":3,"file":"get-extent.d.ts","sourceRoot":"","sources":["../../../src/tools/get-extent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;EAajB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAmC9D"}
1
+ {"version":3,"file":"get-extent.d.ts","sourceRoot":"","sources":["../../../src/tools/get-extent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;EAajB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAoC9D"}
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { GEOMETRY_TYPES, jsonText, mapSpatialRel, resolveGeometryType } from "../helpers.js";
2
+ import { GEOMETRY_TYPES, coerceCount, jsonText, mapSpatialRel, resolveGeometryType } from "../helpers.js";
3
3
  export const schema = z.object({
4
4
  serviceId: z.string().describe("The feature service ID"),
5
5
  layerId: z.number().int().nonnegative().describe("The layer ID within the service"),
@@ -25,8 +25,9 @@ export async function execute(client, input) {
25
25
  returnGeometry: false,
26
26
  extraParams: { returnExtentOnly: true },
27
27
  }));
28
- const hasCount = Object.prototype.hasOwnProperty.call(response, "count");
29
- const count = hasCount && typeof response.count === "number" && Number.isFinite(response.count) ? response.count : undefined;
28
+ // Accept large counts returned as strings by the grpc-web transport (chosen
29
+ // to preserve precision beyond Number.MAX_SAFE_INTEGER) as well as numbers.
30
+ const count = coerceCount(response.count);
30
31
  const hasExtent = Object.prototype.hasOwnProperty.call(response, "extent");
31
32
  if (!hasExtent) {
32
33
  // Some backends can return count-only payloads for empty extent queries.
@@ -39,7 +40,8 @@ export async function execute(client, input) {
39
40
  if (response.extent === null) {
40
41
  extent = null;
41
42
  }
42
- else if (typeof response.extent === "object") {
43
+ else if (typeof response.extent === "object" && !Array.isArray(response.extent)) {
44
+ // A JSON array is `typeof "object"` but is not a valid extent envelope.
43
45
  extent = response.extent;
44
46
  }
45
47
  else {
@@ -0,0 +1,24 @@
1
+ import type { HonuaClient } from "@honua/sdk-js";
2
+ import { z } from "zod";
3
+ export declare const schema: z.ZodObject<{
4
+ styleId: z.ZodOptional<z.ZodString>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ styleId?: string | undefined;
7
+ }, {
8
+ styleId?: string | undefined;
9
+ }>;
10
+ export type Input = z.infer<typeof schema>;
11
+ /**
12
+ * Resolve a style from the server's OGC API – Styles surface. With a `styleId`,
13
+ * returns the canonical `StyleRef` projection (style_id / title / description /
14
+ * style_version / encodings / legend_url), with the MapLibre stylesheet inlined.
15
+ * Without a `styleId`, returns the styles catalog so an agent can discover what
16
+ * is available.
17
+ */
18
+ export declare function execute(client: HonuaClient, input: Input): Promise<{
19
+ content: Array<{
20
+ type: "text";
21
+ text: string;
22
+ }>;
23
+ }>;
24
+ //# sourceMappingURL=get-style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-style.d.ts","sourceRoot":"","sources":["../../../src/tools/get-style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,MAAM;;;;;;EAEjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAsB9D"}
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import { CapabilityUnavailableError, capabilityUnavailable } from "../capability.js";
3
+ import { jsonText } from "../helpers.js";
4
+ import { STYLE_SURFACE, listStyles, resolveStyleRef } from "../styles.js";
5
+ const STYLE_GUIDANCE = "This target is a plain FeatureServer/OGC endpoint with no server-side style catalog. " +
6
+ "Query features and build a MapLibre style client-side, or point honua-mcp at a Honua deployment for managed styles.";
7
+ export const schema = z.object({
8
+ styleId: z.string().optional().describe("Stable style identifier. Omit to list the styles available on the server."),
9
+ });
10
+ /**
11
+ * Resolve a style from the server's OGC API – Styles surface. With a `styleId`,
12
+ * returns the canonical `StyleRef` projection (style_id / title / description /
13
+ * style_version / encodings / legend_url), with the MapLibre stylesheet inlined.
14
+ * Without a `styleId`, returns the styles catalog so an agent can discover what
15
+ * is available.
16
+ */
17
+ export async function execute(client, input) {
18
+ try {
19
+ if (!input.styleId) {
20
+ const list = await listStyles(client);
21
+ return jsonText({
22
+ styles: list.styles.map((entry) => ({
23
+ styleId: entry.id,
24
+ title: entry.title ?? entry.id,
25
+ uri: `honua://styles/${encodeURIComponent(entry.id)}`,
26
+ })),
27
+ default: list.default ?? null,
28
+ });
29
+ }
30
+ const styleRef = await resolveStyleRef(client, input.styleId);
31
+ return jsonText(styleRef);
32
+ }
33
+ catch (err) {
34
+ if (err instanceof CapabilityUnavailableError) {
35
+ return capabilityUnavailable(STYLE_SURFACE, err.reason, STYLE_GUIDANCE);
36
+ }
37
+ throw err;
38
+ }
39
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"list-services.d.ts","sourceRoot":"","sources":["../../../src/tools/list-services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;EAQjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAI3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GAgC9D"}
1
+ {"version":3,"file":"list-services.d.ts","sourceRoot":"","sources":["../../../src/tools/list-services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;EAQjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAI3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GA+C9D"}
@@ -9,7 +9,22 @@ export const schema = z.object({
9
9
  });
10
10
  const METADATA_CONCURRENCY = 8;
11
11
  export async function execute(client, input) {
12
- const response = await client.listServices();
12
+ let response;
13
+ try {
14
+ response = await client.listServices();
15
+ }
16
+ catch (err) {
17
+ // Some targets expose no service catalog at `/rest/services` — e.g. a base
18
+ // URL pointed straight at a single FeatureServer, or an OGC-only endpoint.
19
+ // Degrade to a structured note instead of crashing: the agent can still
20
+ // describe/query a known service+layer directly.
21
+ return jsonText({
22
+ catalogAvailable: false,
23
+ services: [],
24
+ reason: `service catalog is not available on this target: ${err instanceof Error ? err.message : String(err)}`,
25
+ guidance: "No /rest/services directory here. Call honua_describe_layer / honua_query_features with a known serviceId and layerId, or point the base URL at an ArcGIS folder that lists services.",
26
+ });
27
+ }
13
28
  const services = (response.services ?? []).filter((s) => s.type === "FeatureServer");
14
29
  if (!input.includeDetails) {
15
30
  return jsonText(services.map((s) => ({ serviceId: s.name, type: s.type })));
@@ -1 +1 @@
1
- {"version":3,"file":"query-features.d.ts","sourceRoot":"","sources":["../../../src/tools/query-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GA4B9D"}
1
+ {"version":3,"file":"query-features.d.ts","sourceRoot":"","sources":["../../../src/tools/query-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;GA+B9D"}
@@ -24,7 +24,10 @@ export async function execute(client, input) {
24
24
  serviceId: input.serviceId,
25
25
  layerId: input.layerId,
26
26
  where: input.where,
27
- outFields: input.outFields ?? "*",
27
+ // An empty array is a natural "no specific fields" from an agent, but Esri
28
+ // FeatureServer treats an empty outFields as "OBJECTID only". Coerce both
29
+ // missing and empty to "*" so all fields are returned.
30
+ outFields: input.outFields && input.outFields.length > 0 ? input.outFields : "*",
28
31
  geometry: input.geometry,
29
32
  geometryType: resolveGeometryType(input.geometry, input.geometryType),
30
33
  spatialRel: mapSpatialRel(input.spatialRel),