Skip to main content
Glama

hk-spatial-mcp

Hong Kong's 1,154 official spatial datasets → any AI agent, in one function call.

Point any MCP-capable client at this server and it can search the whole Common Spatial Data Infrastructure catalogue in English, 繁體中文 or 简体中文, pull real GeoJSON, answer questions with numbers and charts, and hand back a 2D map, a 3D scene or a printable static map. No ArcGIS account, no API key, no GIS library, no npm install — one Python process and the open data itself.

License: MIT Python Protocol Datasets Dependencies selftest

Ask in Cantonese, get an answer

用 hk-spatial 講我知香港有幾多個水塘, 可唔可以 build 個 map 比我睇下 → 17 reservoirs, 586.05 million m³, chart, then the map below. Takes ~2 minutes end to end, most of it the model thinking.

Any of the 1,154 datasets

EV chargers by district · registered man-made slopes · private buildings · public toilets · 3D pedestrian network · hospitals · country-park attractions · waste facilities · school social work · district boundaries. The reservoirs below are one example, not the scope.

See it work

A conversation, not a config file — the real client run behind the answer above:

An MCP client answering a Cantonese question with cards, a chart and a map from CSDI data

The map it returned — ▶ open it live (3D scene): pan, zoom, and click any feature to see every attribute field. No install needed to look; these pages are the unmodified output of build_map / build_scene, served as static files.

Hong Kong CSDI data on an interactive web map, with a feature's attributes shown

(Attribute card from OBJECTID to SHAPE_AREA is built by the server's own click handler — not a third-party popup library. Basemap tiles are keyless Esri; data is CSDI open data.)

The demo is not a mock-up and not a separate app: docs/ is the plain output of these calls. Regenerate it with any other dataset IDs you like:

HK_MCP_DIR=./docs python3 -c "
import hk_spatial_mcp as m
res, att = 'wsd_rcd_1629267205232_96199', 'afcd_rcd_1728896853370_57183'
m.load_hk_data(res); m.load_hk_data(att)
m.build_map([res, att], 'Hong Kong — Impounding Reservoirs & Country Park Attractions', 'imagery')
m.build_scene([res], 'Hong Kong Impounding Reservoirs', 'imagery', tilt=65)"

Unofficial, community project. CSDI is operated by the Spatial Data Office, Development Bureau, HKSAR Government. The Office has stated that it plans to develop its own CSDI MCP server in 2027. This repository is an independent implementation and claims no affiliation with the Government, the Spatial Data Office, or Esri.

Contents


Related MCP server: data-bs-mcp

Capabilities

Capability

Detail

Catalogue search

All 1,154 CSDI datasets, indexed locally and relevance-ranked. English, 繁體中文 and 简体中文 queries supported.

Data retrieval

Any dataset as GeoJSON in EPSG:4326, returned as a summary (feature count, geometry types, attribute fields, bounding box) rather than a raw feature dump.

Map rendering

One or many datasets rendered as an interactive 2D map or 3D scene (ArcGIS Maps SDK for JavaScript, keyless public basemap; 3D adds Terrain3D relief), served on localhost.

Feature inspection

Click any feature to open an attribute card — every field from the dataset, bilingual column names where CSDI provides them, URLs rendered as links.

Answers, not just maps

summarise_hk_data answers a question in text — counts, sums or averages grouped by any field — and renders a bar chart page. query_hk_data returns a few individual rows so a single value can be checked.

Printable static map

export_static_svg writes a vector map with the data drawn — basemap tiles plus the features as real shapes — ready to print to PDF from a browser.

Geocoding and geometry

Address ↔ coordinate (both directions), project / buffer / simplify on any GeoJSON geometry, ground elevation, via Esri's public services. No key required.

Basemaps

11 keyless Esri basemap styles (imagery, topographic, streets, light/dark gray, terrain, hillshade, ocean, physical, natgeo, shaded relief) plus an optional labels overlay.

Static map export

Render a basemap PNG (no key) into the workspace for reports and decks.

ArcGIS Online (optional)

Publish a dataset as a hosted feature layer, or call any ArcGIS REST endpoint (item search, feature queries, geoprocessing jobs) with your own token.

The data layer is the primary value: CSDI is the source of truth. The map renderer is interchangeable, and the ArcGIS Online tools are optional extensions that require your own credentials.


Requirements

  • Python 3.10 or newer, or uv (recommended — uvx runs the server without a manual install)

  • No other dependencies. Every tool function is pure standard library (json, math, urllib, http.server, threading, pathlib) — verified by running them under python3 -S, which disables site-packages entirely. mcp is imported inside main() only, so it is needed to serve MCP, never to use the functions from your own code.

  • An MCP-capable client (Claude Desktop, Cursor, WorkBuddy / CodeBuddy, Codex, Hermes, DeepSeek Harness (DSH), or any stdio MCP client)

  • Network access to portal.csdi.gov.hk

  • Optional: an ArcGIS Online user or OAuth token, needed only for the publishing and content tools


Installation

Add the server to your MCP client configuration:

{
  "mcpServers": {
    "hk-spatial": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Cyruschu430/hk-spatial-mcp", "hk-spatial-mcp"],
      "env": {
        "ARCGIS_TOKEN": "",
        "HK_MCP_PORT": "8777"
      }
    }
  }
}

Configuration file locations vary by client:

Client

Configuration file

Claude Desktop (macOS)

~/Library/Application Support/Claude/claude_desktop_config.json

Cursor

<project>/.cursor/mcp.json

WorkBuddy / CodeBuddy

~/.workbuddy/mcp.json or <project>/.workbuddy/mcp.json

Codex

~/.codex/config.toml

DeepSeek Harness (DSH)

its own MCP server settings, added as an stdio entry named hk-spatial — set a generous toolCallTimeoutMs (180000) so large layers are not cut off

Any client that speaks MCP over stdio will work; the JSON shape above is the common form. Once the client reports the server as connected, the tools are available in the conversation.

DeepSeek Harness note. DSH keeps its own cache of the uvx environment, so after a new release run uv cache prune (or uvx --refresh …) before expecting the new tools — otherwise you keep testing the previous version. Its MCP client connects over stdio exactly as in the JSON above; a full search → summarise → map → click-a-feature flow completes in about two minutes end to end, most of it the model thinking rather than the tools.

Windows note. uvx --from git+… needs git on PATH. Set HK_MCP_DIR to an absolute path (for example C:\\Users\\you\\hk-spatial) — the default ./hk-spatial is relative to whatever working directory the client happens to launch with. Maps are served on http://localhost:<HK_MCP_PORT>/, so open that URL in your own browser.

Manual installation (without uvx)

git clone https://github.com/Cyruschu430/hk-spatial-mcp
cd hk-spatial-mcp
pip install "mcp>=1.2"
python3 hk_spatial_mcp.py          # stdio MCP server

Prompt cookbook

Ready-to-use instructions for an AI client. The English and Chinese versions are equivalent — use whichever suits your users; the underlying tool calls are identical.

1. Connectivity check

