refactor: use MCPToolset instead of deprecated mcp_servers param
- Switch from Agent(mcp_servers=[...]) to Agent(tools=[MCPToolset(...)]) - Add WEB_MCP_ENABLED + FIRECRAWL_BASE to supervisord agent env - Fixes deprecation warning in livekit-agents 1.7
This commit is contained in:
+24
-13
@@ -70,48 +70,54 @@ SYSTEM_PROMPT = textwrap.dedent("""\
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
# ── MCP servers (web access + any extra configured servers) ─────────────────
|
# ── MCP toolsets (web access + any extra configured servers) ────────────────
|
||||||
|
|
||||||
def build_mcp_servers() -> list[mcp.MCPServer]:
|
def build_mcp_toolsets() -> list[mcp.MCPToolset]:
|
||||||
"""Build the list of MCP servers to attach to the agent.
|
"""Build the list of MCP toolsets to attach to the agent.
|
||||||
|
|
||||||
Always includes the local web-access server (Firecrawl-backed search/scrape)
|
Always includes the local web-access server (Firecrawl-backed search/scrape)
|
||||||
when WEB_MCP_ENABLED is true. Additional servers can be configured via the
|
when WEB_MCP_ENABLED is true. Additional servers can be configured via the
|
||||||
EXTRA_MCP_SERVERS env var (JSON list of {url, transport} objects).
|
EXTRA_MCP_SERVERS env var (JSON list of {url, transport} objects).
|
||||||
"""
|
"""
|
||||||
servers: list[mcp.MCPServer] = []
|
toolsets: list[mcp.MCPToolset] = []
|
||||||
|
|
||||||
if WEB_MCP_ENABLED:
|
if WEB_MCP_ENABLED:
|
||||||
python_bin = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".venv", "bin", "python")
|
python_bin = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".venv", "bin", "python")
|
||||||
web_mcp_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web_mcp.py")
|
web_mcp_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "web_mcp.py")
|
||||||
servers.append(
|
toolsets.append(
|
||||||
mcp.MCPServerStdio(
|
mcp.MCPToolset(
|
||||||
|
id="web-access",
|
||||||
|
mcp_server=mcp.MCPServerStdio(
|
||||||
command=python_bin,
|
command=python_bin,
|
||||||
args=[web_mcp_script],
|
args=[web_mcp_script],
|
||||||
env={**os.environ, "FIRECRAWL_BASE": FIRECRAWL_BASE},
|
env={**os.environ, "FIRECRAWL_BASE": FIRECRAWL_BASE},
|
||||||
client_session_timeout_seconds=120,
|
client_session_timeout_seconds=120,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
logger.info("Web-access MCP server enabled (Firecrawl at %s)", FIRECRAWL_BASE)
|
logger.info("Web-access MCP toolset enabled (Firecrawl at %s)", FIRECRAWL_BASE)
|
||||||
|
|
||||||
extra = os.environ.get("EXTRA_MCP_SERVERS", "")
|
extra = os.environ.get("EXTRA_MCP_SERVERS", "")
|
||||||
if extra:
|
if extra:
|
||||||
try:
|
try:
|
||||||
for entry in json.loads(extra):
|
for i, entry in enumerate(json.loads(extra)):
|
||||||
url = entry.get("url", "")
|
url = entry.get("url", "")
|
||||||
transport = entry.get("transport") # "sse" | "streamable_http" | None (auto)
|
transport = entry.get("transport") # "sse" | "streamable_http" | None (auto)
|
||||||
servers.append(
|
toolsets.append(
|
||||||
mcp.MCPServerHTTP(
|
mcp.MCPToolset(
|
||||||
|
id=f"extra-{i}",
|
||||||
|
mcp_server=mcp.MCPServerHTTP(
|
||||||
url=url,
|
url=url,
|
||||||
transport_type=transport,
|
transport_type=transport,
|
||||||
client_session_timeout_seconds=120,
|
client_session_timeout_seconds=120,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
logger.info("Extra MCP server: %s (%s)", url, transport or "auto")
|
logger.info("Extra MCP toolset: %s (%s)", url, transport or "auto")
|
||||||
except (json.JSONDecodeError, TypeError) as e:
|
except (json.JSONDecodeError, TypeError) as e:
|
||||||
logger.error("Failed to parse EXTRA_MCP_SERVERS: %s", e)
|
logger.error("Failed to parse EXTRA_MCP_SERVERS: %s", e)
|
||||||
|
|
||||||
return servers
|
return toolsets
|
||||||
|
|
||||||
|
|
||||||
class VoiceAssistant(Agent):
|
class VoiceAssistant(Agent):
|
||||||
@@ -125,7 +131,7 @@ class VoiceAssistant(Agent):
|
|||||||
api_key=GEMMA_API_KEY,
|
api_key=GEMMA_API_KEY,
|
||||||
),
|
),
|
||||||
instructions=SYSTEM_PROMPT,
|
instructions=SYSTEM_PROMPT,
|
||||||
mcp_servers=build_mcp_servers(),
|
tools=build_mcp_toolsets(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -219,6 +225,11 @@ async def handle_job(ctx: JobContext) -> None:
|
|||||||
agent=VoiceAssistant(),
|
agent=VoiceAssistant(),
|
||||||
room=ctx.room,
|
room=ctx.room,
|
||||||
room_options=room_io.RoomOptions(
|
room_options=room_io.RoomOptions(
|
||||||
|
# Keep the agent in the room when a participant leaves; it must
|
||||||
|
# survive page reloads/reconnects, otherwise the next join lands
|
||||||
|
# in an agent-less room (LiveKit does not reliably re-dispatch
|
||||||
|
# into an existing room).
|
||||||
|
close_on_disconnect=False,
|
||||||
audio_input=room_io.AudioInputOptions(
|
audio_input=room_io.AudioInputOptions(
|
||||||
# No noise cancellation plugin (self-hosted, no ai-coustics)
|
# No noise cancellation plugin (self-hosted, no ai-coustics)
|
||||||
),
|
),
|
||||||
|
|||||||
+3
-1
@@ -27,7 +27,9 @@ environment=
|
|||||||
AZURE_TTS_VOICE="%(ENV_AZURE_TTS_VOICE)s",
|
AZURE_TTS_VOICE="%(ENV_AZURE_TTS_VOICE)s",
|
||||||
GEMMA_BASE_URL="%(ENV_GEMMA_BASE_URL)s",
|
GEMMA_BASE_URL="%(ENV_GEMMA_BASE_URL)s",
|
||||||
GEMMA_MODEL="%(ENV_GEMMA_MODEL)s",
|
GEMMA_MODEL="%(ENV_GEMMA_MODEL)s",
|
||||||
GEMMA_API_KEY="%(ENV_GEMMA_API_KEY)s"
|
GEMMA_API_KEY="%(ENV_GEMMA_API_KEY)s",
|
||||||
|
WEB_MCP_ENABLED="%(ENV_WEB_MCP_ENABLED)s",
|
||||||
|
FIRECRAWL_BASE="%(ENV_FIRECRAWL_BASE)s"
|
||||||
|
|
||||||
[program:web]
|
[program:web]
|
||||||
command=/usr/sbin/nginx -g "daemon off;"
|
command=/usr/sbin/nginx -g "daemon off;"
|
||||||
|
|||||||
Reference in New Issue
Block a user