Skip to main content
Glama
haksanlulz

mcp-nychousing

by haksanlulz

mcp-nychousing

MCP server for NYC housing data over NYC Open Data (the Socrata / SODA API). Built for tenant organizers, housing-court legal-aid intake, and Right-to-Counsel orgs: pull a building's HPD violations and complaints, find out who actually owns it two different ways (HPD's registration filings, and the property record itself: the assessment roll, recorded deeds and mortgages, and Speculation Watch List), map everything else registered under that owner or agent's name, check HPD litigation, Department of Buildings records, 311 heat complaints, and marshal-executed evictions — or pull the whole picture in one building_profile call.

It wraps seventeen city datasets and normalizes their raw columns (novdescription, violationstatus, registrationid, court_index_number, and so on) into documented tool outputs.

Tools

Tool

Arguments

Returns

building_violations

house_number, street, borough (all required), open_only, violation_class, since, limit

HPD violations for a building (wvxf-dwi5). Server-side per-class count summary (A/B/C/I) plus recent rows: id, apartment, class, description, status, open flag, inspection date.

building_complaints

house_number, street, borough (all required), open_only, since, limit

HPD complaints and problems for a building (ygpa-z7cr). Open/closed count summary plus recent rows: complaint id, category, status, dates.

who_owns

house_number, street, borough (all required)

HPD registration (tesw-yqqr) joined to registration contacts (feu5-w2e2). Owner, head officer, officer, agent, and site manager, with names and business addresses, grouped by type.

landlord_portfolio

name (required), borough, limit

Reverse of who_owns: registration contacts (feu5-w2e2) matched by corporation or person name, resolved to every currently registered building (tesw-yqqr). Address, borough, zip, BIN, registration dates, and which contact(s) matched, plus contact/registration/building counts.

landlord_litigation

house_number + street + borough, and/or respondent, plus case_status, limit

HPD Housing Litigations (59kj-x8nc) by building or by respondent name. Case type, open date, status, judgement, harassment finding, penalty, respondent, with a by-status summary.

eviction_lookup

court_index_number, and/or address, and/or borough, plus since, limit

Marshal-executed evictions (6z8x-wfk4) by court index number or address/borough. Index number, address, executed date, marshal, residential/commercial flag.

building_profile

house_number, street, borough (all required)

One-call profile across nine datasets: registration + contacts, violation counts by class, complaint counts by status, litigation counts by status, executed-eviction count, AEP status (hcir-3275), vacate orders (tb8q-a3ar), latest bedbug filings (wz6d-d3jb), and emergency-repair charge count (sbnd-xujn). Start here, then drill down.

true_owner

house_number, street, borough (all required), docs_limit

Ownership from the property record rather than HPD's filings: the DOF assessment-roll owner (PLUTO 64uk-42ks), recent recorded deeds/mortgages with named parties (ACRIS 8h5j-fqxa -> bnx9-e6tj -> 636b-3b5g), and Speculation Watch List hits (adax-9mit). Always surfaces latest_deed (the newest DEED-family instrument, chased specifically even when the newest documents are other paperwork). Staten Island instruments are with the Richmond County Clerk, not ACRIS.

dob_building

house_number, street, borough (all required), limit

Department of Buildings records — a different agency from HPD: DOB violations (3h2n-5cm9, by-category summary) and DOB complaints (eabe-havv, by-status summary). DOB dates arrive in the agency's raw formats.

building_311

address, borough (both required), complaint_type, since, limit

311 service requests (erm2-nwe9) for an address, defaulting to the heat/hot-water types; pass complaint_type for any other. Newest-first with a by-status summary. Uses the dataset's full-text index ($q) so the 40M-row table answers fast.

borough accepts Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also MN/BX/BK/QN/SI or the codes 1 to 5). violation_class is one of A (non-hazardous), B (hazardous), C (immediately hazardous), I (informational). since is an ISO date (YYYY-MM-DD).

Related MCP server: civic-library-mcp

Data source and grounding

  • Base URL: https://data.cityofnewyork.us/resource/<dataset-id>.json

  • Auth: none. SODA is keyless. An optional Socrata app token (see below) only raises the per-IP rate limit.

  • Response: list and aggregate queries return a bare JSON array. Errors return { "error": true, "message": "..." }.

  • Query language: SoQL via $select, $where, $group, $order, $limit, with upper(...) and like for string matching and || for the first/last-name concatenation in landlord_portfolio. All user text is escaped (a single quote becomes two) before it reaches a query.

Dataset ids and column notes:

Dataset

Id

Notes

HPD Violations

wvxf-dwi5

Address columns housenumber / streetname / boro. Status is violationstatus (Open/Close); currentstatus is the detailed step.

HPD Complaints and Problems

ygpa-z7cr

The current combined dataset (the older uwyv-629c is not publicly readable). Address columns house_number / street_name / borough. One row per problem.

HPD Registrations

tesw-yqqr

Current registrations. Join key registrationid.

HPD Registration Contacts

feu5-w2e2

Owner / agent / officer names. Joined by registrationid.

HPD Housing Litigations

59kj-x8nc

Address columns housenumber / streetname / boroid (numeric 1 to 5, no text borough). Has respondent, penalty, findingofharassment.

Evictions

6z8x-wfk4

Marshal-executed only. Combined eviction_address string plus borough.

DOB Violations

3h2n-5cm9

boro is a NUMERIC-as-text code 1-5 (plus legacy junk rows). Dates in DOB's raw formats (often YYYYMMDD).

DOB Complaints

eabe-havv

NO borough column at all; the community_board first digit is the borough code (filtered via starts_with).

311 Service Requests

erm2-nwe9

~40M rows; a bare LIKE over incident_address full-scans and times out, so the address rides the indexed $q full-text parameter with the LIKE as refiner. Borough is uppercase text.

Bedbug Filings

wz6d-d3jb

Borough uppercase text. Infested / eradicated / re-infested unit counts per filing period.

AEP (Alternative Enforcement)

hcir-3275

boro is Title Case text ("Bronx"); matched case-insensitively.

Vacate Orders

tb8q-a3ar

boro_short_name is the 2-letter code (BX/BK/MN/QN/SI).

HWO Emergency-Repair Charges

sbnd-xujn

Handyman Work Orders billed to landlords. Borough uppercase text.

PLUTO Tax Lots

64uk-42ks

borough is the 2-letter code. Carries the DOF assessment-roll ownername, bbl, block/lot, units, year built.

ACRIS Legals / Master / Parties

8h5j-fqxa / bnx9-e6tj / 636b-3b5g

The recorded-instrument chain: borough/block/lot -> document ids -> doc type/date/amount -> named parties. Text-typed columns, quoted comparisons. Staten Island is NOT in ACRIS (Richmond County Clerk).

Speculation Watch List

adax-9mit

Qualifying flip-risk purchases; matched by block/lot with the row's own bbl confirming borough.

Field map (raw column to normalized output)

Raw column

Normalized field

Tool

violationid, novdescription, currentstatus, violationstatus

violation_id, description, current_status, is_open

building_violations

class, rentimpairing, inspectiondate

class, rent_impairing, inspection_date

building_violations

complaint_id, major_category, complaint_status, received_date

complaint_id, major_category, complaint_status, received_date

building_complaints

registrationid, corporationname, firstname + lastname, business*

registration_id, organization, person_name, business_address

who_owns

housenumber + streetname, boro, bin, lastregistrationdate

building_address, borough, bin, last_registration_date (+ matched_contacts)

landlord_portfolio

litigationid, casetype, casestatus, penalty, respondent

litigation_id, case_type, case_status, penalty, respondent

landlord_litigation

court_index_number, eviction_address, executed_date, marshal_*

court_index_number, eviction_address, executed_date, marshal_name

eviction_lookup

ownername, bbl, block/lot, unitsres, yearbuilt

owner_name, bbl, block/lot, residential_units, year_built

true_owner (PLUTO)

doc_type, document_amt, recorded_datetime, parties by party_type

doc_type, document_amount, recorded_datetime, party_1/party_2/party_3

true_owner (ACRIS)

complaint_type, descriptor, resolution_description, created_date

same names

building_311

Install

Nothing to clone. Point your MCP client at it and npm fetches it on first run:

{
  "mcpServers": {
    "nychousing": {
      "command": "npx",
      "args": ["-y", "@haksanlulz/mcp-nychousing"],
      "env": { "NYC_APP_TOKEN": "your-nyc-app-token" }
    }
  }
}
git clone https://github.com/haksanlulz/mcp-nychousing
cd mcp-nychousing
npm install
npm run build     # emits dist/; the published bin is dist/index.js

