Gwinnett Index

net.gwindexPublished by gwindex.netOfficial publisherv0.1.0Updated Oct 24, 2026

Gwinnett County, GA zoning and land use. Resolves an address to its governing jurisdiction.

VerifiedStreamable HTTPWeb executableLocation & LifestyleKnowledge & Memory

Overview

AI-generated overview

A public, read-only index of Gwinnett County, Georgia zoning and land-use records that lets an assistant resolve an address to its governing jurisdiction and,

What you can do
Resolve an address or parcel to the city or unincorporated county that regulates it, with code citation, confidence and distance to the nearest boundary, and list all 19 indexed jurisdictions with their codes and boundary sources.
When to use it
Use it when answering zoning, setback, land-use or permitting questions about an address in Gwinnett County, Georgia, where a mailing address such as a city name often does not match the governing jurisdiction.
Requirements
A remote streamable HTTP endpoint; no authentication, API keys or environment variables are declared. Network access to the endpoint is needed.
Before you install
Read-only and public, but the data is a mirror and derived analysis, not the system of record; some tables are unverified, OCR text is a reconstruction, and Duluth case fields are a finding aid pointing at source PDFs. Verify against the cited source before relying on it.

Installation

In SourceWeft

  1. Open Gwinnett Index in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/net.gwindex%2Fgwinnett-index/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "gwinnett-index": {
      "type": "http",
      "url": "https://www.gwindex.net/mcp"
    }
  }
}

README

Gwinnett Index

A machine-readable index of zoning, land-use, and development records for Gwinnett County, Georgia and its 17 municipalities. Built for AI agents first, humans second.

Why this exists

A "Duluth, GA" mailing address is usually not in the City of Duluth. It's in unincorporated Gwinnett — a different code, a different board, a different permit portal. Nothing on the internet resolves an address to its governing jurisdiction before answering a zoning question, so every AI assistant answering "what's the setback in Duluth GA" today is guessing.

Unincorporated Gwinnett is 67.3% of the county's land area. Getting this wrong is the default, not the edge case.

What's here

DatasetRecordsSource
Jurisdiction boundaries19 (county + unincorporated + 17 cities)US Census TIGER — public domain
County zoning cases11,739 (1970–2026)Gwinnett GC_Planning ArcGIS
Resolved applicants7,369 (from 8,246 raw spellings)derived
Duluth UDC860 sections, 18 tablescity PDF, 426 pp
Duluth meeting documents356 (7,878 pp, 2023–2026)duluthga.net
Duluth land-use cases109 distinct, 64 with vote recordsagenda mining

Setup — one time

The repo already has a starter README, so clone first and copy in — that avoids a push conflict:

bash
git clone https://github.com/willmobhill-arch/gwinnett-index.gittar -xzf gwinnett-index-repo.tar.gz -C gwinnett-index      # overwrites the stub READMEcd gwinnett-indexgit add -A && git commit -m "Gwinnett Index: pipeline, schema, and extracted corpora"git push

Then, with the repo public, load the corpora. Postgres fetches them itself — you don't run anything locally, and no credential is involved:

sql
-- set to your repo's raw base-- https://raw.githubusercontent.com/willmobhill-arch/gwinnett-index/main/data/
SELECT load_udc_sections_from_url(  'https://raw.githubusercontent.com/willmobhill-arch/gwinnett-index/main/data/udc_sections.jsonl');
SELECT * FROM load_duluth_cases_from_url(  'https://raw.githubusercontent.com/willmobhill-arch/gwinnett-index/main/data/duluth_cases.jsonl');
SELECT load_meeting_docs_from_url(  'https://raw.githubusercontent.com/willmobhill-arch/gwinnett-index/main/data/duluth_meeting_docs.jsonl');

Expected: 860 sections, 228 case rows (109 distinct), 356 meeting documents.

Architecture

Ingestion runs inside Postgres via the http extension — it fetches the county's ArcGIS REST services, Census TIGERweb, and this repo's own raw URLs directly. No external worker, no credentials in transit, and the whole 11,739-case county load moves zero bytes through a client.

ingest/  duluth/          UDC PDF -> 860 sections + 18 tables (extract_udc, extract_tables)  duluth_agendas/  crawl -> OCR -> parse case items from agendas/minutes/packetsdb/migrations/     the schema, md5-verified against the live Supabase projectscripts/           export_snapshot.py (the only thing that talks to Postgres) + loadersdata/              extracted corpora, fetched by the SQL loaders abovesite/              Astro static site + full agent surface (.md twins, llms.txt, DCAT)worker/            Cloudflare Worker: REST API + MCP server, five tools, no authdocs/plans/        design doc, build plan, status

Building the site

