I've spent most of my day held up by this bug, see pydantic/pydantic-ai#1140 (comment)
On main the problem is at
|
await self._incoming_message_stream_writer.send( |
|
notification |
|
) |
If I change these lines to
if not isinstance(notification.root, LoggingMessageNotification):
await self._incoming_message_stream_writer.send(
notification
)
Everything works correctly, obviously that's not a proper solution, but it demonstrates the problem.
In case it helps, to reproduce this problem, run
npx @pydantic/mcp-run-python sse
(see pydantic/pydantic-ai#1140 for context)
Then run
import logging
from logging import basicConfig
from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client
from mcp.client.stdio import stdio_client
from devtools import debug
import logfire
logfire.configure()
logfire.instrument_httpx(capture_all=True)
basicConfig(handlers=[logfire.LogfireLoggingHandler()], level=logging.DEBUG)
# disable httpx logs
logging.getLogger('httpcore.http11').setLevel(logging.CRITICAL)
logging.getLogger('httpx').setLevel(logging.CRITICAL)
logging.getLogger('urllib3.connectionpool').setLevel(logging.CRITICAL)
code = """
import numpy
a = numpy.array([1, 2, 3])
print(a)
a
"""
async def call_tools(session: ClientSession):
await session.initialize()
await session.set_logging_level('debug')
tools = await session.list_tools()
debug(tools)
result = await session.call_tool('run_python_code', {'python_code': code})
debug(result)
async def sse():
async with sse_client('http://localhost:3001/sse') as (read, write):
async with ClientSession(read, write) as session:
await call_tools(session)
async def stdio():
server_params = StdioServerParameters(command='npx', args=['@pydantic/mcp-run-python', 'stdio'])
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await call_tools(session)
if __name__ == '__main__':
import asyncio
with logfire.span('running sse'):
asyncio.run(sse())
Obviously you can disable the logfire bit, I was using it to see the raw http requests, I see the same hanging behaviour with both SSE and stdio.
As I mentioned in the comment linked above, you can also comment out await session.set_logging_level('debug') to avoid the issue.