npm start runs the TypeScript directly via tsx without building.

App token (optional)

Every tool works with no token. If you make heavy or bursty use, a free Socrata app token raises the rate limit. Create one from the developer settings on your NYC Open Data account. Docs: https://dev.socrata.com/docs/app-tokens.html

Expose it as NYC_APP_TOKEN and it is sent as the X-App-Token header:

export NYC_APP_TOKEN=your-token-here   # macOS / Linux
setx NYC_APP_TOKEN your-token-here      # Windows (new shells)

The token is never logged.

MCP client config

Add an "env": { "NYC_APP_TOKEN": "your-token-here" } block only if you want the higher rate limit.

Example

Call building_violations with { "house_number": "1520", "street": "Sedgwick Avenue", "borough": "Bronx", "open_only": true, "limit": 1 }:

{
  "query": {
    "house_number": "1520",
    "street": "Sedgwick Avenue",
    "borough": "BRONX",
    "open_only": true,
    "violation_class": null,
    "since": null
  },
  "summary": { "total_matching": 128, "by_class": { "A": 21, "B": 74, "C": 33 } },
  "returned": 1,
  "results": [
    {
      "violation_id": "19051745",
      "apartment": "2D",
      "story": "2",
      "class": "C",
      "description": "HMC ADM CODE: ... ABATE THE INFESTATION CONSISTING OF MICE ...",
      "current_status": "NOTICE OF ISSUANCE SENT TO TENANT",
      "is_open": true,
      "rent_impairing": false,
      "inspection_date": "2026-07-04T00:00:00.000",
      "nov_issued_date": "2026-07-08T00:00:00.000",
      "nov_type": "Original"
    }
  ],
  "record_scope": "HPD-issued violations: inspection findings on a date, with their own open/close workflow codes. Not court outcomes, and not a current condition report."
}

The counts are illustrative and move as the city updates the data. The summary counts every match server-side; results is the most recent limit of them.

Every response carries a record_scope line stating what that specific dataset does and does not establish. It is per-tool, because each one has a different wrong reading available: landlord_litigation returns HPD workflow codes, not rulings on the merits, and eviction_lookup covers marshal-executed evictions only — so no matching row does not mean no case was ever filed.

Then take a name from who_owns output and reverse it. Call landlord_portfolio with { "name": "WFHA 1520 SEDGWICK LP" }:

{
  "query": { "name": "WFHA 1520 SEDGWICK LP", "borough": null },
  "found": true,
  "summary": { "contact_matches": 1, "distinct_registrations": 1, "buildings_found": 1 },
  "note": "Contacts reflect HPD registration filings. The same landlord may file each building under a separate LLC; officer and agent person names often connect what the LLC names hide.",
  "returned": 1,
  "buildings": [
    {
      "registration_id": "221729",
      "building_id": "108415",
      "building_address": "1520 SEDGWICK AVENUE",
      "borough": "BRONX",
      "zip": "10453",
      "bin": "2009171",
      "last_registration_date": "2025-09-05T00:00:00.000",
      "registration_end_date": "2026-09-01T00:00:00.000",
      "matched_contacts": [
        { "type": "CorporateOwner", "organization": "WFHA 1520 SEDGWICK LP", "person_name": null }
      ]
    }
  ],
  "record_scope": "Buildings matched by registered-party name. Name matching is approximate and distinct entities can share a name; this is not proof of common ownership."
}

A single-building LLC like this one is itself the common NYC pattern; searching an officer or agent person name from the same who_owns output is how you connect the buildings the per-building LLC names hide.

Address matching

There is no geocoding here. Address matching is literal against how HPD stores addresses:

  • Street names are stored uppercase. The server uppercases and trims your street input and matches it as a substring (upper(streetname) like '%YOUR STREET%'). So Sedgwick, sedgwick avenue, and SEDGWICK AVE all match SEDGWICK AVENUE, but a very short input can over-match (5 St would also hit 125 St). Pass the fuller street name when you can.

  • House number is matched exactly (uppercased) first — and on a zero, the per-building tools automatically retry spelling variants: 120 15 and 12015 are re-tried as 120-15 (Queens numbers get the digit-split form), and the response's note names every spelling tried, so a hyphenation zero never silently reads as a clean building. Multi-address buildings can still register under a range (1516-1520).

  • Borough disambiguates same-numbered streets across boroughs, so it is required for the building tools. Litigations store a numeric borough code; evictions mix borough and county spellings (Brooklyn and Kings, Manhattan and New York, Staten Island and Richmond), and the borough filter expands to all of them.

  • landlord_portfolio matches names the same way: uppercase substring against corporationname, firstname, lastname, and the firstname || ' ' || lastname concatenation (so a pasted person_name from who_owns works). LIKE wildcards (%, _) in your input are escaped. Pass the fullest name you have; a short fragment like SMITH or LLC over-matches, and the response says how many contact records matched before any cap.

  • who_owns, landlord_portfolio, landlord_litigation, and the datasets themselves reflect HPD filings, which can lag reality. Confirm anything you intend to act on (for example a name to serve) before relying on it.

