echoing-lamp-18687
12/16/2025, 5:19 AMtall-airline-16756
12/16/2025, 5:19 AMtall-airline-16756
12/16/2025, 5:20 AMuv add livekit-agents[mcp]~=1.2 (MCP features require this extra package).
1. Verify network & URL reachability from the agent host
◦ Can the agent reach your MCP URL? Try: curl -v "<https://backend.test.com/v3/mcp/esfdsdf?transport=sse>" from the same machine/container where the agent runs. Share the response or errors.
1. Confirm the MCP server implements MCP endpoints and responds to list_tools
◦ The agent calls the MCP list_tools endpoint during session init. Ensure that endpoint returns the expected JSON. If possible, paste the list_tools response.
1. Check agent logs for errors during startup or session init
◦ Look for connection, timeout, or JSON parsing errors referencing MCP or list_tools. Share relevant log lines (timestamp + few lines before/after).
1. Note about transports and tool loading behavior
◦ Tools are loaded at session initialization and merged with local tools. There’s no automatic live rediscovery unless you reinitialize the session. Also confirm the MCP server supports the transport you requested (transport=sse).
If you’d like, provide:
• The agent startup/session logs (relevant MCP lines)
• Result of the curl request to the MCP URL
• Confirmation that livekit-agents[mcp] is installed
I’ll use those to point to the exact fix.
Sources: Tool definition and use | LiveKit docs | Agents (Python) | livekit/livekit_composite | DeepWiki | LiveKit Docs MCP Server | LiveKit docsechoing-lamp-18687
12/16/2025, 5:22 AMGET /v3/mcp/e3edc686-bd73-4363-b869-48dd218799a1?transport=sse HTTP/2
Host: backend.composio.dev
user-agent: curl/7.81.0
accept: /* TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.2 (OUT), TLS header, Supplemental data (23): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.2 (IN), TLS header, Supplemental data (23): < HTTP/2 307 < date: Tue, 16 Dec 2025 052115 GMT < content-length: 0 < location: https://backend.composio.dev/v3/mcp/e3edc686-bd73-4363-b869-48dd218799a1/sse?transport=sse < server: cloudflare < cf-ray: 9aebbc6fee48a7a6-DEL < cf-cache-status: DYNAMIC < age: 0 < cache-control: public, max-age=0, must-revalidate < strict-transport-security: max-age=63072000 < vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch < cf-placement: local-DEL < x-matched-path: /v3/mcp/[serverId] < x-vercel-cache: MISS < x-vercel-id: bom1:iad1:v9kjs-1765862474697-fed277665465 < * Connection #0 to host backend.composio.dev left intact
tall-airline-16756
12/16/2025, 5:22 AMlivekit-agents[mcp] installed and your curl shows the MCP endpoint returning an HTTP/2 307 redirect to a URL with /sse. That helps narrow things down.
Next steps to isolate and fix:
1. Confirm agent follows redirects and can reach the final SSE URL
◦ From the agent host run:
curl -v "https://backend.composio.dev/v3/mcp/e3edc686-bd73-4363-b869-48dd218799a1/sse?transport=sse"
• Paste the response or errors.
1. Share the Agent logs showing MCP connection/tool loading lines
◦ I need the lines around Agent startup and session init that reference MCP, list_tools, timeouts, or errors. Include ~10 lines before/after any MCP-related messages.
1. Check for a 307 handling or SSE-specific issue in the agent logs
◦ If logs show the agent failing to follow the redirect or timing out connecting to the SSE path, that’s likely the problem.
1. If the agent reaches the SSE URL but still no tools, provide the list_tools response (JSON) from the MCP server
◦ Run: curl -v "https://…/v3/mcp/<serverId>/list_tools" (or the equivalent endpoint your MCP implements) and paste the JSON.
Tell me the curl result for step 1 and paste the MCP-related agent log snippets (step 2). I’ll point to the precise fix once I see those.echoing-lamp-18687
12/16/2025, 5:27 AMtall-airline-16756
12/16/2025, 5:27 AMmessage attribute, but a plain string was found.
Please do the following so I can pinpoint the fix:
1. Share package versions
◦ Output of: pip show livekit-agents mcp (or pip list | grep -E "livekit-agents|mcp")
1. Search for other MCP/log lines
◦ From your agent logs, paste ~20 lines around any MCP or list_tools activity and any tracebacks besides the one you sent.
1. Quick workaround to test if it’s the unpickling path
◦ Restart the agent after enabling DEBUG logs (if not already). If the same error repeats immediately, the MCP path handling is failing early.
1. If you can, try upgrading packages
◦ Run: uv update livekit-agents[mcp] (or pip install -U livekit-agents[mcp] mcp) and restart the agent, then share the logs again.
Once you share the package versions and the additional log lines, I’ll tell you the exact change to make or confirm the package fix. Would you like instructions for collecting DEBUG logs if you don’t already have them?echoing-lamp-18687
12/16/2025, 6:06 AMRoomInputOptions.close_on_disconnect=False)
{"room": "voice_assistant_room_5981", "participant": "voice_assistant_user_6695",
"reason": "CLIENT_INITIATED", "pid": 510204, "job_id": "AJ_bRujJQ6ihCxy", "room_id": "RM_UpQU5TXR6zr6"}
113519.590 INFO livekit.agents received job request
{"job_id": "AJ_mpGGNgbXdLzQ", "dispatch_id": "AD_GztCs4NRUA58", "room":
"voice_assistant_room_1526", "room_id": "RM_bqKpR7ukAufx", "agent_name": "", "resuming": false, "enable_recording": false}
113519.642 DEBUG livekit.agents received assignment
{"agent_name": "", "room_id": "RM_bqKpR7ukAufx", "room": "voice_assistant_room_1526",
"job_id": "AJ_mpGGNgbXdLzQ", "dispatch_id": "AD_GztCs4NRUA58", "enable_recording": false}
113519.648 INFO livekit.agents initializing process {"pid": 510405}
113520.104 INFO livekit.agents process initialized {"pid": 510405, "elapsed_time": 0.45}
DEBUG asyncio Using selector: EpollSelector {"pid": 510405}
113520.162 DEBUG livekit.agents input stream attached
{"participant": null, "source": "SOURCE_UNKNOWN", "accepted_sources":
["SOURCE_MICROPHONE"], "room": "voice_assistant_room_1526", "pid": 510405, "job_id": "AJ_mpGGNgbXdLzQ", "room_id":
"RM_bqKpR7ukAufx"}
VAAPI is supported.
113534.789 ERROR asyncio Task exception was never retrieved
future: <Task finished name='Task-22'
coro=<RoomIO._on_user_text_input.<locals>._read_text() done, defined at
/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/l…
exception=RuntimeError('AgentSession is closing, cannot use generate_reply()')>
Traceback (most recent call last):
File
"/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/…
line 408, in _read_text
text_input_result = text_input_cb(
File
"/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/…
line 54, in _default_text_input_cb
sess.generate_reply(user_input=ev.text)
File
"/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/…
line 941, in generate_reply
raise RuntimeError("AgentSession is closing, cannot use generate_reply()")
RuntimeError: AgentSession is closing, cannot use generate_reply()
{"room": "voice_assistant_room_1526", "pid": 510405, "job_id": "AJ_mpGGNgbXdLzQ", "room_id":
"RM_bqKpR7ukAufx"}
Traceback (most recent call last):
File
"/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/livekit/agents/voice/room_io/room_io.py", line
408, in _read_text
text_input_result = text_input_cb(
File "/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/livekit/agents/voice/room_io/types.py",
line 54, in _default_text_input_cb
sess.generate_reply(user_input=ev.text)
File "/home/karandeep/Development/agent-starter-python/.venv/lib/python3.10/site-packages/livekit/agents/voice/agent_session.py",
line 941, in generate_reply
raise RuntimeError("AgentSession is closing, cannot use generate_reply()")
RuntimeError: AgentSession is closing, cannot use generate_reply()tall-airline-16756
12/16/2025, 6:07 AMgenerate_reply(). That prevents normal reply generation and can interrupt MCP tool load/use.
• Your earlier curl showed the MCP endpoint issues (307 redirect to an SSE path). The redirect + SSE handling and the unpickling error you saw can all interfere with tool loading and session stability.
What you can do now (quick checklist)
• Prevent the session from auto-closing on participant disconnect:
a. When starting the session, set close_on_disconnect=False in RoomInputOptions.
from livekit.agents.voice.room_io import RoomInputOptions
await session.start(
room=ctx.room,
agent=Assistant(),
room_options=RoomInputOptions(close_on_disconnect=False)
)
• Verify MCP SSE redirect is reachable by the agent process:
a. From the agent host run:
curl -v "https://backend.composio.dev/v3/mcp/<serverId>/sse?transport=sse"
1. If that returns a 200 SSE stream, the agent should be able to connect. If it still redirects, confirm the final URL works and does not require special redirect handling.
• Ensure the MCP optional dependency is present (you said it is installed) and versions are current:
a. Share pip show livekit-agents mcp or pip list | grep -E "livekit-agents|mcp" if you want me to check compatibility.
• Share MCP/server responses used by the agent:
a. Paste the response for the list_tools request or run:
curl -v "https://…/v3/mcp/<serverId>/list_tools" and paste the JSON if possible.
• Address the unpickling AttributeError:
a. That error suggests a mismatch in expected exception object shape during IPC. Please paste package versions (previous step) and any additional traceback lines around the unpickling error so I can point to a precise fix (often a version mismatch between mcp and livekit-agents).
If you want, paste:
• The agent log lines around the AgentSession closing and any MCP-related tracebacks,
• Output of pip list | grep -E "livekit-agents|mcp",
• The curl result for the /sse path or the /list_tools response.
I’ll use those to tell you the exact next change.
Sources: Tool definition and use | LiveKit docs | Events and error handling | LiveKit docsechoing-lamp-18687
12/16/2025, 6:12 AMtall-airline-16756
12/16/2025, 6:12 AMRoomInputOptions and your mcp_servers config). Paste the AgentSession construction and the await session.start(...) call.
2. The agent package versions:
◦ Output of: pip show livekit-agents mcp (or pip list | grep -E "livekit-agents|mcp").
1. MCP responses from the agent host:
◦ Result of:
curl -v "https://backend.composio.dev/v3/mcp/<serverId>/sse?transport=sse" and curl -v "https://backend.composio.dev/v3/mcp/<serverId>/list_tools"
• Paste the responses (headers + body/JSON).
1. Agent logs (full traceback) around the time of the error:
◦ Include ~20 lines before and after the RuntimeError and the earlier unpickling AttributeError.
Quick checks you can run now (optional, helpful if you want to try before sharing logs):
• Ensure RoomInputOptions(close_on_disconnect=False) is passed when starting the session.
• Restart the agent after updating packages: uv update livekit-agents[mcp] mcp or pip install -U livekit-agents[mcp] mcp.
• If you see the unpickling AttributeError again, search your environment for multiple versions of mcp or conflicting installs (virtualenv vs system).
Send the code + package versions + curl outputs + log snippets and I’ll pinpoint the exact fix.echoing-lamp-18687
12/16/2025, 6:16 AMtall-airline-16756
12/16/2025, 6:16 AMAgentSession is closing, cannot use generate_reply(). That means the session is being closed (usually from participant disconnect) while your text input handler calls generate_reply().
To resolve this I need two quick confirmations and one small code change to test:
1) Confirm your AgentSession start code — paste the snippet where you construct AgentSession and call await session.start(...).
• I need to see if RoomInputOptions(close_on_disconnect=False) is being passed.
2) Confirm package versions (you said you used uv):
• Run and paste: pip show livekit-agents mcp (or pip list | grep -E "livekit-agents|mcp").
3) Temporary fix to test now — prevent auto-close:
• If you aren’t already, start the session with:
from livekit.agents.voice.room_io import RoomInputOptions
await session.start(
room=ctx.room,
agent=Assistant(),
room_options=RoomInputOptions(close_on_disconnect=False)
)
• Restart the agent and reproduce the error. If the RuntimeError disappears, the root cause is the session closing on disconnect. If it persists, paste agent logs (20 lines before/after the traceback).
If you prefer, paste the AgentSession code now and I’ll point out exactly where to change it.echoing-lamp-18687
12/16/2025, 6:34 AMtall-airline-16756
12/16/2025, 6:34 AMclose_on_disconnect=False. I’ll help pinpoint why the session is still marked closing.
Please paste these four items (they’re the minimum I need to diagnose):
1) The exact AgentSession construction + the await session.start(...) call you’re using (full snippet including imports and room_options). 2) The agent log lines that occur immediately before the RuntimeError (20–30 lines prior) — I need any messages that show why the session entered a closing state (participant disconnect, explicit close, or error). 3) Output of package versions:
• Run and paste: pip show livekit-agents mcp (or pip list | grep -E "livekit-agents|mcp").
4) The MCP-related curl outputs you ran earlier (final SSE URL and list_tools if available). If you still have the curl responses, paste them again.
If you prefer, paste the full startup log and I’ll extract the relevant pre-error lines. Once I have those four items I’ll give a targeted fix.echoing-lamp-18687
12/16/2025, 6:34 AMfrom livekit.agents import function_tool, RunContext to the top of this file
# @function_tool
# async def lookup_weather(self, context: RunContext, location: str):
# """Use this tool to look up current weather information in the given location.
#
# If the location is not supported by the weather service, the tool will indicate this. You must tell the user the location's weather is unavailable.
#
# Args:
# location: The location to look up weather information for (e.g. city name)
# """
#
# logger.info(f"Looking up weather for {location}")
#
# return "sunny with a temperature of 70 degrees."
server = AgentServer()
def prewarm(proc: JobProcess):
proc.userdata["vad"] = silero.VAD.load()
server.setup_fnc = prewarm
@breezy-insurance-66772.rtc_session()
async def my_agent(ctx: JobContext):
# Logging setup
# Add any other context you want in all log entries here
ctx.log_context_fields = {
"room": ctx.room.name,
}
# Set up a voice AI pipeline using OpenAI, Cartesia, AssemblyAI, and the LiveKit turn detector
session = AgentSession(
# Speech-to-text (STT) is your agent's ears, turning the user's speech into text that the LLM can understand
# See all available models at https://docs.livekit.io/agents/models/stt/
stt=deepgram.STTv2(
model="flux-general-en",
eager_eot_threshold=0.4,
),
# A Large Language Model (LLM) is your agent's brain, processing user input and generating a response
# See all available models at https://docs.livekit.io/agents/models/llm/
llm=openai.LLM(model="gpt-4o-mini"),
# Text-to-speech (TTS) is your agent's voice, turning the LLM's text into speech that the user can hear
# See all available models as well as voice selections at https://docs.livekit.io/agents/models/tts/
# Default
# tts=elevenlabs.TTS(
# voice_id="ODq5zmih8GrVes37Dizd",
# model="eleven_multilingual_v2"
# ),
# Eric
# tts=elevenlabs.TTS(
# model="eleven_turbo_v2_5",
# voice_id="cjVigY5qzO86Huf0OWal",
# ),
# Alice
tts=elevenlabs.TTS(
model="eleven_turbo_v2_5",
voice_id="Xb7hH8MSUJpSbSDYk0k2",
),
# VAD and turn detection are used to determine when the user is speaking and when the agent should respond
# See more at https://docs.livekit.io/agents/build/turns
turn_detection=MultilingualModel(),
vad=ctx.proc.userdata["vad"],
# allow the LLM to generate a response while waiting for the end of turn
# See more at https://docs.livekit.io/agents/build/audio/#preemptive-generation
preemptive_generation=True,
mcp_servers=[mcp.MCPServerHTTP(url="https://backend.composio.dev/v3/mcp/11a72dd6-fb32-4b58-a4d6-7936a6d9b48c")]
)
# To use a realtime model instead of a voice pipeline, use the following session setup instead.
# (Note: This is for the OpenAI Realtime API. For other providers, see https://docs.livekit.io/agents/models/realtime/))
# 1. Install livekit-agents[openai]
# 2. Set OPENAI_API_KEY in .env.local
# 3. Add from livekit.plugins import openai to the top of this file
# 4. Use the following session setup instead of the version above
# session = AgentSession(
# llm=openai.realtime.RealtimeModel(voice="marin")
# )
# # Add a virtual avatar to the session, if desired
# # For other providers, see https://docs.livekit.io/agents/models/avatar/
# avatar = hedra.AvatarSession(
# avatar_id="...", # See https://docs.livekit.io/agents/models/avatar/plugins/hedra
# )
# # Start the avatar and wait for it to join
# await avatar.start(session, room=ctx.room)
# Start the session, which initializes the voice pipeline and warms up the models
await session.start(
agent=Assistant(),
room=ctx.room,
room_options=room_io.RoomOptions(
close_on_disconnect=False,
audio_input=room_io.AudioInputOptions(
noise_cancellation=lambda params: noise_cancellation.BVCTelephony()
if params.participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP
else noise_cancellation.BVC(),
),
),
)
# Join the room and connect to the user
await ctx.connect()
if name == "__main__":
cli.run_app(server)tall-airline-16756
12/16/2025, 6:35 AMRoomOptions(close_on_disconnect=False) (correct) and you still get repeated:
RuntimeError: AgentSession is closing, cannot use generate_reply()
This means something is still putting the session into a closing state while the text input task runs. Based on your logs, curl redirect, and prior unpickle error, the most likely causes and concrete next steps are:
1) Use the final SSE URL (follow the redirect) for the MCPServerHTTP URL
• Your curl returned a 307 Location that ends with /sse?.... Use that final URL in mcp.MCPServerHTTP(...) so the agent connects directly to the SSE path instead of being redirected. Example:
mcp_servers=[mcp.MCPServerHTTP(url="<https://backend.composio.dev/v3/mcp/<serverId>/sse?transport=sse>")]
2) Confirm the MCP server returns a valid list_tools JSON on the expected endpoint
• From the agent host run and paste results:
◦ curl -v "https://backend.composio.dev/v3/mcp/<serverId>/sse?transport=sse"
◦ curl -v "https://backend.composio.dev/v3/mcp/<serverId>/list_tools"
• If list_tools is not valid JSON or is missing, tools won’t load and the session startup can fail.
3) Resolve the unpickling/exception mismatch (if still present) — check package versions and update
• Run and paste results of:
◦ pip show livekit-agents mcp
◦ pip list | grep -E "livekit-agents|mcp"
• If versions are mismatched, update with uv: uv update livekit-agents[mcp] mcp or with pip: pip install -U livekit-agents[mcp] mcp
• Restart the agent after update.
4) Add a defensive check around generate_reply to avoid the RuntimeError while we diagnose
• Replace the default callback or add a small guard before calling `sess.generate_reply(...)`:
if not sess.closing:
await sess.generate_reply(user_input=ev.text)
else:
<http://ctx.log.info|ctx.log.info>("Session closing - skipping generate_reply")
(The AgentSession API exposes the session state used internally; check your version for the exact attribute name — paste package versions and I’ll confirm.)
5) Collect logs that show why the session entered closing state
• Paste ~30 lines before the RuntimeError (search for "closing", "disconnect", "error", "exception" in logs). Those lines show the triggering event (MCP connection failure, unhandled exception, participant disconnect, or explicit close).
What I need from you next (small, concrete set)
• Confirm you changed the MCP URL to the final /sse path and retested; paste the curl output for both /sse and /list_tools.
• Paste pip show livekit-agents mcp (or pip list lines).
• Paste ~30 log lines immediately before the RuntimeError.
Once you paste those three items I’ll tell you the exact line to change (if any), or the package fix to apply, and whether the guard needs a different attribute name for your version.echoing-lamp-18687
12/16/2025, 6:44 AMtall-airline-16756
12/16/2025, 6:44 AMsess.generate_reply(...) is invoked):
# quick defensive guard (adjust attribute name if your AgentSession uses a different flag)
if not getattr(sess, "closing", False) and not getattr(sess, "closed", False):
await sess.generate_reply(user_input=ev.text)
else:
<http://ctx.log.info|ctx.log.info>("Session closing/closed — skipping generate_reply")
Send the three items above and I’ll pinpoint the root cause and exact code/package change needed.echoing-lamp-18687
12/16/2025, 6:46 AMtall-airline-16756
12/16/2025, 6:46 AMgenerate_reply() in your code. That’s expected: the default text input callback inside the LiveKit Agents library calls generate_reply() for you, which is where the RuntimeError originates.
What to do next (minimal, actionable):
1) Replace the default text input callback with a small custom callback that guards against session closing. Add this near your imports and pass it into room_io.RoomOptions as `text_input_cb`:
from livekit.agents.voice import room_io
async def safe_text_input_cb(sess, ev, ctx):
# sess is the AgentSession used by the callback
if getattr(sess, "closing", False) or getattr(sess, "closed", False):
<http://ctx.log.info|ctx.log.info>("Session closing/closed — skipping generate_reply")
return None
# call the existing default behavior
return await room_io.types._default_text_input_cb(sess, ev, ctx)
Then in your session.start(...) call use:
room_options=room_io.RoomOptions(
close_on_disconnect=False,
text_input_cb=safe_text_input_cb,
...
)
2) Send me your package versions so I confirm the correct session-state attribute name:
• Run and paste: pip show livekit-agents mcp
3) If you want me to produce a drop-in replacement for your library version, paste the two things above and I’ll return the exact callback code aligned to your package versions.
Do you want me to generate the ready-to-paste callback adjusted to your livekit-agents version?