Skip to content

melbamorph/zonerMCP

Repository files navigation

ZonerMCP

ZonerMCP is a hardened Model Context Protocol server for Lebanon, NH zoning and GIS lookups. It exposes a Streamable HTTP MCP endpoint, queries an ArcGIS FeatureServer through an explicit layer allowlist, filters returned fields, rate-limits callers, and fails fast when required production security settings are missing.

Quick Start

Install dependencies:

npm install

Run locally without bearer auth while developing:

$env:ARCGIS_BASE_URL="https://services.arcgis.com/.../ArcGIS/rest/services/.../FeatureServer"
$env:REQUIRE_AUTH="false"
npm start

The server listens on http://localhost:5000 by default. The .env.example file documents the full environment surface, but this project does not load .env files automatically; set variables in your shell, host configuration, or Replit Secrets.

MCP Tools

  • list_layers: lists the GIS layers registered for MCP access.
  • describe_layer: returns allowed query modes, field profiles, and limits for one layer.
  • query_features: queries an allowed layer by point, object IDs, or bounding box.
  • lookup_zoning_by_address: searches the Lebanon address layer and returns zoning district matches.

HTTP Endpoints

Endpoint Method Description
/mcp POST Streamable HTTP MCP endpoint for initialize, tools/list, and tools/call.
/mcp GET Server info without a session, or stream handling with a session ID.
/mcp DELETE Session termination.
/health GET Public health check.

Configuration

Variable Default Required Description
ARCGIS_BASE_URL none yes ArcGIS FeatureServer base URL.
MCP_BEARER_TOKEN none when REQUIRE_AUTH=true Bearer token accepted by /mcp.
CORS_ALLOW_ORIGINS none when NODE_ENV=production Comma-separated trusted browser origins.
NODE_ENV development no Enables production startup checks when set to production.
PORT 5000 no HTTP port.
REQUIRE_AUTH true no Set to false only for local unauthenticated development.
ALLOW_STATELESS true in development, false in production no Allows direct one-shot tools/list and tools/call requests without creating a session.
ZONING_LAYER 24 no ArcGIS layer ID for official zoning.
ADDRESS_LAYER_NAME LebanonNHMATMassGeoExport_Layer no ArcGIS layer/table name resolved from the FeatureServer catalog for address lookup.
MAX_SESSIONS 100 no Maximum concurrent MCP sessions.
SESSION_TIMEOUT_MS 1800000 no Idle session timeout.
SESSION_REAPER_INTERVAL_MS 300000 no Session cleanup interval.
RATE_LIMIT_WINDOW_MS 60000 no Rate-limit window.
RATE_LIMIT_MAX_REQUESTS 60 no Base request limit per window.
RATE_LIMIT_AUTH_MULTIPLIER 2 no Multiplier for authenticated request limits.
CACHE_TTL_SECONDS 300 no Query cache TTL.
CACHE_MAX_ENTRIES 500 no Maximum cached query results.
MAX_FIELDS 40 no Maximum explicit fields per query.

Production Setup

Set at least:

NODE_ENV=production
ARCGIS_BASE_URL=<FeatureServer URL>
REQUIRE_AUTH=true
MCP_BEARER_TOKEN=<strong bearer token>
CORS_ALLOW_ORIGINS=https://trusted-client.example

Leave ALLOW_STATELESS unset in production unless a client cannot preserve MCP session IDs. If needed, set ALLOW_STATELESS=true explicitly.

Security Model

  • Authentication is enabled by default.
  • Production startup fails without CORS_ALLOW_ORIGINS.
  • Production stateless one-shot handling is disabled unless explicitly enabled.
  • Queryable layers, fields, query modes, and record caps are controlled by layer-registry.js.
  • Geometry is withheld unless a layer explicitly opts in.
  • Address and feature queries use bounded inputs and validation.

Development Checks

npm test
npm run audit
node --check mcp-server.js

About

ZonerMCP powers zoning lookups for AI agents. It’s a small, flexible MCP server that transforms street addresses into zoning data for Lebanon, NH, and can plug into any OpenAI Agent Builder or ChatKit workflow

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors