fix: disable preemptive_generation for tool call compatibility; add get_time tool

- preemptive_generation was incompatible with MCP tool calls: it starts
  generating before the turn finalizes, breaking the tool execution loop
  (agent said 'let me check' then hung forever)
- Add get_time(location?) to weather_mcp.py for date/time queries
- Update system prompt with Weather & Time section
This commit is contained in:
Shane
2026-08-22 16:13:06 -04:00
parent 24026e47de
commit c620867854
3 changed files with 46 additions and 3 deletions
+6 -3
View File
@@ -70,10 +70,12 @@ SYSTEM_PROMPT = textwrap.dedent("""\
source naturally ("according to..."). If a search comes up empty, say so
briefly and move on.
# Weather
# Weather & Time
You can check the weather for any location. Use get_weather when the user
asks about current conditions, temperature, or forecasts. It returns a
short summary — relay it naturally in your own words.
Use get_time when the user asks what time or day it is. If they mention
a city, pass it as the location argument.
""")
@@ -269,8 +271,9 @@ async def handle_job(ctx: JobContext) -> None:
# VAD-based turn detection: agent waits for user to stop speaking.
# ("adaptive" mode requires the LiveKit Cloud barge-in service.)
interruption={"mode": "vad"},
# Start generating the LLM response before the user fully stops
preemptive_generation={"enabled": True},
# Preemptive generation is incompatible with tool calls — it starts
# generating before the turn finalizes, breaking the MCP execution loop.
preemptive_generation={"enabled": False},
),
)
+39
View File
@@ -14,6 +14,7 @@ The tool returns a short, conversational summary suitable for speech
from __future__ import annotations
import os
from datetime import datetime, timezone
import httpx
from mcp.server.fastmcp import FastMCP
@@ -84,5 +85,43 @@ async def get_weather(location: str) -> str:
return summary
@mcp.tool()
def get_time(location: str = "") -> str:
"""Get the current date and time.
If a location is provided, returns the local time there (approximated
via wttr.in's timezone data). Otherwise returns UTC time.
Use this when the user asks what time or day it is.
"""
if not location:
now = datetime.now(timezone.utc)
return f"It's {now.strftime('%I:%M %p')} on {now.strftime('%A, %B %d')}, UTC."
try:
async def _fetch():
async with httpx.AsyncClient(timeout=15) as client:
resp = await client.get(
f"{WTTR_BASE}/{location}?format=j1",
headers={"User-Agent": "curl/8.0"},
)
resp.raise_for_status()
return resp.json()
import asyncio
data = asyncio.get_event_loop().run_until_complete(_fetch())
current = data.get("current_condition", [{}])[0] or {}
tz_offset = current.get("localObsDateTime", "")
area = data.get("nearest_area", [{}])[0] or {}
city = (area.get("areaName", [{}])[0].get("value") or location).strip()
if tz_offset:
return f"It's {tz_offset.split(' ')[1][:5]} on {tz_offset.split(' ')[0]} in {city}."
except Exception: # noqa: BLE001
pass
now = datetime.now(timezone.utc)
return f"It's {now.strftime('%I:%M %p')} on {now.strftime('%A, %B %d')}, UTC."
if __name__ == "__main__":
mcp.run(transport="stdio")