[Bug][Fixed] mcp服务异常mcp.shared.exceptions.McpError: Session terminated
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
Start with astrbot/core/agent/mcp_client.py, especially call_tool_with_reconnect and the retry and exception-handling points identified in the report. Reproduce with the listed streamable_http configuration and review the Session terminated logs. Done means the MCP service reconnects and the tool call succeeds after the container is restarted.
Written by the indexing model from the issue text.
Description
问题描述
docker使用镜像源部署,添加https://mcpmarket.cn的mcp服务的时候发现mcp.shared.exceptions.McpError: Session terminated。
临时修复:容器内运行
cd /tmp && cat > fix_mcp.py << 'PYEOF'
import io
path = "/AstrBot/astrbot/core/agent/mcp_client.py"
src = io.open(path, encoding="utf-8").read()
# 1. 顶部加 import
if "from mcp.shared.exceptions import McpError" not in src:
assert "import httpx\n" in src, "import anchor not found"
src = src.replace(
"import httpx\n",
"import httpx\nfrom mcp.shared.exceptions import McpError\n",
1,
)
# 2. 扩大重试条件
old_retry = "retry=retry_if_exception_type(anyio.ClosedResourceError),"
new_retry = "retry=retry_if_exception_type((anyio.ClosedResourceError, TimeoutError, McpError)),"
assert src.count(old_retry) == 1, "retry anchor not found"
src = src.replace(old_retry, new_retry)
# 3. 扩大异常捕获并加重连保护
old_exc = """ except anyio.ClosedResourceError:
logger.warning(
f"MCP tool {tool_name} call failed (ClosedResourceError), attempting to reconnect..."
)
# Attempt to reconnect
await self._reconnect()
# Reraise the exception to trigger tenacity retry
raise"""
new_exc = """ except (anyio.ClosedResourceError, TimeoutError, McpError) as e:
logger.warning(
f"MCP tool {tool_name} call failed ({type(e).__name__}: {e}), attempting to reconnect..."
)
# Attempt to reconnect (best effort, don't mask the original error)
try:
await self._reconnect()
except Exception as re:
logger.error(f"Reconnect failed: {re}")
# Reraise the exception to trigger tenacity retry
raise"""
assert src.count(old_exc) == 1, "except anchor not found"
src = src.replace(old_exc, new_exc)
io.open(path, "w", encoding="utf-8").write(src)
print("OK: 三处修改全部完成")
PYEOF
python fix_mcp.py
重启容器后得到解决
如何复现?
正常docker部署,用镜像源m.daocloud.io/docker.io/soulter/astrbot:latest+m.daocloud.io/docker.io/mlikiowa/napcat-docker:latest(版本对应为4.27.4),添加配置:
root@663fab43182d:/AstrBot/data# cat mcp_server.json
{
"mcpServers": {
"高德地图": {
"active": true,
"transport": "streamable_http",
"url": "https://mcpmarket.cn/mcp/688537b7d00f731bbe02e03e",
"headers": {},
"timeout": 5,
"sse_read_timeout": 300
},
"天气查询": {
"active": true,
"transport": "streamable_http",
"url": "https://mcpmarket.cn/mcp/5b3f77de1dac10ca4f373352",
"headers": {},
"timeout": 5,
"sse_read_timeout": 300
},
"12306服务": {
"active": true,
"transport": "streamable_http",
"url": "https://mcpmarket.cn/mcp/6e628a618abaac31b04789e4",
"headers": {},
"timeout": 5,
"sse_read_timeout": 300
},
"MarkitDown": {
"active": true,
"transport": "streamable_http",
"url": "https://mcpmarket.cn/mcp/bfd0296c9522e068abfc6178",
"headers": {},
"timeout": 5,
"sse_read_timeout": 300
},
"百度搜索": {
"active": true,
"transport": "streamable_http",
"url": "https://mcpmarket.cn/mcp/559f4b2ecdd8d3b2efd477fa",
"headers": {},
"timeout": 5,
"sse_read_timeout": 300
}
}
}
在对话中服务不可用。
AstrBot 版本
v4.27.4
操作系统
Linux
部署方式
docker
使用的消息平台适配器
Onebot v11
错误日志
[2026-08-27 07:00:07.922] [Core]
[INFO]
[runners.tool_loop_agent_runner:1152]: 使用工具:get_weather_forecast,参数:{'latitude': 31.4914, 'longitude': 120.3119, 'days': 1, 'hourly_vars': 'temperature_2m,precipitation,windspeed_10m,weathercode,relative_humidity_2m'}
[2026-08-27 07:00:08.078] [Core]
[WARN]
[v4.27.4] [runners.tool_loop_agent_runner:1324]: Traceback (most recent call last):
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1206, in _handle_function_tools
async for resp in self._iter_tool_executor_results(executor): # type: ignore
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1561, in _iter_tool_executor_results
yield next_result_task.result()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1531, in _next_executor_result
return await anext(executor)
^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 185, in execute
async for r in cls._execute_local(tool, run_context, **tool_args):
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 666, in _execute_local
resp = await asyncio.wait_for(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 520, in wait_for
return await fut
^^^^^^^^^
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 807, in call_local_llm_tool
ret = await ready_to_call
^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/func_tool_manager.py", line 269, in call
return await self._wrapped.call(context, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 817, in call
return await self.mcp_client.call_tool_with_reconnect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 774, in call_tool_with_reconnect
return await _call_with_retry()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 193, in async_wrapped
return await copy(fn, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 112, in __call__
do = await self.iter(retry_state=retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/__init__.py", line 393, in <lambda>
self._add_action_func(lambda rs: rs.outcome.result())
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 116, in __call__
result = await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 760, in _call_with_retry
return await self.session.call_tool(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/mcp/client/session.py", line 401, in call_tool
result = await self.send_request(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/mcp/shared/session.py", line 306, in send_request
raise McpError(response_or_error.error)
mcp.shared.exceptions.McpError: Session terminated
[2026-08-27 07:00:08.079] [Core]
[INFO]
[runners.tool_loop_agent_runner:1349]: Tool `get_weather_forecast` Result: error: Session terminated
[2026-08-28 07:00:05.933] [Core]
[INFO]
[runners.tool_loop_agent_runner:1096]: Agent 使用工具: ['get-current-date', 'get_weather_forecast']
[2026-08-28 07:00:05.933] [Core]
[INFO]
[runners.tool_loop_agent_runner:1152]: 使用工具:get-current-date,参数:{}
[2026-08-28 07:02:05.975] [Core]
[WARN]
[v4.27.4] [runners.tool_loop_agent_runner:1324]: Traceback (most recent call last):
File "/usr/local/lib/python3.12/site-packages/anyio/streams/memory.py", line 118, in receive
return self.receive_nowait()
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/anyio/streams/memory.py", line 113, in receive_nowait
raise WouldBlock
anyio.WouldBlock
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 520, in wait_for
return await fut
^^^^^^^^^
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 807, in call_local_llm_tool
ret = await ready_to_call
^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/func_tool_manager.py", line 269, in call
return await self._wrapped.call(context, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 817, in call
return await self.mcp_client.call_tool_with_reconnect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 774, in call_tool_with_reconnect
return await _call_with_retry()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 193, in async_wrapped
return await copy(fn, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 112, in __call__
do = await self.iter(retry_state=retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/__init__.py", line 393, in <lambda>
self._add_action_func(lambda rs: rs.outcome.result())
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 116, in __call__
result = await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/mcp_client.py", line 760, in _call_with_retry
return await self.session.call_tool(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/mcp/client/session.py", line 401, in call_tool
result = await self.send_request(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/mcp/shared/session.py", line 292, in send_request
response_or_error = await response_stream_reader.receive()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/anyio/streams/memory.py", line 126, in receive
await receive_event.wait()
File "/usr/local/lib/python3.12/site-packages/anyio/_backends/_asyncio.py", line 1866, in wait
await self._event.wait()
File "/usr/local/lib/python3.12/asyncio/locks.py", line 212, in wait
await fut
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 666, in _execute_local
resp = await asyncio.wait_for(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 519, in wait_for
async with timeouts.timeout(timeout):
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/timeouts.py", line 115, in __aexit__
raise TimeoutError from exc_val
TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1206, in _handle_function_tools
async for resp in self._iter_tool_executor_results(executor): # type: ignore
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1561, in _iter_tool_executor_results
yield next_result_task.result()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 1531, in _next_executor_result
return await anext(executor)
^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 185, in execute
async for r in cls._execute_local(tool, run_context, **tool_args):
File "/AstrBot/astrbot/core/astr_agent_tool_exec.py", line 699, in _execute_local
raise Exception(
Exception: tool get-current-date execution timeout after 120 seconds.
[2026-08-28 07:02:05.976] [Core]
[INFO]
[runners.tool_loop_agent_runner:1349]: Tool `get-current-date` Result: error: tool get-current-date execution timeout after 120 seconds.
[2026-08-28 07:02:05.992] [Core]
[INFO]
辅助信息
No response
检查清单
- Dominant language
- Python
- Stars
- 40.7k
- Forks
- 2.9k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 112
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from AstrBotDevs/AstrBot
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
AstrBotDevs/AstrBot#10033 · 3 comments ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
AstrBotDevs/AstrBot#9999 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
AstrBotDevs/AstrBot#9945 · 2 comments ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AstrBotDevs/AstrBot#9938 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
AstrBotDevs/AstrBot#9929 · 2 comments ·
All issues in AstrBotDevs/AstrBot
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100