Search the CSDI catalogue for "country park" using hk-spatial and list the first five datasets.
用 hk-spatial 搜尋 CSDI 目錄中的「郊野公園」,列出前五個數據集。

2. Data to map (the core workflow)

Using hk-spatial, find the Hong Kong country parks dataset, load it, and build an interactive web map
titled "HK Country Parks". Then report the preview URL.
用 hk-spatial 找出香港郊野公園數據集,載入後建立一個標題為「HK Country Parks」的互動地圖,
並回報預覽網址。

3. Chinese-language query, single layer

Using hk-spatial, find the location data for public toilets in Hong Kong and produce a map.
用 hk-spatial 找出全港公廁的位置數據,並產生地圖。

4. Multiple layers in one map

Using hk-spatial, retrieve three datasets — electric vehicle chargers, public hospitals and the
pedestrian network — and place them all on a single map with a distinct colour per layer and the
dataset name shown in the legend.
用 hk-spatial 同時取得三組數據:電動車充電站、公立醫院及行人路網絡,全部放在同一張地圖上,
每層使用不同顏色,並在地圖圖例中標示數據集名稱。

5. Extending an existing map

Using hk-spatial, add the bus routes dataset to the map you just built and confirm when it is added.
用 hk-spatial 在剛才建立的地圖上再加入「巴士路線」數據集,完成後通知我。

6. Catalogue reconnaissance before committing

Using hk-spatial, list every dataset related to slope safety and describe each one in a single sentence.
用 hk-spatial 列出所有與斜坡安全相關的數據集,並為每個數據集提供一句說明。

7. Geocode an address onto the map

Using hk-spatial, geocode "Hong Kong Convention and Exhibition Centre" and add it to a map as a
single labelled point.
用 hk-spatial 將「香港會議展覽中心」地理編碼,並以單一標註點加入地圖。

8. Coverage ring (buffer) around a facility

Using hk-spatial, load the electric vehicle chargers dataset, then produce a 500-metre buffer around
the first charger with geometry_op and add it to the map so the coverage ring is visible.
用 hk-spatial 載入電動車充電站數據,再用 geometry_op 為第一個充電站建立 500 米緩衝區,
並加入地圖以顯示其覆蓋範圍。

9. Ask a question, get a table and a chart

Using hk-spatial, find the EV charger dataset and tell me how many public chargers there are in each
district, with a bar chart.
用 hk-spatial 搵電動車充電站數據,話我知每區有幾多個公眾充電站,並出一張棒形圖。

10. Check one value, then print a static map

Using hk-spatial, query the reservoir dataset for the row whose name matches 大潭, then export a printable
static map of the reservoirs that I can open and print to PDF.
用 hk-spatial 喺水塘數據查「大潭」嗰一筆記錄,然後輸出一張可直接列印做 PDF 嘅靜態地圖。

11. Same data as a 3D scene

Using hk-spatial, take the country parks and slopes datasets and render them as a 3D scene with terrain
relief, camera tilted about 60 degrees, then give me the scene URL.
用 hk-spatial 將郊野公園及斜坡數據渲染成 3D 場景,開啟地形起伏、鏡頭傾斜約 60 度,
並提供場景網址。

12. Publish to ArcGIS Online (requires ARCGIS_TOKEN)

Using hk-spatial, publish the country parks dataset to my ArcGIS Online organisation as a hosted
feature layer titled "HK Country Parks" and return the item link.
用 hk-spatial 將郊野公園數據集發佈到我的 ArcGIS Online 組織,命名為「HK Country Parks」,
並回報項目連結。

13. Query existing ArcGIS Online content (requires ARCGIS_TOKEN)

Using hk-spatial's arcgis_request tool, list the five most recent feature layers in my ArcGIS Online
account together with their names and item IDs.
用 hk-spatial 的 arcgis_request 工具,列出我 ArcGIS Online 帳戶中最近五個圖層服務的名稱與項目 ID。

14. Enforce the intended workflow

Load SKILL.md as the agent's skill or system prompt. It constrains the agent to the search → load → build_map sequence, prohibits fabricating data, prohibits pasting feature records into the conversation, and requires the "Powered by Esri" attribution to be preserved.

If the agent starts writing its own HTTP code, instruct it explicitly:

Do not write custom fetch code. Use the hk-spatial tools — they already handle CSDI's catalogue
search, GeoJSON export, coordinate system and non-spatial datasets.
請勿自行編寫抓取程式碼,改用 hk-spatial 工具;它已處理 CSDI 的目錄搜尋、GeoJSON 匯出、
坐標系統及非空間數據集等細節。

Tool reference

search_hk_data(keyword: str = "", limit: int = 10, offset: int = 0)

Searches all 1,154 CSDI datasets using the local index. Returns dataset_id, English and Chinese titles, publishing organisation, last update date, relevance score and an exportable flag.

  • Omitting keyword enumerates the catalogue; paginate with offset. limit is capped at 30.

  • English and Chinese queries are both supported; Hong Kong terminology is expanded automatically (廁所 → 洗手間, 行人路 → pedestrian, 電動車 → electric vehicle charging, 斜坡安全 → slope).

  • When nothing matches locally, the tool falls back to the CSDI catalogue service for broader recall.

load_hk_data(dataset_id: str, name: str = "")

Downloads a dataset as GeoJSON (EPSG:4326) into the workspace and returns a summary: feature count, geometry types, attribute field names, bounding box and file path. Feature records are never returned to the model.

summarise_hk_data(dataset_id, group_by="", value_field="", agg="count", top=20)

Answers a question about a dataset in text, without putting features into the chat.

  • No group_by → an overview: feature count, geometry types, the fields worth grouping by (with their cardinality) and the numeric fields.

  • group_by="NAME_OF_DISTRICT_COUNCIL_DISTRICT_EN" → features per group.

  • agg="sum" (or "avg") plus value_field="MEDIUM_IEC62196_no" → totals or averages per group.

Returns an aligned text table, the same rows as data, and a chart_url for a rendered bar chart page. Example — EV charging sockets per district in Hong Kong:

group                  sum of MEDIUM_IEC62196_no
---------------------------------------------
Kwun Tong                            1,438
Kowloon City                         1,229
Sha Tin                                874
...

query_hk_data(dataset_id, where="", fields="", limit=5)

Returns a few individual features so one value can be verified without opening the GeoJSON file. where is either FIELD=value (case-insensitive match on that field) or bare text searched across all fields. Rows are hard-capped at 20 and each row carries its _geometry type and first vertex — this tool exists to check a number, not to dump a dataset.

dataset_status(dataset_id="", probe=False, limit=10, stale_after_days=365)

Answers "is this dataset still there, and how old is it?" — the question every downstream user asks only after something breaks.

  • No dataset_id → the limit oldest datasets in the catalogue, so drift is visible at a glance.

  • probe=True → also calls the CSDI export endpoint and reports HTTP status + latency. Reads 2 KB and hangs up, so it never re-downloads a dataset just to say "yes". Capped at 10 probes per call.

  • Reports catalogue dct:modified age, a fresh / aging / stale verdict, the exportable flag, and the local cache size/age if you have already downloaded it.

