Add logging for MCP tool function calls with parameters
Added log_mcp_call() helper function that logs all MCP tool invocations with their parameters at INFO level. This provides: - Better debugging and monitoring capabilities - Clear visibility into which tools are being called and with what parameters - Smart parameter formatting (truncates long strings, summarizes long lists) - Consistent logging format across all 10 MCP tools Example log output: INFO - MCP tool called: find_recent_deals_for_address(address=סוקולוב 38 חולון, years_back=2, radius_meters=30, max_deals=100, deal_type=2) This helps track API usage patterns and debug issues in production. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,29 @@ mcp = FastMCP("nadlan-mcp")
|
|||||||
client = GovmapClient()
|
client = GovmapClient()
|
||||||
|
|
||||||
|
|
||||||
|
def log_mcp_call(func_name: str, **params):
|
||||||
|
"""
|
||||||
|
Log MCP tool function calls with their parameters for debugging and monitoring.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
func_name: Name of the MCP tool function being called
|
||||||
|
**params: Keyword arguments passed to the function
|
||||||
|
"""
|
||||||
|
# Format parameters for logging (truncate long strings)
|
||||||
|
formatted_params = {}
|
||||||
|
for key, value in params.items():
|
||||||
|
if isinstance(value, str) and len(value) > 100:
|
||||||
|
formatted_params[key] = f"{value[:97]}..."
|
||||||
|
elif isinstance(value, list) and len(value) > 5:
|
||||||
|
formatted_params[key] = f"[{len(value)} items]"
|
||||||
|
else:
|
||||||
|
formatted_params[key] = value
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"MCP tool called: {func_name}({', '.join(f'{k}={v}' for k, v in formatted_params.items())})"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def strip_bloat_fields(deals: List[Deal]) -> List[Dict[str, Any]]:
|
def strip_bloat_fields(deals: List[Deal]) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Remove bloat fields from Deal models to reduce token usage in MCP responses.
|
Remove bloat fields from Deal models to reduce token usage in MCP responses.
|
||||||
@@ -70,6 +93,7 @@ def autocomplete_address(search_text: str) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing matching addresses with their coordinates
|
JSON string containing matching addresses with their coordinates
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call("autocomplete_address", search_text=search_text)
|
||||||
try:
|
try:
|
||||||
response = client.autocomplete_address(search_text)
|
response = client.autocomplete_address(search_text)
|
||||||
|
|
||||||
@@ -117,6 +141,9 @@ def get_deals_by_radius(latitude: float, longitude: float, radius_meters: int =
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing polygon metadata (areas with deals nearby)
|
JSON string containing polygon metadata (areas with deals nearby)
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"get_deals_by_radius", latitude=latitude, longitude=longitude, radius_meters=radius_meters
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Note: GovmapClient expects (longitude, latitude) tuple
|
# Note: GovmapClient expects (longitude, latitude) tuple
|
||||||
# Returns polygon metadata dicts, not Deal objects
|
# Returns polygon metadata dicts, not Deal objects
|
||||||
@@ -153,6 +180,7 @@ def get_street_deals(polygon_id: str, limit: int = 100, deal_type: int = 2) -> s
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing recent real estate deals for the street
|
JSON string containing recent real estate deals for the street
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call("get_street_deals", polygon_id=polygon_id, limit=limit, deal_type=deal_type)
|
||||||
try:
|
try:
|
||||||
deals = client.get_street_deals(polygon_id, limit, deal_type=deal_type)
|
deals = client.get_street_deals(polygon_id, limit, deal_type=deal_type)
|
||||||
|
|
||||||
@@ -218,6 +246,14 @@ def find_recent_deals_for_address(
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing recent real estate deals for the address
|
JSON string containing recent real estate deals for the address
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"find_recent_deals_for_address",
|
||||||
|
address=address,
|
||||||
|
years_back=years_back,
|
||||||
|
radius_meters=radius_meters,
|
||||||
|
max_deals=max_deals,
|
||||||
|
deal_type=deal_type,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
deals = client.find_recent_deals_for_address(
|
deals = client.find_recent_deals_for_address(
|
||||||
address, years_back, radius_meters, max_deals, deal_type
|
address, years_back, radius_meters, max_deals, deal_type
|
||||||
@@ -323,6 +359,7 @@ def get_neighborhood_deals(polygon_id: str, limit: int = 100, deal_type: int = 2
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing recent real estate deals in the specified neighborhood
|
JSON string containing recent real estate deals in the specified neighborhood
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call("get_neighborhood_deals", polygon_id=polygon_id, limit=limit, deal_type=deal_type)
|
||||||
try:
|
try:
|
||||||
deals = client.get_neighborhood_deals(polygon_id, limit, deal_type=deal_type)
|
deals = client.get_neighborhood_deals(polygon_id, limit, deal_type=deal_type)
|
||||||
|
|
||||||
@@ -387,6 +424,14 @@ def analyze_market_trends(
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing comprehensive market trend analysis (summarized data, not raw deals)
|
JSON string containing comprehensive market trend analysis (summarized data, not raw deals)
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"analyze_market_trends",
|
||||||
|
address=address,
|
||||||
|
years_back=years_back,
|
||||||
|
radius_meters=radius_meters,
|
||||||
|
max_deals=max_deals,
|
||||||
|
deal_type=deal_type,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Get deals for the address with larger radius for trend analysis
|
# Get deals for the address with larger radius for trend analysis
|
||||||
deals = client.find_recent_deals_for_address(
|
deals = client.find_recent_deals_for_address(
|
||||||
@@ -589,6 +634,7 @@ def compare_addresses(addresses: List[str]) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing comparative analysis of multiple addresses
|
JSON string containing comparative analysis of multiple addresses
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call("compare_addresses", addresses=addresses)
|
||||||
try:
|
try:
|
||||||
comparisons = []
|
comparisons = []
|
||||||
|
|
||||||
@@ -752,6 +798,22 @@ def get_valuation_comparables(
|
|||||||
JSON string containing filtered comparable deals with full details.
|
JSON string containing filtered comparable deals with full details.
|
||||||
Returns many comparables so LLM can assess similarity and relevance.
|
Returns many comparables so LLM can assess similarity and relevance.
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"get_valuation_comparables",
|
||||||
|
address=address,
|
||||||
|
years_back=years_back,
|
||||||
|
property_type=property_type,
|
||||||
|
min_rooms=min_rooms,
|
||||||
|
max_rooms=max_rooms,
|
||||||
|
min_price=min_price,
|
||||||
|
max_price=max_price,
|
||||||
|
min_area=min_area,
|
||||||
|
max_area=max_area,
|
||||||
|
min_floor=min_floor,
|
||||||
|
max_floor=max_floor,
|
||||||
|
radius_meters=radius_meters,
|
||||||
|
max_comparables=max_comparables,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Get all deals for the address with higher limits for valuation
|
# Get all deals for the address with higher limits for valuation
|
||||||
deals = client.find_recent_deals_for_address(
|
deals = client.find_recent_deals_for_address(
|
||||||
@@ -866,6 +928,14 @@ def get_deal_statistics(
|
|||||||
Returns:
|
Returns:
|
||||||
JSON string containing statistical metrics (mean, median, percentiles, etc.)
|
JSON string containing statistical metrics (mean, median, percentiles, etc.)
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"get_deal_statistics",
|
||||||
|
address=address,
|
||||||
|
years_back=years_back,
|
||||||
|
property_type=property_type,
|
||||||
|
min_rooms=min_rooms,
|
||||||
|
max_rooms=max_rooms,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Get all deals for the address
|
# Get all deals for the address
|
||||||
deals = client.find_recent_deals_for_address(address, years_back)
|
deals = client.find_recent_deals_for_address(address, years_back)
|
||||||
@@ -974,6 +1044,12 @@ def get_market_activity_metrics(address: str, years_back: int = 2, radius_meters
|
|||||||
- Investment potential analysis
|
- Investment potential analysis
|
||||||
- Price appreciation and volatility
|
- Price appreciation and volatility
|
||||||
"""
|
"""
|
||||||
|
log_mcp_call(
|
||||||
|
"get_market_activity_metrics",
|
||||||
|
address=address,
|
||||||
|
years_back=years_back,
|
||||||
|
radius_meters=radius_meters,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Get deals for the address
|
# Get deals for the address
|
||||||
deals = client.find_recent_deals_for_address(address, years_back, radius_meters)
|
deals = client.find_recent_deals_for_address(address, years_back, radius_meters)
|
||||||
|
|||||||
Reference in New Issue
Block a user