Develop

npm test         # vitest, fetch mocked (no network)
npm run smoke    # one live call per tool against SODA (keyless, no setup)
npm run typecheck

AI assistance

This project was built with AI assistance (Claude). Correctness was established by the mocked vitest suite, by running every tool live against NYC Open Data (npm run smoke; the Queens hyphenated-house-number, NY/NYC borough, and litigation-summary fixes all came from live behavior, not mocks), and by typecheck. The author reviews the code and is accountable for it.

License

MIT. See LICENSE. Data from NYC Open Data (public City of New York data) served via the Socrata SODA API. Unofficial, not affiliated with the City of New York, HPD, or Socrata.

Available Tools

6 tools
building_complaintsA

HPD complaints and problems for one building (dataset ygpa-z7cr; one row per reported problem within a complaint). Give the house number, street, and borough. Returns an open/closed count summary plus the most recent matching problems (category, status, dates). Street is matched as an uppercase substring; house number exactly. Keyless.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax detail rows to return (1-500, default 100). The status summary counts all matches.
sinceNoOnly problems received on/after this ISO date (YYYY-MM-DD).
streetYesStreet name (matched case-insensitively as a substring).
boroughYesNYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5).
open_onlyNoOnly complaints still open (default false).
house_numberYesBuilding house number, e.g. "1520".

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses key behavioral details like substring matching and exact match for house number, and states 'Keyless', but no annotations exist to supplement. Could mention data freshness or pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two efficient sentences, front-loaded with purpose and output, no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose and output structure, but lacks guidance on sibling tools, error cases, or detailed output field descriptions. Adequate for a simple lookup.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so description adds limited value. It reiterates required parameters and matching details, but doesn't enrich semantics beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as retrieving HPD complaints for a building, specifies the dataset, and distinguishes it from siblings like building_violations by focusing on complaints.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs to provide house number, street, and borough, and describes the output. Lacks explicit when-not-to-use or comparisons with siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

building_violationsA

HPD Housing Maintenance Code violations for one building (dataset wvxf-dwi5). Give the house number, street, and borough. Returns a server-side per-class count summary (class A non-hazardous, B hazardous, C immediately hazardous, I informational) plus the most recent matching violations. Street is matched as an uppercase substring; house number is matched exactly. Keyless; an optional NYC_APP_TOKEN only raises the rate limit.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax detail rows to return (1-500, default 100). The class summary counts all matches.
sinceNoOnly violations inspected on/after this ISO date (YYYY-MM-DD).
streetYesStreet name, e.g. "Sedgwick Avenue" (matched case-insensitively as a substring).
boroughYesNYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5).
open_onlyNoOnly violations still open (default false).
house_numberYesBuilding house number, e.g. "1520".
violation_classNoFilter to one class: "A", "B", "C", or "I".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses: returns a server-side per-class count summary plus most recent violations, street matched as uppercase substring, house number matched exactly, keyless, optional token raises rate limit. This is excellent behavioral detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively long but every sentence adds value. It front-loads the purpose and dataset ID, then explains parameters and behavior. Could be slightly more concise, but no extraneous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by explaining the two-part return (class count summary + recent violations). It also covers matching behavior, required parameters, and optional token. For a tool with 7 parameters, this is complete and leaves no major gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, providing a baseline of 3. However, the description adds significant semantic value beyond schema: explains matching logic for street and house_number, clarifies the class summary, and notes that the optional token only affects rate limits. This greatly aids correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns HPD Housing Maintenance Code violations for one building, with a specific dataset reference. It distinguishes from siblings by focusing on violations and mentioning the class count summary and recent violations. The verb 'get' is implied, and the resource is explicitly 'violations for one building'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description tells users to provide house number, street, and borough, and mentions an optional token. It does not explicitly state when to use this tool versus siblings like building_complaints or who_owns, but the purpose is clear enough that an agent can infer it is for violations only.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eviction_lookupA