Catalogue date ≠ data freshness. catalogue_updated is when CSDI revised the record. The statistical reference period of the data itself is a separate thing and is not reported here. Keep both when you cite.

{"checked": 5, "probed": 1, "stale": 5,
 "datasets": [{"dataset_id": "landsd_rcd_1631586233...", "catalogue_updated": "2022-03-31",
               "age_days": 1667.0, "state": "stale", "exportable": true, "local_cache": null,
               "live": {"http": 200, "ms": 228, "body": "geojson"}}]}

build_map(dataset_ids, title="Hong Kong Spatial Data", basemap="imagery", labels=False)

Builds an interactive map from the loaded datasets and serves it on http://localhost:<HK_MCP_PORT>/. Returns the URL, layer list, total feature count and warnings for oversized layers. Layers above 3,000 features are streamed from the served file rather than inlined into the page.

basemap accepts any keyless style: imagery, topographic, streets, light-gray, dark-gray, terrain, hillshade, ocean, physical, natgeo, shaded-relief. labels=True adds Esri's boundaries-and-places reference overlay on top.

Clicking a feature opens an attribute card in the bottom-left corner of the page: every attribute field of that feature, NAME_TC / LOCATION_TC shown next to the English columns, and any URL rendered as a link. The field labels come from the dataset itself, so nothing is hard-coded per dataset. Multi-layer maps work the same way — whichever layer the click hits wins.

build_scene(dataset_ids, title="Hong Kong Spatial Data", basemap="imagery", labels=False, tilt=60)

Same datasets as build_map, rendered in a 3D scene served at scene.html: Terrain3D ground, tilted camera (tilt degrees), lines and polygons draped on the terrain. Use it when relief, height or coastal context matters — slopes, trails, towers, district skyline. Keyless, same warnings as build_map.

Both pages are plain static HTML over the same served GeoJSON, so you can keep the 2D map for analysis and the 3D scene for the walkthrough of the same workspace.

Every build also writes a build-specific page (2d-<title>-<hash>.html, 3d-…, chart-…) and returns its URL, so building a new map never destroys an earlier one. The conventional names (index.html, scene.html, chart.html) are refreshed to the newest build for convenience; latest_url in the response points at them.

geocode_address(single_line="", max_results=5, lon=None, lat=None)

Geocodes an address or place name and returns candidates with longitude, latitude and a match score (EPSG:4326). Pass lon and lat instead to reverse geocode a coordinate into a street address — in Hong Kong it returns Chinese addresses. No key required; the endpoint is rate-limited, so use an ArcGIS Location Platform key for production volumes.

elevation_at(lon: float, lat: float)

Ground elevation in metres from Esri's public Terrain3D service. No key required.

export_static_map(bbox=None, center=None, zoom=14, basemap="streets", size="900,600")

Renders a basemap PNG into <workspace>/exports/ and returns the file path and a served URL. Give either bbox (minx,miny,maxx,maxy in EPSG:4326) or center + zoom. No key required.

The image contains the basemap only — CSDI features are not drawn on it. For a static map that does include the data, use export_static_svg below.

export_static_svg(dataset_ids, title="Hong Kong", basemap="streets", max_px=1400)

Writes a printable static map with the data drawn: basemap tiles referenced by URL plus every feature as a real vector shape (points, polylines, polygons), a legend box with per-layer colours and counts, and the attribution line. Output is one self-contained .svg; open it in a browser and print to PDF for a report.

The zoom is chosen automatically so the whole extent fits within max_px. No key, no headless browser and no image library are involved — it is string assembly over the same local GeoJSON the other tools use.

geometry_op(operation, geojson, in_sr=4326, out_sr=None, distance=500, unit="meters", max_deviation=None)

Runs one geometry operation through Esri's public Geometry service and returns GeoJSON. No key required.

Operation

Use

project

Reproject a geometry, e.g. in_sr=2326, out_sr=4326 for CSDI layers published in HK1980 Grid

buffer

Coverage rings — distance in unit (meters, kilometers, feet, miles, nauticalmiles)

simplify

Reduce vertex count on large polygons before rendering (max_deviation in input units)

Accepts and returns GeoJSON Point, MultiPoint, LineString, MultiLineString, Polygon and MultiPolygon.

arcgis_request(path: str, params: dict | None = None, method: str = "GET")

Calls any ArcGIS REST endpoint with the configured token. The token is never echoed back in a response.

arcgis_request("search", {"q": "owner:me", "num": 10})                      # find items
arcgis_request("content/items/<itemId>/data")                               # item JSON
arcgis_request("<featureServiceUrl>/0/query", {"where": "1=1", "returnCountOnly": "true"})

publish_layer(dataset_id: str, title: str = "", tags: str = "CSDI,Hong Kong")

Uploads a dataset to ArcGIS Online as a hosted feature layer and returns the itemId and item URL. Consumes organisation credits and storage capacity.

Authentication. arcgis_request and publish_layer require ARCGIS_TOKEN set to a user or OAuth token. An ArcGIS API key is sufficient for basemaps and geocoding but cannot read or create organisation content.


Configuration

Variable

Default

Purpose

HK_MCP_DIR

./hk-spatial

Workspace for the catalogue cache, downloaded GeoJSON and the generated map

HK_MCP_PORT

8777

Port for the map preview server

HK_MCP_BIND

127.0.0.1

Bind address for the map preview server; set 0.0.0.0 only behind a reverse proxy

HK_MCP_PUBLIC_URL

(empty)

Public base URL that build_map returns, e.g. https://maps.example.hk/

HK_MCP_TRANSPORT

stdio

stdio, streamable-http or sse

HK_MCP_HOST

127.0.0.1

Bind address for the HTTP transport

HK_MCP_HTTP_PORT

8788

Port for the HTTP transport (endpoint /mcp)

ARCGIS_TOKEN

(empty)

ArcGIS Online user/OAuth token; required only for the content and publishing tools

ARCGIS_URL

https://www.arcgis.com

Portal base URL, for ArcGIS Enterprise deployments


Data source and coverage

  • Source: CSDI portal (portal.csdi.gov.hk) — CSW 2.0.2 catalogue service and the file-api GeoJSON export endpoint.

  • Coverage verified 2026-10-22: 1,154 datasets from 70+ government departments and organisations.

  • Caching: the full catalogue is retrieved in a single request (~2 s, ~2.8 MB) and cached for seven days as catalog.json in the workspace; searches then run offline.

  • Non-spatial datasets: 13 of the 1,154 have no GeoJSON export and are flagged exportable: false; load_hk_data returns an explanatory error together with the metadata page link.

  • Licensing: each dataset carries its own terms. CSDI data is published by the HKSAR Government — review the individual dataset's licence before redistribution or commercial use.


Using it without the SDK, or inside your own information system

Nothing to install for the rendering layer. The map and scene pages load ArcGIS Maps SDK 5 from js.arcgis.com as ES modules. There is no npm install, no bundler, no build step, and no ArcGIS account: the only requirement is that the viewer's browser can reach js.arcgis.com and server.arcgisonline.com. An agent that has never heard of the SDK still produces a working map, because the server writes the page and reports a URL.

