Skip to main content
Glama

Search NYC underused buildings

search_nyc_underused_properties
Read-onlyIdempotent

Lists NYC buildings with unused or vacant space: office buildings, school buildings and religious property (churches, convents, synagogues) in any of the five boroughs. A building is flagged when its owner reports it half occupied or less, half or more of its storefronts are reported vacant, it is listed for lease, a city order to vacate it is in force, or it is a school building with no school registered in it. Buildings listed for sale are returned too. Each row gives the BBL, address, owner of record, building size and every figure behind the flag, marked owner-reported, seen or inferred, with its date. The underused flag itself is derived. Never spends credits. On any paid plan the first 25 rows each day are free; other workspaces pay for every row. Rows already pulled are free again. Past the free rows, rows cost 1 credit per row, and this tool returns them as a quote: tell the user the credit cost and ask before calling run_nyc_underused_search with the quote_id. No contacts in the result: use unlock_nyc_property_report and then unlock_nyc_owner_contacts on a BBL for the owner's phones and emails. Up to 50 rows per call (default 25), largest buildings first; page with offset.

Input Schema

NameRequiredDescriptionDefault
useNooffice (office buildings), school (school buildings) or religious (churches, convents, synagogues and other property of religious owners). Every use when omitted.
ntasNo2020 neighborhood codes from find_nyc_area, for example MN0801 Upper East Side-Lenox Hill-Roosevelt Island. Use them whenever the person names a neighborhood, so rows outside it are never quoted.
zipsNoNYC ZIP codes. Combined with ntas as any of those places.
limitNo
offsetNo
reasonNoKeep only buildings with this signal: low_occupancy (owner reports half or less occupied), vacant_storefronts (half or more vacant), for_lease, for_sale, vacate_order (a city order to vacate still in force), no_school (a school building with no school registered in it).
boroughNoOne NYC borough. All five when omitted.
min_building_sqftNoSmallest building area in square feet.

Output Schema

NameRequiredDescriptionDefault
rowsYes
quoteYes
offsetYes
totalMatchesYes
creditsChargedYes
freeRowsPerDayYes
freeRowsUsedTodayYes
underusedIsDerivedYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / ntas
      Added value: +{
      +  "description": "2020 neighborhood codes from find_nyc_area, for example MN0801 Upper East Side-Lenox Hill-Roosevelt Island. Use them whenever the person names a neighborhood, so rows outside it are never quoted.",
      +  "items": {
      +    "pattern": "^[A-Z]{2}\\d{4}$",
      +    "type": "string"
      +  },
      +  "maxItems": 40,
      +  "type": "array"
      +}
    • addedInput schema / properties / zips
      Added value: +{
      +  "description": "NYC ZIP codes. Combined with ntas as any of those places.",
      +  "items": {
      +    "pattern": "^\\d{5}$",
      +    "type": "string"
      +  },
      +  "maxItems": 40,
      +  "type": "array"
      +}
  2. Changed7 schema fields changed
    • addedOutput schema / properties / creditsCharged
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / freeRowsPerDay
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / freeRowsUsedToday
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / quote
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": false,
      +      "properties": {
      +        "affordable": {
      +          "type": "boolean"
      +        },
      +        "balance": {
      +          "type": "number"
      +        },
      +        "balanceAfter": {
      +          "type": "number"
      +        },
      +        "credits": {
      +          "type": "number"
      +        },
      +        "expiresAt": {
      +          "type": "string"
      +        },
      +        "offset": {
      +          "type": "number"
      +        },
      +        "quoteId": {
      +          "type": "string"
      +        },
      +        "rowsInQuote": {
      +          "type": "number"
      +        }
      +      },
      +      "required": [
      +        "quoteId",
      +        "offset",
      +        "rowsInQuote",
      +        "credits",
      +        "balance",
      +        "balanceAfter",
      +        "affordable",
      +        "expiresAt"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / id
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / rows / items / required
      Previous value: -[
      -  "bbl",
      -  "address",
      -  "borough",
      -  "zip",
      -  "use",
      -  "buildingClass",
      -  "ownerOfRecord",
      -  "buildingSqft",
      -  "occupancyPct",
      -  "occupancyYear",
      -  "storefrontsReported",
      -  "storefrontsVacant",
      -  "listingStatus",
      -  "listingSqft",
      -  "listingSeenOn",
      -  "vacateOrderSince",
      -  "noSchoolRegistered",
      -  "underused",
      -  "reasons"
      -]New value: +[
      +  "id",
      +  "bbl",
      +  "address",
      +  "borough",
      +  "zip",
      +  "use",
      +  "buildingClass",
      +  "ownerOfRecord",
      +  "buildingSqft",
      +  "occupancyPct",
      +  "occupancyYear",
      +  "storefrontsReported",
      +  "storefrontsVacant",
      +  "listingStatus",
      +  "listingSqft",
      +  "listingSeenOn",
      +  "vacateOrderSince",
      +  "noSchoolRegistered",
      +  "underused",
      +  "reasons"
      +]
    • changedOutput schema / required
      Previous value: -[
      -  "rows",
      -  "offset",
      -  "totalMatches",
      -  "underusedIsDerived"
      -]New value: +[
      +  "rows",
      +  "offset",
      +  "totalMatches",
      +  "freeRowsUsedToday",
      +  "freeRowsPerDay",
      +  "creditsCharged",
      +  "quote",
      +  "underusedIsDerived"
      +]
  3. Added

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare the safe-read profile (readOnly, idempotent, non-destructive), and the description goes well beyond them: it discloses the credit model (first 25 rows free daily on paid plans, 1 credit per row afterward, re-pulled rows free), the quote-vs-run split, ordering (largest buildings first), pagination limits, and the provenance labeling of returned figures. This is the kind of context an agent cannot infer from the schema or annotations.

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 paragraph is dense but front-loaded with purpose and flag criteria before moving to credit mechanics and contact routing, and every sentence carries operational information. It is on the long side for a single block, and the credit rules are interleaved rather than clearly segmented, but nothing is filler.

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 read/search tool with 8 optional params, an output schema, and a two-step quote/run credit flow, the description covers everything needed to call it correctly: filtering semantics, pagination, cost disclosure duties, and the handoff to unlock tools. Nothing material is missing.

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 75% and the schema descriptions are already substantive (ntas codes, reason enum meanings, borough enum). The description still adds value by restating the use classes, the 'any of those places' combination of ntas and zips, and the default-25/up-to-50 limit with offset paging that the schema leaves unexplained for limit/offset.

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 a specific verb and resource (lists NYC buildings with unused or vacant space), enumerates the covered use classes, and defines exactly what qualifies as 'underused' via its six flag conditions. It is clearly distinguishable from run_nyc_underused_search (the execution step) and from the unlock_* contact tools named in the same paragraph.

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

Usage Guidelines5/5

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

It gives an explicit workflow rule: past the free rows this tool is a quote, so tell the user the credit cost and ask before invoking run_nyc_underused_search with the quote_id. It also routes the agent away from this tool when contacts are needed ('No contacts in the result: use unlock_nyc_property_report and then unlock_nyc_owner_contacts'), naming both the alternative and the condition.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources