Skip to main content

CNG MCP Server

Model Context Protocol (MCP) server for CNG Sandbox. Exposes datasets, stories, connections, and validation as composable tools for agents.

What is MCP?

MCP is a protocol that lets applications (agents, CLI tools, SDKs) discover and interact with tools and resources in a standardized way. This server makes the CNG Sandbox accessible to any MCP-compatible client.

Installation

pip install cngstorytelling-mcp

This installs the cng-mcp command. To run against your own instance, see the self-hosting guide.

Quick Start

1. Start the Server

# Default API URL (http://localhost:8086)
cng-mcp --workspace-id <8-char-id>

# Custom API URL
cng-mcp --api-url http://your-sandbox.com --workspace-id <8-char-id>

The server communicates over stdio. Connect with any MCP client.

The ingestion API requires an X-Workspace-Id header on workspace-listing endpoints (/api/datasets, /api/connections, /api/stories). Pass --workspace-id (or set SANDBOX_WORKSPACE_ID) so the server can forward it — without it, listing endpoints return 400.

2. Use with Claude Desktop / Code

Add to your MCP client config:

{
  "mcpServers": {
    "cng-sandbox": {
      "command": "cng-mcp",
      "args": ["--api-url", "http://localhost:8086", "--workspace-id", "abcd1234"]
    }
  }
}

Tools

read_datasets

List all datasets in your workspace with IDs, types, and bounds.

read_story

Get a story's metadata and chapters. Input: story_id (string)

create_story

Create a new story. Input:

  • title (string)
  • description (string)
  • chapters (array): each with title, narrative, map_state, and layer_config (containing dataset_id or connection_id)
    • map_state: { center: [lng, lat], zoom, bearing, pitch, basemap } plus optional 3D fields:
      • terrain: { enabled: bool, exaggeration: number } — 3D terrain relief. Ignored when the chapter has a bound data layer (data can't drape on terrain in v1); use terrain on scene-setting chapters only.
      • globe: bool — globe projection with atmosphere; works with data layers.
      • buildings: bool — extruded 3D buildings (OpenFreeMap).
      • Omit these for a flat 2D map. Portable/archival HTML exports ignore 3D fields and render flat.
  • Chapter type may be "flyover": a scroll-scrubbed 3D camera flight. Flyover chapters add:
    • keyframes (array, >= 2 to fly): { center: [lng, lat], zoom, bearing, pitch, caption? } — the camera path, interpolated smoothly in reader scroll order. caption is markdown shown as the camera passes that keyframe.
    • scroll_length (number, default 1): scroll distance multiplier (~one viewport height per keyframe segment at 1).
    • layer_config is optional; as with other chapters, terrain is ignored when a data layer is bound. The best flyovers are terrain/buildings scene-setters with no data layer.
    • map_state pose fields are ignored — keyframe 0 is the entry camera. Compute keyframes from dataset bounds for an easy orbit: fix center/zoom/pitch, sweep bearing across ~180° in 5 steps.

update_story

Modify an existing story. Input: story_id, updates (object with changed fields)

read_connections

List external tile source connections.

create_connection

Create a new external tile source connection. Input:

  • name (string)
  • url (string)
  • connection_type (string): one of zarr, cog, pmtiles, xyz_raster, xyz_vector, geoparquet, copc
  • bounds (array, optional): [west, south, east, north]
  • min_zoom / max_zoom (integer, optional)
  • tile_type (string, optional): tile image format (e.g. png, webp)
  • band_count (integer, optional)
  • rescale (string, optional): range as "min,max"
  • config (object, optional): additional tiler config
  • geozarr_attrs (object, optional): GeoZarr-spec attributes

validate_layer_config

Check if a layer configuration is valid before creating a chapter. Input: dataset_id, optional colormap, rescale_min/rescale_max, and color_mode (elevation/intensity/classification/rgb) for point-cloud (copc) layers. Provide either a colormap (raster) or a color_mode (copc).

Ingestion & export

get_job_status

Get the status of a conversion job by job ID (pending/converting/ready/failed). Input: job_id (string)

ingest_url

Ingest a remote geospatial file (GeoTIFF, GeoJSON, Shapefile .zip, NetCDF, HDF5) into a dataset. Waits for conversion to finish and returns the dataset ID. Input: url (string); optional wait (boolean, default true), timeout (number, default 600)

discover_remote

List geospatial files at a remote URL or S3 prefix before connecting them. Input: url (string)

connect_remote_temporal

Register remote COGs as a temporal (date-stepped, time-slider) or mosaic dataset. Discovers files at the URL if an explicit file list is not given; waits for the job to finish. Input: url (string); optional mode (temporal or mosaic, default temporal), files (array of {url, filename}), timeout (number)

upload_story_asset

Upload a local image or CSV file as a story asset (for image chapters and CSV chart chapters). Returns the asset ID and URL. Input: file_path (string), kind (image or csv); optional story_id (string)

update_connection_colormap

Set the preferred colormap for a raster connection (cog/xyz_raster/raster pmtiles). Input: connection_id (string), colormap (string); optional reversed (boolean)

update_connection_categories

Update category labels/colors for a categorical connection. Input: connection_id (string), categories (array of {value:int, label?:str, color?:'#RRGGBB'})

delete_connection

Delete an external tile source connection by ID. Input: connection_id (string)

export_story_interactive

Build and download a story's self-contained interactive HTML bundle (.zip) to a local path. Stories with zarr layers, flyover chapters, or scrolly chapters needing snapshots return an error. Input: story_id (string), output_path (string)

Resources

  • cng://datasets — Catalog of available datasets
  • cng://story-templates — Pre-built templates agents can reference
  • cng://colormaps — Valid colormap names

Development

cd mcp
uv sync --extra dev
uv run pytest tests/ -v

See CONTRIBUTING.md and ARCHITECTURE.md.

Troubleshooting

"Connection refused" on localhost:8086

Verify sandbox stack is running: docker compose ps. If not, start it: docker compose up -d.

"Unknown colormap" validation error

List valid colormaps via the cng://colormaps resource and pick one.

Server doesn't discover tools

Run with debug logging: cng-mcp --log-level DEBUG. Check for tool registration messages.

"ModuleNotFoundError: No module named 'cng_mcp'"

Install in editable mode from the mcp/ directory: pip install -e mcp/.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cngstorytelling_mcp-2.13.0.tar.gz (81.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cngstorytelling_mcp-2.13.0-py3-none-any.whl (24.1 kB view details)

Uploaded Python 3

File details

Details for the file cngstorytelling_mcp-2.13.0.tar.gz.

File metadata

  • Download URL: cngstorytelling_mcp-2.13.0.tar.gz
  • Upload date:
  • Size: 81.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for cngstorytelling_mcp-2.13.0.tar.gz
Algorithm Hash digest
SHA256 6cc01b3a127a9a69d808fbed3a5f35a0b17f37fe063d0b8b4eea6e33d72dc062
MD5 454a4147d4ff1fcf776f5bda05aafca3
BLAKE2b-256 98b56dcb06947813e6f8e86df1aa63a369bcb6a892fcf9c4f1ddd6525d101a08

See more details on using hashes here.

Provenance

The following attestation bundles were made for cngstorytelling_mcp-2.13.0.tar.gz:

Publisher: publish-mcp.yml on aboydnw/cng-sandbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cngstorytelling_mcp-2.13.0-py3-none-any.whl.

File metadata

File hashes

Hashes for cngstorytelling_mcp-2.13.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d1528e0760c2c074dba7006f02e69440540aa46df48913c61dacf09092c4fa31
MD5 f00d64ac2aad9b50b7a2cb342e0abbd8
BLAKE2b-256 540685fc5019c9d3e3f9e0008645ffc18f51df1d4c6e8ce62cbbf7a571f62838

See more details on using hashes here.

Provenance

The following attestation bundles were made for cngstorytelling_mcp-2.13.0-py3-none-any.whl:

Publisher: publish-mcp.yml on aboydnw/cng-sandbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.15.0

2 files

2.14.0

2 files

This release

2.13.0 This release

2 files

2.12.0

2 files

2.11.0

2 files

2.10.0

2 files

2.9.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page