@sfranalytics/mcp 0.6.2 → 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/README.md +67 -50
- package/dist/analytics/logger.d.ts +3 -0
- package/dist/analytics/logger.js +39 -0
- package/dist/analytics/logger.js.map +1 -0
- package/dist/analytics/requestContext.d.ts +21 -0
- package/dist/analytics/requestContext.js +39 -0
- package/dist/analytics/requestContext.js.map +1 -0
- package/dist/analytics/sanitize.d.ts +1 -0
- package/dist/analytics/sanitize.js +78 -0
- package/dist/analytics/sanitize.js.map +1 -0
- package/dist/http.js +260 -41
- package/dist/http.js.map +1 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/landing.d.ts +3 -0
- package/dist/landing.js +904 -0
- package/dist/landing.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.js +12 -4
- package/dist/server.js.map +1 -1
- package/dist/services/httpClient.d.ts +22 -0
- package/dist/services/httpClient.js +147 -26
- package/dist/services/httpClient.js.map +1 -1
- package/dist/tools/formatters.js +33 -1
- package/dist/tools/formatters.js.map +1 -1
- package/dist/tools/health.js +84 -7
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/plr/borrowerContacts.js +47 -10
- package/dist/tools/plr/borrowerContacts.js.map +1 -1
- package/dist/tools/plr/borrowerProfile.js +11 -5
- package/dist/tools/plr/borrowerProfile.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/registerToolSafe.d.ts +5 -1
- package/dist/tools/registerToolSafe.js +110 -4
- package/dist/tools/registerToolSafe.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/rentalStats.js +19 -3
- package/dist/tools/sfr/rentalStats.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 -0
- 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/dist/tools/welcome.d.ts +3 -0
- package/dist/tools/welcome.js +58 -0
- package/dist/tools/welcome.js.map +1 -0
- package/package.json +2 -2
|
@@ -2,8 +2,12 @@ import { z } from "zod";
|
|
|
2
2
|
import { structuredResult, kvSummary } 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
|
});
|
|
8
12
|
export function registerGetPropertyTool(server, sfr) {
|
|
9
13
|
registerToolSafe(server, "sfr_get_property", {
|
|
@@ -14,129 +18,148 @@ export function registerGetPropertyTool(server, sfr) {
|
|
|
14
18
|
"For transaction history, use sfr_property_transactions.",
|
|
15
19
|
inputSchema: Input,
|
|
16
20
|
}, async (args) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
[
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
[
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
[
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
[
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
[
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
21
|
+
try {
|
|
22
|
+
const data = await sfr.getPropertyByAddress(args.address);
|
|
23
|
+
const addr = data?.address;
|
|
24
|
+
const fullAddr = addr
|
|
25
|
+
? `${addr.formatted_street_address}, ${addr.city}, ${addr.state} ${addr.zip_code}`
|
|
26
|
+
: args.address;
|
|
27
|
+
const lines = [
|
|
28
|
+
`## Property Details — ${fullAddr}`,
|
|
29
|
+
"",
|
|
30
|
+
"### Location",
|
|
31
|
+
kvSummary([
|
|
32
|
+
["Address", addr?.formatted_street_address],
|
|
33
|
+
["City", addr?.city],
|
|
34
|
+
["State", addr?.state],
|
|
35
|
+
["Zip", addr?.zip_code],
|
|
36
|
+
["County", data?.county],
|
|
37
|
+
["MSA", data?.msa],
|
|
38
|
+
["Latitude", addr?.latitude],
|
|
39
|
+
["Longitude", addr?.longitude],
|
|
40
|
+
]),
|
|
41
|
+
"",
|
|
42
|
+
"### Structure",
|
|
43
|
+
kvSummary([
|
|
44
|
+
["Beds", data?.structure?.beds_count],
|
|
45
|
+
["Baths", data?.structure?.baths],
|
|
46
|
+
["Sqft", data?.structure?.total_area_sq_ft ?? data?.structure?.living_area_sqft],
|
|
47
|
+
["Lot Size (sqft)", data?.parcel?.area_sq_ft],
|
|
48
|
+
["Year Built", data?.structure?.year_built],
|
|
49
|
+
["Stories", data?.structure?.stories],
|
|
50
|
+
["Property Type", data?.property_type ?? data?.property_class_description],
|
|
51
|
+
["Units", data?.structure?.units_count],
|
|
52
|
+
]),
|
|
53
|
+
"",
|
|
54
|
+
"### Valuation & Assessments",
|
|
55
|
+
kvSummary([
|
|
56
|
+
["Assessed Value", data?.assessments?.assessed_value ? `$${Number(data.assessments.assessed_value).toLocaleString()}` : undefined],
|
|
57
|
+
["Land Value", data?.assessments?.land_value ? `$${Number(data.assessments.land_value).toLocaleString()}` : undefined],
|
|
58
|
+
["Market Value", data?.assessments?.market_value ? `$${Number(data.assessments.market_value).toLocaleString()}` : undefined],
|
|
59
|
+
["AVM", data?.valuation?.value ? `$${Number(data.valuation.value).toLocaleString()}` : undefined],
|
|
60
|
+
["Tax Amount", data?.tax_amount ? `$${Number(data.tax_amount).toLocaleString()}` : undefined],
|
|
61
|
+
]),
|
|
62
|
+
"",
|
|
63
|
+
"### Last Sale",
|
|
64
|
+
kvSummary([
|
|
65
|
+
["Date", data?.last_sale?.date],
|
|
66
|
+
["Price", data?.last_sale?.price ? `$${Number(data.last_sale.price).toLocaleString()}` : undefined],
|
|
67
|
+
["Document Type", data?.last_sale?.document_type],
|
|
68
|
+
["Mortgage Amount", data?.last_sale?.mtg_amount ? `$${Number(data.last_sale.mtg_amount).toLocaleString()}` : undefined],
|
|
69
|
+
["Lender", data?.last_sale?.lender],
|
|
70
|
+
["Months Owned", data?.months_owned],
|
|
71
|
+
]),
|
|
72
|
+
"",
|
|
73
|
+
"### Owner",
|
|
74
|
+
kvSummary([
|
|
75
|
+
["Name", data?.owner?.name],
|
|
76
|
+
["Owner Occupied", data?.owner?.owner_occupied],
|
|
77
|
+
["Corporate", data?.owner?.corporate_owner],
|
|
78
|
+
["Owner Type", data?.owner_type],
|
|
79
|
+
["Purchase Method", data?.purchase_method],
|
|
80
|
+
]),
|
|
81
|
+
"",
|
|
82
|
+
"### Status",
|
|
83
|
+
kvSummary([
|
|
84
|
+
["Listing Status", data?.listing_status],
|
|
85
|
+
["HOA", data?.hoa],
|
|
86
|
+
["Vacant", data?.vacant],
|
|
87
|
+
["Pre-foreclosure", data?.pre_foreclosure?.flag],
|
|
88
|
+
]),
|
|
89
|
+
];
|
|
90
|
+
if (data?.owner?.corporate_owner === true && data?.owner_type === "Individual") {
|
|
91
|
+
lines.push("", "> **Note:** owner_type is reported as \"Individual\" but corporate_owner is true.", "> The owner_type field may be unreliable for entity-owned properties.");
|
|
92
|
+
}
|
|
93
|
+
const actions = [
|
|
94
|
+
action("sfr_rental_comparables", "Estimate rental income", { address: fullAddr }),
|
|
95
|
+
action("sfr_property_comps", "Sales comps for valuation", { address: fullAddr }),
|
|
96
|
+
action("sfr_property_transactions", "Full ownership history", { address: fullAddr }),
|
|
97
|
+
action("plr_loans_nearby", "Private lending activity nearby", { propertyAddress: fullAddr }),
|
|
98
|
+
];
|
|
99
|
+
const structured = {
|
|
100
|
+
address: addr ? {
|
|
101
|
+
formatted_street_address: addr.formatted_street_address,
|
|
102
|
+
city: addr.city,
|
|
103
|
+
state: addr.state,
|
|
104
|
+
zip_code: addr.zip_code,
|
|
105
|
+
latitude: addr.latitude,
|
|
106
|
+
longitude: addr.longitude,
|
|
107
|
+
} : undefined,
|
|
108
|
+
county: data?.county,
|
|
109
|
+
msa: data?.msa,
|
|
110
|
+
structure: data?.structure ? {
|
|
111
|
+
beds_count: data.structure.beds_count,
|
|
112
|
+
baths: data.structure.baths,
|
|
113
|
+
total_area_sq_ft: data.structure.total_area_sq_ft ?? data.structure.living_area_sqft,
|
|
114
|
+
year_built: data.structure.year_built,
|
|
115
|
+
stories: data.structure.stories,
|
|
116
|
+
units_count: data.structure.units_count,
|
|
117
|
+
} : undefined,
|
|
118
|
+
property_type: data?.property_type ?? data?.property_class_description,
|
|
119
|
+
lot_sq_ft: data?.parcel?.area_sq_ft,
|
|
120
|
+
assessments: data?.assessments ? {
|
|
121
|
+
assessed_value: data.assessments.assessed_value,
|
|
122
|
+
land_value: data.assessments.land_value,
|
|
123
|
+
market_value: data.assessments.market_value,
|
|
124
|
+
} : undefined,
|
|
125
|
+
valuation: data?.valuation?.value != null ? { value: data.valuation.value } : undefined,
|
|
126
|
+
tax_amount: data?.tax_amount,
|
|
127
|
+
last_sale: data?.last_sale ? {
|
|
128
|
+
date: data.last_sale.date,
|
|
129
|
+
price: data.last_sale.price,
|
|
130
|
+
document_type: data.last_sale.document_type,
|
|
131
|
+
mtg_amount: data.last_sale.mtg_amount,
|
|
132
|
+
lender: data.last_sale.lender,
|
|
133
|
+
} : undefined,
|
|
134
|
+
months_owned: data?.months_owned,
|
|
135
|
+
owner: data?.owner ? {
|
|
136
|
+
name: data.owner.name,
|
|
137
|
+
owner_occupied: data.owner.owner_occupied,
|
|
138
|
+
corporate_owner: data.owner.corporate_owner,
|
|
139
|
+
} : undefined,
|
|
140
|
+
owner_type: data?.owner_type,
|
|
141
|
+
purchase_method: data?.purchase_method,
|
|
142
|
+
listing_status: data?.listing_status,
|
|
143
|
+
hoa: data?.hoa,
|
|
144
|
+
vacant: data?.vacant,
|
|
145
|
+
pre_foreclosure: data?.pre_foreclosure?.flag,
|
|
146
|
+
};
|
|
147
|
+
if (data?.owner?.corporate_owner === true && data?.owner_type === "Individual") {
|
|
148
|
+
structured.owner_type_warning = "owner_type='Individual' conflicts with corporate_owner=true";
|
|
149
|
+
}
|
|
150
|
+
return structuredResult(lines.join("\n"), structured, actions);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
154
|
+
const zipMatch = args.address.match(/\b(\d{5})\b/);
|
|
155
|
+
const zip = zipMatch?.[1];
|
|
156
|
+
return structuredResult(`## Property Details — ${args.address}\n\n` +
|
|
157
|
+
`_Property not found at this address. The address must exactly match the dataset ` +
|
|
158
|
+
`(including directional prefixes like 'E'/'W', abbreviations like 'St'/'Ave', and unit numbers). ` +
|
|
159
|
+
`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)]);
|
|
160
|
+
}
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
140
163
|
});
|
|
141
164
|
}
|
|
142
165
|
//# sourceMappingURL=getProperty.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getProperty.js","sourceRoot":"","sources":["../../../src/tools/sfr/getProperty.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"getProperty.js","sourceRoot":"","sources":["../../../src/tools/sfr/getProperty.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,9 @@ const Input = z.object({
|
|
|
7
7
|
.array(z.string())
|
|
8
8
|
.min(1)
|
|
9
9
|
.max(100)
|
|
10
|
-
.describe("Array of full addresses
|
|
10
|
+
.describe("Array of full addresses exactly as recorded (e.g. ['123 Main St, Phoenix, AZ 85004']). " +
|
|
11
|
+
"Each address must match the dataset precisely — abbreviations (St/Ave/Blvd), directional " +
|
|
12
|
+
"prefixes (N/S/E/W), and unit numbers matter. Non-matching addresses return per-item errors."),
|
|
11
13
|
});
|
|
12
14
|
export function registerMlsListingsTool(server, sfr) {
|
|
13
15
|
registerToolSafe(server, "sfr_property_batch", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propertyBatch.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyBatch.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;AAE1D,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IACrB,SAAS,EAAE,CAAC;SACT,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,
|
|
1
|
+
{"version":3,"file":"propertyBatch.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyBatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
page: z.coerce.number().default(1).describe("Page number"),
|
|
8
12
|
page_size: z.coerce.number().min(20).default(25).describe("Results per page (min 20)"),
|
|
9
13
|
});
|
|
@@ -16,41 +20,54 @@ export function registerPropertyCompsTool(server, sfr) {
|
|
|
16
20
|
"For RENTAL comparables, use sfr_rental_comparables instead.",
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
try {
|
|
24
|
+
const data = await sfr.getNearbySales({
|
|
25
|
+
address: args.address,
|
|
26
|
+
page: args.page,
|
|
27
|
+
page_size: args.page_size,
|
|
28
|
+
});
|
|
29
|
+
const items = data?.data ?? (Array.isArray(data) ? data : []);
|
|
30
|
+
const total = data?.total ?? items.length;
|
|
31
|
+
const lines = [
|
|
32
|
+
`## Nearby Sales — ${args.address}`,
|
|
33
|
+
`**Total:** ${total} comparables`,
|
|
34
|
+
"",
|
|
35
|
+
];
|
|
36
|
+
if (items.length > 0) {
|
|
37
|
+
const fmt$ = (v) => v != null ? `$${Number(v).toLocaleString()}` : "—";
|
|
38
|
+
const rows = items.slice(0, 25).map((c) => [
|
|
39
|
+
c.FULL_STREET_ADDRESS ?? c.address ?? "—",
|
|
40
|
+
c.CITY ?? c.city ?? "—",
|
|
41
|
+
fmt$(c.SALE_AMT ?? c.sales_price),
|
|
42
|
+
c.RECORDING_DATE ?? c.recording_date ?? c.SALE_DATE ?? "—",
|
|
43
|
+
c.SUM_BUILDING_SQFT ?? c.building_sqft ?? "—",
|
|
44
|
+
c.YEAR_BUILT ?? c.year_built ?? "—",
|
|
45
|
+
]);
|
|
46
|
+
lines.push(markdownTable(["Address", "City", "Price", "Date", "Sqft", "Year Built"], rows));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
lines.push("```json");
|
|
50
|
+
lines.push(truncatedJson(data, 3000));
|
|
51
|
+
lines.push("```");
|
|
52
|
+
}
|
|
53
|
+
const actions = [
|
|
54
|
+
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
55
|
+
action("sfr_rental_comparables", "Rental comps to estimate income", { address: args.address }),
|
|
56
|
+
action("plr_loans_nearby", "Private lending activity nearby", { propertyAddress: args.address }),
|
|
57
|
+
];
|
|
58
|
+
return structuredResult(lines.join("\n"), { items, total, page: args.page }, actions);
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
62
|
+
const zipMatch = args.address.match(/\b(\d{5})\b/);
|
|
63
|
+
const zip = zipMatch?.[1];
|
|
64
|
+
return structuredResult(`## Nearby Sales — ${args.address}\n\n` +
|
|
65
|
+
`_Property not found at this address. The address must exactly match the dataset ` +
|
|
66
|
+
`(including directional prefixes like 'E'/'W', abbreviations like 'St'/'Ave', and unit numbers). ` +
|
|
67
|
+
`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)]);
|
|
68
|
+
}
|
|
69
|
+
throw err;
|
|
47
70
|
}
|
|
48
|
-
const actions = [
|
|
49
|
-
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
50
|
-
action("sfr_rental_comparables", "Rental comps to estimate income", { address: args.address }),
|
|
51
|
-
action("plr_loans_nearby", "Private lending activity nearby", { propertyAddress: args.address }),
|
|
52
|
-
];
|
|
53
|
-
return structuredResult(lines.join("\n"), { items, total, page: args.page }, actions);
|
|
54
71
|
});
|
|
55
72
|
}
|
|
56
73
|
//# sourceMappingURL=propertyComps.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propertyComps.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyComps.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":"propertyComps.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyComps.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
});
|
|
8
12
|
export function registerPropertyTransactionsTool(server, sfr) {
|
|
9
13
|
registerToolSafe(server, "sfr_property_transactions", {
|
|
@@ -13,38 +17,51 @@ export function registerPropertyTransactionsTool(server, sfr) {
|
|
|
13
17
|
"Use this to understand a property's chain of title, price appreciation, and financing patterns.",
|
|
14
18
|
inputSchema: Input,
|
|
15
19
|
}, async (args) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
try {
|
|
21
|
+
const data = await sfr.getPropertyTransactions(args.address);
|
|
22
|
+
// API returns {property_id, address, transactions: [...]}
|
|
23
|
+
const items = data?.transactions ?? data?.data ?? (Array.isArray(data) ? data : []);
|
|
24
|
+
const lines = [
|
|
25
|
+
`## Transaction History — ${args.address}`,
|
|
26
|
+
`**Transactions:** ${items.length}`,
|
|
27
|
+
"",
|
|
28
|
+
];
|
|
29
|
+
if (items.length > 0) {
|
|
30
|
+
const fmt$ = (v) => v != null && Number(v) > 0 ? `$${Number(v).toLocaleString()}` : "—";
|
|
31
|
+
const rows = items.slice(0, 30).map((t) => [
|
|
32
|
+
t.RECORDING_DATE ?? t.recording_date ?? "—",
|
|
33
|
+
t.TRANSACTION_TYPE ?? t.transaction_type ?? "—",
|
|
34
|
+
fmt$(t.SALE_AMT ?? t.sale_amt),
|
|
35
|
+
t.BUYER_BORROWER1_NAME ?? t.buyer_name ?? "—",
|
|
36
|
+
t.SELLER1_NAME ?? t.seller_name ?? "—",
|
|
37
|
+
fmt$(t.FIRST_MTG_AMT ?? t.mortgage_amount),
|
|
38
|
+
t.FIRST_MTG_LENDER_NAME ?? "—",
|
|
39
|
+
]);
|
|
40
|
+
lines.push(markdownTable(["Date", "Type", "Sale Price", "Buyer", "Seller", "Mortgage", "Lender"], rows));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
lines.push("```json");
|
|
44
|
+
lines.push(truncatedJson(data, 3000));
|
|
45
|
+
lines.push("```");
|
|
46
|
+
}
|
|
47
|
+
const actions = [
|
|
48
|
+
action("sfr_get_property", "Current property details & valuation", { address: args.address }),
|
|
49
|
+
action("sfr_rental_comparables", "Estimate rental income", { address: args.address }),
|
|
50
|
+
action("plr_transaction_history", "Private lending history", { propertyAddress: args.address }),
|
|
51
|
+
];
|
|
52
|
+
return structuredResult(lines.join("\n"), { items, total: items.length, page: 1 }, actions);
|
|
36
53
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
catch (err) {
|
|
55
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
56
|
+
const zipMatch = args.address.match(/\b(\d{5})\b/);
|
|
57
|
+
const zip = zipMatch?.[1];
|
|
58
|
+
return structuredResult(`## Transaction History — ${args.address}\n\n` +
|
|
59
|
+
`_Property not found at this address. The address must exactly match the dataset ` +
|
|
60
|
+
`(including directional prefixes like 'E'/'W', abbreviations like 'St'/'Ave', and unit numbers). ` +
|
|
61
|
+
`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)]);
|
|
62
|
+
}
|
|
63
|
+
throw err;
|
|
41
64
|
}
|
|
42
|
-
const actions = [
|
|
43
|
-
action("sfr_get_property", "Current property details & valuation", { address: args.address }),
|
|
44
|
-
action("sfr_rental_comparables", "Estimate rental income", { address: args.address }),
|
|
45
|
-
action("plr_transaction_history", "Private lending history", { propertyAddress: args.address }),
|
|
46
|
-
];
|
|
47
|
-
return structuredResult(lines.join("\n"), { items, total: items.length, page: 1 }, actions);
|
|
48
65
|
});
|
|
49
66
|
}
|
|
50
67
|
//# sourceMappingURL=propertyTransactions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propertyTransactions.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyTransactions.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":"propertyTransactions.js","sourceRoot":"","sources":["../../../src/tools/sfr/propertyTransactions.ts"],"names":[],"mappings":"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"}
|