pmtiles-mcp
v0.1.1
Published
MCP server for inspecting, querying, and extracting features from PMTiles archives
Maintainers
Readme
pmtiles-mcp
MCP server for inspecting, querying, and extracting features from PMTiles archives.
pmtiles-mcp gives agents read-only access to cloud-hosted PMTiles files. It works over HTTP range requests, decodes vector tiles into GeoJSON, and returns raster tiles as MCP image content.
Quick Start
Install it with your MCP client config. Claude Desktop and Cursor use the same server shape, but store it in different files.
Claude Desktop config:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"pmtiles": {
"command": "npx",
"args": ["-y", "pmtiles-mcp"]
}
}
}Cursor config: .cursor/mcp.json in your project root.
{
"mcpServers": {
"pmtiles": {
"command": "npx",
"args": ["-y", "pmtiles-mcp"]
}
}
}Restart the client after saving the config.
Example Data
Known working PMTiles archive:
https://r2-public.protomaps.com/protomaps-sample-datasets/nz-buildings-v3.pmtilesExample tool call:
{
"name": "inspect_archive",
"arguments": {
"url": "https://r2-public.protomaps.com/protomaps-sample-datasets/nz-buildings-v3.pmtiles"
}
}Example response, shortened:
{
"content": [
{
"type": "text",
"text": "PMTiles archive: vector mvt, zoom 0-14, 1 layers, 12345 addressed tiles."
}
],
"structuredContent": {
"format": "vector",
"tileType": "mvt",
"zoom": { "min": 0, "max": 14 },
"layers": ["buildings"]
}
}Tools
inspect_archive
Reads the PMTiles header and metadata.
Input:
{
"url": "https://example.com/archive.pmtiles"
}Returns format, bounds, center point, zoom range, tile counts, compression details, metadata, and layer names when available.
list_layers
Lists vector layers and attribute schemas.
Input:
{
"url": "https://example.com/archive.pmtiles",
"zoom": 12
}Layer data comes from TileJSON metadata first. If metadata is missing, the server samples a tile near the archive center.
get_tile
Fetches one tile.
Input:
{
"url": "https://example.com/archive.pmtiles",
"z": 12,
"x": 4096,
"y": 2724,
"layer": "buildings"
}Vector tiles return GeoJSON FeatureCollections. Raster tiles return MCP image content with the tile bytes encoded as base64.
query_location
Finds features at a latitude and longitude, or returns the raster tile covering that location.
Input:
{
"url": "https://example.com/archive.pmtiles",
"lat": -41.2865,
"lon": 174.7762,
"zoom": 14
}For vector tiles, polygon features use point-in-polygon filtering.
search_bbox
Searches features intersecting a bounding box.
Input:
{
"url": "https://example.com/archive.pmtiles",
"bbox": [174.75, -41.31, 174.82, -41.25],
"zoom": 14,
"layer": "buildings",
"limit": 1000,
"maxTiles": 64
}Results are deduplicated across tile boundaries. Large result sets are truncated and marked in the structured response.
Supported Sources
The server accepts public or pre-signed URLs for:
- plain HTTP and HTTPS PMTiles files
- S3-compatible object storage
- Cloudflare R2
- temporary signed URLs from private buckets
Custom authentication headers are not part of v0.1. Use a pre-signed URL instead.
Error Codes
| Code | Meaning | Suggested action |
| --- | --- | --- |
| INVALID_URL | The URL is missing, malformed, or blocked by URL safety checks. | Check the URL and use a public or pre-signed PMTiles URL. |
| HTTP_ERROR | The remote server returned a failing HTTP status. | Confirm the archive exists and the server supports range requests. |
| UNSUPPORTED_FORMAT | The requested tool does not support this tile format. | Use vector-only tools with MVT archives, or get_tile for raster tiles. |
| UNSUPPORTED_VERSION | The archive is not a supported PMTiles version. | Convert file: pmtiles convert old.pmtiles new.pmtiles. |
| TILE_NOT_FOUND | The requested tile is outside the archive or absent. | Use inspect_archive to check bounds and zoom range. |
| DECODE_ERROR | Vector tile decoding failed. | Verify the archive contains valid MVT tile data. |
| INVALID_PARAMS | The tool arguments are valid JSON but not a valid request. | Check input constraints in tool schema. |
| NETWORK_ERROR | Fetching the archive failed before an HTTP response was available. | For timeouts, increase timeout via PMTILES_MCP_TIMEOUT_MS. |
Environment Variables
PMTILES_MCP_ALLOW_PRIVATE=1 allows private, loopback, and link-local addresses. Leave this unset unless you are testing local files or internal buckets.
PMTILES_MCP_TIMEOUT_MS sets the request timeout in milliseconds. The default is 30000.
Security
pmtiles-mcp is designed for untrusted URLs. It blocks private and loopback IP ranges by default, validates redirects, and uses request timeouts. DNS rebinding is still a residual risk for any tool that fetches user-provided URLs. Run the server in a network-restricted environment when using it with untrusted agents.
Development
pnpm install
pnpm dev
pnpm build
pnpm typecheck
pnpm lint
pnpm testIntegration tests hit public PMTiles URLs:
RUN_INTEGRATION=1 pnpm test
pnpm test:integrationLicense
MIT © 2026 Matt Dempsey
