@sfranalytics/mcp 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +69 -3
- package/dist/http.js.map +1 -1
- package/dist/landing.js +17 -4
- package/dist/landing.js.map +1 -1
- package/dist/tools/formatters.js +4 -0
- package/dist/tools/formatters.js.map +1 -1
- package/dist/tools/plr/loansNearby.js +100 -84
- package/dist/tools/plr/loansNearby.js.map +1 -1
- package/dist/tools/plr/transactionHistory.js +67 -50
- package/dist/tools/plr/transactionHistory.js.map +1 -1
- package/dist/tools/sfr/bestBuyers.js +58 -41
- package/dist/tools/sfr/bestBuyers.js.map +1 -1
- package/dist/tools/sfr/buyerProfile.js +6 -3
- package/dist/tools/sfr/buyerProfile.js.map +1 -1
- package/dist/tools/sfr/getProperty.js +147 -124
- package/dist/tools/sfr/getProperty.js.map +1 -1
- package/dist/tools/sfr/propertyBatch.js +3 -1
- package/dist/tools/sfr/propertyBatch.js.map +1 -1
- package/dist/tools/sfr/propertyComps.js +51 -34
- package/dist/tools/sfr/propertyComps.js.map +1 -1
- package/dist/tools/sfr/propertyTransactions.js +48 -31
- package/dist/tools/sfr/propertyTransactions.js.map +1 -1
- package/dist/tools/sfr/rentalComparables.js +83 -66
- package/dist/tools/sfr/rentalComparables.js.map +1 -1
- package/dist/tools/sfr/rentalMarketAnalysis.js +5 -2
- package/dist/tools/sfr/rentalMarketAnalysis.js.map +1 -1
- package/dist/tools/sfr/searchProperties.js +3 -1
- package/dist/tools/sfr/searchProperties.js.map +1 -1
- package/dist/tools/sfr/topBuyers.js +4 -1
- package/dist/tools/sfr/topBuyers.js.map +1 -1
- package/dist/tools/sfr/zipDetail.js +83 -72
- package/dist/tools/sfr/zipDetail.js.map +1 -1
- package/dist/tools/sfr/zipFinder.js +24 -15
- package/dist/tools/sfr/zipFinder.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,8 +2,12 @@ import { z } from "zod";
|
|
|
2
2
|
import { structuredResult, markdownTable, truncatedJson } from "../formatters.js";
|
|
3
3
|
import { action } from "../nextActions.js";
|
|
4
4
|
import { registerToolSafe } from "../registerToolSafe.js";
|
|
5
|
+
import { ApiError } from "../../services/httpClient.js";
|
|
5
6
|
const Input = z.object({
|
|
6
|
-
address: z.string().describe("Full property address
|
|
7
|
+
address: z.string().describe("Full property address exactly as recorded (e.g. '123 Main St, Phoenix, AZ 85004'). " +
|
|
8
|
+
"Must match dataset precisely — abbreviations (St/Ave/Blvd), directional prefixes (N/S/E/W), " +
|
|
9
|
+
"and unit numbers matter. If unsure, use sfr_search_properties with the zip code first to find " +
|
|
10
|
+
"the canonical address."),
|
|
7
11
|
radius: z.coerce.number().optional().describe("Search radius in miles (default varies by API)"),
|
|
8
12
|
page: z.coerce.number().default(1).describe("Page number (default 1)"),
|
|
9
13
|
page_size: z.coerce.number().default(25).describe("Results per page (default 25, max 100)"),
|
|
@@ -16,76 +20,89 @@ export function registerRentalComparablesTool(server, sfr) {
|
|
|
16
20
|
"Use this to estimate fair market rent for an investment property.",
|
|
17
21
|
inputSchema: Input,
|
|
18
22
|
}, async (args) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
else {
|
|
38
|
-
// Fallback: pass as-is and let the API handle it
|
|
39
|
-
query.street = args.address;
|
|
40
|
-
}
|
|
41
|
-
if (args.radius !== undefined)
|
|
42
|
-
query.radius = args.radius;
|
|
43
|
-
const data = await sfr.getRentalComparables(query);
|
|
44
|
-
// API returns {subject, comparables: [...], analysis}
|
|
45
|
-
const items = data?.comparables ?? data?.data ?? (Array.isArray(data) ? data : []);
|
|
46
|
-
const total = items.length;
|
|
47
|
-
const lines = [
|
|
48
|
-
`## Rental Comparables — ${args.address}`,
|
|
49
|
-
`**Total:** ${total} comps`,
|
|
50
|
-
"",
|
|
51
|
-
];
|
|
52
|
-
if (data?.subject) {
|
|
53
|
-
const subj = data.subject;
|
|
54
|
-
lines.push(`**Subject:** ${subj.address}`);
|
|
55
|
-
if (subj.attributes) {
|
|
56
|
-
const a = subj.attributes;
|
|
57
|
-
lines.push(`**Attributes:** ${a.bedrooms ?? "?"} bed / ${a.bathrooms ?? "?"} bath / ${a.sqft ?? "?"} sqft / ${a.propertyType ?? "?"}`);
|
|
23
|
+
try {
|
|
24
|
+
// API requires separate street/city/state/zip_code fields
|
|
25
|
+
const parts = args.address.split(",").map((s) => s.trim());
|
|
26
|
+
const query = {
|
|
27
|
+
page: args.page,
|
|
28
|
+
page_size: args.page_size,
|
|
29
|
+
};
|
|
30
|
+
if (parts.length >= 3) {
|
|
31
|
+
// "123 Main St, City, ST 85004" or "123 Main St, City, ST, 85004"
|
|
32
|
+
query.street = parts[0];
|
|
33
|
+
query.city = parts[1];
|
|
34
|
+
const stateZip = parts.length >= 4
|
|
35
|
+
? { state: parts[2], zip_code: parts[3] }
|
|
36
|
+
: (() => {
|
|
37
|
+
const m = parts[2].match(/^([A-Z]{2})\s+(\d{5})/);
|
|
38
|
+
return m ? { state: m[1], zip_code: m[2] } : { state: parts[2] };
|
|
39
|
+
})();
|
|
40
|
+
Object.assign(query, stateZip);
|
|
58
41
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
42
|
+
else {
|
|
43
|
+
// Fallback: pass as-is and let the API handle it
|
|
44
|
+
query.street = args.address;
|
|
45
|
+
}
|
|
46
|
+
if (args.radius !== undefined)
|
|
47
|
+
query.radius = args.radius;
|
|
48
|
+
const data = await sfr.getRentalComparables(query);
|
|
49
|
+
// API returns {subject, comparables: [...], analysis}
|
|
50
|
+
const items = data?.comparables ?? data?.data ?? (Array.isArray(data) ? data : []);
|
|
51
|
+
const total = items.length;
|
|
52
|
+
const lines = [
|
|
53
|
+
`## Rental Comparables — ${args.address}`,
|
|
54
|
+
`**Total:** ${total} comps`,
|
|
55
|
+
"",
|
|
56
|
+
];
|
|
57
|
+
if (data?.subject) {
|
|
58
|
+
const subj = data.subject;
|
|
59
|
+
lines.push(`**Subject:** ${subj.address}`);
|
|
60
|
+
if (subj.attributes) {
|
|
61
|
+
const a = subj.attributes;
|
|
62
|
+
lines.push(`**Attributes:** ${a.bedrooms ?? "?"} bed / ${a.bathrooms ?? "?"} bath / ${a.sqft ?? "?"} sqft / ${a.propertyType ?? "?"}`);
|
|
63
|
+
}
|
|
64
|
+
lines.push("");
|
|
65
|
+
}
|
|
66
|
+
if (items.length > 0) {
|
|
67
|
+
const rows = items.slice(0, 25).map((c) => [
|
|
68
|
+
c.address ?? "—",
|
|
69
|
+
c.rent != null ? `$${Math.round(Number(c.rent)).toLocaleString()}/mo` : "—",
|
|
70
|
+
c.rentPerSqft != null ? `$${Number(c.rentPerSqft).toFixed(2)}` : "—",
|
|
71
|
+
c.attributes?.bedrooms ?? "—",
|
|
72
|
+
c.attributes?.bathrooms ?? "—",
|
|
73
|
+
c.attributes?.sqft ?? "—",
|
|
74
|
+
c.similarity != null ? `${(Number(c.similarity) * 100).toFixed(0)}%` : "—",
|
|
75
|
+
]);
|
|
76
|
+
lines.push(markdownTable(["Address", "Rent", "$/Sqft", "Beds", "Baths", "Sqft", "Similarity"], rows));
|
|
77
|
+
if (data?.analysis) {
|
|
78
|
+
lines.push("", "### Analysis", "```json");
|
|
79
|
+
lines.push(truncatedJson(data.analysis, 2000));
|
|
80
|
+
lines.push("```");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
lines.push("```json");
|
|
85
|
+
lines.push(truncatedJson(data, 3000));
|
|
75
86
|
lines.push("```");
|
|
76
87
|
}
|
|
88
|
+
const actions = [
|
|
89
|
+
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
90
|
+
action("sfr_property_comps", "Sales comps for valuation", { address: args.address }),
|
|
91
|
+
action("plr_loans_nearby", "Private lending activity nearby", { propertyAddress: args.address }),
|
|
92
|
+
];
|
|
93
|
+
return structuredResult(lines.join("\n"), { subject: data?.subject, analysis: data?.analysis, items, total, page: args.page }, actions);
|
|
77
94
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
97
|
+
const zipMatch = args.address.match(/\b(\d{5})\b/);
|
|
98
|
+
const zip = zipMatch?.[1];
|
|
99
|
+
return structuredResult(`## Rental Comparables — ${args.address}\n\n` +
|
|
100
|
+
`_Property not found at this address. The address must exactly match the dataset ` +
|
|
101
|
+
`(including directional prefixes like 'E'/'W', abbreviations like 'St'/'Ave', and unit numbers). ` +
|
|
102
|
+
`Use sfr_search_properties with the zip code to find the canonical address._`, { address: args.address, error: "not_found" }, [action("sfr_search_properties", "Search by zip to find correct address", zip ? { search_type: "zip", zips: zip } : undefined)]);
|
|
103
|
+
}
|
|
104
|
+
throw err;
|
|
82
105
|
}
|
|
83
|
-
const actions = [
|
|
84
|
-
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
85
|
-
action("sfr_property_comps", "Sales comps for valuation", { address: args.address }),
|
|
86
|
-
action("plr_loans_nearby", "Private lending activity nearby", { propertyAddress: args.address }),
|
|
87
|
-
];
|
|
88
|
-
return structuredResult(lines.join("\n"), { subject: data?.subject, analysis: data?.analysis, items, total, page: args.page }, actions);
|
|
89
106
|
});
|
|
90
107
|
}
|
|
91
108
|
//# sourceMappingURL=rentalComparables.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rentalComparables.js","sourceRoot":"","sources":["../../../src/tools/sfr/rentalComparables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"rentalComparables.js","sourceRoot":"","sources":["../../../src/tools/sfr/rentalComparables.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,10 +28,13 @@ export function registerRentalMarketAnalysisTool(server, sfr) {
|
|
|
28
28
|
geography_type: args.geography_type,
|
|
29
29
|
geography_values: args.geography_values,
|
|
30
30
|
};
|
|
31
|
-
if (args.time_range_start)
|
|
31
|
+
if (args.time_range_start) {
|
|
32
32
|
query.time_range_start = args.time_range_start;
|
|
33
|
-
|
|
33
|
+
query.time_range_end = args.time_range_end ?? new Date().toISOString().slice(0, 10);
|
|
34
|
+
}
|
|
35
|
+
if (!args.time_range_start && args.time_range_end) {
|
|
34
36
|
query.time_range_end = args.time_range_end;
|
|
37
|
+
}
|
|
35
38
|
if (args.property_types)
|
|
36
39
|
query.property_types = args.property_types;
|
|
37
40
|
if (args.bedrooms)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rentalMarketAnalysis.js","sourceRoot":"","sources":["../../../src/tools/sfr/rentalMarketAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAc,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC;SACd,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;SACnD,QAAQ,CAAC,8BAA8B,CAAC;IAC3C,gBAAgB,EAAE,CAAC;SAChB,MAAM,EAAE;SACR,QAAQ,CAAC,yFAAyF,CAAC;IACtG,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IAC3E,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAChF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;CAC1F,CAAC,CAAC;AAEH,MAAM,UAAU,gCAAgC,CAAC,MAAiB,EAAE,GAAc;IAChF,gBAAgB,CAAC,MAAM,EACrB,4BAA4B,EAC5B;QACE,KAAK,EAAE,0CAA0C;QACjD,WAAW,EACT,0FAA0F;YAC1F,6DAA6D;YAC7D,kEAAkE;YAClE,6KAA6K;YAC7K,qFAAqF;QACvF,WAAW,EAAE,KAAK;KACnB,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,KAAK,GAA4B;YACrC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC;QACF,IAAI,IAAI,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"rentalMarketAnalysis.js","sourceRoot":"","sources":["../../../src/tools/sfr/rentalMarketAnalysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,9 @@ export function registerSearchPropertiesTool(server, sfr) {
|
|
|
35
35
|
registerToolSafe(server, "sfr_search_properties", {
|
|
36
36
|
title: "Search buyer activity / property transactions (SFR)",
|
|
37
37
|
description: "Search property transactions by location with filters for price, date, size, and buyer type. " +
|
|
38
|
-
"Returns individual transaction records with address, price, date, and buyer name. " +
|
|
38
|
+
"Returns individual transaction records (purchases/sales) with address, price, date, and buyer name — NOT current ownership. " +
|
|
39
|
+
"To approximate current holdings for an investor, search for their purchases and exclude properties they've subsequently sold (check sfr_property_transactions per address). " +
|
|
40
|
+
"For distressed properties by owner, use sfr_distress_search with owner_name. " +
|
|
39
41
|
"Requires search_type + matching location param (e.g. search_type='zip' + zips='85281'). " +
|
|
40
42
|
"BEST TOOL for 'where is [institution] selling?' queries — use seller_name filter (e.g. seller_name='INVITATION' to find Invitation Homes dispositions). " +
|
|
41
43
|
"Supports broader date ranges than sfr_investor_activity. " +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchProperties.js","sourceRoot":"","sources":["../../../src/tools/sfr/searchProperties.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"searchProperties.js","sourceRoot":"","sources":["../../../src/tools/sfr/searchProperties.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,8 @@ export function registerTopBuyersTool(server, sfr) {
|
|
|
22
22
|
"ranked by recent acquisition count. Use for 'who is buying in [location]' or " +
|
|
23
23
|
"'where are investors buying in [city/state]' queries. " +
|
|
24
24
|
"Returns buyer names, acquisition counts, contact availability, and profile availability. " +
|
|
25
|
+
"hasProfile is an upstream signal and may not resolve for all buyers — if sfr_buyer_profile returns not_found despite hasProfile=true, the buyer exists in the dataset but lacks a dedicated profile page. " +
|
|
26
|
+
"hasContact indicates contact data exists in the source system, but contact fields are not exposed through the SFR API. For investor contact info (phone/email), use plr_borrower_search or plr_borrower_contacts with the investor name. " +
|
|
25
27
|
"NOTE: search_type='city' requires state param (e.g. city='Birmingham', state='AL'). " +
|
|
26
28
|
"For MSA-only with city/date filters, use sfr_market_highlights. " +
|
|
27
29
|
"For institutional REITs/funds only, use sfr_institutional_owners. " +
|
|
@@ -66,7 +68,8 @@ export function registerTopBuyersTool(server, sfr) {
|
|
|
66
68
|
b.hasProfilePage ? "Yes" : "No",
|
|
67
69
|
]);
|
|
68
70
|
lines.push(markdownTable(["#", "Buyer", "Acquisitions", "Contact Info", "Profile"], rows));
|
|
69
|
-
lines.push("", "_Note: 'Profile=Yes' is an upstream signal and may still return
|
|
71
|
+
lines.push("", "_Note: 'Profile=Yes' is an upstream signal and may still return not\\_found for some buyers. " +
|
|
72
|
+
"'Contact=Yes' means the source system has contact data, but SFR API does not expose it — use plr\\_borrower\\_search for investor contacts._");
|
|
70
73
|
}
|
|
71
74
|
else {
|
|
72
75
|
lines.push("_No buyers found for this location._ " +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topBuyers.js","sourceRoot":"","sources":["../../../src/tools/sfr/topBuyers.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"topBuyers.js","sourceRoot":"","sources":["../../../src/tools/sfr/topBuyers.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { structuredResult, kvSummary, truncatedJson } from "../formatters.js";
|
|
3
3
|
import { action } from "../nextActions.js";
|
|
4
4
|
import { registerToolSafe } from "../registerToolSafe.js";
|
|
5
|
+
import { ApiError } from "../../services/httpClient.js";
|
|
5
6
|
const Input = z.object({
|
|
6
7
|
zipCode: z.string().describe("5-digit zip code, e.g. '85281'"),
|
|
7
8
|
});
|
|
@@ -13,80 +14,90 @@ export function registerZipDetailTool(server, sfr) {
|
|
|
13
14
|
"More detailed than sfr_zip_finder which ranks many zips — this deep-dives into one.",
|
|
14
15
|
inputSchema: Input,
|
|
15
16
|
}, async (args) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
try {
|
|
18
|
+
const data = await sfr.getZipDetail(args.zipCode);
|
|
19
|
+
if (!data || typeof data !== "object") {
|
|
20
|
+
return structuredResult(`## Zip Code Detail — ${args.zipCode}\n\n_No data found._`, {});
|
|
21
|
+
}
|
|
22
|
+
const fmt$ = (v) => v != null ? `$${Math.round(Number(v)).toLocaleString()}` : undefined;
|
|
23
|
+
const fmtPct01 = (v) => v != null ? `${(Number(v) * 100).toFixed(1)}%` : undefined;
|
|
24
|
+
const fmtNum = (v) => v != null ? Number(v).toLocaleString() : undefined;
|
|
25
|
+
const grossYieldRaw = data.grossYield ?? data.gross_yield;
|
|
26
|
+
const grossYieldCapped = grossYieldRaw != null && Number.isFinite(Number(grossYieldRaw)) && Number(grossYieldRaw) >= 0 && Number(grossYieldRaw) <= 0.4
|
|
27
|
+
? Number(grossYieldRaw)
|
|
28
|
+
: null;
|
|
29
|
+
const grossYieldDisplay = grossYieldCapped != null
|
|
30
|
+
? fmtPct01(grossYieldCapped)
|
|
31
|
+
: "— (no reliable rent data)";
|
|
32
|
+
const lines = [
|
|
33
|
+
`## Zip Code Detail — ${data.zipCode ?? args.zipCode}`,
|
|
34
|
+
"",
|
|
35
|
+
"### Demographics",
|
|
36
|
+
kvSummary([
|
|
37
|
+
["Population", fmtNum(data.population)],
|
|
38
|
+
["Population Density", data.populationDensity != null
|
|
39
|
+
? `${Number(data.populationDensity).toFixed(0)}/sq mi` : undefined],
|
|
40
|
+
["Housing Units", fmtNum(data.housingUnits)],
|
|
41
|
+
["Median Household Income", fmt$(data.medianHouseholdIncome)],
|
|
42
|
+
["Income vs MSA", fmtPct01(data.incomeRelativeToMsa)],
|
|
43
|
+
]),
|
|
44
|
+
"",
|
|
45
|
+
"### Investment Metrics",
|
|
46
|
+
kvSummary([
|
|
47
|
+
["Median Home Value", fmt$(data.medianHomeValue)],
|
|
48
|
+
["Median Rent", data.medianRent != null ? `$${Math.round(Number(data.medianRent)).toLocaleString()}/mo` : undefined],
|
|
49
|
+
["Gross Yield", grossYieldDisplay],
|
|
50
|
+
["Inst. Ownership", fmtPct01(data.instOwnPercentage)],
|
|
51
|
+
]),
|
|
52
|
+
];
|
|
53
|
+
// Append any additional fields as raw JSON
|
|
54
|
+
const knownKeys = new Set([
|
|
55
|
+
"zipCode", "population", "populationDensity", "populationGrowthForecast",
|
|
56
|
+
"housingUnits", "medianHouseholdIncome", "medianHomeValue", "medianRent",
|
|
57
|
+
"instOwnPercentage", "grossYield", "incomeRelativeToMsa",
|
|
58
|
+
]);
|
|
59
|
+
const extra = {};
|
|
60
|
+
for (const [k, v] of Object.entries(data)) {
|
|
61
|
+
if (!knownKeys.has(k) && v != null)
|
|
62
|
+
extra[k] = v;
|
|
63
|
+
}
|
|
64
|
+
if (Object.keys(extra).length > 0) {
|
|
65
|
+
lines.push("");
|
|
66
|
+
lines.push("### Additional Data");
|
|
67
|
+
lines.push("```json");
|
|
68
|
+
lines.push(truncatedJson(extra, 2000));
|
|
69
|
+
lines.push("```");
|
|
70
|
+
}
|
|
71
|
+
const zip = args.zipCode;
|
|
72
|
+
const actions = [
|
|
73
|
+
action("sfr_rental_stats", "Rental market stats", { search_type: "zip", zips: zip }),
|
|
74
|
+
action("sfr_top_buyers", "Active buyers in zip", { search_type: "zip", zips: zip }),
|
|
75
|
+
action("sfr_search_properties", "Browse transactions", { search_type: "zip", zips: zip }),
|
|
76
|
+
action("sfr_institutional_owners", "Institutional owners in zip", { search_type: "zip", zips: zip }),
|
|
77
|
+
];
|
|
78
|
+
const structured = {
|
|
79
|
+
zipCode: data.zipCode,
|
|
80
|
+
population: data.population,
|
|
81
|
+
populationDensity: data.populationDensity,
|
|
82
|
+
populationGrowthForecast: data.populationGrowthForecast,
|
|
83
|
+
housingUnits: data.housingUnits,
|
|
84
|
+
medianHouseholdIncome: data.medianHouseholdIncome,
|
|
85
|
+
medianHomeValue: data.medianHomeValue,
|
|
86
|
+
medianRent: data.medianRent,
|
|
87
|
+
grossYield: grossYieldCapped,
|
|
88
|
+
instOwnPercentage: data.instOwnPercentage,
|
|
89
|
+
incomeRelativeToMsa: data.incomeRelativeToMsa,
|
|
90
|
+
};
|
|
91
|
+
return structuredResult(lines.join("\n"), structured, actions);
|
|
19
92
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const grossYieldDisplay = grossYieldCapped != null
|
|
28
|
-
? fmtPct01(grossYieldCapped)
|
|
29
|
-
: "— (no reliable rent data)";
|
|
30
|
-
const lines = [
|
|
31
|
-
`## Zip Code Detail — ${data.zipCode ?? args.zipCode}`,
|
|
32
|
-
"",
|
|
33
|
-
"### Demographics",
|
|
34
|
-
kvSummary([
|
|
35
|
-
["Population", fmtNum(data.population)],
|
|
36
|
-
["Population Density", data.populationDensity != null
|
|
37
|
-
? `${Number(data.populationDensity).toFixed(0)}/sq mi` : undefined],
|
|
38
|
-
["Housing Units", fmtNum(data.housingUnits)],
|
|
39
|
-
["Median Household Income", fmt$(data.medianHouseholdIncome)],
|
|
40
|
-
["Income vs MSA", fmtPct01(data.incomeRelativeToMsa)],
|
|
41
|
-
]),
|
|
42
|
-
"",
|
|
43
|
-
"### Investment Metrics",
|
|
44
|
-
kvSummary([
|
|
45
|
-
["Median Home Value", fmt$(data.medianHomeValue)],
|
|
46
|
-
["Median Rent", data.medianRent != null ? `$${Math.round(Number(data.medianRent)).toLocaleString()}/mo` : undefined],
|
|
47
|
-
["Gross Yield", grossYieldDisplay],
|
|
48
|
-
["Inst. Ownership", fmtPct01(data.instOwnPercentage)],
|
|
49
|
-
]),
|
|
50
|
-
];
|
|
51
|
-
// Append any additional fields as raw JSON
|
|
52
|
-
const knownKeys = new Set([
|
|
53
|
-
"zipCode", "population", "populationDensity", "populationGrowthForecast",
|
|
54
|
-
"housingUnits", "medianHouseholdIncome", "medianHomeValue", "medianRent",
|
|
55
|
-
"instOwnPercentage", "grossYield", "incomeRelativeToMsa",
|
|
56
|
-
]);
|
|
57
|
-
const extra = {};
|
|
58
|
-
for (const [k, v] of Object.entries(data)) {
|
|
59
|
-
if (!knownKeys.has(k) && v != null)
|
|
60
|
-
extra[k] = v;
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
95
|
+
return structuredResult(`## Zip Code Detail — ${args.zipCode}\n\n` +
|
|
96
|
+
`_No data found for zip code "${args.zipCode}". Verify the 5-digit zip code is correct. ` +
|
|
97
|
+
`Use sfr_zip_finder to discover zip codes with investment data._`, { zipCode: args.zipCode, error: "not_found" }, [action("sfr_zip_finder", "Find valid zip codes", {})]);
|
|
98
|
+
}
|
|
99
|
+
throw err;
|
|
61
100
|
}
|
|
62
|
-
if (Object.keys(extra).length > 0) {
|
|
63
|
-
lines.push("");
|
|
64
|
-
lines.push("### Additional Data");
|
|
65
|
-
lines.push("```json");
|
|
66
|
-
lines.push(truncatedJson(extra, 2000));
|
|
67
|
-
lines.push("```");
|
|
68
|
-
}
|
|
69
|
-
const zip = args.zipCode;
|
|
70
|
-
const actions = [
|
|
71
|
-
action("sfr_rental_stats", "Rental market stats", { search_type: "zip", zips: zip }),
|
|
72
|
-
action("sfr_top_buyers", "Active buyers in zip", { search_type: "zip", zips: zip }),
|
|
73
|
-
action("sfr_search_properties", "Browse transactions", { search_type: "zip", zips: zip }),
|
|
74
|
-
action("sfr_institutional_owners", "Institutional owners in zip", { search_type: "zip", zips: zip }),
|
|
75
|
-
];
|
|
76
|
-
const structured = {
|
|
77
|
-
zipCode: data.zipCode,
|
|
78
|
-
population: data.population,
|
|
79
|
-
populationDensity: data.populationDensity,
|
|
80
|
-
populationGrowthForecast: data.populationGrowthForecast,
|
|
81
|
-
housingUnits: data.housingUnits,
|
|
82
|
-
medianHouseholdIncome: data.medianHouseholdIncome,
|
|
83
|
-
medianHomeValue: data.medianHomeValue,
|
|
84
|
-
medianRent: data.medianRent,
|
|
85
|
-
grossYield: grossYieldCapped,
|
|
86
|
-
instOwnPercentage: data.instOwnPercentage,
|
|
87
|
-
incomeRelativeToMsa: data.incomeRelativeToMsa,
|
|
88
|
-
};
|
|
89
|
-
return structuredResult(lines.join("\n"), structured, actions);
|
|
90
101
|
});
|
|
91
102
|
}
|
|
92
103
|
//# sourceMappingURL=zipDetail.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zipDetail.js","sourceRoot":"","sources":["../../../src/tools/sfr/zipDetail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"zipDetail.js","sourceRoot":"","sources":["../../../src/tools/sfr/zipDetail.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,18 +22,6 @@ export function registerZipFinderTool(server, sfr) {
|
|
|
22
22
|
"For detailed stats on a single zip, use sfr_zip_detail.",
|
|
23
23
|
inputSchema: Input,
|
|
24
24
|
}, async (args) => {
|
|
25
|
-
const query = {
|
|
26
|
-
search_type: args.search_type,
|
|
27
|
-
page: args.page,
|
|
28
|
-
page_size: args.page_size,
|
|
29
|
-
};
|
|
30
|
-
if (args.zips)
|
|
31
|
-
query.zips = args.zips;
|
|
32
|
-
if (args.sort)
|
|
33
|
-
query.sort = args.sort;
|
|
34
|
-
const data = await sfr.getZipFinder(query);
|
|
35
|
-
const rawItems = data?.data ?? data?.results ?? (Array.isArray(data) ? data : []);
|
|
36
|
-
const total = data?.total ?? data?.count ?? rawItems.length;
|
|
37
25
|
const normalizedSort = (args.sort ?? "").toLowerCase();
|
|
38
26
|
const isGrossYieldSort = normalizedSort.includes("gross_yield") || normalizedSort.includes("grossyield");
|
|
39
27
|
// Workaround for upstream API bug: grossYield can be corrupt (>1.0) when rent is null.
|
|
@@ -46,6 +34,20 @@ export function registerZipFinderTool(server, sfr) {
|
|
|
46
34
|
return null;
|
|
47
35
|
return n;
|
|
48
36
|
};
|
|
37
|
+
// When sorting by yield, over-fetch to compensate for corrupt data being filtered out.
|
|
38
|
+
// The top results from the API often have invalid yields (>40% from null rents).
|
|
39
|
+
const fetchPageSize = isGrossYieldSort ? Math.min(args.page_size * 4, 100) : args.page_size;
|
|
40
|
+
const query = {
|
|
41
|
+
search_type: args.search_type,
|
|
42
|
+
page: args.page,
|
|
43
|
+
page_size: fetchPageSize,
|
|
44
|
+
};
|
|
45
|
+
if (args.zips)
|
|
46
|
+
query.zips = args.zips;
|
|
47
|
+
if (args.sort)
|
|
48
|
+
query.sort = args.sort;
|
|
49
|
+
const data = await sfr.getZipFinder(query);
|
|
50
|
+
const rawItems = data?.data ?? data?.results ?? (Array.isArray(data) ? data : []);
|
|
49
51
|
const sanitizedItems = rawItems.map((item) => {
|
|
50
52
|
const normalizedGrossYield = normalizeGrossYield(item.grossYield ?? item.gross_yield);
|
|
51
53
|
return {
|
|
@@ -54,12 +56,16 @@ export function registerZipFinderTool(server, sfr) {
|
|
|
54
56
|
gross_yield: normalizedGrossYield,
|
|
55
57
|
};
|
|
56
58
|
});
|
|
57
|
-
const
|
|
59
|
+
const allValid = isGrossYieldSort
|
|
58
60
|
? sanitizedItems.filter((item) => item.grossYield != null || item.gross_yield != null)
|
|
59
61
|
: sanitizedItems;
|
|
62
|
+
// Trim back to the requested page_size after filtering
|
|
63
|
+
const items = allValid.slice(0, args.page_size);
|
|
64
|
+
const filteredOut = sanitizedItems.length - allValid.length;
|
|
60
65
|
const lines = [
|
|
61
66
|
`## Zip Code Finder`,
|
|
62
|
-
`**Total:** ${
|
|
67
|
+
`**Total:** ${items.length} zips | **Page:** ${args.page}`,
|
|
68
|
+
...(filteredOut > 0 ? [`*${filteredOut} zips excluded due to missing or invalid yield data*`] : []),
|
|
63
69
|
"",
|
|
64
70
|
];
|
|
65
71
|
if (items.length > 0) {
|
|
@@ -81,6 +87,9 @@ export function registerZipFinderTool(server, sfr) {
|
|
|
81
87
|
]);
|
|
82
88
|
lines.push(markdownTable(["Zip", "Pop", "Income", "Home Value", "Rent", "Yield", "Inst Own"], rows));
|
|
83
89
|
}
|
|
90
|
+
else if (filteredOut > 0) {
|
|
91
|
+
lines.push("All results had invalid yield data and were excluded. Try removing the sort or sorting by a different field (e.g. `-median_home_value`).");
|
|
92
|
+
}
|
|
84
93
|
else {
|
|
85
94
|
lines.push("```json");
|
|
86
95
|
lines.push(truncatedJson(data, 3000));
|
|
@@ -92,7 +101,7 @@ export function registerZipFinderTool(server, sfr) {
|
|
|
92
101
|
...(topZip ? [action("sfr_rental_stats", "Rental market for top zip", { search_type: "zip", zips: String(topZip) })] : []),
|
|
93
102
|
...(topZip ? [action("sfr_top_buyers", "Active buyers in top zip", { search_type: "zip", zips: String(topZip) })] : []),
|
|
94
103
|
];
|
|
95
|
-
return structuredResult(lines.join("\n"), { items, total, page: args.page }, actions);
|
|
104
|
+
return structuredResult(lines.join("\n"), { items, total: items.length, page: args.page }, actions);
|
|
96
105
|
});
|
|
97
106
|
}
|
|
98
107
|
//# sourceMappingURL=zipFinder.js.map
|