Read-only MCP server for querying ArcGIS Online (AGOL) content. Search org/public content and query hosted feature layers. Signs in as a named user (username/password) by default; api-key and anonymous auth also supported via config.json.
Strong tool naming (verb_noun pattern) and comprehensive parameter schemas with type definitions. Descriptions are detailed and actionable (avg 180 chars), exceeding baseline. All 11 tools have explicit input schemas with typed parameters. However, output schemas are not formally documented, responses are JSON-dumped but structure is not declared in tool definitions. Error handling returns generic 'ArcGIS error' messages without recovery guidance. No tool annotations (readOnlyHint, idempotentHint) despite all being read-only. Missing parameter constraints (enums for geometry_type, spatial_rel). Some parameter descriptions could be more concise.
Server-side group-by statistics — SUM/AVG/COUNT/MIN/MAX/STDDEV/VAR computed by the service, no rows pulled. Ideal for rollups and dashboards. Identify the layer by EITHER `item_id` (+ `layer_index`) OR `service_url`. - `statistics`: list of {statisticType, onStatisticField[, outStatisticFieldName]}, e.g. [{"statisticType":"sum","onStatisticField":"ACRES"}, {"statisticType":"count","onStatisticField":"OBJECTID","outStatisticFieldName":"n"}]. - `group_by`: comma-separated fields to group on (omit for a grand total). - `where`: pre-aggregation filter. `having`: post-aggregation filter on a stat. - `order_by`: e.g. "sum_ACRES DESC". Returns {count, groups:[{attributes}]}.
Return only the count of features matching a `where` clause — cheap way to size a query before pulling records. Identify the layer by EITHER `item_id` (+ `layer_index`) OR `service_url`.
Describe one layer/table: field names & types, geometry type, extent, object-id field and current record count. Identify the layer by EITHER `item_id` (+ `layer_index`, default 0) OR a direct `service_url` (service root + layer_index, or a full layer URL).
Return the distinct value combinations of one or more `fields` (comma-separated) — great for discovering the categories/codes in a field before filtering. Identify the layer by EITHER `item_id` (+ `layer_index`) OR `service_url`. Returns {count, exceededTransferLimit, values:[{attributes}]}.
Output schemas not formally documented. Tools return JSON-dumped objects but structure (fields, types, required keys) is not declared in tool definitions. LLMs cannot plan downstream calls or extract specific fields reliably.
Error handling lacks recovery guidance. All exceptions caught and returned as generic 'ArcGIS error: {exc}' strings. LLMs cannot determine if error is retryable, user-fixable, or fatal, or what corrective action to take.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Return the full portal metadata for a content item by its id.
Return an item's /data payload — a Web Map's operational layers, or an app/dashboard config. Use to trace which feature services a map or app references. Returns {} for items with no data part.
List the layers and tables of a feature service, with their ids, names and geometry types. Provide EITHER a feature-service `item_id` OR a direct `service_url` (a FeatureServer root or a specific layer URL). Use a layer's `id` as the `layer_index` for describe_layer / query_features.
Query features from a layer/table and return their attributes as JSON. Identify the layer by EITHER `item_id` (+ `layer_index`) OR `service_url`. - `where`: SQL-style filter, e.g. "STATUS = 'Active' AND ACRES > 5" (default "1=1"). - `out_fields`: comma-separated field names, or "*" for all (default). - `order_by`: e.g. "ACRES DESC" or "NAME ASC". - `limit` / `offset`: paging (limit is capped by the server's max_records). - `return_geometry`: include geometry (off by default for compact output). - `out_sr`: output spatial reference WKID (e.g. 4326) when returning geometry. Returns {count, exceededTransferLimit, features:[{attributes[, geometry]}]}. If exceededTransferLimit is true, page with offset or narrow the where.
Search org and public content. `query` is ArcGIS search syntax (e.g. 'owner:rajiv AND parcels', or '' for everything). Optional `item_type` filters by item type, e.g. 'Feature Service', 'Web Map', 'Feature Layer'. `sort_field` can be e.g. 'modified', 'numViews', 'title'. Returns id, title, type, owner and service url for each match.
Query features filtered by a geometry, optionally buffered by a distance. Identify the layer by EITHER `item_id` (+ `layer_index`) OR `service_url`. - `geometry`: ArcGIS geometry as a dict or JSON string. A point is {"x":-79.38,"y":43.65}; an envelope is {"xmin":.."ymin":.."xmax":.."ymax":..}. - `geometry_type`: esriGeometryPoint | esriGeometryEnvelope | esriGeometryPolygon | esriGeometryPolyline | esriGeometryMultipoint. - `in_sr`: WKID of the input geometry (default 4326 / lat-long). - `distance` + `units` (e.g. "esriSRUnit_Meter"): find features within that distance of the geometry — e.g. everything within 500 m of a point. - `spatial_rel`: default esriSpatialRelIntersects. - `where`, `out_fields`, `order_by`, `limit`, `offset`, `return_geometry`, `out_sr`: as in query_features. Returns {count, exceededTransferLimit, features:[{attributes[, geometry]}]}.
Return the signed-in user and portal info. Use first to confirm the connection and credentials are working.
Missing tool annotations. All 11 tools are read-only (no state modification), but none declare readOnlyHint=true. Agents cannot distinguish safe tools from destructive ones without explicit hints.
Enum constraints missing for constrained parameters. geometry_type accepts 5 specific values (esriGeometryPoint, esriGeometryEnvelope, etc.) but defined as free-form string. spatial_rel has default but no enum. LLMs may hallucinate invalid values.
Pagination guidance incomplete. query_features and spatial_query mention exceededTransferLimit and offset/limit but do not document max_records server cap or recommend result limits. Large queries may exhaust context window.