69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
"""Dispatch MCP server — lets Hope spawn background tasks.
|
|
|
|
The main agent calls dispatch_task(description) when the user asks for
|
|
something long-running. The tool returns immediately with a task ID; the
|
|
actual work runs in a background asyncio task via TaskWorker.
|
|
|
|
Communication with the main agent process happens via /tmp/tasks/events.jsonl
|
|
(the file-based registry).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import logging
|
|
import os
|
|
|
|
from mcp.server.fastmcp import FastMCP
|
|
|
|
logger = logging.getLogger("voice-agent.dispatch")
|
|
|
|
mcp = FastMCP("dispatch")
|
|
|
|
|
|
@mcp.tool()
|
|
async def dispatch_task(description: str) -> str:
|
|
"""Spawn a background task to research or look something up.
|
|
|
|
Use this when the user asks you to do something that will take more than
|
|
a few seconds (research, look up news, multi-step investigation). The task
|
|
runs in parallel while you continue the conversation. When it completes,
|
|
the result will be delivered back to you automatically — you can tell the
|
|
user "I'll let you know when I find out."
|
|
|
|
Returns a short confirmation with the task ID.
|
|
"""
|
|
try:
|
|
from agent.task_registry import registry
|
|
from agent.task_worker import TaskWorker
|
|
except ImportError:
|
|
from task_registry import registry
|
|
from task_worker import TaskWorker
|
|
|
|
task = registry.create(description)
|
|
worker = TaskWorker(task.id, description)
|
|
asyncio.create_task(_run_worker(worker, task.id))
|
|
logger.info("Dispatched task %s: %s", task.id, description)
|
|
return f"Task {task.id} started. I'll report back when it's done."
|
|
|
|
|
|
async def _run_worker(worker: "TaskWorker", task_id: str):
|
|
try:
|
|
from agent.task_registry import registry
|
|
except ImportError:
|
|
from task_registry import registry
|
|
|
|
timeout_seconds = float(os.environ.get("TASK_TIMEOUT_SECONDS", "180"))
|
|
try:
|
|
await asyncio.wait_for(worker.run(), timeout=timeout_seconds)
|
|
except asyncio.TimeoutError:
|
|
message = f"Timed out after {timeout_seconds:g} seconds"
|
|
logger.error("Task %s %s", task_id, message.lower())
|
|
registry.fail(task_id, message)
|
|
except Exception as e:
|
|
logger.exception("Task %s crashed: %s", task_id, e)
|
|
registry.fail(task_id, str(e))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mcp.run(transport="stdio")
|