nyc-311-mcp
nyc-311-mcp is an MCP server that lets an AI assistant answer NYC 311 questions using City data and BetaNYC's BoardStat, with sourcing and caveats.
Find how to report a 311 problem from a plain-language description, browse 311 categories, and draft a paste-ready 311 report; it never files anything.
Identify the community district and Council district for an address.
Analyze a district: summaries, top problems, trends, agency response times, still-open requests, top addresses, address history, request lists, and BoardStat links/status.
Rebuild Local Law 47 reports: monthly service-request reports, community-board monthly request lists, and limited directory-assistance reports.
Check today’s city status: alternate side parking, trash/recycling/schools calendar, and emergency statuses like Code Blue or snow emergencies.
Look up one or several 311 service requests by 311 number.
Learn what changed, who built the server, and where its data comes from, including currency, officialness, caveats, and how to verify figures.
Note: some tools need a free NYC 311 API key; answers are informational, district figures are not official City statistics, and emergencies should go to 911.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nyc-311-mcp Check alternate side parking for today."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nyc-311-mcp
An MCP server that connects an AI assistant like Claude to New York City's 311 data. Ask it how to report a problem, what your community district reports most, how fast agencies close requests, or whether alternate side parking is on today. It answers from the City's own data and tells you where each answer came from.
Built by BetaNYC. Free and open source.
See every tool, with real questions and answers: betanyc.github.io/nyc-311-mcp
If this is an emergency, or if you think this is an emergency, call 911. Every answer from every tool ends with this text: "For informational purposes only. BetaNYC builds these answers from City data; they may contain errors. Check the City's 311 page before you report. If this is an emergency, or if you think this is an emergency, call 911."
What's new in 1.3.0
Version 1.3.0 has 24 tools. Three are new: whats_changed tells you what changed in the
server, about_betanyc says who built it and where to report a bug in this server or ask for a new feature,
and about_data says where each answer's data comes from, whether it is official, how current it is, and
where to check it. Every BetaNYC MCP server is getting these three tools; nyc-311-mcp is the first. The
data sources are listed in DATA-SOURCES.json and published as a
DCAT-US 3.0 catalog. Every change a reader would notice, including corrections, is listed
in WHATS-CHANGED.md and on the
website.
Related MCP server: Weather MCP Server
What was new in 1.2.0
Version 1.1.0 had 4 tools. Version 1.2.0 had 21.
Help reporting a problem. Describe it in your own words. It finds the City's 311 article for it, the agency, and every way to report it, and it can write a short report for you to paste in. It never files anything for you.
Your community district or Council district. Eleven tools that answer from BoardStat, which BetaNYC builds every night from NYC Open Data: top problems, trends, how fast agencies close requests, what's still open, and every request at an address. Each answer links to the matching BoardStat page.
The Local Law 47 reports. Rebuilds of the monthly 311 reports that Local Law 47 of 2005 (Gale A. Brewer) put in Charter § 1075. They are BetaNYC rebuilds, not the City's official reports.
Clearer answers from the original four. Request status comes back in words, and the status alerts say yes or no.
A closing note on every answer, the one quoted above.
It went through 19 beta builds before this release. The full history is in CHANGELOG.md.
Install
You need Node.js 18 or later.
Claude Desktop. In the Claude menu, choose Settings… › Developer › Edit Config,
and add this inside mcpServers in claude_desktop_config.json:
{
"mcpServers": {
"nyc-311": {
"command": "npx",
"args": ["-y", "@betanyc/nyc-311-mcp"],
"env": { "NYC_311_API_KEY": "your_key_here" }
}
}
}Save, quit Claude Desktop completely, and open it again. No API key? Leave out the "env"
line and the comma before it.
Claude Code. In a terminal:
claude mcp add --env NYC_311_API_KEY=your_key_here --transport stdio nyc-311 \
-- npx -y @betanyc/nyc-311-mcpAdd --scope user to use it in every project. Check it with claude mcp get nyc-311. No API
key? Leave out --env NYC_311_API_KEY=your_key_here.
Any other MCP app. Run npx -y @betanyc/nyc-311-mcp, with NYC_311_API_KEY set if you
have one.
To check it worked, ask your assistant "Which nyc-311 tools do you have?" You should see 24
(21 on version 1.2.0), including draft_311_report. The install guide has more detail.
Already on 1.1.0? npx keeps a copy of what it downloaded. If you still see 4 tools, quit
your app, delete the _npx folder in npm's cache (~/.npm/_npx on a Mac or Linux,
%LOCALAPPDATA%\npm-cache\_npx on Windows), and open the app again.
Its data cache is about 85 MB of public City data, in ~/Library/Caches/nyc-311-mcp on a
Mac, %LOCALAPPDATA%\nyc-311-mcp\Cache on Windows, and ~/.cache/nyc-311-mcp on Linux. Set
NYC_311_MCP_CACHE_DIR to put it somewhere else.
Get a free API key
Seven tools use the NYC 311 Public API and need a free key: the calendar, status, the two request lookups, and the three reporting-help tools. The district tools and the Local Law 47 reports work without one.
Go to api-portal.nyc.gov and sign in or register.
Subscribe to NYC 311 Public Developers. It's self-serve.
Copy a key from your profile page. Each subscription has a primary and a secondary key. Either one works.
Keep the key to yourself. Never paste it into a GitHub issue.
The portal lists two other products. NYC 311 Public — High Demand gives a higher rate limit. NYC 311 Developer Partner is for creating service requests, which this server never does. You don't need either.
Every tool
You don't need to know the tool names. Ask in plain English and your assistant picks the tool. The website has the same list with a replay of a real answer for each.
Help reporting a problem
Tell it what's wrong in your own words. It finds the City's own 311 article for that problem, the agency that handles it, and every way to report it. It can also write a short report for you to paste in. It never files anything. You do that yourself.
how_to_report(New in 1.2.0; needs the free 311 API key). Describe the problem the way you'd tell a neighbor. It searches the City's 311 articles and gives back the best match: the article title and link on 311 Online, the agency, the 311 problem type, what the City says happens next, and every way to report it. Give it your district and it also tells you how often people there reported the same thing. If your description sounds dangerous, the first line tells you to call 911. It catches a lot, but it will miss some emergencies, so don't count on it for that.Try asking:
“There's a pothole on my block that keeps getting bigger. How do I report it?”
“My upstairs neighbor plays loud music every night.”
“No heat in my apartment.”
“Overflowing trash can and a broken bench in the park.”
Inputs:
description(required),borough,community_district,council_district,last_days,category_id,limit
draft_311_report(New in 1.2.0; needs the free 311 API key). Writes a short report you can paste into 311 Online: the problem, where, when, and what you saw. It doesn't fill in anything you didn't tell it. If something is missing, it marks the gap and asks you. It links the right 311 page, lists the City's Problem Detail options (from a 2024 City list, so they may be out of date), and says what happens after you report. It won't write a draft when it sees danger. It tells you to call 911 instead. It doesn't send anything or fill in any form.Try asking:
“Help me write a 311 report about a pothole at 7th Avenue and 9th Street in Brooklyn. It's been there since last week.”
“Draft a 311 report about a broken streetlight on my corner.”
Inputs:
description(required),location,borough,when,ongoing,details,include_contact
list_311_categories(New in 1.2.0; needs the free 311 API key). Browse 311's own topics, the same ones on 311 Online, when a match looks wrong or you just want to see what 311 covers. Pick a topic to list its articles, 20 at a time.Try asking:
“What kinds of things can I report to 311?”
“Show me 311's noise articles.”
Inputs:
category_id,offset
Your community district or Council district
These read the files BoardStat builds every night from NYC Open Data, with 311 requests from 2020 on. Every answer links to the BoardStat page with the same district, dates and problems, so you can check the numbers yourself. No API key needed.
find_district(New in 1.2.0; no key needed). Type an address the way you normally would. It tells you the community district and the Council district, and how many 311 requests have been made there since 2020.Try asking:
“What community board and Council district is 250 Broadway in?”
Inputs:
address(required),borough
district_summary(New in 1.2.0; no key needed). The big picture for one district: how many requests, how many aren't closed, how long they take to close, and the top problems. For each top problem, it compares the district's share with the borough's and the city's.Try asking:
“Give me a summary of 311 in Brooklyn Community Board 6.”
“What does 311 look like in Council District 7 this fiscal year?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,limit
top_problems(New in 1.2.0; no key needed). The most-reported problems in a district for any period, next to the same days a year earlier.Try asking:
“What were the top 311 complaints in Brooklyn 6 in the last 30 days?”
“Top problems in Council District 39 last fiscal year?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,agency,status,limit
problem_trend(New in 1.2.0; no key needed). One problem, month by month, in one district, with the same days a year earlier next to each month.Try asking:
“How has residential noise in Brooklyn 6 changed month to month this year?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problem(required),descriptions,exclude_descriptions,agency,status
agency_response(New in 1.2.0; no key needed). For each agency: how many requests, how many are closed, and the median and average days to close. Remember that closed doesn't mean fixed.Try asking:
“How fast do agencies close requests in Council District 39?”
“Which agency is slowest in Bronx 1 this fiscal year?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problems,descriptions,exclude_descriptions,limit
still_open(New in 1.2.0; no key needed). Requests that aren't closed yet, oldest first, with how many days each has been open and a count by agency. The City doesn't define its statuses, so we explain each one and label the explanation as ours.Try asking:
“What 311 requests in Brooklyn 6 are still open?”
“Which agency has the most open requests in Queens 1?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problems,descriptions,exclude_descriptions,agency,limit
top_addresses(New in 1.2.0; no key needed). The addresses with the most requests in a district, with each one's most common problem. You can narrow it to one problem.Try asking:
“Which addresses in Brooklyn 6 get the most 311 requests?”
“Where are the most heat complaints in Bronx 5?”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problems,descriptions,exclude_descriptions,agency,status,limit
address_history(New in 1.2.0; no key needed). Every request at one address since 2020, newest first, with the status explained and the agency's own resolution text. It's the closest thing to looking up a request when you don't have its number.Try asking:
“What's been reported at 1 Centre Street?”
“Any open requests at City Hall?”
Inputs:
address(required),borough,community_district,from_date,to_date,fiscal_year,last_days,problems,status,limit,offset,data_as_of
find_requests(New in 1.2.0; no key needed). Every request in a district, newest first, a page at a time. Filter by problem, agency, or status, including the City's own statuses like Pending.Try asking:
“Show me the newest street-condition requests in Brooklyn 6.”
“List DOT requests in Manhattan 3 that are Pending.”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problems,descriptions,exclude_descriptions,agency,status,statuses,limit,offset,data_as_of
boardstat_link(New in 1.2.0; no key needed). Makes a BoardStat link with your district, dates, problem, agency, and status already set, so you can open the map and charts yourself.Try asking:
“Give me a BoardStat link for residential noise in Brooklyn 6, last 90 days.”
Inputs:
community_district,council_district,from_date,to_date,fiscal_year,last_days,problems,descriptions,exclude_descriptions,agency,status
boardstat_status(New in 1.2.0; no key needed). How fresh BoardStat's data is, and whether last night's build ran late. Ask this when a number looks off.Try asking:
“How fresh is BoardStat's data?”
Inputs: none
The Local Law 47 reports
In 2005, Local Law 47 (Gale A. Brewer) required monthly 311 reports from the City, written into Charter § 1075. Two of those reports were repealed in 2023. We rebuilt all three from NYC Open Data. They are BetaNYC rebuilds, not the City's official reports, and every answer says so. No API key needed.
ll47_service_request_report(New in 1.2.0; no key needed). Rebuilds the monthly report on requests for service, formerly Charter § 1075(b): totals by category, agency, and status, and the average and median days to close, for a month and for the fiscal year to date. Citywide, by borough, or for one district.Try asking:
“Rebuild the Local Law 47 monthly 311 report for Brooklyn 6.”
“Run the § 1075(b) report for Queens for October.”
Inputs:
month,fiscal_year,community_district,council_district,borough,by_district,read_every_district,limit
cb_monthly_list(New in 1.2.0; no key needed). The list that Charter § 1075(d), still law, says community boards should get: one district's requests for a month, every older request still unresolved, and the ones closed since. Comes in pages, or as a CSV.Try asking:
“Give Brooklyn Community Board 6 its monthly list of 311 requests for October.”
“Same list for Staten Island 1, as a CSV.”
Inputs:
community_district(required),month,part,data_as_of,limit,offset,format
ll47_directory_assistance_report(New in 1.2.0; no key needed). Calls answered by 311 agents, by topic, for a month and the fiscal year to date, formerly Charter § 1075(c). This one is limited, and the answer says so: the open data can't separate out directory-assistance calls, and its agency column is blank. NYC Open Data can be slow here, so the first full-year answer may take a few tries.Try asking:
“How many calls did 311 agents answer in October, by topic?”
Inputs:
month,fiscal_year,limit
Today in the city
The City's own 311 calendar and status alerts. These were in 1.1.0, too.
get_calendar(Same as 1.1.0; needs the free 311 API key). Alternate side parking, trash and recycling collection, and schools, for a day or up to 90 days.Try asking:
“Is alternate side parking in effect today?”
“Is trash pickup on schedule the week of Thanksgiving?”
Inputs:
date,from_date,to_date
get_status(Improved in 1.2.0; needs the free 311 API key). Whether Code Blue, a fire hydrant emergency, snow or ice, or an emergency management alert is in effect right now. The answer now says it in words.Try asking:
“Is there a Code Blue tonight?”
“Is there a snow emergency on the streets?”
Inputs:
type(required)
Look up a 311 request
Have a 311 number, like 311-12345678? These tell you where it stands, in words. The City sends a status code, and we translate it.
get_service_request(Improved in 1.2.0; needs the free 311 API key). Look up a request by its 311 number. You get the agency, the problem, the status in words, and the agency's own note about what it did. ZIP codes are removed.Try asking:
“What happened with 311 request 311-17323508?”
Inputs:
sr_number(required)
get_service_request_list(Improved in 1.2.0; needs the free 311 API key). Several 311 numbers at once. Any number the City can't find is listed, so nothing quietly goes missing.Try asking:
“Check these three 311 numbers for me: …”
Inputs:
sr_numbers(required)
About this server
Ask what changed in the server lately, who built it, or where its data comes from. Every BetaNYC MCP server is getting these three tools; nyc-311-mcp is the first. One reads the same list as the What's changed page; another reads the server's list of data sources, which is also published as a data catalog. No API key needed.
whats_changed(New in 1.3.0; no key needed). What changed in this server, newest first: new tools, data fixes, and corrections when an answer was wrong. You can ask for corrections only, or for changes since a date.Try asking:
“What's new in the 311 server?”
“Has the 311 server ever corrected a wrong answer?”
Inputs:
since,tag,limit
about_betanyc(New in 1.3.0; no key needed). Who built this server, where to report a bug in this server or ask for a new feature, and links to BetaNYC's events, newsletter, and ways to get involved.Try asking:
“Who made this 311 tool?”
“Where do I report a bug in the 311 server?”
Inputs: none
about_data(New in 1.3.0; no key needed). Tells you where each answer's data comes from. It names the publisher and says whether the numbers are an official record or BetaNYC's own, what BetaNYC changed, and how current the data is on your computer. It also gives what the data leaves out, the credit line to use, where to check a number with the City, and where to report a mistake.Try asking:
“Where do the 311 district numbers come from?”
“Are these 311 numbers official?”
“How current is the 311 data?”
Inputs:
topic
How the district tools read districts and dates
Districts. Give a community district or a Council district, not both.
Community districts use BoardStat's numbers: the borough digit, then the district. Manhattan is 101 to 112, the Bronx 201 to 212, Brooklyn 301 to 318, Queens 401 to 414, and Staten Island 501 to 503. Board codes and names work too:
BK06,MN01, "Brooklyn 6".Parks and other areas outside every community district have their own numbers (Joint Interest Areas): 164, 226, 227, 228, 355, 356, 480 to 484, and 595.
Council districts are 1 to 51.
Dates. Give one of these:
from_dateandto_date, as YYYY-MM-DD. Data starts January 1, 2020.A City
fiscal_year. It runs July 1 to June 30 and is named for the year it ends, so2027or"FY27"is July 1, 2026, to June 30, 2027.last_days. It counts back from the newest request in the data, not from today, because the City publishes 311 data a few days late.
With no dates, a tool uses the dates BoardStat's page opens with, about the last year.
Every district answer includes data_as_of, a boardstat_url, plain-language caveats, and
its source.
Before you rely on an answer
311 counts are reports, not problems. They show who reports and how, and not only how many problems there are.
"Closed" means an agency closed the request. It doesn't mean the problem was fixed. Read the agency's resolution text.
The district numbers aren't official City statistics. Check them against the BoardStat page each answer links to.
The City doesn't publish what its request statuses mean. Where we explain a status, the answer says the explanation is ours (
meaning_source: "BetaNYC").A request's 311 number (
311-XXXXXXXX) and NYC Open Data'sunique_keyare different numbers, and nothing published links them. The district tools listunique_key, whichget_service_requestcan't look up. Useaddress_historyinstead. Details: docs/service-requests.md.Danger detection in
how_to_reportanddraft_311_reportlooks for words and phrases. It will miss some emergencies. Every answer also tells the assistant to send the person to 911 whenever anything suggests danger.We left ZIP codes out on purpose. ZIP codes are mail routes, not City districts.
Tell us what you find
Open an issue. Tell us which tool, what you asked, what you got, and what you expected. GitHub issues are public, so leave out names, phone numbers, home addresses, 311 request numbers, and your API key. A street corner or a district is enough.
Reference
The original four tools, in detail
get_calendar
Alternate side parking, collections (trash, recycling, and compost), and schools, for one date or a range of up to 90 days. With no dates, it gives today. Dates are New York time.
Parameter | Type | Required | Default | Description |
| string | no | today | One date, YYYY-MM-DD |
| string | no | — | Range start, YYYY-MM-DD |
| string | no | — | Range end, YYYY-MM-DD |
A normal weekday:
{
"days": [
{
"today_id": "20261109",
"items": [
{ "type": "Alternate Side Parking", "status": "IN EFFECT", "details": "Alternate side parking and meters are in effect." },
{ "type": "Collections", "status": "ON SCHEDULE", "details": "Trash, recycling, and compost collections are on schedule." },
{ "type": "Schools", "status": "OPEN", "details": "Public schools are open." }
]
}
]
}On a holiday, each item also has an exceptionName. A Memorial Day lookup returns
"status": "SUSPENDED" with "exceptionName": "Memorial Day 2026".
get_status
Whether one City status is in effect right now. You get the API's own answer (inEffect, and
eventName for OEM) plus a plain_language block that says yes or no in words and when it was
asked. It isn't alternate side parking. Use get_calendar for that.
| The City's description, from the 311 API portal (read 2026-11-08) |
| "API to determine if Code Blue status is currently active" |
| "API to determine if Fire Hydrant emergency is currently active" |
| "API to get OEM event currently active" |
| "API to determine if Snow or Ice on Sidewalk emergency is currently active" |
| "API to determine if Snow or Ice on Street emergency is currently active" |
get_service_request
One request by its 311 number (sr_number, as 311-XXXXXXXX). You get the API's fields with
ZIP codes removed: agency, problem, problem details, status code, when it was submitted, the
address, and the agency's resolution text. Since 1.2.0, a plain_language block adds the
status in words (the API sends a code, 614110003 means Closed) and the address to give
address_history.
get_service_request_list
Several requests at once (sr_numbers, a list). Each comes back as in get_service_request.
The City leaves out a number it can't find without saying so, so since 1.2.0 they are listed
in not_found.
Run it from source
git clone https://github.com/BetaNYC/nyc-311-mcp.git
cd nyc-311-mcp
npm install
npm run build
NYC_311_API_KEY=your_key npm startRun the tests (they build first and need no API key or network):
npm testData sources
The four lookup tools and the three reporting-help tools use the NYC 311 Public API, run by the NYC Office of Technology and Innovation (OTI). The reporting help reads the same 311 articles you see on 311 Online.
The eleven district tools,
ll47_service_request_report, andcb_monthly_listread the files BoardStat publishes every night from NYC Open Data's 311 Service Requests dataset. Onlywww.beta.nycis contacted.ll47_directory_assistance_reportreads NYC Open Data's 311 Call Center Inquiry dataset (wewp-mm3p), one month at a time, and saves what it reads. SetSOCRATA_APP_TOKENif you have one. It works without one.draft_311_reportreads NYC Open Data's 311 Service Level Agreements for Problem Detail options. The City last updated that list on March 5, 2024.
Rate limits on the 311 API depend on your subscription, not on this server.
DATA-SOURCES.json lists every source, source by source: who publishes it,
what BetaNYC changed, what it covers, its terms and credit line, where to check a number and
where to report an error. The about_data tool answers from it, and says how current each
source is on your computer from what the server last downloaded. A test fails if a tool is
not listed under a source. data.json, a DCAT-US 3.0
catalog, is made from the same file, at the repo root (it ships in the npm package). A copy on
the website (docs/data.json) is made the same
way, and CI fails unless the two match. There is no croissant.json, because this repo publishes no
data files of its own; BoardStat publishes the district files. After changing DATA-SOURCES.json:
python3 scripts/whats_changed.py about-data check DATA-SOURCES.json
python3 scripts/whats_changed.py about-data catalog DATA-SOURCES.json
python3 scripts/whats_changed.py about-data catalog DATA-SOURCES.json --dcat docs/data.jsonCI fails while data.json is stale, and validates it against the DCAT-US 3.0 schema
(scripts/tests/catalog_validate.py and scripts/mcp_shared/, copies of BetaNYC's shared
files). Questions about the data go to BetaNYC at lab@beta.nyc, the contact address in
DATA-SOURCES.json and data.json.
This is an independent, community-built project. It is not affiliated with, endorsed by, or an official product of the City of New York.
The website
The site at betanyc.github.io/nyc-311-mcp is built by
GitHub Pages from the docs/ folder. docs/index.html and docs/tools.html are plain HTML.
Their demos are real answers, shortened, and every line shown is copied word for
word from the tool's answer. The Markdown pages in docs/ share docs/_layouts/default.html.
docs/whats-changed.html is built from WHATS-CHANGED.md by
scripts/whats_changed.py, a copy of BetaNYC's shared script (never edit the copy). After
changing WHATS-CHANGED.md, rebuild the page and commit it; CI fails while it is stale:
python3 scripts/whats_changed.py check WHATS-CHANGED.md
python3 scripts/whats_changed.py render WHATS-CHANGED.md --format jekyll --layout whats-changed \
--out docs/whats-changed.html --repo-url https://github.com/BetaNYC/nyc-311-mcpA release that adds or changes a tool also adds a WHATS-CHANGED.md entry tagged MCP, in the
same pull request as the version bump, headed ## Unreleased: Title. The release commit
changes that heading to ## YYYY-MM-DD: Title (the release date in New York, same title), and
the tag goes on that commit; the Release workflow refuses to publish while an Unreleased entry
is left. src/betanyc-tools.ts (the whats_changed,
about_betanyc and about_data tools) is a copy too.
Releases
Pushing a tag vX.Y.Z that matches the version in package.json runs
.github/workflows/release.yml. It runs the tests, publishes @betanyc/nyc-311-mcp to npm
with provenance, and creates a GitHub Release. Version history is in
CHANGELOG.md. Publishing needs the NPM_TOKEN repository secret.
Release day. A version bump merges with its WHATS-CHANGED.md entry headed
## Unreleased: Title and its CHANGELOG.md heading undated (## [X.Y.Z] - Unreleased), the
entry's MCP version linking to CHANGELOG.md with no anchor. On the day the tag goes on, make
one commit that:
changes
## Unreleased: Titleto## YYYY-MM-DD: Title(same title, today's date in New York;checkrejects a future date);gives the
CHANGELOG.mdheading the same date (## [X.Y.Z] - YYYY-MM-DD);adds the dated anchor to the MCP version link, computed with the script, never by hand:
python3 -c "import sys; sys.path.insert(0,'scripts'); import whats_changed as w; print(w.github_slug('[X.Y.Z] - YYYY-MM-DD'))";rebuilds
docs/whats-changed.html(the command under "The website") and runspython3 scripts/whats_changed.py check WHATS-CHANGED.md --release.
The title stays exactly the same: only Unreleased becomes the date. That commit may reword
the entry's other lines; until it has a date, an Unreleased entry's body counts as
unpublished, so the append-only check needs no Whats-changed-edit: trailer for it.
Then tag that commit vX.Y.Z and push the tag. The Release workflow runs the same
check --release before npm publish and stops while an Unreleased entry is left. It also
runs python3 scripts/whats_changed.py about-data check DATA-SOURCES.json --release, which
stops a release while the contact address in DATA-SOURCES.json is a placeholder.
When the Release workflow succeeds, .github/workflows/publish-mcp.yml lists the new version
in the official MCP Registry as
io.github.BetaNYC/nyc-311-mcp, from server.json. Keep server.json at the same version
as package.json; the Release workflow checks.
More from BetaNYC
Related MCP servers
We maintain a set of free MCP servers for NYC and New York State civic data. The full directory, with install steps for each, is at beta.nyc/ai-tools.
nyc-council-mcp: City Council legislation, hearings, votes, and members
nyc-checkbook-mcp: City spending, contracts, budget, payroll, and revenue
nyc-record-mcp: City Record notices, including procurement, awards, and public hearings
nyc-charter-laws-rules: the NYC Charter, Administrative Code, and Rules of the City of New York
nys-openlegislation-mcp: New York State bills, laws, members, and committees
For questions across all of NYC Open Data, including the full 311 dataset, try socrata-mcp-server, a third-party MCP by Nathan Storey.
About BetaNYC
BetaNYC is New York's civic technology and open data community. We work to improve lives in New York through civic design, technology, and data.
Come do civic tech with us. We run NYC School of Data, CityCamp NYC, and events all year. See what's coming up on our events calendar.
Building on this? Tell us!
If you build something with this, we'd love to hear about it, and we can help other New Yorkers find it. Subscribe to our weekly newsletter, or send us a link for an upcoming issue.
Contributing
Issues and pull requests are welcome at github.com/BetaNYC/nyc-311-mcp. Other BetaNYC MCPs in testing are listed on Beta MCPs.
Support our work
These servers are free. Freedom isn't free. Become a Beta Builder.
License
MIT License
Copyright (c) 2026 BetaNYC
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Available Tools
24 toolsabout_betanycAbout BetaNYC and this serverARead-only
Who built this server and how to reach them: BetaNYC, a project of the Fund for the City of New York. Returns what BetaNYC is, links to its events, newsletter and donation page, where to report a bug in this server or ask for a new feature (this server's GitHub issues), and this server's name and version.
Inputs: no named parameters. Returns: about, links, server, history, +4 more
about_dataWhere this server's data comes fromARead-only
Where this server's data comes from and how far to trust it. For each kind of data: who publishes it and a link, whether it is an official record or BetaNYC's curation, how it was gathered, what BetaNYC changed (for example cleaned, address-matched, merged or counted), how current it is on this server, what it covers and what is missing, the terms of use and the credit line to print, where to check a figure at the official source, where to report an error (to the publisher, or in this server), which tools use it, and corrections that touched it. Call it whenever someone asks where an answer comes from, how current or accurate it is, or how to check or cite it. topic narrows it to one kind of data, or to the data behind one tool (give the tool's name). For who built this server, use about_betanyc. Topics on this server: calendar-and-status, service-request-lookup, 311-articles, built-in-911-lines, service-requests-by-district, ll47-service-request-reports, community-district-boundaries, council-district-boundaries, call-center-inquiries, service-level-agreements.
Inputs: topic. Returns: note, topic, server, topics, +5 more
address_historyA
Every request at one address, newest first, with its status, days to close or days open, and the agency's resolution text, plus counts by problem. The address is converted to the City's spelling as in find_district. With no dates, covers every request since 2020. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: address (required), limit, offset, status, +8 more.
agency_responseA
For each agency in a district and period: requests, how many are closed and not yet closed, and the median and average days to close (closed requests only). Optional problem and description filters. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, to_date, problems, from_date, +6 more.
boardstat_linkB
A link to BoardStat's district page with the given district, dates, problems, descriptions, agency and status already set, so a person can see and check the numbers. Problem and description names are checked against BoardStat's data.
Inputs: agency, status, to_date, problems, +7 more.
boardstat_statusB
How fresh BoardStat's data is: when it was last built, the newest request in it, whether the nightly run is late, the boundary versions, and counts of known City data problems (such as requests closed before they were created).
Inputs: no named parameters.
cb_monthly_listA
The monthly list of Charter § 1075(d), current law, for one community district: every 311 request created in a month (default: the newest complete month), plus earlier requests still not closed and those unresolved at the month's end that have closed since; each with its number, date, category, description, agency, current status and address. Pages with limit and offset; format 'csv' returns the page as CSV text. From BoardStat's nightly files. A BetaNYC rebuild from NYC Open Data, not the City's official report. No ZIP codes, nothing before 2020.
Inputs: community_district (required), part, limit, month, +3 more.
district_summaryA
Totals for a community or council district and period: requests, how many are not yet closed, median and average days to close, the top problems, and each top problem's share compared with the borough and the whole city. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, to_date, from_date, last_days, +3 more.
draft_311_reportA
Draft a 311 report for the person to submit themselves: a short ready-to-paste text (problem, where, when, what they saw), the 311 Online article link to report it on, questions to ask them for anything missing (marked [add: …], never made up), Problem Detail options from the City's 2024 Service Level Agreements list (labeled old), what the City's article says about contact details and photos, and what happens next. Uses how_to_report's matching. Files nothing, sends nothing, and fills no form: the City does not publish each form's fields, so the form may ask for more. If the description suggests an emergency it does not draft and says to call 911. A description of two problems gets one draft each. Every answer and error starts with "For informational purposes only. BetaNYC builds these answers from City data; they may contain errors. Check the City's 311 page before you report. If this is an emergency, or if you think this is an emergency, call 911." Danger detection here is keyword-based and will miss some emergencies. If anything the person says suggests someone may be in danger or need urgent medical help, tell them to call 911 first, even if this tool did not flag it.
Inputs: description (required), when, borough, details, +3 more.
find_districtA
Which community district and City Council district an address is in. Type it as usual ('350 5th Ave'); it is converted to the City's spelling ('350 5 AVENUE') and looked up among addresses in 311 requests since 2020. If not found, says so and suggests close City spellings. Not a geocoder. ZIP codes are ignored. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: address (required), borough.
find_requestsA
List the requests in a community or council district, newest first, with any status, paged with limit and offset. Each has its status, days to close or days open, address and the agency's resolution text; by_status counts each status and says in plain words what it means. Filter by problems, descriptions, agency, status, or statuses (the City's own values). For one address use address_history; for only what is still open, still_open. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, agency, offset, status, +11 more.
get_calendarA
Get Alternate Side Parking, Garbage & Recycling, and Schools status for a date or date range (max 90 days). Dates are interpreted in America/New_York (Eastern Time); if no date is given, defaults to today in New York.
Inputs: date, to_date, from_date.
get_service_requestA
Look up one 311 service request by its 311 number (format 311-XXXXXXXX), from the City's 311 Public API. Returns agency, problem, status, submitted time, address (ZIP code removed) and the agency's resolution text, plus a plain_language block: the status in words and what it means. The 311 number is not NYC Open Data's unique_key, so it is not matched to BoardStat's rows by number; for other requests at the same address, pass plain_language.address_lookup to address_history.
Inputs: sr_number (required).
get_service_request_listA
Look up several 311 service requests by their 311 numbers in one call. Each comes back as in get_service_request, with its plain_language block; numbers the API did not find are listed in not_found (the API leaves them out without an error).
Inputs: sr_numbers (required).
get_statusA
Whether a City status is in effect right now, from the 311 Public API: Code Blue (cold weather), Fire Hydrant emergency, an OEM emergency event, Snow or Ice on Sidewalk, or Snow or Ice on Street. Returns the API's answer plus plain_language: yes or no in words, what it checks, and when it was asked. Not alternate side parking: use get_calendar for that.
Inputs: type (required).
how_to_reportA
Find how to report a problem to 311, from a plain description ('a pothole on my block', 'no heat in my apartment'). Returns the best 311 articles from the City's own 311 content (title, KA number, link on 311 Online), the agency and the 311 problem type each names (the problem type is NYC Open Data's complaint_type), what the article says to do and what happens next, and the ways to report (311 Online, the NYC311 app, phone 311 or 212-NEW-YORK, text 311-692), all from City text. Every answer starts with 'For informational purposes only. BetaNYC builds these answers from City data; they may contain errors. Check the City's 311 page before you report. If this is an emergency, or if you think this is an emergency, call 911.'; a description that suggests danger, and every no-match answer, leads with a 911 line, in the City's words only when the City article is that danger. IMPORTANT: danger detection here is keyword-based and will miss some emergencies. If anything the person says suggests someone may be in danger or need urgent medical help, tell them to call 911 first, even if this tool did not flag it. Matching is by keyword, done by BetaNYC, and reads only a few 311 categories (listed in searched). Give community_district or council_district to add how often that problem type was reported there (BoardStat). Does not file anything.
Inputs: description (required), limit, borough, last_days, +3 more.
list_311_categoriesA
Browse 311's own topic categories (the ones on 311 Online), or, given a category_id, the articles in it with their KA numbers and links. Use it when how_to_report's match looks wrong, then pass the category_id to how_to_report. Danger detection in these tools is keyword-based and will miss some emergencies: if anything the person says suggests someone may be in danger or need urgent medical help, tell them to call 911 first.
Inputs: offset, category_id.
ll47_directory_assistance_reportA
Rebuilds the monthly directory-assistance report of former Charter § 1075(c) (Local Law 47 of 2005; repealed by Local Law 69 of 2023), as far as the open data allows: calls to 311 agents for a month and the fiscal year to date, by topic, from NYC Open Data's 311 Call Center Inquiry dataset (wewp-mm3p). Marked limited: the dataset cannot tell directory-assistance calls from others, and its agency and call-resolution columns are blank in recent years, so there is no breakdown by agency. Queries NYC Open Data (one query per month, cached; the month in progress is asked again after an hour). A month call fetches only that month; its fiscal year to date uses saved months. A fiscal_year call answers within about 12 s: saved months at once, others listed as still loading while they keep loading (an incomplete period shows each saved month's count and a partial sum, labeled, never a total); asking again a minute later finishes it. A BetaNYC rebuild from NYC Open Data, not the City's official report. No ZIP codes, nothing before 2020.
Inputs: limit, month, fiscal_year.
ll47_service_request_reportA
Rebuilds the monthly 311 service request report of former Charter § 1075(b) (Local Law 47 of 2005; repealed by Local Law 69 of 2023): for a month and the fiscal year to date, totals by category (the City's complaint type) and by agency, totals by status, and the average (and median) days to close for each category and agency. Citywide, one borough, one community district or one council district; or by_district for a table of every district. From BoardStat's nightly files. Citywide and borough answers give totals by problem only, unless read_every_district is true. A BetaNYC rebuild from NYC Open Data, not the City's official report. No ZIP codes, nothing before 2020.
Inputs: limit, month, borough, by_district, +4 more.
problem_trendA
Requests per month for one problem in one district, with the same days a year earlier. Optional description, agency and status filters. Months only partly covered are marked. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: problem (required), agency, status, to_date, +7 more.
still_openA
Requests in a district that are not yet closed, oldest first, with days open, plus a count and the oldest date for each agency. With no dates, covers every request since 2020. Optional problem, description and agency filters. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, agency, to_date, problems, +7 more.
top_addressesA
The addresses in a district with the most requests for a period, optionally for given problems or descriptions. Addresses are as the City spelled them. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, agency, status, to_date, +8 more.
top_problemsA
The most-reported problems in a community or council district for a period, each with the count for the same days a year earlier and the median days to close. Optional agency and status filters. From BoardStat (BetaNYC, NYC Open Data, 2020 on); not an official City report. 311 counts are reports, not problems; 'closed' is not 'fixed'.
Inputs: limit, agency, status, to_date, +5 more.
whats_changedWhat's changedARead-only
What has changed in this server, its data and its website, newest first, from the project's WHATS-CHANGED.md: new tools and pages, new data, data fixes, and corrections when BetaNYC published something wrong. Each correction says what to re-check if you used the old numbers. Call this before relying on a figure you got from this server earlier, or when a user asks whether something was fixed. Filter with since (YYYY-MM-DD; also keeps older entries that have an update on or after that date) and tag (Site, Data, MCP or Correction).
Inputs: tag, limit, since. Returns: note, server, source, entries, +4 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 24 tools
The many district-analytics tools (district_summary, top_problems, problem_trend, agency_response, still_open, top_addresses, find_requests) each return a distinct metric, and descriptions explicitly route callers elsewhere ('For one address use address_history; for only what is still open, still_open'). Remaining overlap is modest: ll47_service_request_report, cb_monthly_list, and find_requests all enumerate requests by district/month, and how_to_report vs draft_311_report vs list_311_categories share the reporting-guidance space but differ in output shape.
All names are snake_case, so it is at least uniform in style. But the convention is mixed: some are verb_noun (get_calendar, find_district, list_311_categories, draft_311_report) while many are bare noun phrases (district_summary, top_problems, agency_response, boardstat_link, cb_monthly_list), so an agent cannot predict the name form.
24 tools sits at the heavy end of the range and the surface spans several sub-domains (calendar/status, single-request lookup, district analytics, LL47 reports, reporting guidance, provenance). Each tool is defensible individually, but the set is large enough that selection cost is real.
As a read-only data/guidance server it covers the lifecycle well: lookup by number (single and batch), address-to-district, district totals/trends/agency performance/open requests/top addresses, full address and district history listings, regulatory report rebuilds, how-to-report guidance, and provenance/freshness/changelog meta-tools. Gaps are minor and documented (find_district is not a geocoder, ZIP codes ignored, data only from 2020 on).
Maintenance
Related MCP Connectors
MCP server that lets AI assistants use all OneSchema features exposed via the public API.
Hosted MCP server for live public-data APIs and Skills for AI agents.
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
MCP server giving Claude AI access to 22+ NYC public-record databases for real estate due diligence
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA server that integrates the MCP library with OpenAI's API, allowing users to interact with various tools, such as the weather tool, through natural language queries.MIT
- FlicenseBqualityDmaintenanceAn MCP server that provides weather information and alerts for US locations using the National Weather Service API, enabling retrieval of weather forecasts and active weather alerts.2-
- FlicenseNot gradedqualityDmaintenanceA demo MCP server that provides AI assistants access to live US weather data via the free National Weather Service API, offering forecast and alert tools without requiring an API key.-
- FlicenseNot gradedqualityDmaintenanceMCP server providing tools to chat with an AI agent, fetch weather data, and monitor agent status via the Model Context Protocol.-