/** * @fileoverview Geography resolution service. Converts place names and addresses to * Census FIPS codes using TIGERweb MapServer REST API and Census Geocoder. * @module services/geography/geography-service */ import type { Context } from '@cyanheads/mcp-ts-core'; import type { GeographyType, ResolvedGeography } from './types.js'; export declare class GeographyService { /** * Resolve a place name or address to Census FIPS identifiers. * * Without an explicit `geographyType` the name is matched against an ordered chain of * layers (see {@link GeographyService.detectGeographyTypes}); a layer with no rows falls * through to the next, and only an exhausted chain is a `no_match`. * * A `countyFips` restricts that chain to the levels whose layers carry `COUNTY`, so the * scope is either applied or reported — never carried past a layer that cannot express it. */ resolveGeography(params: { name: string; geographyType?: GeographyType; countyFips?: string; }, ctx: Context): Promise; /** * Build the `county_scope_unsupported` error for a `county_fips` no level reached by this * call can apply — only `county` and `tract` sit inside a county, and a street address * resolves to a single point rather than a set a county could narrow. */ private countyScopeUnsupported; /** Query one geography level. Resolves to `null` when its layers have no row for the name. */ private resolveNamedPlace; /** Fetch TIGERweb features across a level's layers and map them to a ResolvedGeography. */ private fetchAndMapFeatures; /** Query one TIGERweb layer, returning its rows. */ private queryLayer; /** * Read one code off a TIGERweb row, zero-padded to its documented width. * * TIGERweb drops leading zeros on some numeric fields — an unpadded `5` for Arkansas would * miss every FIPS lookup keyed on `05`. */ private levelCode; /** * Narrow to rows whose name spans the state the caller named. * * A statistical area covers whatever states it covers, so its layer carries no `STATE` to * put in a WHERE clause — but its name ends in the hyphenated list of those states, which * means the named one can sit second or third rather than first: "Kansas City, MO" and * "Kansas City, KS" are both the MO-KS metro area. A row whose name yields no state list * fails the check, since an unverifiable row does not satisfy a scope that was asked for. */ private filterByStateInName; /** * Narrow to rows whose name is exactly the queried term, when any are. * * A `NAME LIKE '%term%'` query also matches longer names — "Kansas City" returns * "North Kansas City city" alongside "Kansas City city" — so without this the first * row TIGERweb happens to return can be a different place than the one asked for. */ private preferExactMatches; /** * Build the `ambiguous_name` error, giving each candidate enough to act on without a * re-query: its own code, plus the state that separates same-named places. */ private ambiguousName; /** Build the `no_match` error for a name no layer in the chain matched. */ private noMatch; /** Split a trailing two-letter state abbreviation ("Seattle, WA") off a place name. */ private splitStateSuffix; private resolveAddress; /** * Ordered layer chain for a name with no explicit `geography_type`. * * Anything that is neither a state name nor a county/tract keyword is tried as a place * first and a county second, so "Seattle, WA" reaches the place layer while a name that * exists only as a county-equivalent still resolves. A spelled-out state name must match * the whole input — a substring test would read "West Virginia University" as a state. * * "New York" resolves to the state: the Census place name for New York City is also * exactly "New York", and there is no qualifier a caller would naturally add to tell them * apart, so the city requires an explicit `geography_type: "place"`. */ private detectGeographyTypes; private looksLikeAddress; } export declare function initGeographyService(): void; export declare function getGeographyService(): GeographyService; //# sourceMappingURL=geography-service.d.ts.map