@honua/mcp-server 0.1.2-beta.0 → 0.1.8-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 (117) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +232 -9
  3. package/dist/src/certification/admin-parity.d.ts +96 -0
  4. package/dist/src/certification/admin-parity.d.ts.map +1 -0
  5. package/dist/src/certification/admin-parity.js +235 -0
  6. package/dist/src/certification/census-fixture-client.d.ts.map +1 -1
  7. package/dist/src/certification/census-fixture-client.js +5 -0
  8. package/dist/src/certification/certifier.d.ts +1 -1
  9. package/dist/src/certification/certifier.d.ts.map +1 -1
  10. package/dist/src/certification/certifier.js +28 -20
  11. package/dist/src/certification/cli.js +1 -1
  12. package/dist/src/certification/cql2.d.ts +24 -0
  13. package/dist/src/certification/cql2.d.ts.map +1 -0
  14. package/dist/src/certification/cql2.js +354 -0
  15. package/dist/src/certification/fixtures.d.ts +8 -0
  16. package/dist/src/certification/fixtures.d.ts.map +1 -1
  17. package/dist/src/certification/fixtures.js +26 -10
  18. package/dist/src/certification/ogc-data.d.ts +30 -0
  19. package/dist/src/certification/ogc-data.d.ts.map +1 -0
  20. package/dist/src/certification/ogc-data.js +726 -0
  21. package/dist/src/certification/ogc-fixture-client.d.ts +4 -0
  22. package/dist/src/certification/ogc-fixture-client.d.ts.map +1 -0
  23. package/dist/src/certification/ogc-fixture-client.js +190 -0
  24. package/dist/src/certification/target.d.ts +10 -1
  25. package/dist/src/certification/target.d.ts.map +1 -1
  26. package/dist/src/certification/target.js +63 -28
  27. package/dist/src/credential-endpoint.d.ts +3 -0
  28. package/dist/src/credential-endpoint.d.ts.map +1 -0
  29. package/dist/src/credential-endpoint.js +24 -0
  30. package/dist/src/eval/cli.js +6 -3
  31. package/dist/src/eval/corpus.d.ts +7 -0
  32. package/dist/src/eval/corpus.d.ts.map +1 -1
  33. package/dist/src/eval/corpus.js +12 -0
  34. package/dist/src/eval/ogc-corpus.d.ts +3 -0
  35. package/dist/src/eval/ogc-corpus.d.ts.map +1 -0
  36. package/dist/src/eval/ogc-corpus.js +437 -0
  37. package/dist/src/eval/runner.d.ts +6 -0
  38. package/dist/src/eval/runner.d.ts.map +1 -1
  39. package/dist/src/eval/runner.js +21 -7
  40. package/dist/src/helpers.d.ts +8 -13
  41. package/dist/src/helpers.d.ts.map +1 -1
  42. package/dist/src/helpers.js +7 -35
  43. package/dist/src/index.d.ts +36 -8
  44. package/dist/src/index.d.ts.map +1 -1
  45. package/dist/src/index.js +55 -18
  46. package/dist/src/neutral/errors.d.ts +73 -0
  47. package/dist/src/neutral/errors.d.ts.map +1 -0
  48. package/dist/src/neutral/errors.js +112 -0
  49. package/dist/src/neutral/filter.d.ts +108 -0
  50. package/dist/src/neutral/filter.d.ts.map +1 -0
  51. package/dist/src/neutral/filter.js +271 -0
  52. package/dist/src/neutral/query.d.ts +101 -0
  53. package/dist/src/neutral/query.d.ts.map +1 -0
  54. package/dist/src/neutral/query.js +180 -0
  55. package/dist/src/neutral/result.d.ts +33 -0
  56. package/dist/src/neutral/result.d.ts.map +1 -0
  57. package/dist/src/neutral/result.js +38 -0
  58. package/dist/src/neutral/source-ref.d.ts +126 -0
  59. package/dist/src/neutral/source-ref.d.ts.map +1 -0
  60. package/dist/src/neutral/source-ref.js +267 -0
  61. package/dist/src/nl-map-control.d.ts.map +1 -1
  62. package/dist/src/proxy.d.ts.map +1 -1
  63. package/dist/src/proxy.js +29 -14
  64. package/dist/src/release/zero-to-map-checkpoint.d.ts +34 -0
  65. package/dist/src/release/zero-to-map-checkpoint.d.ts.map +1 -0
  66. package/dist/src/release/zero-to-map-checkpoint.js +369 -0
  67. package/dist/src/release/zero-to-map-cli.d.ts +51 -0
  68. package/dist/src/release/zero-to-map-cli.d.ts.map +1 -0
  69. package/dist/src/release/zero-to-map-cli.js +880 -0
  70. package/dist/src/release/zero-to-map-provision.d.ts +37 -0
  71. package/dist/src/release/zero-to-map-provision.d.ts.map +1 -0
  72. package/dist/src/release/zero-to-map-provision.js +177 -0
  73. package/dist/src/release/zero-to-map.d.ts +296 -0
  74. package/dist/src/release/zero-to-map.d.ts.map +1 -0
  75. package/dist/src/release/zero-to-map.js +1069 -0
  76. package/dist/src/tools/admin-install-local.d.ts +30 -0
  77. package/dist/src/tools/admin-install-local.d.ts.map +1 -0
  78. package/dist/src/tools/admin-install-local.js +22 -0
  79. package/dist/src/tools/control-plane-command.d.ts +99 -0
  80. package/dist/src/tools/control-plane-command.d.ts.map +1 -0
  81. package/dist/src/tools/control-plane-command.js +180 -0
  82. package/dist/src/tools/count-features.d.ts +85 -11
  83. package/dist/src/tools/count-features.d.ts.map +1 -1
  84. package/dist/src/tools/count-features.js +49 -31
  85. package/dist/src/tools/describe-layer.d.ts +30 -6
  86. package/dist/src/tools/describe-layer.d.ts.map +1 -1
  87. package/dist/src/tools/describe-layer.js +99 -8
  88. package/dist/src/tools/docs-search.d.ts +100 -0
  89. package/dist/src/tools/docs-search.d.ts.map +1 -0
  90. package/dist/src/tools/docs-search.js +381 -0
  91. package/dist/src/tools/get-extent.d.ts +69 -11
  92. package/dist/src/tools/get-extent.d.ts.map +1 -1
  93. package/dist/src/tools/get-extent.js +28 -46
  94. package/dist/src/tools/list-services.d.ts +7 -0
  95. package/dist/src/tools/list-services.d.ts.map +1 -1
  96. package/dist/src/tools/list-services.js +8 -1
  97. package/dist/src/tools/list-sources.d.ts +44 -0
  98. package/dist/src/tools/list-sources.d.ts.map +1 -0
  99. package/dist/src/tools/list-sources.js +138 -0
  100. package/dist/src/tools/query-features.d.ts +99 -19
  101. package/dist/src/tools/query-features.d.ts.map +1 -1
  102. package/dist/src/tools/query-features.js +38 -45
  103. package/dist/src/tools/statistics.d.ts +80 -12
  104. package/dist/src/tools/statistics.d.ts.map +1 -1
  105. package/dist/src/tools/statistics.js +56 -23
  106. package/package.json +37 -8
  107. package/release/zero-to-map/README.md +174 -0
  108. package/release/zero-to-map/configs/claude-code.mcp.json +11 -0
  109. package/release/zero-to-map/configs/claude-desktop.json +11 -0
  110. package/release/zero-to-map/configs/cursor.json +11 -0
  111. package/release/zero-to-map/contracts/aws-ecs-provision-binding.schema.json +59 -0
  112. package/release/zero-to-map/contracts/checkpoint.schema.json +152 -0
  113. package/release/zero-to-map/contracts/console-receipt.schema.json +150 -0
  114. package/release/zero-to-map/contracts/esri-gp-mcp.v1.json +73 -0
  115. package/release/zero-to-map/fixtures/parcels.geojson +33 -0
  116. package/release/zero-to-map/fixtures/zoning.geojson +24 -0
  117. package/release/zero-to-map/journey.v1.json +1248 -0
