MCP server for the City of Cape Town Open Data Portal, exposing layers and tables from the ODP_SPLIT_* ArcGIS feature services
8 tools with complete input schemas and descriptions. Naming is clear and verb-based (load_shedding, query_layer, layer_info). Descriptions are adequate (50-100 chars) but lack LLM-optimized guidance on WHEN to use each tool or dependencies between them. All parameters are typed and described, but descriptions are terse and lack examples of valid values or constraints. Output schema (FeatureResult) is well-documented in code but not exposed in tool definitions. Error handling is present (annotateErr) but generic, does not guide recovery or classify errors as retryable vs fatal. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite all tools being read-only.
Get distinct values for a field in a layer, useful for understanding valid filter values
Query heritage sites and cultural property inventory
Query land parcel and property data, optionally filtered by suburb
Get metadata for a layer or table, including field names, types, and aliases
Query load shedding schedules and related data
Query any layer or table from a specified split service by layer ID
List all layers and tables across all split services, optionally filtered by name
Query ward boundary and administrative data
Descriptions lack LLM-optimized guidance. No explanation of WHEN to use each tool or dependencies (e.g., 'Call service_info first to discover layer IDs, then query_layer'). Descriptions are 50-100 chars; baseline for A-grade is 50-200 chars with context.
No tool annotations despite all 8 tools being read-only. Missing readOnlyHint annotation would help agents understand these tools are safe to call without side effects.
Error handling is generic. annotateErr() wraps errors with retry guidance for timeouts, but does not classify errors as retryable vs user-fixable vs fatal. LLM cannot determine whether to retry, ask user, or abort.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 54 | 2026-07-28+ | v2 |
Parameter descriptions lack constraint details. E.g., 'limit' says 'default 200, max 2000' but does not state minimum (1?). 'where' accepts ArcGIS SQL but does not warn against injection or list safe operators.
Output schema (FeatureResult, Feature) is documented in code but not exposed in tool definitions. LLM cannot see that features include 'attributes' and optional 'geometry' fields, forcing it to guess response structure.