Skip to main content
Glama
README.md
# Alaska Geoportal MCP

A statewide [Model Context Protocol](https://modelcontextprotocol.io/) server
over the **State of Alaska Geoportal** -- the Alaska Geospatial Office's
ArcGIS Online organization (`soa-dnr`), which publishes several hundred public
Feature Services from DNR (land status, statewide parcels, forestry, state
parks, oil & gas, DGGS geology) and hosts the catalog that other state
agencies and boroughs share into.

Ask a connected model "how many miles of forestry road are in the Mat-Su
Borough", "which fire service area is this point in", or "list the CWPP
areas", and it answers from the official layers: discover the layer, read
its schema, query or aggregate it, and report the number with the caveats the
data carries (regional coverage, Web Mercator area inflation, capped fetches).

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![MCP Compatible](https://img.shields.io/badge/MCP-Compatible-green.svg)](https://modelcontextprotocol.io/)

This is a standalone fork of
[codeforanchorage/anchorage-gis-mcp](https://github.com/codeforanchorage/anchorage-gis-mcp),
pointed at the state org instead of the Municipality of Anchorage, with the
two MOA-only parcel tools removed and the Anchorage-specific geometry
(coverage bbox, area correction) generalized to the whole state. Both are
built on [OpenContext](https://github.com/srihari-raman/opencontext).

---

## Scope

| | |
|---|---|
| Hub site | <https://gis.data.alaska.gov> |
| ArcGIS Online org | `soa-dnr` (`7HDiw78fcUiM2BWn`) |
| Public Feature Services | ~665, hosted on `services1.arcgis.com` and the on-prem `arcgis.dnr.alaska.gov` / `geoportal.dggs.dnr.alaska.gov` servers |
| Catalog groups searched | 22: the 6 state-owned groups plus the groups of 13 Alaska partner orgs (see `config-alaska-geoportal.yaml`) |
| Alaska partner orgs | Municipality of Anchorage, Mat-Su, Kenai Peninsula, Fairbanks North Star, Kodiak Island and Haines boroughs, City of Unalaska, ADF&G, DEC, DCRA, DOT&PF, Alaska Energy Authority, UAA ACCS |

**State and Alaska-partner layers are queryable; federal ones are not.** The
Geoportal catalog also lists content from federal partners (Census, USGS,
NOAA, USFS, BLM, FEMA ...) whose services live in federal ArcGIS tenants.
Those show up in search but are refused on query, by design (see
[docs/SECURITY.md](docs/SECURITY.md)). Search results label each partner
layer with its publishing agency; unlabelled results are the state org's.
[docs/ALASKA_SOURCES.md](docs/ALASKA_SOURCES.md) records every org and how
it was verified.

## Tools (14, all read-only)

| Tool | What it does |
|---|---|
| `find_gis_content` | Combined search of the catalog groups (maps/apps) and the org's spatial layers by topic |
| `browse_gallery` | Browse or keyword-search the catalog groups (viewers, not queryable) |
| `search_spatial_layers` | Search Feature/Map Services and downloadable data by keyword |
| `get_item_details` | Full portal item description, URL, extent, tags |
| `get_layer_schema` | Real, case-sensitive field names, types and coded-value domains |
| `get_distinct_values` | Exact stored values of a field (for building WHERE clauses) |
| `search_layers_by_field` | Find layers that carry a given field name |
| `query_data` | Attribute query with WHERE / out_fields / order_by; leads with TOTAL COUNT |
| `spatial_query_point` | "What is at lon/lat" against a polygon layer |
| `spatial_query_polygon` | "Which X are inside / within N miles of Y", filter by another layer's polygon or inline GeoJSON |
| `aggregate_by_polygon` | Count / sum source features per polygon (with optional buffer) |
| `coverage_by_polygon` | Share of each target polygon covered by an overlay layer |
| `filter_by_polygon` | Source features inside a named container polygon |
| `find_features_spanning_classifications` | Source features that touch >= N distinct values of a classification layer |

## Quick start

```bash
uv sync                                   # or: pip install -r requirements.txt
cp config-alaska-geoportal.yaml config.yaml
PYTHONIOENCODING=utf-8 python scripts/local_server.py   # http://localhost:8000/mcp

# in another shell: 20 end-to-end checks against the live org
SMOKE_URL=http://localhost:8000/mcp python scripts/smoke_prod.py
```

## Connecting

The production server is at:

```
https://alaska-geoportal.codeforanchorage.org/mcp
```

In Claude: Settings, Connectors, Add custom connector, paste the URL above.
The `/mcp` path is required; the bare hostname
(<https://alaska-geoportal.codeforanchorage.org/>) serves a short landing
page that repeats these instructions, so a pasted URL without the path
tells you what went wrong instead of failing silently.

Claude Desktop and Claude Code can also connect through `stdio_bridge.py` or
the Go client in `client/`. See
[docs/GETTING_STARTED.md](docs/GETTING_STARTED.md).

## Deploy

AWS Lambda + API Gateway via Terraform (`terraform/aws/`), one Lambda per
fork. `./scripts/deploy.sh -e prod` packages `config.yaml` into the zip and
plans before applying. Deployed to prod on 2026-09-15; the custom domain
cutover is pending DNS. Operations notes are in
[docs/RUNBOOK.md](docs/RUNBOOK.md).

## Documentation

| Doc | Description |
|---|---|
| [Alaska sources](docs/ALASKA_SOURCES.md) | The state org, its catalog groups, and the other Alaska orgs (verified ids) |
| [Security](docs/SECURITY.md) | Threat model, tenant scoping, host allowlist |
| [Runbook](docs/RUNBOOK.md) | Kill switch, traffic postures, alarms, smoke |
| [Architecture](docs/ARCHITECTURE.md) | OpenContext plugin design (one fork = one server) |
| [Custom plugins](docs/CUSTOM_PLUGINS.md) | Writing a plugin |
| [Deployment](docs/DEPLOYMENT.md) | AWS, Terraform, monitoring |
| [Testing](docs/TESTING.md) | Local testing (terminal, Claude, MCP Inspector) |
| [SMOKE.md](SMOKE.md) | Output of the initial live smoke against `soa-dnr` |

## Contributing

```bash
uv run ruff check core/ plugins/ server/ tests/
uv run pytest tests/ -n auto
```

Pre-commit hooks (Ruff, yamllint, gofmt): `pip install pre-commit && pre-commit install`.

## License and attribution

MIT -- see [LICENSE](LICENSE).

- **OpenContext** (the plugin framework, `core/`, `server/`, the generic
  `ckan` / `arcgis` / `socrata` plugins, Terraform and deploy tooling):
  Srihari Raman, City of Boston Department of Innovation and Technology.
- **Anchorage GIS MCP** (the ArcGIS Portal plugin this one is derived from,
  the spatial tools, caveat machinery and security model) and this
  statewide fork: [Code for Anchorage](https://codeforanchorage.org).
- Data: State of Alaska, Alaska Geospatial Office / Department of Natural
  Resources, via the public Alaska Geoportal. Check each layer's own terms
  of use in its item description.