Skip to main content
Glama
WillHsiaoNYC

NYC Open Data Capital Projects MCP Server

by WillHsiaoNYC

rank_projects

Read-onlyIdempotent

Rank NYC capital project schedules and budgets by timeline variance, total budget, spend, or budget changes, with filters for agency, category, delays, and budget range.

Instructions

Rank schedules (entity='schedule', rows=PIDs) or budgets (entity='budget', rows=FMS lines). rank_by must be NATIVE to entity; the other domain is filter-only. Echoes ranked_entity. Budget rank_by: total_budget | spend_to_date | spend_pct | budget_variance (last-period delta) | cumulative_budget_change (latest - original budget). Optional category (see list_categories) filters to one program type, e.g. 'Library'. Optional agency scopes to one agency; agency_role ('auto'|'sponsor'|'managing') picks the lens — 'auto' uses the owner (sponsor) view, except DDC/DCAS/EDC default to builder (managing). Echoes agency_scope; schedule rows carry forecast_past_due — a forecast already past as of the observation period (never true for completed/cancelled). population_scope='latest_known' uses each entity's own latest observation; 'current' uses values at the selected complete snapshot. Rows include their reporting_period and current-snapshot presence. category_scope='current' uses current funding links; 'all_history' also matches removed funding links.

Interpretation rules:

  • [relationships] "Project" is ambiguous: PID identifies a SCHEDULE; FMS ID identifies a BUDGET. They are MANY-TO-MANY: a budget can fund several PIDs and a PID can have several budgets. LIST ALL linked counterparts; never silently select one. One linked counterpart does not establish a 1:1 relationship in the reverse direction. A budget without a PID is normal before Design and for lines that do not require schedules; absence alone does not establish missing data. Source-only schedules can also lack dashboard funding links.

  • [grain] Schedule questions use PID; budget questions use the BUDGET LINE key (managing_agency, fms_id). The same FMS ID under different holders is distinct lines. Schedule history is PID x reporting_period; budget history is budget line x reporting_period; fiscal-year budgets also key on fiscal_year. The schedule source has no fms_id; budget sources have no pid. The combined source repeats rows across PID-budget links and location splits: deduplicate at the requested entity grain before counting or summing. Never compare budgets using fms_id alone.

  • [population] Listings/rankings default to population_scope='latest_known' (each entity's own latest observation). Use population_scope='current' for the selected complete snapshot. State the population_scope and observation period; respect present_in_current_snapshot. Detail tools use latest-known state and each anchor's latest available link period; these links are not proof of presence in the current complete snapshot.

  • [presence] Presence in a selected reporting snapshot means reportable at that period. There is no separate active flag. Historical presence or a latest-known row does not prove presence in the current complete snapshot. A completed project can retain an open budget line for years; presence does not mean construction is in progress.

  • [agency_roles] Agency attribution is role-aware: an agency's projects mean its sponsor (owner) view, except DDC/DCAS/EDC default to managing (builder). State the returned agency_scope. managing_agency is the executor on schedules and the budget-holder on budgets; a budget-only holder is not a schedule executor. list_agencies exposes is_schedule_executor. For sponsor-scoped budget totals, use a semi-join to fms_sponsor; a value-bearing join can multiply lines. Co-owner totals can overlap and must not be added together.

  • [categories] Classify with the curated category_dim, not project-name searches: specific ten-year labels/FMS prefixes precede sponsor routing, then generic facility keywords and Other. Categories key on (managing_agency, fms_id); institution owner rules can use all-history ownership. Schedule category_scope='current' uses each PID's current funding links; 'all_history' includes former links. A PID can count in multiple categories, so schedule category counts are non-additive; each budget line has one category.

  • [funding_totals] attributed_budget counts a funding line fully on every PID it funds; it is not an allocated share or an independent project cost. Summing it across PIDs can double-count shared funding. For the portfolio's distinct funding total use summary.line_budget_total, which counts each (managing_agency, fms_id) once. State which budget basis is reported.

  • [budget_baseline] budget_variance is change from the previous reporting period; cumulative_budget_change is latest minus original. State which basis is used. original_budget prefers the adopted first budget, with first_snapshot as fallback: disclose original_budget_source. Adoption months are calendar months from a separate first-budget system, not reporting snapshots.

  • [signed_values] Report neutral, SIGNED changes: "moved 45 days later" or "budget decreased $2M". Do not echo loaded terms in the answer. "slippage" means positive schedule change and "overrun" means positive budget growth; neither includes the decreasing side. Preserve the returned direction and metric basis.

  • [schedule_coverage] Schedule totals and cumulative variance use dashboard-aligned schedule_history. source_schedule_history retains native observations absent from that population; schedule_source_coverage reconciles them. State the schedule universe and cumulative basis. Parenthesized phases are no-schedule reasons. Respect excluded variance artifacts and missing/invalid-duration counts; forward duration statistics exclude reversed dates.

  • [lifecycle] Lifecycle: Pre-Design -> Design -> Construction Procurement -> Construction -> Close-out. Schedule progression is reported from Design through Construction. Forecasts and most actual milestones can be suppressed outside those phases; actual_construction_end is the exception and means substantial completion. NULL milestones need not mean missing data. Budget spend%=100 does not prove completion. forecast_past_due is evaluated as of the observation period, not today's date.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nNo
agencyNo
entityYes
rank_byYes
categoryNo
directionNotop
agency_roleNoauto
delayed_onlyNo
category_scopeNocurrent
max_total_budgetNo
min_total_budgetNo
population_scopeNolatest_known

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
rowsYes
labelYes
rank_byYes
provenanceYes
ranked_entityYes
interpretation_rulesYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changedv0.1.1
    • addedInput schema / properties / agency_role / enum
      Added value: +[
      +  "auto",
      +  "sponsor",
      +  "managing"
      +]
    • addedInput schema / properties / category_scope
      Added value: +{
      +  "default": "current",
      +  "enum": [
      +    "current",
      +    "all_history"
      +  ],
      +  "title": "Category Scope",
      +  "type": "string"
      +}
    • addedInput schema / properties / direction / enum
      Added value: +[
      +  "top",
      +  "bottom"
      +]
    • addedInput schema / properties / entity / enum
      Added value: +[
      +  "schedule",
      +  "budget"
      +]
    • addedInput schema / properties / n / maximum
      Added value: +500
    • addedInput schema / properties / n / minimum
      Added value: +1
    • addedInput schema / properties / population_scope
      Added value: +{
      +  "default": "latest_known",
      +  "enum": [
      +    "latest_known",
      +    "current"
      +  ],
      +  "title": "Population Scope",
      +  "type": "string"
      +}
    • addedInput schema / properties / rank_by / enum
      Added value: +[
      +  "period_variance_days",
      +  "cumulative_variance_days",
      +  "total_budget",
      +  "spend_to_date",
      +  "spend_pct",
      +  "budget_variance",
      +  "cumulative_budget_change"
      +]
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$defs": {
      +    "InterpretationRule": {
      +      "properties": {
      +        "id": {
      +          "description": "Stable identifier of the domain rule.",
      +          "title": "Id",
      +          "type": "string"
      +        },
      +        "text": {
      +          "description": "Guidance for interpreting and reporting this tool's result.",
      +          "title": "Text",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "id",
      +        "text"
      +      ],
      +      "title": "InterpretationRule",
      +      "type": "object"
      +    }
      +  },
      +  "additionalProperties": true,
      +  "properties": {
      +    "interpretation_rules": {
      +      "items": {
      +        "$ref": "#/$defs/InterpretationRule"
      +      },
      +      "title": "Interpretation Rules",
      +      "type": "array"
      +    },
      +    "label": {
      +      "title": "Label",
      +      "type": "string"
      +    },
      +    "provenance": {
      +      "additionalProperties": true,
      +      "title": "Provenance",
      +      "type": "object"
      +    },
      +    "rank_by": {
      +      "enum": [
      +        "period_variance_days",
      +        "cumulative_variance_days",
      +        "total_budget",
      +        "spend_to_date",
      +        "spend_pct",
      +        "budget_variance",
      +        "cumulative_budget_change"
      +      ],
      +      "title": "Rank By",
      +      "type": "string"
      +    },
      +    "ranked_entity": {
      +      "enum": [
      +        "schedule",
      +        "budget"
      +      ],
      +      "title": "Ranked Entity",
      +      "type": "string"
      +    },
      +    "rows": {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "title": "Rows",
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "provenance",
      +    "interpretation_rules",
      +    "ranked_entity",
      +    "rank_by",
      +    "rows",
      +    "label"
      +  ],
      +  "title": "RankingResult",
      +  "type": "object"
      +}
  2. First observedv0.1.0

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnly/idempotent, so safety is covered. The description adds rich behavioral context (echoes ranked_entity, forecast_past_due semantics, population/presence rules), but this is extended interpretation content rather than the tool's own operation-level behavior.

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

Conciseness3/5

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

The core operation is front-loaded but is immediately followed by a very long interpretation-rules block with many relationship/grain/presence nuances that go beyond invocation guidance. It is information-dense but not tightly scoped to the call.

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?

Given 12 params, no schema descriptions, and an output schema present, the description covers the critical rank_by and scope semantics well. Some under-documented filters and the extensive interpretation rules leave minor gaps.

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 description coverage is 0%, so the description must compensate and it does: it defines rank_by options per entity, category/agency/agency_role/agency_scope semantics, population_scope, and category_scope. Several filters (n, direction, delayed_only, min/max_total_budget) remain only briefly covered.

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

Purpose4/5

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

States specific verb (rank) and resources (schedules/budgets by PID/FMS lines) and distinguishes entity modes for schedule vs budget. Sibling differentiation is implicit (e.g., vs schedule_breakdown/budget_breakdown) but not named, so it stops short of a 5.

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?

Explains when to use each entity, population_scope, and category_scope, and clarifies rank_by must be native to the entity with the other domain filter-only. No explicit alternatives/exclusions, so not a 5.

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