@honua/mcp-server 0.1.13 → 0.1.14

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/README.md CHANGED
@@ -260,7 +260,7 @@ Embedding the server in your own Node.js host needs the packages as local
260
260
  dependencies of that host project:
261
261
 
262
262
  ```bash
263
- npm install @honua/mcp-server @honua/sdk-js
263
+ npm install @honua/mcp-server@0.1.13 @honua/sdk-js@0.1.13
264
264
  ```
265
265
 
266
266
  The map runtime, model callback, approval verifier, receipt signer, and
@@ -346,6 +346,7 @@ cd honua-sdk-js
346
346
  npm ci
347
347
  ```
348
348
 
349
+ <!-- doc-run: checkout -->
349
350
  ```bash
350
351
  npm run build # the SDK that mcp/ links to; takes a few minutes
351
352
  cd mcp
@@ -354,6 +355,7 @@ npm ci
354
355
 
355
356
  From `mcp/`:
356
357
 
358
+ <!-- doc-run: checkout=mcp -->
357
359
  ```bash
358
360
  # Run the certifier against the offline fixture backend and write artifacts:
359
361
  npm run certify
@@ -384,6 +386,7 @@ skip-with-reason. Fixture-backed and deterministic — no network — as long as
384
386
  instead (the scheduled live variant). Unset it if you exported it for `honua-mcp`
385
387
  above:
386
388
 
389
+ <!-- doc-run: checkout=mcp -->
387
390
  ```bash
388
391
  unset HONUA_BASE_URL
389
392
  npm run certify:standalone # platform-free cert (plain FeatureServer fixture)
@@ -406,6 +409,7 @@ in `config/live-conformance-endpoints.v1.json`). Nothing Esri exists there: the
406
409
  GeoServices entry points all reject, so a tool that still secretly required
407
410
  `serviceId`/`layerId` fails loudly instead of passing by accident.
408
411
 
412
+ <!-- doc-run: checkout=mcp -->
409
413
  ```bash
410
414
  npm run certify:standalone-ogc # non-GeoServices cert (OGC API Features fixture)
411
415
  npm run test:certification:standalone-ogc # CI gate variant
@@ -521,6 +525,7 @@ honua-io/honua-server#1956.)
521
525
  dependencies); keys come from the environment and are never hardcoded. Set
522
526
  `HONUA_MCP_REMOTE_URL` to drive a live remote `/mcp` instead of the fixture.
523
527
 
528
+ <!-- doc-run: checkout=mcp -->
524
529
  ```bash
525
530
  npm run eval # run the eval (live models join if their keys are set)
526
531
  npm run eval:offline # force the deterministic control + fixture surface
@@ -546,6 +551,7 @@ guards. Because the fixture replays real recorded data, a wrong number or a
546
551
  hallucinated place name fails. The grading taxonomy is documented in
547
552
  [`evals/README.md`](evals/README.md).
548
553
 
554
+ <!-- doc-run: checkout=mcp -->
549
555
  ```bash
550
556
  npm run eval:standalone # deterministic control over the census fixture (offline)
551
557
  ```
@@ -564,6 +570,7 @@ an extent that came from the declared collection extent must say so, and a CQL2
564
570
  spatial predicate the endpoint does not publish must come back as a structured
565
571
  capability refusal — never as an empty result set.
566
572
 
573
+ <!-- doc-run: checkout=mcp -->
567
574
  ```bash
568
575
  npm run eval:ogc # deterministic control over the OGC API Features fixture (offline)
569
576
  ```
package/dist/src/index.js CHANGED
@@ -172,10 +172,10 @@ export function createServer(client, options = {}) {
172
172
  registerNlMapControlMcpTools(server, options.nlMapControl);
173
173
  }
174
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)));
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)));
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)));
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)));
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, extra) => queryFeatures.execute(client, queryFeatures.schema.parse(args), extra?.signal));
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, extra) => countFeatures.execute(client, countFeatures.schema.parse(args), extra?.signal));
177
+ server.tool("honua_get_extent", "Get the spatial bounding box of features matching a filter.", getExtent.schema.shape, async (args, extra) => getExtent.execute(client, getExtent.schema.parse(args), extra?.signal));
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, extra) => statistics.execute(client, statistics.schema.parse(args), extra?.signal));
179
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)));
180
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)));
181
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)));
@@ -16,9 +16,9 @@ export type GeometryFormat = "geojson" | "esri-json";
16
16
  export declare function projectGeometry(geometry: Record<string, unknown> | null | undefined, format: GeometryFormat): Record<string, unknown> | null;
17
17
  /** Normalize `Result.degraded` for tool output; `undefined` when nothing degraded. */
18
18
  export declare function projectDegraded(degraded: readonly DegradedReason[] | undefined): {
19
- capability: import("@honua/sdk-js/contract").Capability;
19
+ capability: import("@honua/sdk-js").Capability;
20
20
  reason: string;
21
- protocol: import("@honua/sdk-js/contract").Protocol | null;
21
+ protocol: import("@honua/sdk-js").Protocol | null;
22
22
  sourceId: string | null;
23
23
  }[] | undefined;
24
24
  export interface ProjectFeaturesOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/neutral/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGrE;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAMrD,gEAAgE;AAChE,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACpD,MAAM,EAAE,cAAc,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMhC;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS;;;;;gBAQ9E;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;;;IAU9E"}
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/neutral/result.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGrE;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAMrD,gEAAgE;AAChE,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACpD,MAAM,EAAE,cAAc,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWhC;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS;;;;;gBAQ9E;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;;;IAU9E"}
@@ -1,13 +1,20 @@
1
- import { esriToGeoJson } from "@honua/sdk-js/geometry";
1
+ import { HonuaCapabilityNotSupportedError } from "@honua/sdk-js";
2
+ import { esriToGeoJson, geoJsonToEsri } from "@honua/sdk-js/geometry";
2
3
  function looksGeoJson(geometry) {
3
- return typeof geometry.type === "string" && "coordinates" in geometry;
4
+ return typeof geometry.type === "string" && ("coordinates" in geometry || geometry.type === "GeometryCollection");
4
5
  }
5
6
  /** Re-encode one feature geometry into the requested format. */
