Skip to content

Your first cluster

The repo ships a sample input at test.json. It's a GeoJSON FeatureCollection with a few dozen points scattered across two density hotspots. Let's cluster them.

1. The input

A trimmed view of test.json:

{
  "type": "FeatureCollection",
  "features": [
    { "type": "Feature", "geometry": { "type": "Point", "coordinates": [28.04, -26.20] }, "properties": {} },
    { "type": "Feature", "geometry": { "type": "Point", "coordinates": [28.05, -26.20] }, "properties": {} },
    { "type": "Feature", "geometry": { "type": "Point", "coordinates": [18.42, -33.92] }, "properties": {} }
  ]
}

2. The MCP request

MCP clients call tools with a JSON payload. The repo also ships request.json with a ready-to-use tools/call:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cluster_points",
    "arguments": {
      "geojson": "<<contents of test.json as a string>>",
      "eps": 5000,
      "minPts": 3
    }
  }
}

3. Drive it from the shell

./spatial-cluster-static < request.json

Or, if you prefer Nix:

nix run .#run < request.json

4. The output

You get a FeatureCollection of polygon "circles" — one per cluster:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [ [ ... 32 vertices ... ] ]
      },
      "properties": {
        "cluster_id": 0,
        "point_count": 14,
        "radius_meters": 2843.7,
        "kartoza_credit": "Processed by Kartoza.com tools"
      }
    }
  ]
}

Open it in QGIS, Felt, Leaflet, Mapbox — anywhere that consumes GeoJSON — and you'll see filled circles centred on each density hotspot, sized to enclose every member point.

Tune eps and minPts

  • eps is the maximum distance (metres) between two points in the same neighbourhood. Smaller → tighter clusters.
  • minPts is the minimum count of points to form a cluster. Bigger → fewer, more confident clusters.

See Tool reference for the full parameter list and edge-case behaviour.

Next: Configure Claude Desktop so your model can call this directly.