@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.
- package/LICENSE +201 -0
- package/README.md +232 -9
- package/dist/src/certification/admin-parity.d.ts +96 -0
- package/dist/src/certification/admin-parity.d.ts.map +1 -0
- package/dist/src/certification/admin-parity.js +235 -0
- package/dist/src/certification/census-fixture-client.d.ts.map +1 -1
- package/dist/src/certification/census-fixture-client.js +5 -0
- package/dist/src/certification/certifier.d.ts +1 -1
- package/dist/src/certification/certifier.d.ts.map +1 -1
- package/dist/src/certification/certifier.js +28 -20
- package/dist/src/certification/cli.js +1 -1
- package/dist/src/certification/cql2.d.ts +24 -0
- package/dist/src/certification/cql2.d.ts.map +1 -0
- package/dist/src/certification/cql2.js +354 -0
- package/dist/src/certification/fixtures.d.ts +8 -0
- package/dist/src/certification/fixtures.d.ts.map +1 -1
- package/dist/src/certification/fixtures.js +26 -10
- package/dist/src/certification/ogc-data.d.ts +30 -0
- package/dist/src/certification/ogc-data.d.ts.map +1 -0
- package/dist/src/certification/ogc-data.js +726 -0
- package/dist/src/certification/ogc-fixture-client.d.ts +4 -0
- package/dist/src/certification/ogc-fixture-client.d.ts.map +1 -0
- package/dist/src/certification/ogc-fixture-client.js +190 -0
- package/dist/src/certification/target.d.ts +10 -1
- package/dist/src/certification/target.d.ts.map +1 -1
- package/dist/src/certification/target.js +63 -28
- package/dist/src/credential-endpoint.d.ts +3 -0
- package/dist/src/credential-endpoint.d.ts.map +1 -0
- package/dist/src/credential-endpoint.js +24 -0
- package/dist/src/eval/cli.js +6 -3
- package/dist/src/eval/corpus.d.ts +7 -0
- package/dist/src/eval/corpus.d.ts.map +1 -1
- package/dist/src/eval/corpus.js +12 -0
- package/dist/src/eval/ogc-corpus.d.ts +3 -0
- package/dist/src/eval/ogc-corpus.d.ts.map +1 -0
- package/dist/src/eval/ogc-corpus.js +437 -0
- package/dist/src/eval/runner.d.ts +6 -0
- package/dist/src/eval/runner.d.ts.map +1 -1
- package/dist/src/eval/runner.js +21 -7
- package/dist/src/helpers.d.ts +8 -13
- package/dist/src/helpers.d.ts.map +1 -1
- package/dist/src/helpers.js +7 -35
- package/dist/src/index.d.ts +36 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +55 -18
- package/dist/src/neutral/errors.d.ts +73 -0
- package/dist/src/neutral/errors.d.ts.map +1 -0
- package/dist/src/neutral/errors.js +112 -0
- package/dist/src/neutral/filter.d.ts +108 -0
- package/dist/src/neutral/filter.d.ts.map +1 -0
- package/dist/src/neutral/filter.js +271 -0
- package/dist/src/neutral/query.d.ts +101 -0
- package/dist/src/neutral/query.d.ts.map +1 -0
- package/dist/src/neutral/query.js +180 -0
- package/dist/src/neutral/result.d.ts +33 -0
- package/dist/src/neutral/result.d.ts.map +1 -0
- package/dist/src/neutral/result.js +38 -0
- package/dist/src/neutral/source-ref.d.ts +126 -0
- package/dist/src/neutral/source-ref.d.ts.map +1 -0
- package/dist/src/neutral/source-ref.js +267 -0
- package/dist/src/nl-map-control.d.ts.map +1 -1
- package/dist/src/proxy.d.ts.map +1 -1
- package/dist/src/proxy.js +29 -14
- package/dist/src/release/zero-to-map-checkpoint.d.ts +34 -0
- package/dist/src/release/zero-to-map-checkpoint.d.ts.map +1 -0
- package/dist/src/release/zero-to-map-checkpoint.js +369 -0
- package/dist/src/release/zero-to-map-cli.d.ts +51 -0
- package/dist/src/release/zero-to-map-cli.d.ts.map +1 -0
- package/dist/src/release/zero-to-map-cli.js +880 -0
- package/dist/src/release/zero-to-map-provision.d.ts +37 -0
- package/dist/src/release/zero-to-map-provision.d.ts.map +1 -0
- package/dist/src/release/zero-to-map-provision.js +177 -0
- package/dist/src/release/zero-to-map.d.ts +296 -0
- package/dist/src/release/zero-to-map.d.ts.map +1 -0
- package/dist/src/release/zero-to-map.js +1069 -0
- package/dist/src/tools/admin-install-local.d.ts +30 -0
- package/dist/src/tools/admin-install-local.d.ts.map +1 -0
- package/dist/src/tools/admin-install-local.js +22 -0
- package/dist/src/tools/control-plane-command.d.ts +99 -0
- package/dist/src/tools/control-plane-command.d.ts.map +1 -0
- package/dist/src/tools/control-plane-command.js +180 -0
- package/dist/src/tools/count-features.d.ts +85 -11
- package/dist/src/tools/count-features.d.ts.map +1 -1
- package/dist/src/tools/count-features.js +49 -31
- package/dist/src/tools/describe-layer.d.ts +30 -6
- package/dist/src/tools/describe-layer.d.ts.map +1 -1
- package/dist/src/tools/describe-layer.js +99 -8
- package/dist/src/tools/docs-search.d.ts +100 -0
- package/dist/src/tools/docs-search.d.ts.map +1 -0
- package/dist/src/tools/docs-search.js +381 -0
- package/dist/src/tools/get-extent.d.ts +69 -11
- package/dist/src/tools/get-extent.d.ts.map +1 -1
- package/dist/src/tools/get-extent.js +28 -46
- package/dist/src/tools/list-services.d.ts +7 -0
- package/dist/src/tools/list-services.d.ts.map +1 -1
- package/dist/src/tools/list-services.js +8 -1
- package/dist/src/tools/list-sources.d.ts +44 -0
- package/dist/src/tools/list-sources.d.ts.map +1 -0
- package/dist/src/tools/list-sources.js +138 -0
- package/dist/src/tools/query-features.d.ts +99 -19
- package/dist/src/tools/query-features.d.ts.map +1 -1
- package/dist/src/tools/query-features.js +38 -45
- package/dist/src/tools/statistics.d.ts +80 -12
- package/dist/src/tools/statistics.d.ts.map +1 -1
- package/dist/src/tools/statistics.js +56 -23
- package/package.json +37 -8
- package/release/zero-to-map/README.md +174 -0
- package/release/zero-to-map/configs/claude-code.mcp.json +11 -0
- package/release/zero-to-map/configs/claude-desktop.json +11 -0
- package/release/zero-to-map/configs/cursor.json +11 -0
- package/release/zero-to-map/contracts/aws-ecs-provision-binding.schema.json +59 -0
- package/release/zero-to-map/contracts/checkpoint.schema.json +152 -0
- package/release/zero-to-map/contracts/console-receipt.schema.json +150 -0
- package/release/zero-to-map/contracts/esri-gp-mcp.v1.json +73 -0
- package/release/zero-to-map/fixtures/parcels.geojson +33 -0
- package/release/zero-to-map/fixtures/zoning.geojson +24 -0
- package/release/zero-to-map/journey.v1.json +1248 -0
package/dist/src/index.d.ts
CHANGED
|
@@ -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:
|
|
26
|
-
* straight onto `@honua/sdk-js
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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
|
|
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.
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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:
|
|
125
|
-
* straight onto `@honua/sdk-js
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
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("
|
|
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", "
|
|
153
|
-
server.tool("honua_query_features", "Query features with
|
|
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 (
|
|
162
|
-
server.resource("layer-schema", new ResourceTemplate(layerSchemaResource.uriTemplate, { list: undefined }), async (
|
|
163
|
-
server.resource("styles-catalog", stylesResource.uri, async (
|
|
164
|
-
server.resource("style", new ResourceTemplate(stylesResource.uriTemplate, { list: undefined }), async (
|
|
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
|
|
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
|
|
182
|
-
const server = createServer(
|
|
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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"}
|