Charlotte-Mecklenburg MCP Server

Charlotte-Mecklenburg MCP Server

An MCP server that exposes Charlotte, NC and Mecklenburg County open data as tools for an LLM agent, enabling queries about trash pickup, parcels, zoning, crime, and more by geocoding addresses and querying live ArcGIS layers.

Category
访问服务器

README

Charlotte-Mecklenburg MCP Server

An MCP (Model Context Protocol) server that exposes Charlotte, NC and Mecklenburg County open data as tools for an LLM agent. Ask about trash pickup, parcels and zoning, crime and 311 requests, planning areas and rezonings, bike lanes and ADA infrastructure, or environmental data (watersheds, tree canopy, brownfields) at any address in the city/county, and the server geocodes the address and queries the relevant live ArcGIS layer for you.

Core motion behind almost every tool: geocode an address → spatial or attribute query against an ArcGIS REST layer → structured result + a human-readable summary.

Data sources

Everything is queried live, at call time, from public ArcGIS REST endpoints — there is no local copy of the underlying data (a small local registry of endpoint metadata, not the data itself, lives in data/registry.json; see "Endpoint discovery" below). Four backends are in play:

Source What it is Base URL
City of Charlotte on-prem ArcGIS Server City departmental data (CMPD, sanitation, 311, zoning) https://gis.charlottenc.gov/arcgis/rest/services
Mecklenburg County on-prem ArcGIS Server County data (parcels, tax foreclosures) https://meckags.mecklenburgcountync.gov/server/rest/services
City of Charlotte ArcGIS Online (AGOL) org Solid waste routes, bike lanes, ADA infrastructure, CATS transit, watersheds, tree canopy https://services.arcgis.com/9Nl857LBlQVyzq54/arcgis/rest/services
Mecklenburg County ArcGIS Online (AGOL) org Capital Improvement Projects, brownfields, battery/HHW recycling sites https://services.arcgis.com/BWD3gDuaqc7SQmy7/arcgis/rest/services

All endpoints are public and require no authentication/token. Geocoding uses Esri's public World geocoder (https://geocode.arcgis.com/...), also token-free for non-stored results.

An offline registry of ~1,875 discovered service/layer entries across all four sources (crawled via scripts/build_registry.py) backs the list_datasets tool, so an agent can search for "what layer has X" before calling a specific tool.

Install

git clone <this repo> charlotte-mcp
cd charlotte-mcp
uv sync

Register with Claude Code:

claude mcp add charlotte -- uv --directory /Users/dwlavoie/charlotte-mcp run charlotte-mcp

(Substitute your actual clone path for /Users/dwlavoie/charlotte-mcp.) The server runs over stdio — no ports, no API keys, no config needed.

You can also run it directly for local testing:

uv run charlotte-mcp

Use from ChatGPT (remote connector)

ChatGPT cannot run local MCP servers — it only supports remote custom connectors (a public HTTPS endpoint, added in Developer Mode). A hosted instance of this server runs at:

https://pcygic2am3.us-east-1.awsapprunner.com/mcp

To connect it (requires ChatGPT Plus/Pro; custom connectors are read-only on those plans, which is all this server needs):

  1. On chatgpt.com, open Settings → Apps & Connectors → Advanced settings and enable Developer mode.
  2. Add a custom connector: name Charlotte City Data, MCP server URL https://pcygic2am3.us-east-1.awsapprunner.com/mcp, authentication none.
  3. Start a new chat, enable the connector from the tools menu, and test with "When is trash pickup at 2437 Remount Rd?" (expected answer: Thursday).

Non-technical users: paste the block below into a new ChatGPT chat and it will walk you through the steps above interactively.

You're going to help me connect a custom connector called "Charlotte City Data" — a read-only tool that answers questions about Charlotte, NC using the city's official open data. Source: https://github.com/Lavoiedavidw/Charlotte-City-MCP Please walk me through, one step at a time, waiting for my confirmation between each: (1) confirm I'm signed in to ChatGPT Plus or Pro on chatgpt.com in a web browser; (2) guide me to Settings → Apps & Connectors → Advanced settings and help me turn on Developer mode; (3) guide me to add a custom connector named "Charlotte City Data" with MCP server URL https://pcygic2am3.us-east-1.awsapprunner.com/mcp and no authentication; (4) have me start a new chat, enable the connector from the tools menu, and test it with "When is trash pickup at 2437 Remount Rd?" — the answer should be Thursday. Afterward, give me five examples of useful things I can ask it about any Charlotte address.

Remote hosting (AWS)

The same server serves streamable HTTP for remote MCP clients:

uv run charlotte-mcp --transport http --host 0.0.0.0 --port 8080

The hosted instance is defined as two CloudFormation stacks in infra/:

  • infra/build.yaml — ECR repository + a CodeBuild project that builds the Dockerfile directly from this public GitHub repo (no GitHub↔AWS OAuth connection needed) and pushes :latest.
  • infra/service.yaml — an App Runner service (0.25 vCPU / 0.5 GB, ≈$3–5/mo at light usage) serving the image with auto-deploy on new pushes. Deploy it after the first CodeBuild run, since App Runner requires the image to exist.

One transport gotcha, fixed in server.py: FastMCP enables localhost-only DNS rebinding protection at construction time, which makes a public deployment reject its own hostname with HTTP 421. The entrypoint disables that protection when binding to a non-loopback --host.