The tools are plain Python. Every tool is an ordinary function returning JSON — the MCP wrapper is separate. If you are building an information system (a portal, an internal dashboard, a report generator), import them directly and skip MCP altogether:

from hk_spatial_mcp import search_hk_data, load_hk_data, summarise_hk_data, build_map

hit = json.loads(search_hk_data("電動車充電", 1))["hits"][0]
load_hk_data(hit["dataset_id"], hit["title"])

stats = json.loads(summarise_hk_data(hit["dataset_id"],
                                     "NAME_OF_DISTRICT_COUNCIL_DISTRICT_EN", "", "count"))
print(stats["table"])          # a text answer for the UI
print(stats["chart_url"])      # an SVG bar chart page, same origin as the map

map_url = json.loads(build_map([hit["dataset_id"]], "EV chargers"))["url"]

That is the whole integration: text answers, a chart page, a map page — all from the same process, with no cloud account and no billing.

Keyless Esri services

Everything in this table answered without a key or token when verified on 2026-10-22, and is wired into a tool where one exists:

Service

Use

Tool

server.arcgisonline.com/.../<Basemap>/MapServer

11 basemap styles + boundaries/labels overlay

build_map(basemap=…)

<Basemap>/MapServer/export

server-side basemap PNG

export_static_map()

utility.arcgisonline.com/.../Geometry/GeometryServer

project, buffer, simplify, convexHull, findTransformations

geometry_op()

geocode.arcgis.com/.../World/GeocodeServer

findAddressCandidates, reverseGeocode

geocode_address()

elevation3d.arcgis.com/.../Terrain3D/ImageServer

identify → ground elevation

elevation_at()

Public Living Atlas feature services

read-only reference layers (e.g. World_Countries)

arcgis_request() / layer URL

Needs ARCGIS_TOKEN, and usually credits: AGOL standard analysis (analysis.arcgis.com), routing (route-api.arcgis.com), GeoEnrichment, print services, and any content in your own organisation.

Tested and deliberately not wrapped: the Geometry service's lengths, areasAndLengths, distance, densify, labelPoints and autoComplete operations reject the standard parameter names this client sends (empty geometry / must be specified errors). They are not exposed rather than exposed broken — compute lengths and distances locally, which is exact enough at city scale anyway.

SDK and design system

The rendering layer is deliberately thin and explicit, so it doubles as a reference implementation:

Piece

What is used

Where

Maps SDK

ArcGIS Maps SDK for JavaScript 5.0, ESM modules from js.arcgis.com/5.0

the template in hk_spatial_mcp.py

2D / 3D views

MapView and SceneView over the same Map object

build_map vs build_scene

Terrain

ElevationLayer on map.ground (Terrain3D, keyless)

3D scene only

Data layers

GeoJSONLayer with a geometry-aware renderer, streamed above 3,000 features

both

Basemaps

TileLayer against public arcgisonline.com services

both

UI

hand-written dark glass CSS — no component library, no build step

both pages

