An MCP server for the Chicago Data Portal. Hands Claude Code (and any other MCP client) a small, well-typed set of tools for discovering and querying Chicago's public-safety datasets — crimes, arrests, towed vehicles, COPA cases — without hand-rolling SoQL each time.
This repo is the server only. Apps built on top of it live elsewhere.
| Tool | What it does |
|---|---|
list_datasets |
Browse the portal's catalog. Defaults to the Public Safety category. |
get_dataset_metadata |
Schema, description, and last-updated time for a dataset. Accepts 4x4 ids (e.g. ijzp-q8t2) and short aliases (crimes, arrests, towed_vehicles, copa_by_complainant, copa_by_officer). |
query_dataset |
Raw SoQL passthrough ($select, $where, $group, $order, $q, $limit, $offset). |
search_records |
Full-text search across a dataset. |
search_crimes |
Filter the Crimes - 2001 to Present dataset by date range, primary type, community area / ward / district / beat, arrest/domestic flags, or a lat/lng radius. |
aggregate_crimes |
count(*) grouped by primary type, community area, ward, district, beat, year, month, location description, or FBI code. |
search_arrests |
Filter CPD Arrests by date range, case number, or charge description. |
search_towed_vehicles |
Look up impounded vehicles by plate, make, color, state, or tow date (last ~90 days). |
search_copa_cases |
COPA complaints, by complainant or by involved officer. |
Requires Python 3.12+. The recommended runner is uv.
# Clone and sync dependencies
git clone https://github.com/gblush/606data.git
cd 606data
uv syncThe server works anonymously, but you'll hit Socrata rate limits quickly. Get
a free App Token (not an API Key) and expose it via the SOCRATA_APP_TOKEN
env var.
Go to https://data.cityofchicago.org/profile/edit/developer_settings.
The portal lets you create two kinds of credentials — make sure you pick the right one:
- App Token — what we want. Identifies an application; sent in the
X-App-Tokenheader; unlocks the higher rate-limit tier for reading public data. This is exactly whatchicago_mcp.clientuses. - API Key — not what we want. A user credential (key ID + secret) for write operations and accessing private/restricted datasets. This server doesn't need either.
Fill out the App Token form:
| Field | Value |
|---|---|
| Application Name | anything memorable, e.g. chicago-mcp |
| Description | optional |
| Application URL | optional |
| Callback Prefix | leave blank, or http://localhost/ if the form requires a value — this is only used for OAuth flows that we don't do |
| Public | yes. A public token can be used standalone in the X-App-Token header; a non-public token must be paired with user credentials on every request, which defeats the point. |
Public ≠ "share it freely." Still keep the token out of public repos. It just means "usable without combining with user auth."
The server reads SOCRATA_APP_TOKEN from its process environment. Either:
- Export it in your shell (e.g. add to
~/.zshrc):export SOCRATA_APP_TOKEN=your-token - Or pass it explicitly to
claude mcp add(see below).
.env.example is included as documentation of which env vars the server reads.
claude mcp add chicago-mcp -- \
uv run --directory /absolute/path/to/606data chicago-mcp(Replace /absolute/path/to/606data with the real path.) If you'd rather pass
the app token explicitly instead of using .env:
claude mcp add chicago-mcp \
--env SOCRATA_APP_TOKEN=your-token \
-- uv run --directory /absolute/path/to/606data chicago-mcpAdd to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"chicago-mcp": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/606data", "chicago-mcp"],
"env": { "SOCRATA_APP_TOKEN": "your-token" }
}
}
}Once the server is wired up, try asking your MCP client things like:
- "How many thefts were reported in community area 32 last week?"
- "What are the most common crime types in Chicago in 2024 so far?"
- "Were any white Honda Civics towed in the last 30 days?"
- "Show me COPA cases involving police shootings opened this year."
- "List all public-safety datasets that mention 'shotspotter'."
| Alias | 4x4 id | Dataset |
|---|---|---|
crimes |
ijzp-q8t2 |
Crimes - 2001 to Present |
crimes_map |
dfnk-7re6 |
Crimes - Map (last year) |
arrests |
dpt3-jri9 |
Arrests |
towed_vehicles |
ygr5-vcbg |
Towed Vehicles |
copa_by_complainant |
vnz2-rmie |
COPA Cases - By Complainant or Subject |
copa_by_officer |
ufxy-tgry |
COPA Cases - By Involved Officer |
Any other dataset on the portal can still be queried via query_dataset with
its 4x4 id; the aliases are just for the helpers' convenience.
uv sync # install runtime + dev deps
uv run pytest # run unit tests
uv run chicago-mcp # start the server on stdio (for manual MCP testing)MIT.