@@ -3,7 +3,10 @@ import { HonuaClient } from "@honua/sdk-js";
3
3
  import type { HonuaTransport } from "@honua/sdk-js";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { type NlMapControlMcpHost } from "./nl-map-control.js";
6
+ import type { ControlPlaneCommandMcpHost } from "./tools/control-plane-command.js";
6
7
  export { createNlMapControlMcpHost, registerNlMapControlMcpTools, } from "./nl-map-control.js";
8
+ export { CONTROL_PLANE_COMMAND_TOOL_PREFIX, controlPlaneCommandToolName, controlPlaneCommandToolSchema, registerControlPlaneCommandTools, } from "./tools/control-plane-command.js";
9
+ export type { ControlPlaneCommandMcpHost } from "./tools/control-plane-command.js";
7
10
  export type { CreateNlMapControlMcpHostOptions, McpNlMapExecutionResponse, McpNlMapPlanResponse, McpNlMapReceipt, NlMapControlMcpHost, NlMapControlMcpRequestContext, } from "./nl-map-control.js";
8
11
  export interface RuntimeOptions {
9
12
  baseUrl: string;
@@ -15,6 +18,13 @@ export interface RuntimeOptions {
15
18
  export interface CreateServerOptions {
16
19
  /** Optional BYO-LLM/map-runtime host for the experimental NL map-plan tools. */
17
20
  readonly nlMapControl?: NlMapControlMcpHost;
21
+ /**
22
+ * Optional control-plane command runtime. When supplied, the server also
23
+ * publishes one generated thin adapter per shared command (see
24
+ * {@link registerControlPlaneCommandTools}). Omitted by default so the
25
+ * standalone catalog stays platform-free and read-only.
26
+ */
27
+ readonly controlPlaneCommands?: ControlPlaneCommandMcpHost;
18
28
  }
19
29
  export declare const SERVER_VERSION: string;
20
30
  export declare function resolveRuntimeOptions(env: NodeJS.ProcessEnv): RuntimeOptions;
@@ -22,13 +32,20 @@ export declare function createClientFromEnv(env?: NodeJS.ProcessEnv): HonuaClien
22
32
  /**
23
33
  * The PLATFORM-FREE standalone MCP surface (issue #369).
24
34
  *
25
- * This is the direct-SDK operator surface: nine read-only geospatial tools wired
26
- * straight onto `@honua/sdk-js`, which speaks plain Esri GeoServices / OGC API
27
- * over standard REST paths (`/rest/services`, `/FeatureServer/{id}/query`, …).
28
- * Point it at ANY public FeatureServer / OGC endpoint (e.g. a `services.arcgis.com`
29
- * FeatureServer) with ZERO Honua-server assumptions — no admin API, no `/healthz`,
30
- * no `/mcp` catalog. This is what the `honua-mcp` bin runs (see {@link runStandalone}),
31
- * and what the platform-free certification lane + eval corpus exercise.
35
+ * This is the direct-SDK operator surface: ten read-only geospatial tools wired
36
+ * straight onto `@honua/sdk-js`. Point it at ANY public FeatureServer / OGC API /
37
+ * STAC / WFS / OData endpoint with ZERO Honua-server assumptions — no admin API,
38
+ * no `/healthz`, no `/mcp` catalog. This is what the `honua-mcp` bin runs (see
39
+ * {@link runStandalone}), and what the platform-free certification lanes + eval
40
+ * corpora exercise.
41
+ *
42
+ * The tool contract is PROTOCOL-NEUTRAL (issue #1005): sources are addressed by
43
+ * a `<protocol>:<address>` reference (`honua_list_sources` emits them), filters
44
+ * are the SDK's typed semantic filter, geometry is GeoJSON, and execution goes
45
+ * through the canonical `Dataset`/`Source`/`Query`/`Result` contract so one call
46
+ * means the same thing on every protocol. The GeoServices `serviceId`/`layerId`
47
+ * pair is still accepted as a deprecated compatibility input; no tool schema
48
+ * requires an Esri-only field.
32
49
  *
33
50
  * Tools that need a Honua-only surface (server-side styling via OGC API – Styles,
34
51
  * a `/rest/services` catalog) degrade gracefully on a plain target: they return a
@@ -39,13 +56,24 @@ export declare function createClientFromEnv(env?: NodeJS.ProcessEnv): HonuaClien
39
56
  * mutation, jobs, and publishing — is a superset reached over streamable-HTTP and
40
57
  * mirrored to stdio by `honua-mcp-proxy` ({@link runProxy}); it requires a Honua
41
58
  * deployment. Standalone is the front door; the proxy is the upgrade path.
59
+ * Local installation is intentionally absent from this catalog and is exposed
60
+ * only by {@link createBootstrapServer}.
61
+ *
62
+ * Control-plane MUTATION is likewise absent by default, and when a host does
63
+ * enable it ({@link CreateServerOptions.controlPlaneCommands}) MCP does not get
64
+ * a workflow of its own: the tools are generated from the shared command
65
+ * catalog in `@honua/sdk-js/control-plane`, so an MCP invocation and the
66
+ * equivalent `honua` CLI, Studio, or direct-JS invocation share one
67
+ * implementation and one receipt `auditKey`.
42
68
  */
43
69
  export declare function createServer(client: HonuaClient, options?: CreateServerOptions): McpServer;
70
+ /** Bootstrap-only MCP surface for a laptop that does not have Honua yet. */
71
+ export declare function createBootstrapServer(): McpServer;
44
72
  /**
45
73
  * Run the platform-free standalone server end-to-end over stdio.
46
74
  *
47
75
  * Builds a `HonuaClient` from the environment (`HONUA_BASE_URL` + optional
48
- * transport/auth) and exposes {@link createServer} — the nine read-only tools —
76
+ * transport/auth) and exposes {@link createServer} — the ten read-only tools —
49
77
  * to a stdio MCP client (Claude Desktop / Claude Code / any MCP agent). Point
50
78
  * `HONUA_BASE_URL` at any public FeatureServer/OGC endpoint; no Honua server is
51
79
  * required. For the Honua-enhanced `/mcp` catalog, use `honua-mcp-proxy` instead.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAGtF,OAAO,EAAE,KAAK,mBAAmB,EAAgC,MAAM,qBAAqB,CAAC;AAc7F,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;CAC7C;AAMD,eAAO,MAAM,cAAc,QAAyB,CAAC;AA2DrD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,cAAc,CAgD5E;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,WAAW,CASrF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,mBAAwB,aA6FlF;AAMD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAGtF,OAAO,EAAE,KAAK,mBAAmB,EAAgC,MAAM,qBAAqB,CAAC;AAM7F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAanF,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iCAAiC,EACjC,2BAA2B,EAC3B,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AACnF,YAAY,EACV,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CAC5D;AAMD,eAAO,MAAM,cAAc,QAAyB,CAAC;AA2DrD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,cAAc,CAgD5E;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,WAAW,CASrF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,mBAAwB,aAoHlF;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,IAAI,SAAS,CAIjD;AAgBD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvF"}
package/dist/src/index.js CHANGED
@@ -8,16 +8,21 @@ import { registerNlMapControlMcpTools } from "./nl-map-control.js";
8
8
  import * as layerSchemaResource from "./resources/layer-schema.js";
9
9
  import * as servicesResource from "./resources/services.js";
10
10
  import * as stylesResource from "./resources/styles.js";
11
+ import * as adminInstallLocal from "./tools/admin-install-local.js";
11
12
  import * as applyStylePreset from "./tools/apply-style-preset.js";
13
+ import * as controlPlaneCommand from "./tools/control-plane-command.js";
12
14
  import * as countFeatures from "./tools/count-features.js";
13
15
  import * as describeLayer from "./tools/describe-layer.js";
16
+ import * as docsSearch from "./tools/docs-search.js";
14
17
  import * as explainCapabilityGap from "./tools/explain-capability-gap.js";
15
18
  import * as getExtent from "./tools/get-extent.js";
16
19
  import * as getStyle from "./tools/get-style.js";
17
20
  import * as listServices from "./tools/list-services.js";
21
+ import * as listSources from "./tools/list-sources.js";
18
22
  import * as queryFeatures from "./tools/query-features.js";
19
23
  import * as statistics from "./tools/statistics.js";
20
24
  export { createNlMapControlMcpHost, registerNlMapControlMcpTools, } from "./nl-map-control.js";
25
+ export { CONTROL_PLANE_COMMAND_TOOL_PREFIX, controlPlaneCommandToolName, controlPlaneCommandToolSchema, registerControlPlaneCommandTools, } from "./tools/control-plane-command.js";
21
26
  const DEFAULT_TIMEOUT_MS = 30_000;
22
27
  const DEFAULT_MAX_RETRIES = 2;
23
28
  const DEFAULT_SERVER_VERSION = "0.0.3-alpha.0";
@@ -121,13 +126,20 @@ export function createClientFromEnv(env = process.env) {
121
126
  /**
122
127
  * The PLATFORM-FREE standalone MCP surface (issue #369).
123
128
  *
124
- * This is the direct-SDK operator surface: nine read-only geospatial tools wired
125
- * straight onto `@honua/sdk-js`, which speaks plain Esri GeoServices / OGC API
126
- * over standard REST paths (`/rest/services`, `/FeatureServer/{id}/query`, …).
127
- * Point it at ANY public FeatureServer / OGC endpoint (e.g. a `services.arcgis.com`
128
- * FeatureServer) with ZERO Honua-server assumptions — no admin API, no `/healthz`,
129
- * no `/mcp` catalog. This is what the `honua-mcp` bin runs (see {@link runStandalone}),
130
- * and what the platform-free certification lane + eval corpus exercise.
129
+ * This is the direct-SDK operator surface: ten read-only geospatial tools wired
130
+ * straight onto `@honua/sdk-js`. Point it at ANY public FeatureServer / OGC API /
131
+ * STAC / WFS / OData endpoint with ZERO Honua-server assumptions — no admin API,
132
+ * no `/healthz`, no `/mcp` catalog. This is what the `honua-mcp` bin runs (see
133
+ * {@link runStandalone}), and what the platform-free certification lanes + eval
134
+ * corpora exercise.
135
+ *
136
+ * The tool contract is PROTOCOL-NEUTRAL (issue #1005): sources are addressed by
137
+ * a `<protocol>:<address>` reference (`honua_list_sources` emits them), filters
138
+ * are the SDK's typed semantic filter, geometry is GeoJSON, and execution goes
139
+ * through the canonical `Dataset`/`Source`/`Query`/`Result` contract so one call
140
+ * means the same thing on every protocol. The GeoServices `serviceId`/`layerId`
141
+ * pair is still accepted as a deprecated compatibility input; no tool schema
142
+ * requires an Esri-only field.
131
143
  *
132
144
  * Tools that need a Honua-only surface (server-side styling via OGC API – Styles,
133
145
  * a `/rest/services` catalog) degrade gracefully on a plain target: they return a
@@ -138,6 +150,15 @@ export function createClientFromEnv(env = process.env) {
138
150
  * mutation, jobs, and publishing — is a superset reached over streamable-HTTP and
139
151
  * mirrored to stdio by `honua-mcp-proxy` ({@link runProxy}); it requires a Honua
140
152
  * deployment. Standalone is the front door; the proxy is the upgrade path.
153
+ * Local installation is intentionally absent from this catalog and is exposed
154
+ * only by {@link createBootstrapServer}.
155
+ *
156
+ * Control-plane MUTATION is likewise absent by default, and when a host does
157
+ * enable it ({@link CreateServerOptions.controlPlaneCommands}) MCP does not get
158
+ * a workflow of its own: the tools are generated from the shared command
159
+ * catalog in `@honua/sdk-js/control-plane`, so an MCP invocation and the
160
+ * equivalent `honua` CLI, Studio, or direct-JS invocation share one
161
+ * implementation and one receipt `auditKey`.
141
162
  */
142
163
  export function createServer(client, options = {}) {
143
164
  const server = new McpServer({
@@ -145,25 +166,41 @@ export function createServer(client, options = {}) {
145
166
  version: SERVER_VERSION,
146
167
  });
147
168
  // ── Tools ──────────────────────────────────────────────────────
148
- server.tool("honua_list_services", "Discover all available feature services on any FeatureServer folder. Set includeDetails=true for descriptions, layer counts, and spatial references. Degrades gracefully when the target has no service catalog.", listServices.schema.shape, async (args) => listServices.execute(client, listServices.schema.parse(args)));
169
+ server.tool("honua_list_sources", 'Discover queryable sources on this endpoint, across protocols. Returns protocol-neutral `<protocol>:<address>` source references (e.g. "ogc-features:hotels", "geoservices-feature-service:Parks/0") to pass verbatim to the query tools, plus each source\'s capabilities. Each protocol family degrades independently with a reason.', listSources.schema.shape, async (args) => listSources.execute(client, listSources.schema.parse(args)));
170
+ server.tool("honua_list_services", "[GeoServices-specific; prefer honua_list_sources] Discover feature services on a FeatureServer folder. Set includeDetails=true for descriptions, layer counts, and spatial references. Degrades gracefully when the target has no service catalog.", listServices.schema.shape, async (args) => listServices.execute(client, listServices.schema.parse(args)));
149
171
  if (options.nlMapControl) {
150
172
  registerNlMapControlMcpTools(server, options.nlMapControl);
151
173
  }
152
- server.tool("honua_describe_layer", "Get full schema for a layer — fields, geometry type, extent, relationships.", describeLayer.schema.shape, async (args) => describeLayer.execute(client, describeLayer.schema.parse(args)));
153
- server.tool("honua_query_features", "Query features with attribute filters, spatial filters, field selection, and pagination. returnGeometry defaults to false to save tokens.", queryFeatures.schema.shape, async (args) => queryFeatures.execute(client, queryFeatures.schema.parse(args)));
174
+ server.tool("honua_describe_layer", "Describe a source: its protocol, the capabilities it actually supports, field schema, geometry type, and extent. Address it with `source` (from honua_list_sources); the serviceId/layerId pair is deprecated but still accepted.", describeLayer.schema.shape, async (args) => describeLayer.execute(client, describeLayer.schema.parse(args)));
175
+ server.tool("honua_query_features", "Query features from any supported protocol. Address the source with `source`; filter with the typed protocol-neutral `filter`, a GeoJSON `geometry` or `bbox` plus `spatialRel`, and `temporal`. returnGeometry defaults to false to save tokens. A construct the backing protocol cannot express returns a structured capability error, never a silently empty result.", queryFeatures.schema.shape, async (args) => queryFeatures.execute(client, queryFeatures.schema.parse(args)));
154
176
  server.tool("honua_count_features", "Count features matching a filter without returning data. Use before querying to check cardinality.", countFeatures.schema.shape, async (args) => countFeatures.execute(client, countFeatures.schema.parse(args)));
155
177
  server.tool("honua_get_extent", "Get the spatial bounding box of features matching a filter.", getExtent.schema.shape, async (args) => getExtent.execute(client, getExtent.schema.parse(args)));
156
- server.tool("honua_statistics", "Compute aggregate statistics (count, sum, avg, min, max, stddev) on a field, optionally grouped.", statistics.schema.shape, async (args) => statistics.execute(client, statistics.schema.parse(args)));
178
+ server.tool("honua_statistics", "Compute aggregate statistics (count, sum, avg, min, max, stddev, var) on a field, optionally grouped. Protocols without server-side aggregation answer client-side and report the degradation.", statistics.schema.shape, async (args) => statistics.execute(client, statistics.schema.parse(args)));
157
179
  server.tool("honua_explain_capability_gap", "Explain whether a source/protocol supports a capability and suggest a safe fallback when it does not.", explainCapabilityGap.schema.shape, async (args) => explainCapabilityGap.execute(client, explainCapabilityGap.schema.parse(args)));
158
180
  server.tool("honua_get_style", "Resolve a style from a server's OGC API – Styles surface. Pass styleId for the canonical StyleRef (style_id, title, encodings incl. inlined MapLibre); omit it to list available styles. On a plain FeatureServer with no styling surface, reports a structured 'not available on this target' result.", getStyle.schema.shape, async (args) => getStyle.execute(client, getStyle.schema.parse(args)));
159
181
  server.tool("honua_apply_style_preset", "Resolve a style preset and its MapLibre stylesheet for client-side application. Read-only: returns the stylesheet to apply locally; it does not mutate server state. Degrades gracefully on a target with no styling surface.", applyStylePreset.schema.shape, async (args) => applyStylePreset.execute(client, applyStylePreset.schema.parse(args)));
182
+ if (options.controlPlaneCommands) {
183
+ // Thin adapters generated from the shared command catalog. Registered last
184
+ // so the platform-free read-only surface keeps its stable tool order.
185
+ controlPlaneCommand.registerControlPlaneCommandTools(server, options.controlPlaneCommands);
186
+ }
187
+ server.tool("honua_docs_search", "Answer a Honua documentation question from the local versioned documentation corpus (llms-full.txt), returning ranked excerpts with a source-file and release-version citation for each hit. Local and offline: reads committed docs, never the network. Use it before guessing at an API, a CLI flag, or a contract. Reports a structured 'not available' result when the corpus is not present in this installation.", docsSearch.schema.shape, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async (args) => docsSearch.execute(client, docsSearch.schema.parse(args)));
160
188
  // ── Resources ──────────────────────────────────────────────────
161
- server.resource("services-catalog", servicesResource.uri, async (uri) => servicesResource.read(client));
162
- server.resource("layer-schema", new ResourceTemplate(layerSchemaResource.uriTemplate, { list: undefined }), async (uri, params) => layerSchemaResource.read(client, params.encodedServiceId, params.layerId));
163
- server.resource("styles-catalog", stylesResource.uri, async (uri) => stylesResource.readCatalog(client));
164
- server.resource("style", new ResourceTemplate(stylesResource.uriTemplate, { list: undefined }), async (uri, params) => stylesResource.read(client, params.styleId));
189
+ server.resource("services-catalog", servicesResource.uri, async (_uri) => servicesResource.read(client));
190
+ server.resource("layer-schema", new ResourceTemplate(layerSchemaResource.uriTemplate, { list: undefined }), async (_uri, params) => layerSchemaResource.read(client, params.encodedServiceId, params.layerId));
191
+ server.resource("styles-catalog", stylesResource.uri, async (_uri) => stylesResource.readCatalog(client));
192
+ server.resource("style", new ResourceTemplate(stylesResource.uriTemplate, { list: undefined }), async (_uri, params) => stylesResource.read(client, params.styleId));
165
193
  return server;
166
194
  }
195
+ /** Bootstrap-only MCP surface for a laptop that does not have Honua yet. */
196
+ export function createBootstrapServer() {
197
+ const server = new McpServer({ name: "honua-bootstrap", version: SERVER_VERSION });
198
+ registerLocalInstallTool(server);
199
+ return server;
200
+ }
201
+ function registerLocalInstallTool(server) {
202
+ server.tool("honua_admin_install_local", "Install the manifest-pinned Honua Server, PostGIS, and Redis on this laptop, wait for readiness, bootstrap a scoped admin key, and write proxy MCP configuration. Requires confirm=true.", adminInstallLocal.schema.shape, { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }, async (args) => adminInstallLocal.execute(adminInstallLocal.schema.parse(args)));
203
+ }
167
204
  /* v8 ignore start -- live-process entry: wires the stdio transport to a real
168
205
  SDK client against HONUA_BASE_URL; exercised by running the bin, not unit tests.
169
206
  The unit-testable logic (option resolution, client construction, server wiring)
@@ -172,14 +209,14 @@ export function createServer(client, options = {}) {
172
209
  * Run the platform-free standalone server end-to-end over stdio.
173
210
  *
174
211
  * Builds a `HonuaClient` from the environment (`HONUA_BASE_URL` + optional
175
- * transport/auth) and exposes {@link createServer} — the nine read-only tools —
212
+ * transport/auth) and exposes {@link createServer} — the ten read-only tools —
176
213
  * to a stdio MCP client (Claude Desktop / Claude Code / any MCP agent). Point
177
214
  * `HONUA_BASE_URL` at any public FeatureServer/OGC endpoint; no Honua server is
178
215
  * required. For the Honua-enhanced `/mcp` catalog, use `honua-mcp-proxy` instead.
179
216
  */
180
217
  export async function runStandalone(env = process.env) {
181
- const client = createClientFromEnv(env);
182
- const server = createServer(client);
218
+ const bootstrapOnly = env.HONUA_MCP_BOOTSTRAP === "1" || env.HONUA_MCP_BOOTSTRAP === "true";
219
+ const server = bootstrapOnly ? createBootstrapServer() : createServer(createClientFromEnv(env));
183
220
  const transport = new StdioServerTransport();
184
221
  await server.connect(transport);
185
222
  }
@@ -0,0 +1,73 @@
1
+ import { HonuaCapabilityNotSupportedError } from "@honua/sdk-js";
2
+ /**
3
+ * CAPABILITY HONESTY on the tool surface (#1005).
4
+ *
5
+ * The SDK's contract is that a capability gap throws
6
+ * `HonuaCapabilityNotSupportedError` rather than returning empty data. That
7
+ * guarantee is worthless if the MCP layer swallows the throw and hands the
8
+ * model an empty feature list — the model would report "no features match"
9
+ * for what is actually "this protocol cannot express that request".
10
+ *
11
+ * So every capability refusal becomes an explicit `isError` tool result
12
+ * carrying a machine-actionable `code`, the refused capability/construct, the
13
+ * protocol that refused it, and — for real capability identifiers — the same
14
+ * explanation `honua_explain_capability_gap` would give, including what to do
15
+ * instead. Degradations that DID produce an answer travel the other channel,
16
+ * `Result.degraded`, and are reported alongside the data.
17
+ */
18
+ /**
19
+ * `kind` values come from the vendored geospatial-mcp `GeoprocessingError`
20
+ * taxonomy — the standard forbids a parallel MCP-local error vocabulary, so a
21
+ * capability refusal is an `ExecutionFailed` (a well-formed request the target
22
+ * cannot run) and a bad argument is a `ValidationFailed`. The precise reason
23
+ * travels in the envelope's machine-actionable `code` plus the typed fields.
24
+ */
25
+ export type ToolErrorKind = "ValidationFailed" | "ExecutionFailed";
26
+ export interface ToolErrorViolation {
27
+ readonly code: string;
28
+ readonly message: string;
29
+ readonly fieldPath?: string;
30
+ }
31
+ export interface ToolErrorPayload {
32
+ readonly code: string;
33
+ readonly error: {
34
+ readonly kind: ToolErrorKind;
35
+ readonly message: string;
36
+ readonly capability?: string;
37
+ readonly protocol?: string;
38
+ readonly source?: string;
39
+ readonly guidance?: string;
40
+ readonly explanation?: unknown;
41
+ readonly violations?: readonly ToolErrorViolation[];
42
+ };
43
+ }
44
+ /** Build the structured payload for a capability refusal. */
45
+ export declare function capabilityErrorPayload(error: HonuaCapabilityNotSupportedError): ToolErrorPayload;
46
+ /** Build the structured payload for an invalid tool argument. */
47
+ export declare function validationErrorPayload(code: string, message: string, violations?: readonly ToolErrorViolation[]): ToolErrorPayload;
48
+ /**
49
+ * Wrap a payload as an `isError` MCP tool result.
50
+ *
51
+ * The payload rides in both channels: `structuredContent` for clients (and the
52
+ * certification error-shape contract) that branch on machine-readable fields,
53
+ * and the text block for models that only read text.
54
+ */
55
+ export declare function toolErrorResult(payload: ToolErrorPayload): {
56
+ structuredContent: Record<string, unknown>;
57
+ isError: true;
58
+ content: Array<{
59
+ type: "text";
60
+ text: string;
61
+ }>;
62
+ };
63
+ /** Map any thrown value onto a structured tool-error payload. */
64
+ export declare function toToolErrorPayload(error: unknown): ToolErrorPayload;
65
+ /**
66
+ * Run a tool body, converting capability refusals and argument-validation
67
+ * failures into structured `isError` results. Anything else is rethrown so a
68
+ * genuine transport/server fault is not disguised as a data answer.
69
+ */
70
+ export declare function withCapabilityHonesty<T extends {
71
+ content: unknown;
72
+ }>(run: () => Promise<T>): Promise<T | ReturnType<typeof toolErrorResult>>;
73
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/neutral/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AASjE;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;KACrD,CAAC;CACH;AAUD,6DAA6D;AAC7D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gCAAgC,GAAG,gBAAgB,CAkChG;AAED,iEAAiE;AACjE,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,SAAS,kBAAkB,EAAwB,GAC9D,gBAAgB,CAKlB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB;uBAGZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;EAGnE;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CA4BnE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EACxE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAcjD"}
@@ -0,0 +1,112 @@
1
+ import { HonuaCapabilityNotSupportedError } from "@honua/sdk-js";
2
+ import { explainHonuaCapabilityGap } from "@honua/sdk-js/agent-tools";
3
+ import { CAPABILITIES, PROTOCOLS } from "@honua/sdk-js/contract";
4
+ import { z } from "zod";
5
+ import { jsonText } from "../helpers.js";
6
+ import { FilterInputError } from "./filter.js";
7
+ import { SourceRefError } from "./source-ref.js";
8
+ function isKnownCapability(value) {
9
+ return CAPABILITIES.includes(value);
10
+ }
11
+ function isKnownProtocol(value) {
12
+ return PROTOCOLS.includes(value);
13
+ }
14
+ /** Build the structured payload for a capability refusal. */
15
+ export function capabilityErrorPayload(error) {
16
+ // Filter refusals name a construct (`filter.spatial.multiple`) rather than a
17
+ // registry capability; only real capability identifiers can be explained
18
+ // against the protocol capability registry.
19
+ const explanation = isKnownCapability(error.capability) && (error.protocol === undefined || isKnownProtocol(error.protocol))
20
+ ? explainHonuaCapabilityGap({
21
+ capability: error.capability,
22
+ ...(isKnownProtocol(error.protocol) ? { protocol: error.protocol } : {}),
23
+ ...(error.sourceId ? { sourceId: error.sourceId } : {}),
24
+ })
25
+ : undefined;
26
+ return {
27
+ code: "capability_not_supported",
28
+ error: {
29
+ kind: "ExecutionFailed",
30
+ message: error.message,
31
+ capability: error.capability,
32
+ protocol: error.protocol,
33
+ ...(error.sourceId ? { source: error.sourceId } : {}),
34
+ violations: [
35
+ {
36
+ code: "capability_not_supported",
37
+ message: error.message,
38
+ fieldPath: error.capability.startsWith("filter.") ? "filter" : "source",
39
+ },
40
+ ],
41
+ guidance: explanation?.suggestedAction ??
42
+ "This protocol cannot express the request exactly. Re-issue it against a source whose protocol advertises the capability, or restate the request within what this protocol supports — do not treat this as an empty result.",
43
+ ...(explanation ? { explanation } : {}),
44
+ },
45
+ };
46
+ }
47
+ /** Build the structured payload for an invalid tool argument. */
48
+ export function validationErrorPayload(code, message, violations = [{ code, message }]) {
49
+ return {
50
+ code,
51
+ error: { kind: "ValidationFailed", message, violations },
52
+ };
53
+ }
54
+ /**
55
+ * Wrap a payload as an `isError` MCP tool result.
56
+ *
57
+ * The payload rides in both channels: `structuredContent` for clients (and the
58
+ * certification error-shape contract) that branch on machine-readable fields,
59
+ * and the text block for models that only read text.
60
+ */
61
+ export function toolErrorResult(payload) {
62
+ return {
63
+ ...jsonText(payload),
64
+ structuredContent: payload,
65
+ isError: true,
66
+ };
67
+ }
68
+ /** Map any thrown value onto a structured tool-error payload. */
69
+ export function toToolErrorPayload(error) {
70
+ if (error instanceof HonuaCapabilityNotSupportedError) {
71
+ return capabilityErrorPayload(error);
72
+ }
73
+ if (error instanceof SourceRefError) {
74
+ const code = error.code.toLowerCase();
75
+ return validationErrorPayload(code, error.message, [{ code, message: error.message, fieldPath: "source" }]);
76
+ }
77
+ if (error instanceof FilterInputError) {
78
+ const code = error.code.toLowerCase();
79
+ return validationErrorPayload(code, error.message, [{ code, message: error.message, fieldPath: "filter" }]);
80
+ }
81
+ if (error instanceof z.ZodError) {
82
+ return validationErrorPayload("invalid_arguments", "Tool arguments failed validation.", error.issues.map((issue) => ({
83
+ code: issue.code,
84
+ message: issue.message,
85
+ fieldPath: issue.path.join("."),
86
+ })));
87
+ }
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ return {
90
+ code: "tool_execution_failed",
91
+ error: { kind: "ExecutionFailed", message, violations: [{ code: "tool_execution_failed", message }] },
92
+ };
93
+ }
94
+ /**
95
+ * Run a tool body, converting capability refusals and argument-validation
96
+ * failures into structured `isError` results. Anything else is rethrown so a
97
+ * genuine transport/server fault is not disguised as a data answer.
98
+ */
99
+ export async function withCapabilityHonesty(run) {
100
+ try {
101
+ return await run();
102
+ }
103
+ catch (error) {
104
+ if (error instanceof HonuaCapabilityNotSupportedError ||
105
+ error instanceof SourceRefError ||
106
+ error instanceof FilterInputError ||
107
+ error instanceof z.ZodError) {
108
+ return toolErrorResult(toToolErrorPayload(error));
109
+ }
110
+ throw error;
111
+ }
112
+ }
@@ -0,0 +1,108 @@
1
+ import type { QueryFilterExpression, QueryFilterGeometryOperand, QueryTemporalFilter } from "@honua/sdk-js/contract";
2
+ import { z } from "zod";
3
+ import { GEOMETRY_TYPES } from "../helpers.js";
4
+ /** Protocol-neutral spatial predicates (`QueryFilterSpatialPredicate`). */
5
+ export declare const SPATIAL_PREDICATES: readonly ["intersects", "contains", "within", "crosses", "touches", "overlaps", "bbox-intersects"];
6
+ declare const TEMPORAL_PREDICATES: readonly ["before", "after", "during", "time-intersects"];
7
+ /** GeoJSON geometry accepted anywhere a spatial constraint is expressed. */
8
+ export declare const geoJsonGeometrySchema: z.ZodObject<{
9
+ type: z.ZodEnum<["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]>;
10
+ coordinates: z.ZodArray<z.ZodUnknown, "many">;
11
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
12
+ type: z.ZodEnum<["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]>;
13
+ coordinates: z.ZodArray<z.ZodUnknown, "many">;
14
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
15
+ type: z.ZodEnum<["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]>;
16
+ coordinates: z.ZodArray<z.ZodUnknown, "many">;
17
+ }, z.ZodTypeAny, "passthrough">>;
18
+ /**
19
+ * A geometry operand: GeoJSON (canonical) or Esri-JSON (accepted for
20
+ * compatibility). Kept as a loose record so an Esri envelope / rings payload
21
+ * from an existing client still validates.
22
+ */
23
+ export declare const geometrySchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
24
+ export declare const bboxSchema: z.ZodArray<z.ZodNumber, "many">;
25
+ export type FilterNode = {
26
+ op: "and" | "or";
27
+ args: FilterNode[];
28
+ } | {
29
+ op: "not";
30
+ arg: FilterNode;
31
+ } | {
32
+ op: "eq" | "ne" | "lt" | "lte" | "gt" | "gte";
33
+ field: string;
34
+ value: string | number | boolean | null;
35
+ } | {
36
+ op: "in";
37
+ field: string;
38
+ values: (string | number | boolean | null)[];
39
+ } | {
40
+ op: "between";
41
+ field: string;
42
+ lower: string | number | boolean | null;
43
+ upper: string | number | boolean | null;
44
+ } | {
45
+ op: "is-null" | "is-not-null";
46
+ field: string;
47
+ } | {
48
+ op: "like";
49
+ field: string;
50
+ pattern: string;
51
+ caseSensitive?: boolean;
52
+ } | {
53
+ op: (typeof SPATIAL_PREDICATES)[number];
54
+ geometry?: Record<string, unknown>;
55
+ bbox?: number[];
56
+ field?: string;
57
+ geometryType?: (typeof GEOMETRY_TYPES)[number];
58
+ } | {
59
+ op: (typeof TEMPORAL_PREDICATES)[number];
60
+ field: string;
61
+ value: string | string[];
62
+ };
63
+ /**
64
+ * Recursive zod schema for {@link FilterNode}. `z.lazy` keeps `and`/`or`/`not`
65
+ * genuinely recursive; zod-to-json-schema emits it as a `$ref`, which stays
66
+ * well-formed JSON Schema for MCP clients and for the certification harness.
67
+ */
68
+ export declare const filterSchema: z.ZodType<FilterNode>;
69
+ export declare class FilterInputError extends Error {
70
+ readonly code = "INVALID_FILTER";
71
+ constructor(message: string);
72
+ }
73
+ /** Build an Esri envelope from a `[minX, minY, maxX, maxY]` bbox. */
74
+ export declare function bboxToOperand(bbox: readonly number[], srid?: number): QueryFilterGeometryOperand;
75
+ /**
76
+ * Normalize a geometry input onto the canonical geometry operand.
77
+ *
78
+ * GeoJSON is the documented input; Esri-JSON is accepted so existing clients
79
+ * keep working. The canonical operand is Esri-shaped inside the SDK — that is
80
+ * an SDK implementation detail, not part of this tool contract.
81
+ */
82
+ export declare function toGeometryOperand(geometry: Record<string, unknown>, esriGeometryType?: (typeof GEOMETRY_TYPES)[number], srid?: number): QueryFilterGeometryOperand;
83
+ /** Lower the wire filter DSL onto the SDK's canonical typed filter expression. */
84
+ export declare function toQueryFilter(node: FilterNode): QueryFilterExpression;
85
+ /** Conjoin filter expressions; `undefined` when nothing was supplied. */
86
+ export declare function andFilters(parts: readonly QueryFilterExpression[]): QueryFilterExpression | undefined;
87
+ /** Canonical time constraint accepted on the tool surface. */
88
+ export declare const temporalSchema: z.ZodObject<{
89
+ instant: z.ZodOptional<z.ZodString>;
90
+ start: z.ZodOptional<z.ZodNullable<z.ZodString>>;
91
+ end: z.ZodOptional<z.ZodNullable<z.ZodString>>;
92
+ field: z.ZodOptional<z.ZodString>;
93
+ }, "strip", z.ZodTypeAny, {
94
+ field?: string | undefined;
95
+ instant?: string | undefined;
96
+ start?: string | null | undefined;
97
+ end?: string | null | undefined;
98
+ }, {
99
+ field?: string | undefined;
100
+ instant?: string | undefined;
101
+ start?: string | null | undefined;
102
+ end?: string | null | undefined;
103
+ }>;
104
+ export type TemporalInput = z.infer<typeof temporalSchema>;
105
+ /** Lower the wire temporal input onto `Query.temporalFilter`. */
106
+ export declare function toTemporalFilter(input: TemporalInput): QueryTemporalFilter;
107
+ export {};
108
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/neutral/filter.ts"],"names":[],"mappings":"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"}