analyze_market
Generate market statistics and trends for real estate by location, providing rental and sales data analysis to inform property decisions.
Instructions
Get comprehensive market statistics and trends for specific locations
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | City name for market analysis | |
| dataType | No | Type of market data to analyze | All |
| state | No | State abbreviation for market analysis | |
| zipCode | No | ZIP code for market analysis |
Implementation Reference
- src/index.ts:402-453 (handler)The main execution handler for the 'analyze_market' tool. It constructs parameters, calls the Rentcast API's getMarketData method, processes the response, formats sale and rental market data using helper functions, and returns a formatted text response.server.tool( "analyze_market", "Get comprehensive market statistics and trends for specific locations", MarketAnalysisSchema.shape, async (params) => { try { const searchParams: any = { dataType: params.dataType }; if (params.zipCode) searchParams.zipCode = params.zipCode; if (params.city) searchParams.city = params.city; if (params.state) searchParams.state = params.state; const result = await rentcastAPI.getMarketData(searchParams); if (!result.success) { return createErrorResponse("Error analyzing market", result.error); } // Simplified market data handling - focus on the structure we know API returns const market = Array.isArray(result.data) ? result.data[0] : result.data; if (!market || (!market.saleData && !market.rentalData)) { return createErrorResponse("No market data found for the specified location"); } let resultText = `π Market Statistics for ${market.zipCode ? `ZIP: ${market.zipCode}` : (params.city ? `${params.city}, ${params.state}` : 'Location')}\n`; // Add location info if (market.zipCode) { resultText += `\nπ Location: ZIP ${market.zipCode}`; } if (market.city && market.state) { resultText += `\nποΈ ${market.city}, ${market.state}`; } // Format market data if (market.saleData) { resultText += formatSaleMarketData(market.saleData); } if (market.rentalData) { resultText += formatRentalMarketData(market.rentalData); } return createSuccessResponse(resultText); } catch (error) { return createErrorResponse("Failed to analyze market", error instanceof Error ? error.message : 'Unknown error'); } } );
- src/types/index.ts:217-228 (schema)Zod schema defining the input parameters for the 'analyze_market' tool, including optional location fields and data type.export const MarketAnalysisSchema = z.object({ zipCode: z.string().optional().describe("ZIP code for market analysis"), city: z.string().optional().describe("City name for market analysis"), state: z .string() .optional() .describe("State abbreviation for market analysis"), dataType: z .enum(["All", "Sale", "Rental"]) .default("All") .describe("Type of market data to analyze"), });
- src/index.ts:110-145 (helper)Helper function to format sale market data (average/median prices, listings, etc.) for the analyze_market tool response.function formatSaleMarketData(saleData: any): string { if (!saleData) return ''; let result = `\nSales Market:`; // Current month data if (saleData.averagePrice !== undefined) { result += `\nAverage Price: $${Number(saleData.averagePrice).toLocaleString()}`; } if (saleData.medianPrice !== undefined) { result += `\nπ Median Price: $${Number(saleData.medianPrice).toLocaleString()}`; } if (saleData.averagePricePerSquareFoot !== undefined) { result += `\nπ Avg Price/Sqft: $${Number(saleData.averagePricePerSquareFoot).toFixed(2)}`; } if (saleData.averageDaysOnMarket !== undefined) { result += `\nAvg Days on Market: ${Number(saleData.averageDaysOnMarket).toFixed(1)}`; } if (saleData.newListings !== undefined) { result += `\nπ New Listings: ${saleData.newListings}`; } if (saleData.totalListings !== undefined) { result += `\nπ Total Listings: ${saleData.totalListings}`; } // Property type breakdown if (saleData.dataByPropertyType && saleData.dataByPropertyType.length > 0) { result += `\n\nπ By Property Type:`; saleData.dataByPropertyType.slice(0, 3).forEach((typeData: any) => { const avgPrice = typeData.averagePrice ? `$${Number(typeData.averagePrice).toLocaleString()}` : 'N/A'; result += `\nβ’ ${typeData.propertyType}: ${avgPrice} avg`; }); } return result; }
- src/index.ts:150-181 (helper)Helper function to format rental market data (average/median rents, listings, etc.) for the analyze_market tool response.function formatRentalMarketData(rentalData: any): string { if (!rentalData) return ''; let result = `\n\nποΈ Rental Market:`; // Current month data if (rentalData.averageRent !== undefined) { result += `\nπ° Average Rent: $${Number(rentalData.averageRent).toLocaleString()}/month`; } if (rentalData.medianRent !== undefined) { result += `\nπ Median Rent: $${Number(rentalData.medianRent).toLocaleString()}/month`; } if (rentalData.averageRentPerSquareFoot !== undefined) { result += `\nπ Avg Rent/Sqft: $${Number(rentalData.averageRentPerSquareFoot).toFixed(2)}`; } if (rentalData.newListings !== undefined) { result += `\nπ New Listings: ${rentalData.newListings}`; } if (rentalData.totalListings !== undefined) { result += `\nπ Total Listings: ${rentalData.totalListings}`; } // Property type breakdown if (rentalData.dataByPropertyType && rentalData.dataByPropertyType.length > 0) { result += `\n\nπ By Property Type:`; rentalData.dataByPropertyType.slice(0, 3).forEach((typeData: any) => { const avgRent = typeData.averageRent ? `$${Number(typeData.averageRent).toLocaleString()}/month` : 'N/A'; result += `\nβ’ ${typeData.propertyType}: ${avgRent} avg`; }); } return result;
- src/services/rentcast-api.ts:113-126 (helper)Service method in RentcastAPI that performs the actual API call to /markets endpoint, used by the analyze_market handler.async getMarketData( params: { zipCode?: string; city?: string; state?: string; dataType?: string; } = {}, ): Promise<ApiCallResult> { const result = await this.makeRequest<RentcastMarket[]>("/markets", { ...params, dataType: params.dataType || "All", }); return result; }