bash
DATABASE_URL=postgresql://... python3 scripts/export_snapshot.py   # writes data/snapshot/cd site && npm ci && SITE_URL=https://your-domain npm run ci        # build + 15 gates

Without a snapshot the site builds from site/fixtures/ — a small committed sample with identical shapes — and says so on every page. npm run ci fails the build if any route lacks a .md twin, any page presents records before naming its governing jurisdiction, or the bulk export contains geometry.

The API and MCP server

bash
cd worker && npm ci && npm test        # 10 protocol tests, no networkwrangler secret put SUPABASE_ANON_KEY && wrangler deploy

Five tools, public, read-only, no auth: resolve_jurisdiction (always call first), search_cases, get_case, get_code_section, list_jurisdictions. The REST API mirrors the same five operations from the same implementation and publishes /openapi.json.

The adapter pattern

17 jurisdictions cannot be 17 hand-written scrapers. The vendor landscape consolidates hard — Municode, ArcGIS REST, CivicPlus, CivicClerk, BS&A, Accela — so roughly six adapters cover ~90% of them, and adding a city is a config file. Health metric: if a new city needs new code rather than a new config, the adapter layer is leaking.

Data quality, stated honestly

  • Jurisdiction resolver: scored on 1,915 probe points from the county's own zoning layers. At confidence='high' it is correct 1,546/1,546 — 100%. Every error falls inside the low-confidence band. All 22 disagreements were within 141 m of a boundary (annexation lag; Census updates yearly).
  • Duluth UDC: 97.3% raw text coverage; the gap is stripped heading lines, leaving 591 unexplained characters across 426 pages.
  • UDC Table 2-B (dimensional standards) is verified cell-for-cell against the rendered source page. The other 17 tables are extracted but not spot-checked, and Table 2-B's merged PUD/CBD rows remain unreliable. Flags are in the data.
  • Duluth minutes: 57–69% are scanned with no text layer (printed, signed, re-scanned). OCR text is stored separately with text_source='ocr' and is a reconstruction, never a quotation of the record.
  • Duluth's 109 cases are a finding aid, not a dataset. Measured field by field: 67 have a "location" containing no street number, 57 have a "request" that is just the word ORDINANCE, 23 have an applicant field that ran on into a mailing address, and only 13 carry a zoning district. Each row links to the PDF it came from; the document is the record and the fields point at it. Published as stats.duluth_extraction.
  • Applicant resolution: 271 variants merged on tight edit distance; 262 lower-confidence pairs are queued for human review rather than merged on a guess. A split entity is visibly wrong; a wrongly merged one looks authoritative and is invisible.

Legal posture

ContentPostureBasis
Ordinance / plan textMirror in fullGeorgia v. Public.Resource.Org (2020) — edicts of government
Case recordsMirror in fullFacts; Georgia Open Records Act
County parcel/zoning geometryProxy only, never rehostGwinnett GIS licence forbids redistribution
Jurisdiction boundariesHostUS Census TIGER — public domain
IBC/IRC base textNeverICC copyright; index Georgia amendments only

This index is a mirror and derived analysis, not the system of record. Every record carries source_url and last_verified.

Published under CC0.

Source: README.md at commit 14ad249

Tools

5

resolve_jurisdiction

Resolve governing jurisdiction — ALWAYS CALL FIRST

ALWAYS CALL THIS FIRST for any Gwinnett County address or parcel. Returns which government actually regulates the land — one of 17 cities, or unincorporated Gwinnett County (67.3% of the county) — with its code citation, a confidence band and the distance to the nearest jurisdiction boundary. A mailing address is NOT the jurisdiction: most "Duluth, GA" addresses are not in the City of Duluth.

Parameterspinband_maddress

search_cases

Search land-use cases

Search 11,848 zoning and land-use cases (1970–2026) by applicant, use, address, case number, type, year range or zoning district. County records cover UNINCORPORATED Gwinnett only.

Parameterszonelimitqueryyear_tocase_typeyear_fromjurisdiction

get_case

Get one land-use case

Full record for a case number, including staff recommendation, Planning Commission recommendation, decision, parcels and a deep link to the source record.

Parameterscase_numberrequiredjurisdiction

get_code_section

Get a development code section or table

Ordinance text or a dimensional-standards table by citation, with its adoption and amendment dates. Accepts "402.03", "§ 402.03", "Duluth UDC § 402.03" or "Table 2-B". Tables that have not been verified against the rendered source page say so in the response.

Parameterscitationrequiredjurisdictionrequired

list_jurisdictions

List jurisdictions

All 19 jurisdictions indexed: Gwinnett County as a container, unincorporated Gwinnett as a jurisdiction in its own right, and the 17 municipalities — with their codes and boundary sources.

Takes no parameters.

Version history

1
  1. v0.1.0LatestSep 16, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

    Declare a license in the repository or the registry entry.