6
7
  export function projectGeometry(geometry, format) {
7
8
  if (!geometry)
8
9
  return null;
9
- if (format === "esri-json")
10
- return geometry;
10
+ if (format === "esri-json") {
11
+ if (!looksGeoJson(geometry))
12
+ return geometry;
13
+ const converted = geoJsonToEsri(geometry);
14
+ if (!converted)
15
+ throw new HonuaCapabilityNotSupportedError("geometryFormat.esri-json", "geometry-projection");
16
+ return converted;
17
+ }
11
18
  if (looksGeoJson(geometry))
12
19
  return geometry;
13
20
  const converted = esriToGeoJson(geometry);
@@ -89,7 +89,7 @@ interface CountOutcome {
89
89
  }
90
90
  /** Resolve a feature count through the canonical `Source` surface. */
91
91
  export declare function countThroughSource(source: CapabilityAwareSource, query: Query, protocol: string, sourceId: string): Promise<CountOutcome>;
92
- export declare function execute(client: HonuaClient, input: Input): Promise<{
92
+ export declare function execute(client: HonuaClient, input: Input, signal?: AbortSignal): Promise<{
93
93
  content: Array<{
94
94
  type: "text";
95
95
  text: string;
@@ -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;AAEjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,GAAG,YAAY,CAAC;IACvC,QAAQ,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAC9C;AAED,sEAAsE;AACtE,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAevB;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;;;;;;;;GAmB9D"}
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;AAEjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE3C,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,GAAG,YAAY,CAAC;IACvC,QAAQ,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAC9C;AAED,sEAAsE;AACtE,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAevB;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;GAoBpF"}
@@ -38,10 +38,11 @@ export async function countThroughSource(source, query, protocol, sourceId) {
38
38
  }
39
39
  throw new HonuaCapabilityNotSupportedError("count", protocol, sourceId);
40
40
  }
41
- export async function execute(client, input) {
41
+ export async function execute(client, input, signal) {
42
42
  return withCapabilityHonesty(async () => {
43
43
  const resolved = resolveSource(client, input);
44
44
  const query = toQuery(input, { protocol: resolved.descriptor.protocol, paginate: false });
45
+ query.signal = signal;
45
46
  const outcome = await countThroughSource(resolved.source, query, resolved.descriptor.protocol, resolved.descriptor.id);
46
47
  return jsonText({
47
48
  source: resolved.ref.ref,
@@ -74,7 +74,7 @@ export declare const schema: z.ZodObject<{
74
74
  spatialRel?: "intersects" | "contains" | "within" | "crosses" | "touches" | "overlaps" | "bbox-intersects" | undefined;
75
75
  }>;
76
76
  export type Input = z.infer<typeof schema>;
77
- export declare function execute(client: HonuaClient, input: Input): Promise<{
77
+ export declare function execute(client: HonuaClient, input: Input, signal?: AbortSignal): Promise<{
78
78
  content: Array<{
79
79
  type: "text";
80
80
  text: string;
@@ -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;AAMxB;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjB,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;;;;;;;;;;;;GAgB9D"}
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;AAMxB;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjB,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,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;GAiBpF"}
@@ -15,10 +15,11 @@ export const schema = z.object({
15
15
  ...sourceRefFields,
16
16
  ...queryFilterFields,
17
17
  });
18
- export async function execute(client, input) {
18
+ export async function execute(client, input, signal) {
19
19
  return withCapabilityHonesty(async () => {
20
20
  const resolved = resolveSource(client, input);
21
21
  const query = toQuery(input, { protocol: resolved.descriptor.protocol, paginate: false });
22
+ query.signal = signal;
22
23
  const { extent, count } = await resolved.source.queryExtent(query);
23
24
  return jsonText({
24
25
  source: resolved.ref.ref,
@@ -111,7 +111,7 @@ export declare const schema: z.ZodObject<{
111
111
  outSr?: string | number | undefined;
112
112
  }>;
113
113
  export type Input = z.infer<typeof schema>;
114
- export declare function execute(client: HonuaClient, input: Input): Promise<{
114
+ export declare function execute(client: HonuaClient, input: Input, signal?: AbortSignal): Promise<{
115
115
  content: Array<{
116
116
  type: "text";
117
117
  text: string;
@@ -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;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAIjB,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;;;;;;;;;;;;GAyB9D"}
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;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAIjB,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,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;GA0BpF"}
@@ -18,10 +18,11 @@ export const schema = z.object({
18
18
  ...queryFilterFields,
19
19
  ...queryShapeFields,
20
20
  });
21
- export async function execute(client, input) {
21
+ export async function execute(client, input, signal) {
22
22
  return withCapabilityHonesty(async () => {
23
23
  const resolved = resolveSource(client, input);
24
24
  const query = toQuery(input, { protocol: resolved.descriptor.protocol });
25
+ query.signal = signal;
25
26
  const result = await resolved.source.query(query);
26
27
  // Legacy addressing keeps legacy output: a client that still sends
27
28
  // serviceId/layerId also still expects Esri-JSON geometry. Neutral
@@ -84,7 +84,7 @@ export declare const schema: z.ZodObject<{
84
84
  groupBy?: string | string[] | undefined;
85
85
  }>;
86
86
  export type Input = z.infer<typeof schema>;
87
- export declare function execute(client: HonuaClient, input: Input): Promise<{
87
+ export declare function execute(client: HonuaClient, input: Input, signal?: AbortSignal): Promise<{
88
88
  content: Array<{
89
89
  type: "text";
90
90
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../../../src/tools/statistics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAQ3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;;;;;;;;GAgC9D"}
1
+ {"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../../../src/tools/statistics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWjB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAQ3C,wBAAsB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;;;;;;GAiCpF"}
@@ -31,10 +31,11 @@ function normalizeGroupBy(groupBy) {
31
31
  const fields = (Array.isArray(groupBy) ? groupBy : groupBy.split(",")).map((f) => f.trim()).filter(Boolean);
32
32
  return fields.length > 0 ? fields : undefined;
33
33
  }
34
- export async function execute(client, input) {
34
+ export async function execute(client, input, signal) {
35
35
  return withCapabilityHonesty(async () => {
36
36
  const resolved = resolveSource(client, input);
37
37
  const base = toQuery(input, { protocol: resolved.descriptor.protocol, paginate: false });
38
+ base.signal = signal;
38
39
  // GeoServices rejects an `outStatistics` query that carries no `where`;
39
40
  // every other protocol treats "no filter" as "all records". Supplying the
40
41
  // tautology keeps the neutral "omit the filter ⇒ aggregate everything"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honua/mcp-server",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Platform-free MCP server for geospatial services: expose discovery, query, and analysis over any public ArcGIS/Esri FeatureServer or OGC API endpoint to any MCP client, with no platform lock-in",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Honua",
@@ -89,7 +89,7 @@
89
89
  "qs": "^6.16.0"
90
90
  },
91
91
  "peerDependencies": {
92
- "@honua/sdk-js": "^0.1.13"
92
+ "@honua/sdk-js": "^0.1.14"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@biomejs/biome": "1.9.4",