Marshal-executed evictions (dataset 6z8x-wfk4). IMPORTANT: this dataset lists evictions a city marshal actually CARRIED OUT, not filings, warrants, or pending housing-court cases. Look up by court index number OR by address and/or borough. At least one is required. Returns court index number, address, executed date, marshal, and residential/commercial flag. Address is matched as a case-insensitive substring of the combined eviction address. Keyless.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax rows to return (1-500, default 50).
sinceNoOnly evictions executed on/after this ISO date (YYYY-MM-DD).
addressNoAddress substring to match, e.g. "123 Example Avenue" (matched within the combined eviction address).
boroughNoNYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5).
court_index_numberNoHousing-court index number to match exactly, e.g. "123456/24".

TDQS

A4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It lacks explicit statements about read-only nature, rate limits, or auth requirements. While the function is implied non-destructive, these traits are not disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is succinct, front-loads the key purpose and distinction, then explains parameters and output. Every sentence adds value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the main purpose, required parameter combinations, matching behavior, and output fields. Missing pagination details and the meaning of 'Keyless' is unclear, but overall sufficient for a lookup tool with no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% but the description adds valuable constraints: at least one of court_index_number or address/borough is required, and address matching is case-insensitive substring. It also lists the return fields, which is not in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool looks up marshal-executed evictions from a specific dataset, distinguishing it from filings or pending cases. It specifies the lookup methods and return fields, making it distinct from sibling tools which cover other property records.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly warns against using this for filings, warrants, or pending cases, and states that at least one of court index number or address/borough is required. It provides clear context for when to use, though it doesn't compare directly with siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

landlord_litigationA

HPD Housing Litigations (dataset 59kj-x8nc): HPD-initiated cases against landlords plus tenant actions. Look up by building (house_number + street + borough) OR by respondent (landlord/owner) name. At least one is required. Returns case type, open date, status, judgement, any harassment finding, penalty, and respondent, with a by-status summary. Respondent and street are matched as case-insensitive substrings. Keyless.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax cases to return (1-500, default 100).
streetNoStreet name (building lookup; matched as a substring).
boroughNoNYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5). Required for a building lookup.
respondentNoRespondent name to match, e.g. an LLC or owner (substring, e.g. "realty llc").
case_statusNoOptional status filter, e.g. "OPEN" or "CLOSED".
house_numberNoBuilding house number (building lookup; requires street + borough too).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full behavioral disclosure. It details return fields (case type, open date, status, etc.), matching behavior (case-insensitive substrings for respondent and street), and notes the tool is 'keyless'. No side effects or rate limits are mentioned, but for a read-only lookup this is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (about 5 sentences), front-loaded with the dataset ID and purpose, and contains no redundant information. Every sentence serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the absence of an output schema, the description adequately explains return values and includes a summary by status. It covers the key usage scenarios and matching behavior, making it complete for this lookup tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for all 6 parameters. The description adds value by explaining required parameter combinations (building vs respondent), substring matching details, and borough shorthand (MN/BX/BK/QN/SI).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: looking up HPD housing litigations by building or respondent. It specifies the data source (dataset 59kj-x8nc) and distinguishes from sibling tools like building_violations which handle different types of records.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains how to use the tool: look up by building (house_number + street + borough) or by respondent name, with at least one required. It does not explicitly state when not to use it or name alternative tools, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

landlord_portfolioA