Tools

21 tools total: 1 geocoder, 1 dataset-discovery tool, and 19 domain tools across six tool packs. Every location-based tool accepts either address: str or lat: float, lon: float and returns a dict with a summary field.

Tool Pack Description
geocode core Geocode a free-form address to lat/lon via the Esri World geocoder
list_datasets datasets Search the ~1,875-entry endpoint registry by keyword/source
lookup_parcel property Look up a parcel by address, point, PID, or NC-PIN (ParcelStatus)
get_zoning property Get zoning code and rezone date for a parcel (Parcel_Zoning_Lookup)
search_tax_foreclosures property Search county tax foreclosures by neighborhood/zip/status (TaxForeclosures)
get_trash_schedule sanitation Garbage/recycling/yard-waste day, provider, route, and GREEN/ORANGE recycling week
crime_near safety CMPD patrol + domestic-violence calls-for-service near a point (NPA-aggregate)
violent_crime_near safety CMPD violent-offense counts (homicide/rape/robbery/assault) near a point (NPA-aggregate)
homicides_near safety Point-level homicide incidents near a point, with weapon/clearance detail
service_requests_near safety 311 service requests near a point
get_planning_area planning Named community planning area containing a location
rezonings_near planning Approved rezonings (since 2016) near a point
area_plans_at planning Area plan(s) covering a location
bike_lanes_near transport Bike lane segments near a point (street, lane type, width, year built)
ada_features_near transport ADA curb ramps, accessible parking, and pedestrian signals near a point
cip_projects_near transport County Capital Improvement (stormwater) projects near a point
cats_projects_near transport CATS transit capital projects (stations + corridors) near a point
brownfields_near environment Recorded NC Brownfields Program sites near a point
watershed_at environment Named watershed/basin containing a location
tree_canopy_at environment Tree canopy / vegetation / impervious-surface stats for a location
battery_recycling_sites_near environment Household hazardous waste / battery recycling drop-off sites near a point

Example prompts

  • "When is trash pickup at 2437 Remount Rd?"
  • "What's the zoning for 2437 Remount Rd, and has it been rezoned recently?"
  • "Are there any tax foreclosures in zip code 28208?"
  • "What watershed is 2437 Remount Rd in, and what's the tree canopy like there?"
  • "Any 311 requests or CMPD calls for service near 600 E 4th St in the last 90 days?"
  • "Find bike lanes and ADA curb ramps within 400 meters of 600 E 4th St."
  • "What capital improvement or CATS transit projects are planned near uptown?"
  • "Search the dataset registry for anything related to 'waste'."

See docs/demo.md for a full worked transcript of the trash-pickup question.

Known data quirks

  • City SWS/AddressLocator geocoder is broken — it returns roughly (0, 0) in its native spatial reference (wkid 2264) instead of a real match. The server does not use it; geocode and every tool's address resolution go through Esri's World geocoder instead.
  • ParcelStatus (county on-prem) rejects outFields=* — the layer's query operation returns an HTTP 200 with an ArcGIS {"error": {"code": 400, ...}} body whenever outFields=* or resultRecordCount is present, regardless of the where/point/envelope filter. lookup_parcel always passes an explicit field list and never a page-size hint to work around it. This is isolated to this layer.
  • TaxForeclosures.status is null on every row in the current dataset (629 total rows checked). The status filter is still exposed by search_tax_foreclosures as documented — it just won't match anything until the county populates that column. cde_symbology_val and bpo_status are the actually-populated status-like fields.
  • CMPD_Calls_for_Service and ViolentCrimeData are aggregate-only tables, not incident-level data — no geometry, no per-incident rows, just monthly counts by Neighborhood Profile Area (NPA). crime_near and violent_crime_near proxy "near this point" by sampling nearby NPAs from the spatial ServiceRequests311 layer, then filtering the aggregate tables to those NPAs — a best-effort approximation, not a true point-in-polygon match. homicides_near and service_requests_near, by contrast, query real point-level layers directly.
  • ArcGIS distance + units=esriSRUnit_Meter buffer overshoot, on some AGOL layers. During development the environment tool pack found Brownfields and Battery_Recycling_Sites (both hosted on layers with a native NC State Plane feet spatial reference) returning features far outside the requested meter radius — consistent with the server silently treating the requested distance as the layer's native unit (feet) instead of converting from meters, a roughly 3.28x overshoot. environment.py's brownfields_near and battery_recycling_sites_near work around this by fetching the full (small: 170 and 5 records respectively) layer once and filtering with a client-side haversine calculation instead of relying on the server-side buffer. A follow-up audit of every other radius-based tool (all of safety.py and transport.py, plus a re-probe of the two originally-flagged layers) found the meter buffer behaving correctly everywhere else, including on a fresh re-test of Brownfields/Battery_Recycling_Sites — see the "Task 8 distance-buffer regression check" note in PLAN.md for the full methodology and a caution for future maintainers about re-verifying before trusting (or removing a workaround for) the buffer on any new layer.

Development

uv run pytest -m live   # live smoke tests against real endpoints, one file per tool pack

Tests are marked live because they hit real network services; expect occasional transient failures from upstream ArcGIS endpoints rather than code bugs.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选