Calcite (Esri's design system) is not bundled on purpose. The template's CSS exists so the page works with zero dependencies and stays readable when you customise it. If you want Calcite components for a production app, the CDN is available and versioned:

<link rel="stylesheet" href="https://js.arcgis.com/calcite-components/3.3.0/calcite.css" />
<script type="module" src="https://js.arcgis.com/calcite-components/3.3.0/calcite.esm.js"></script>
<calcite-block heading="Layers" open> … </calcite-block>

Those two URLs were confirmed reachable (200, text/css and JS) but are not exercised by this repository's tests — swap the panel markup for calcite-shell / calcite-block / calcite-list and verify visually before shipping.

Performance

Measured on a 2 vCPU / 3.5 GB VPS with a warm catalogue cache:

Step

Time

search_hk_data (local index)

10–20 ms

load_hk_data, first download (small dataset)

0.3 s

load_hk_data, first download (87,946 features / 30 MB)

14 s

load_hk_data, cache hit (same layer)

0.3 s — the file is reused; refresh=True re-downloads

build_map / build_scene (any layer count)

under 25 ms — it writes HTML, the browser does the rest

2D page until view.when() resolves (headless Chrome, 3 layers, no GPU)

2.8 s, 250 requests

Whole flow in a real client (DeepSeek Harness: search → summarise → map → click a feature)

~2 min wall clock, dominated by model thinking

The 3D scene is heavier on the client: same data plus terrain tiles and WebGL. On a GPU-less headless browser it stays saturated well past 30 s, which says nothing useful about a real machine — open scene.html locally and read window.__readyMs in the console for your own number.

The model-facing cost is small by design: a full search → load → build_map flow returns roughly 2,600 characters of JSON, so the agent does not need long reasoning to produce a map.

Design notes

  • No SDK popup. On Maps SDK 5.0 a programmatically created MapView does not inject the popup UI — the popup is a beta web component (<arcgis-popup>) and popupEnabled on its own opens nothing. Rather than pull in a beta component, the template ships one view.on("click") handler and one styled card. Predictable across SDK releases, and it matches the rest of the UI.

  • Every layer is served by URL. GeoJSONLayer with an inline data property (and with blob) fails to load on 5.0 — TypeError: Cannot read properties of null (reading 'type'). All layers are written to data/<dataset>.geojson and referenced by URL, so there is one code path and the HTML stays small.

  • Why a local index. The catalogue service's AnyText query is high-recall but low-precision (a Chinese query such as 廁所 returns 185 hits with irrelevant ranking). Indexing the full catalogue locally allows field-weighted ranking across English, Traditional and Simplified Chinese metadata, and removes a network round-trip from every search.

  • Large datasets. file-api returns complete datasets — for example Registered Man-made Slopes is 61,527 features (153 MB) and Building is 87,946 features (30 MB). Layers above 3,000 features are streamed from the served file instead of embedded in the HTML, and layers above 60 MB produce an explicit performance warning. Data is never silently sampled or truncated.

  • Coordinate system. All output is EPSG:4326. No reprojection is performed, and a Hong Kong bounding-box assertion guards the pipeline against projection errors.

  • Basemap. Keyless Esri World Imagery tiles with the SDK's own attribution. Attribution is a licensing requirement of the basemap — keep "Powered by Esri" visible if you adapt the template.


FAQ

Do I need an ArcGIS account?

No. search_hk_data, load_hk_data and build_map need no account, no key and no subscription — the basemap uses Esri's keyless public tiles and CSDI itself is open data. Only publish_layer and arcgis_request require ARCGIS_TOKEN; without it they return a clear error and the other three tools continue to work normally. If you never need ArcGIS Online, ignore those two tools entirely: the GeoJSON is already on disk, so you can ship it to your own server, a static site, or any other viewer.

What about geoprocessing / spatial analysis?

There is no built-in analysis engine, and that is deliberate — the server's job is to get authoritative data out of CSDI intact. Two supported routes:

  1. ArcGIS public geometry operations (no key, no credits). geometry_op covers projection, buffering and simplification — enough for coverage rings, CSDI layers published in HK1980 Grid, and rendering preparation. geocode_address covers address → point. Both are exercised by the self-test.

  2. ArcGIS Online geoprocessing. Locate a GP service task and drive it through arcgis_request: submitJob with the parameters, then poll jobs/<jobId>. This requires ARCGIS_TOKEN, and the service consumes organisation credits. The request passthrough itself is implemented and its token handling is tested; a live geoprocessing run has not been exercised in this repository's test suite (no test organisation credentials are bundled), so validate against your own service before relying on it.

  3. Local analysis. Every dataset is on disk as GeoJSON in EPSG:4326, so an agent can process it with whatever Python stack is installed (shapely, pyproj, geopandas, duckdb spatial) and hand the result back through build_map. This keeps the analysis explainable and free of credit costs.

Are any web development dependencies required?

None. build_map writes a single static HTML file and serves it with Python's standard-library HTTP server. The map library (ArcGIS Maps SDK for JavaScript) is loaded as ES modules from js.arcgis.com/5.0 — no npm, no Node.js, no bundler, no build step, no transpiler. The generated page is plain HTML/CSS/JS you can open, edit or re-host anywhere.

Requirement to be aware of: the browser must be able to reach js.arcgis.com and server.arcgisonline.com. In an air-gapped or restricted intranet deployment the map will render blank — self-host the SDK assets and substitute a locally reachable tile source in that case.

On the server side the only dependency is the mcp package (uvx installs it automatically); everything else is the Python standard library.

Does it work alongside other agent skills and tools?

Yes. It is a standard MCP server over stdio or HTTP, so it composes in the same client with any other MCP server — file system, git, web search, databases, or other geospatial servers. Nothing here assumes it is the only tool available.

Two mechanisms improve reliability when several tools are present:

  • SKILL.md — load it as the agent's skill or system prompt to pin the search → load → build_map sequence and prohibit ad-hoc HTTP code.

  • Self-describing tool metadata — each tool documents its arguments and return shape, so most clients route correctly without extra prompting.

The wider GIS MCP ecosystem (including Esri's ArcGIS Location Services MCP and various ArcGIS Pro / ArcPy bridges) is complementary rather than duplicative: those expose geoprocessing and location services, whereas this server's focus is the CSDI data layer.

Can it run as a remote MCP server?

Yes. stdio is only the default. Set the transport and it serves MCP over HTTP:

HK_MCP_TRANSPORT=streamable-http HK_MCP_HOST=0.0.0.0 HK_MCP_HTTP_PORT=8788 python3 hk_spatial_mcp.py
# endpoint: POST http://<host>:8788/mcp   (text/event-stream; `sse` is also supported)

Verified in this repository: initialize and tools/list succeed over Streamable HTTP. Clients that support HTTP MCP servers connect to the URL and headers instead of spawning a process.

Two things must be configured for the map to be usable by a remote caller:

HK_MCP_BIND=0.0.0.0                       # let the map preview server accept non-loopback traffic
HK_MCP_PUBLIC_URL=https://maps.example.hk/  # the URL build_map returns to the caller

Deployment caveats — read before exposing it:

  • This repository does not host, deploy or operate any server. Running it remotely is entirely the operator's responsibility.

  • There is no built-in authentication. Do not expose the port to the internet directly. Terminate TLS and enforce a bearer token or OAuth at a reverse proxy in front of it (MCP's OAuth flow requires an authorization server, which is out of scope here).

  • A shared ARCGIS_TOKEN makes every caller act as that account. For any multi-user deployment, issue per-user tokens, or expose read-only tools only, or omit the publishing tools from the deployed build.

  • State is per process. The workspace directory and the single map preview are shared by all callers, so concurrent users overwrite each other's map. For real multi-tenant use, run one process (with its own HK_MCP_DIR) per user or per session.

Troubleshooting

Symptom

Cause and resolution

Client reports the server as disconnected

The process exited during start-up. Run python3 hk_spatial_mcp.py directly to see the traceback; the usual cause is a missing mcp package or Python older than 3.10.

ARCGIS_TOKEN not set

Expected for the two ArcGIS Online tools. Set a user or OAuth token in the client's env block.

HTTP 404 on load_hk_data

The dataset has no GeoJSON export (13 of 1,154). Search again and use a result with exportable: true.

The map does not refresh

The preview page must be reloaded after each build_map call.

The map is slow or the browser stalls

The layer is very large. Use the warn output from build_map as a guide and prefer smaller or district-level datasets.

Port 8777 is already in use

Set HK_MCP_PORT to a free port in the client's env block.


Verification

python3 hk_spatial_mcp.py --selftest

The self-test harvests the catalogue, asserts it contains more than 1,100 datasets, runs English and Chinese searches with expected top results, downloads a dataset, asserts Hong Kong coordinates, builds the map and confirms the page is served.

Two integration tests exercise the MCP protocol over stdio:

python3 test_mcp_client.py       # against the local file
python3 test_install_path.py     # against the published git URL — i.e. what users actually install

Licensing and attribution

  • Source code: MIT (see LICENSE).

  • CSDI data: © HKSAR Government, subject to each dataset's licence.

  • Basemap: Esri World Imagery, used under Esri's terms; "Powered by Esri" attribution retained.

Available Tools

14 tools
arcgis_requestB

Call any ArcGIS Online REST endpoint with the configured token.

Examples: path="search", params={"q": 'title:"my layer"', "num": 5} → find items path="content/items//data", params={} → item JSON path="content/items/", params={} → item metadata path="/0/query", params={"where":"1=1","outFields":"*","f":"json","returnCountOnly":"true"} → count analysis: run a GP task under //submitJob (then /jobs/)

NameRequiredDescriptionDefault
pathYes
methodNoGET
paramsNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It mentions the configured token but does not disclose whether requests can mutate data, how the method affects safety, whether errors are surfaced, or what happens with POST versus GET; the examples include a job submission but no warning about side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a one-sentence purpose followed by compact, concrete examples. The examples are directly relevant and no sentence is wasted for a tool that must cover arbitrary ArcGIS endpoints.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-level generic REST caller with no annotations and 0% schema description coverage, the definition is missing critical context: method semantics, mutation/safety guidance, error behavior, and when to prefer this over the many sibling tools. The output schema exists, so return-value documentation is appropriately not repeated in the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully compensate. It gives useful path and params examples, but the method parameter is never explained—even though choosing GET versus POST is critical for a generic REST caller—and the null/default behavior of params is not clarified beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Call any ArcGIS Online REST endpoint with the configured token.' It is clear what the tool does, but it does not explicitly differentiate itself from the many higher-level sibling tools such as query_hk_data or build_map.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The examples imply several usage scenarios—searching items, fetching item JSON, querying feature services, and submitting GP jobs—but there is no explicit guidance on when to use this generic tool versus the domain-specific siblings, nor any stated exclusions or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

build_mapB

Build an interactive 2D web map (ArcGIS Maps SDK, keyless basemap) from loaded datasets and serve it on localhost. Open the returned URL in your client's browser or preview pane.

NameRequiredDescriptionDefault
titleNoHong Kong Spatial Data
labelsNo
basemapNoimagery
dataset_idsYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose useful traits: keyless basemap (no token needed), a localhost server is started, and the caller receives a URL to open. It omits server lifecycle (does it keep running, on what port, how is it stopped), failure behavior for invalid dataset_ids, and whether writes occur on disk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with the core capability front-loaded and the post-call action (open the URL) as the trailing detail. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the description covers what the tool produces at a high level. But for a 4-parameter tool with 0% schema coverage and zero annotations, three of four parameters and the server's behavior remain undocumented.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 4 parameters, so the description must compensate and largely does not: only dataset_ids is hinted at via 'from loaded datasets.' The default basemap ('imagery') is only obliquely gestured at by 'keyless basemap,' and title and labels are never mentioned at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Build an interactive 2D web map'), names the rendering stack (ArcGIS Maps SDK) and the input source (loaded datasets), and says it serves the result on localhost. It never explicitly contrasts with build_scene (3D) or export_static_map, so an agent must infer the 2D-vs-3D and interactive-vs-static split from adjectives alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'from loaded datasets' implies the prerequisite that data must first be loaded via load_hk_data, and 'open the returned URL in your client's browser' tells the agent what to do after. There is no explicit when-not guidance and no routing to build_scene or export_static_map for alternative output shapes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

build_sceneA

Same datasets, rendered in a 3D scene: terrain relief, tilted camera, layers draped on the ground. Keyless (public imagery + Terrain3D elevation). Use it when relief, height or a walk-through view matters — towers, slopes, trails, coastal context.

NameRequiredDescriptionDefault
tiltNo
titleNoHong Kong Spatial Data
labelsNo
basemapNoimagery
dataset_idsYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose the important operational fact: 'Keyless (public imagery + Terrain3D elevation)', which tells the agent no credentials or setup are needed. It says nothing about side effects, whether a scene is persisted/published, or rendering cost, so the write/read profile remains ambiguous.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, purpose front-loaded, then the use case. No filler, no repetition of the tool name, and the concrete examples land at the end where they help most.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be described, and the description adequately covers what the tool produces and when to reach for it. The remaining gap is invocation-level: no guidance on tilt values, when to enable labels, or allowed basemaps, which matters given a 0%-described schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 5 parameters, so the description must compensate and largely doesn't. Only 'tilted camera' loosely hints at the tilt parameter and 'imagery' at the basemap default; labels, title, and the meaning of dataset_ids are left entirely undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: rendering datasets as a 3D scene with terrain relief and a tilted camera. The opening 'Same datasets, rendered in a 3D scene' implicitly contrasts with the 2D sibling build_map, though it never names it. An agent can tell what it produces, if not exactly how it differs from build_map's static output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use it when relief, height or a walk-through view matters — towers, slopes, trails, coastal context' gives a concrete selection criterion tied to the user's intent. It stops short of explicitly routing the agent to build_map when a flat map suffices, so the alternative is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

dataset_statusA

Are these datasets still being served, and how stale are they?

No dataset_id -> lists the limit oldest datasets in the catalogue, so you can see drift at a glance. probe=True also calls the CSDI export endpoint to confirm it answers right now (reads 2 KB only, costs a round trip each — capped at 10 per call).

Treat catalogue date and data freshness as SEPARATE things: the date below is CSDI's dct:modified (when the record was revised), not the statistical reference period of the data.

NameRequiredDescriptionDefault
limitNo
probeNo
dataset_idNo
stale_after_daysNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses that probe makes a live network round trip, reads only 2 KB, and is capped at 10 per call — the kind of cost/limit detail an agent needs before enabling it. It also flags a semantic trap (dct:modified is record revision date, not the statistical reference period). It stops short of describing failure behavior when a probe does not answer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core question, then structured into mode behavior and a distinct caveat paragraph. Every sentence carries information; only the question-form opener costs a little directness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and the probe cost/cap and date-semantics caveat are covered. But one of four parameters (stale_after_days) is left completely undefined, which is a real gap for a tool whose central claim is judging staleness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains limit (the N oldest datasets), probe (live endpoint check with cost and cap), and the absence of dataset_id (list mode), but stale_after_days — which clearly drives the staleness verdict — is never mentioned anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The rhetorical question is immediately grounded by concrete explanation: it reports whether datasets are still served and how stale they are, including a catalogue-listing mode. This is clearly distinguishable from catalogue-search or data-loading siblings such as search_hk_data and load_hk_data, though the opening framing is less direct than a verb+resource statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the two usage modes explicitly: omit dataset_id to get a drift overview of the oldest datasets, or pass probe=True to actively verify the CSDI export endpoint answers. It does not name a sibling as an alternative, but the when-to-use context is clear enough to act on.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

elevation_atB

Ground elevation in metres at a coordinate, from Esri's public Terrain3D service — no key. Handy for hiking/relief context (e.g. trail comfort, slope warnings) alongside CSDI layers.

NameRequiredDescriptionDefault
latYes
lonYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that no key is required and the return units, but omits accuracy, coordinate system expectations, coverage limits, and error behavior. Some value, but incomplete for a geospatial lookup.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose. The second sentence adds useful context without bloat, though it could be slightly tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values needn't be explained, and the description mentions units and no-key access. However, gaps in coordinate format and accuracy/coverage limit completeness for a geospatial tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only says 'at a coordinate' without specifying lat/lon format, order, projection, or valid ranges. Minimal compensation for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (ground elevation at a coordinate), units (metres), and source (Esri Terrain3D). It does not explicitly differentiate from siblings, but the operation is unique among them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear usage context: handy for hiking/relief context, trail comfort, slope warnings, alongside CSDI layers. No explicit when-not or alternatives are given, but the use case is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_static_mapA

Render a basemap-only PNG (no key) into the workspace — for reports, decks and docs. Give either bbox ("minx,miny,maxx,maxy" in EPSG:4326) or center + zoom. NOTE: CSDI features are NOT drawn on this image; use build_map for the interactive version, or an ArcGIS Online print service (needs ARCGIS_TOKEN) for data-on-basemap statics.

NameRequiredDescriptionDefault
bboxNo
sizeNo900,600
zoomNo
centerNo
basemapNostreets

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden and does disclose important traits: the result is a basemap-only PNG, CSDI features are excluded, and the ArcGIS alternative requires ARCGIS_TOKEN. It is less clear about file overwrite/naming behavior after writing into the workspace.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core operation and followed by invocation guidance and an important exclusion. Every sentence adds useful information without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main invocation path and alternatives well, and the output schema means return values need not be explained. However, for a 5-parameter tool with no annotations and 0% schema description coverage, size and basemap behavior remain under-specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description compensates only partially. It explains bbox format and CRS and the bbox-vs-center+zoom choice, but leaves size, basemap values, and center format undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: render a basemap-only PNG into the workspace. It clearly scopes the output to reports/decks/docs and explicitly separates this tool from build_map and ArcGIS print services.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit use cases (reports, decks, docs), tells the agent how to specify the area via bbox or center+zoom, and warns that CSDI features are not drawn. It also names the correct alternatives when data-on-basemap output is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_static_svgB

Write a printable static map WITH the data drawn, as one self-contained SVG page.

Basemap tiles are referenced by URL (they load in any browser with internet), features are drawn as real vector shapes on top — so the result prints cleanly to PDF from the browser's print dialog. No key, no headless browser, no image library.

NameRequiredDescriptionDefault
titleNoHong Kong
max_pxNo
basemapNostreets
dataset_idsYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses that basemap tiles are remote URLs requiring internet, that features are real vector shapes, and that no API key, headless browser, or image library is needed. It stops short of saying what file/path is produced or whether multiple datasets merge into one page.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the output artifact and then the mechanism. No filler, though the line-wrapped formatting slightly obscures the structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the behavioral picture is solid. The significant remaining gap is that a required parameter and the sizing/title options are undocumented anywhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% across four parameters, and the description documents none of them explicitly. 'Basemap tiles are referenced by URL' hints at the basemap option, but the required dataset_ids, the title, and the max_px pixel ceiling are never explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and artifact: 'Write a printable static map WITH the data drawn, as one self-contained SVG page.' The SVG/vector/print framing implicitly differentiates it from a raster export such as export_static_map, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The described use case (clean PDF printing from the browser print dialog) implies when to choose this tool, but there is no explicit 'use this instead of export_static_map when...' routing or any stated exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

geocode_addressA

Geocode an address/place to coordinates, or reverse-geocode a coordinate to an address. Esri public world geocoder — no key required. Reverse mode: pass lon and lat.

NameRequiredDescriptionDefault
latNo
lonNo
max_resultsNo
single_lineNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It usefully discloses that this is an Esri public world geocoder and that no key is required, but it does not mention rate limits, error behavior, or how result limits are handled.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three short sentences and is front-loaded with the primary purpose. The reverse-mode note follows logically and every sentence adds useful information without waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema is present, so return values need not be explained. But with no annotations and 0% schema coverage, the description is incomplete: it omits the forward-geocoding parameter and the meaning of `max_results`, leaving an agent with insufficient guidance for a four-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain the four parameters. It documents reverse-mode `lon` and `lat`, but leaves `single_line` and `max_results` unexplained, including the forward geocoding input path.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: geocode an address/place to coordinates, or reverse-geocode a coordinate to an address. It clearly separates the two modes and names the provider, making the tool distinct from the search/query/map siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a mode-specific instruction for reverse geocoding: pass `lon` and `lat`. However, it does not explain when to use this tool versus alternatives such as `arcgis_request`, nor does it clarify how forward geocoding should select the appropriate input parameter.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

geometry_opA

Project, buffer or simplify one GeoJSON geometry with Esri's public Geometry service — no key.

operation: "project" (in_sr -> out_sr, e.g. 2326 -> 4326), "buffer" (distance in unit), "simplify" (max_deviation in the input SR's units).

NameRequiredDescriptionDefault
unitNometers
in_srNo
out_srNo
geojsonYes
distanceNo
operationYes
max_deviationNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden, but it does disclose useful context: it uses Esri's public Geometry service and requires no key. It does not mention remote-call implications, rate limits, error behavior, or whether the input geometry is left unchanged, leaving meaningful gaps for an unannotated tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loaded, and wastes no words. The operation breakdown is compact and directly tied to invocation choices.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema exists, so return values need not be described. Still, for a 7-parameter, unannotated tool with 0% schema description coverage, the description is only partially complete: it covers the main operation-to-parameter relationships but omits unit vocabularies, validation expectations, and service limitations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It usefully maps operation modes to parameters: project uses in_sr/out_sr, buffer uses distance with unit, and simplify uses max_deviation in input SR units. It still leaves unit allowed values, SR ID expectations, geojson format details, and optional-parameter behavior unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names three specific operations (project, buffer, simplify) on a clearly scoped resource: one GeoJSON geometry. It also identifies the backing service, Esri's public Geometry service, so an agent can distinguish this computational geometry tool from the data, map, geocode, and export siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The operation-specific notes imply when each mode is appropriate: project for SR conversion, buffer for distance expansion, simplify for deviation reduction. However, there is no explicit when-to-use or when-not-to-use guidance and no comparison against siblings such as build_map or arcgis_request.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

load_hk_dataA

Download one CSDI dataset as GeoJSON (WGS84) into the workspace. Returns a SUMMARY, not the data itself — never paste the features into the chat, put them on a map with build_map(). The local copy is reused on later calls; pass refresh=True to re-download.

NameRequiredDescriptionDefault
nameNo
refreshNo
dataset_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that the return value is a summary rather than the data, that local copies are reused on later calls, that refresh=True forces a re-download, and that data is GeoJSON in WGS84. It does not cover failure modes, permissions, or dataset_id validation, so it is strong but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action and followed by the most important usage warning and caching detail. Every sentence adds practical value with no repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not explain the summary structure. For a data-loading tool with no annotations, it sufficiently covers output type, local caching, refresh semantics, and downstream map usage. The main remaining gap is parameter semantics for dataset_id and name.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains refresh=True behavior meaningfully, but leaves dataset_id format/valid values and the purpose of the name parameter undocumented. Only one of three parameters receives useful semantic explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Download one CSDI dataset as GeoJSON (WGS84) into the workspace.' It also clarifies the scope and points to build_map for visualization rather than pasting features, which helps distinguish it from query/search siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context: download data locally, then put it on a map with build_map(), and never paste features into chat. It also explains refresh behavior for re-downloading. It does not explicitly say when to use this instead of search_hk_data or query_hk_data, so it falls short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

publish_layerA

Publish a loaded CSDI dataset to ArcGIS Online as a hosted feature layer. Needs ARCGIS_TOKEN. Returns itemId + the new service URL.

NameRequiredDescriptionDefault
tagsNoCSDI,Hong Kong
titleNo
dataset_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose the key behaviors: an external auth requirement (ARCGIS_TOKEN) and a real side effect (creating a hosted layer in an external account). It omits whether publishing overwrites an existing service, who can see the result, or how to undo it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and destination, followed by the auth requirement and return shape. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because an output schema exists, the description needn't explain return values, though it helpfully does (itemId + service URL). The real gap is argument documentation: for a 3-param mutation with zero schema coverage, the description should at least say what dataset_id refers to and what title/tags control.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 3 parameters, and the description names none of them. Neither dataset_id (required) nor title nor tags (with its 'CSDI,Hong Kong' default) is explained, so an agent learns nothing about arguments from either source.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (publish), a specific resource (a loaded CSDI dataset), and a specific destination (ArcGIS Online as a hosted feature layer). It is clearly separable from siblings like load_hk_data (local ingest) and build_map (visualization).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'loaded CSDI dataset' implies the prerequisite that load_hk_data must run first, which is useful context. However, no alternative is named and no explicit when-not-to-use condition is given, so guidance is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_hk_dataA

Read a FEW individual features, so a single value can be verified without opening the GeoJSON.

where is either FIELD=value (case-insensitive match on one field) or bare text searched across all fields. Rows are capped at 20 — this tool exists to check a value, not to dump a dataset; use summarise_hk_data for aggregates and build_map to see the layer.

NameRequiredDescriptionDefault
limitNo
whereNo
fieldsNo
dataset_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the hard 20-row cap and the matching semantics of `where` (case-insensitive field match vs. free text across all fields), which are real behavioral facts. It is silent on error/empty-result behavior and permissions, but the read-only nature is clear from 'Read'.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short paragraphs with the core purpose front-loaded and no filler sentences; every clause either scopes the tool or routes to a sibling. The second paragraph blends query semantics with alternative-tool guidance, a minor organizational quibble.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. However, with zero annotation coverage and zero schema property descriptions, leaving `fields` undocumented and no note on empty results means the definition is not fully sufficient for a 4-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains `where` thoroughly and implies the row cap that governs `limit`, but `fields` is never explained despite being a non-obvious parameter (field projection). Roughly half the parameters gain meaning from the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Read a FEW individual features') and states the scope limit (single value verification, capped at 20 rows). It also explicitly distinguishes itself from `summarise_hk_data` (aggregates) and `build_map` (visualize layer), so an agent can tell what this tool is for without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear when-to-use ('so a single value can be verified') and when-not-to-use ('this tool exists to check a value, not to dump a dataset'), and names two alternatives with their purposes. It does not address the closest sibling, `search_hk_data`, leaving the query-vs-search distinction to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_hk_dataA

Search ALL ~1150 CSDI datasets locally (English or Chinese), ranked. No keyword = browse.

Chinese and English both work — Chinese terms are expanded with Hong Kong usage (廁所 -> 洗手間, 行人路 -> pedestrian, 電動車 -> electric vehicle charging, …). Returns dataset_id + bilingual title + why it matched. Feed dataset_id to load_hk_data().

NameRequiredDescriptionDefault
limitNo
offsetNo
keywordNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses local search scope, ranked results, Chinese synonym expansion, and the returned fields. It does not describe auth needs, rate limits, or pagination behavior, but for a local read-style search the key behavioral traits are mostly covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with scope and browse behavior, then adds language expansion and the load_hk_data handoff. It has minor redundancy in saying both 'English or Chinese' and 'Chinese and English both work', but otherwise every sentence is useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, and the description still helpfully notes the returned dataset_id and bilingual title. The main gap is lack of limit/offset guidance for paging, but the schema supplies defaults, so the definition is largely complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for all parameters. It explains keyword semantics well, including empty keyword browse mode and bilingual expansion, but it never mentions the limit or offset parameters, leaving two of three parameters to be inferred from bare schema defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: search ALL ~1150 CSDI datasets. It specifies scope (local), language handling, ranking, and browse behavior, and it distinguishes the next step from the sibling load_hk_data by saying to feed the dataset_id there.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context: no keyword means browse, and results should be passed to load_hk_data. However, it does not explicitly contrast with siblings like query_hk_data or summarise_hk_data, so the agent must infer those alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

summarise_hk_dataA

Answer a question about a dataset in TEXT (and a bar chart), without putting features in the chat.

  • group_by empty: an overview — feature count, geometry, which fields are worth grouping by.

  • group_by="NAME_OF_DISTRICT_COUNCIL_DISTRICT_EN" with agg="count": how many features per group.

  • agg="sum" / "avg" with value_field="MEDIUM_IEC62196_no": totals or averages per group. Returns an aligned text table, the same rows as data, and a chart URL served on localhost.

NameRequiredDescriptionDefault
aggNocount
topNo
group_byNo
dataset_idYes
value_fieldNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden and does disclose important output behavior: a text table, data rows, a localhost chart URL, and no features in the chat. However, it does not discuss limits such as the top parameter, permissions, or whether the operation is purely read-only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and structured with focused bullets for each grouping/aggregation case. It is efficient overall, though the final return-value sentence could be tighter and partly duplicates what an output schema may cover.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description gives enough to perform common aggregations and notes return behavior, and an output schema exists. Still, with five parameters at 0% schema coverage and no annotations, the unexplained top parameter and lack of explicit sibling routing leave meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains group_by, agg, and value_field with examples, but it leaves top and dataset_id semantics unaddressed, so coverage is only partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool answers a question about a dataset in text and with a bar chart, and it explains the summarization behavior without returning raw features. It is distinguishable from map/query siblings by its aggregate text-and-chart output, though it does not explicitly name those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage scenarios: empty group_by for an overview, group_by with agg=count for feature counts per group, and sum/avg with value_field for totals or averages. It does not state when not to use this tool or explicitly route to siblings such as query_hk_data.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 14 tool updatesv0.12.0
    • First observedarcgis_request
    • First observedbuild_map
    • First observedbuild_scene
    • First observeddataset_status
    • First observedelevation_at
    • First observedexport_static_map
    • First observedexport_static_svg
    • First observedgeocode_address
    • First observedgeometry_op
    • First observedload_hk_data
    • First observedpublish_layer
    • First observedquery_hk_data
    • First observedsearch_hk_data
    • First observedsummarise_hk_data

TDQS

A3.5/5.0

Scored across 14 tools

Disambiguation4/5

The core pipeline is clearly staged: search_hk_data -> load_hk_data -> query_hk_data / summarise_hk_data -> build_map / build_scene, with each step's role spelled out (verify a value vs. aggregate vs. visualize). The only real soft spots are the three output tools (build_map, export_static_map, export_static_svg), differentiated mainly by paragraph-level caveats rather than by name, and arcgis_request, which is a generic escape hatch that can duplicate geocode/publish/query functions.

Naming Consistency3/5

Most tools are verb_noun (search_hk_data, load_hk_data, build_map, export_static_map, publish_layer), with a nice *_hk_data family for the data lifecycle. But four tools break the verb-first pattern entirely (geometry_op, elevation_at, arcgis_request, dataset_status), and the hk_ prefix is applied inconsistently to the geo tools, so the convention is readable but not predictable.

Tool Count4/5

Fourteen tools is a reasonable, well-scoped size for a geospatial data server covering discovery, retrieval, analysis, visualization and publishing. There is mild redundancy in having three separate map-output tools (interactive, PNG, SVG), one of which is basemap-only and arguably an edge case.

Completeness4/5

The surface covers the full discovery-to-output lifecycle plus analysis helpers (geocode, buffer/project/simplify, elevation), raw REST access and a data-freshness check — no dead ends for the stated purpose. Minor gaps: no tool to list or clean up datasets already loaded in the workspace, and no way to export a filtered subset back out as data (CSV/GeoJSON) rather than an image or map.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables access to Hong Kong government's official open data portal (DATA.GOV.HK) through natural language queries. Supports searching datasets, browsing categories, and retrieving detailed information about Hong Kong's public data resources.
    8
    8
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    MCP server for querying Huwise/Opendatasoft data portals. Enables dataset search, metadata retrieval, record filtering with ODSQL, and data export.
    5
    3
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables searching and querying Washington DC's open geospatial datasets (parcels, zoning, addresses, transport) via ArcGIS feature services, with tools for dataset discovery, attribute/geometry queries, and schema inspection.
    7 npm
    MIT