The reverse of who_owns: every building currently registered with HPD under a given landlord, corporation, officer, or agent name. Searches HPD Registration Contacts (feu5-w2e2) for the name (case-insensitive substring against corporation names and person first/last names), then resolves each matched registration to its building (tesw-yqqr): address, borough, zip, BIN, registration dates, and which contact matched. Start from a name surfaced by who_owns or landlord_litigation. Landlords often hold each building in a separate LLC; officer and agent person names frequently connect buildings the LLC names hide. Reflects current HPD registration filings only. Keyless.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesOwner / corporation / officer / agent name to match, e.g. "WFHA 1520 SEDGWICK LP" or "JOHN WARREN" (case-insensitive substring against HPD registration-contact names; pass the fullest name you have, short fragments over-match).
limitNoMax buildings to return (1-500, default 50).
boroughNoOptional filter: only buildings in this borough. NYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description discloses case-insensitive substring matching, resolution to buildings with details, current registration only, and the 'Keyless' access. It implies a read-only query.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured but slightly verbose. It efficiently covers purpose, process, usage, and limitations in a few sentences. Could be trimmed slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description fully explains the return values (address, borough, zip, BIN, registration dates, matched contact) and data source. Context is thorough for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds meaningful guidance: name is case-insensitive substring, pass fullest name to avoid over-matching, limit default 50, borough accepts multiple formats.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is the reverse of who_owns, listing buildings under a landlord/corporation/officer/agent name. It specifies the data source (HPD Registration Contacts) and distinguishes from sibling tools like who_owns and landlord_litigation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It advises starting from names surfaced by who_owns or landlord_litigation, explaining when to use this tool to uncover hidden connections. It does not explicitly state when not to use, but provides clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

who_ownsA

Who is on file with HPD for a building, the 'who do I actually serve' tool. Joins HPD Registrations (tesw-yqqr) to Registration Contacts (feu5-w2e2) by registration id. Give the house number, street, and borough. Returns the registration(s) and every contact (corporate/individual owner, head officer, officer, agent, site manager) with names and business addresses. Reflects HPD registration filings, which can lag reality. Keyless.

ParametersJSON Schema
NameRequiredDescriptionDefault
streetYesStreet name (matched case-insensitively as a substring).
boroughYesNYC borough: Manhattan, Bronx, Brooklyn, Queens, or Staten Island (also accepts MN/BX/BK/QN/SI or 1-5).
house_numberYesBuilding house number, e.g. "1520".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavioral traits: it joins specific datasets, returns contact names and addresses, reflects HPD filings (which may lag reality), and notes it requires no API key. No contradictions exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, with three sentences that front-load the purpose and provide essential details without fluff. Every sentence adds value: purpose, data join, input/output, and limitations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with three parameters and no output schema, the description sufficiently explains inputs, outputs, data source, and limitations. It covers all necessary context for an AI agent to decide when and how to use it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully covers all three required parameters with descriptions (100% coverage). The description adds value by framing them as user instructions ('Give the house number...') and mentions matching behavior indirectly (substring matching for street is detailed in the schema).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool does: it identifies who is on file with HPD, acts as the 'who do I actually serve' tool, and explains the data join process. It clearly distinguishes from sibling tools like building_violations by focusing on ownership contacts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly lists required inputs (house number, street, borough) and mentions the output (registrations and contacts). It provides a caveat about data lag, but lacks explicit guidance on when to use this tool versus sibling tools like landlord_portfolio.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.3/5.0
Disambiguation5/5

Each tool targets a distinct aspect of NYC housing data: building violations, building complaints, building ownership, landlord portfolio, landlord litigation, and eviction lookups. There is no overlap in their purposes.

Naming Consistency4/5

Tool names use lowercase with underscores and follow a domain-prefix pattern for most (building_*, landlord_*). However, 'who_owns' and 'eviction_lookup' break the pattern slightly, though they are still clear.

Tool Count5/5

With 6 tools, the server covers key aspects of NYC housing data without being bloated or sparse. Each tool serves a distinct purpose, and the count is well-scoped for the domain.

Completeness4/5

The tools cover violations, complaints, ownership, portfolio, litigation, and evictions—core for housing research. Missing potential areas like building permits or tax info, but the set is largely complete for its focus.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    MCP server for NYC real estate due diligence. Lets Claude query 22+ NYC public-record databases — DOB/HPD/ECB violations, ACRIS deeds, DOF sales, 311 complaints, FDNY incidents, NYPD complaints, marshal evictions, PLUTO, rent stabilization — in plain English.
    18
    7
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for HUD housing data, enabling Fair Market Rent lookups, Section 8 income limits, and ZIP-to-county crosswalk mapping for affordable housing assessments.
    6
    89
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server over the U.S. Department of Labor Wage and Hour Division (WHD) enforcement dataset: employer wage-theft history, back wages owed, civil penalties, and affected-employee counts. Built for worker-justice nonprofits, legal-aid intake, and union researchers.
    4
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/haksanlulz/mcp-nychousing'

If you have feedback or need assistance with the MCP directory API, please join our Discord server