You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am running into an issue when attempting to use callable objects with FastMCP.
Description / Reproducible Example
Regular, synchronous callable objects work (mostly) as expected, with the exception of having to set self.__name__:
importasynciofrommcp.server.fastmcpimportFastMCPclassTestTool:
def__init__(self) ->None:
self.__name__="TestTool"def__call__(self) ->str:
return"Hello from TestTool!"mcp=FastMCP()
mcp.add_tool(TestTool())
asyncdefmain() ->None:
# prints "Hello from TestTool!"print(awaitmcp.call_tool("TestTool", {}))
if__name__=="__main__":
asyncio.run(main())
However, making the __call__ method async breaks things:
importasynciofrommcp.server.fastmcpimportFastMCPclassTestTool:
def__init__(self) ->None:
self.__name__="TestTool"asyncdef__call__(self) ->str:
return"Hello from TestTool!"mcp=FastMCP()
mcp.add_tool(TestTool())
asyncdefmain() ->None:
# prints [TextContent(type='text', text='<coroutine object TestTool.__call__ at 0x103155300>', annotations=None)]print(awaitmcp.call_tool("TestTool", {}))
if__name__=="__main__":
asyncio.run(main())
Simple Fix
I tracked this down to this line in Tool.from_function, which does not work properly for async callable objects:
is_async=inspect.iscoroutinefunction(fn)
I know this use-case is slightly out-of-the-ordinary, but it would be extremely helpful if we could improve this to work properly for callable objects as well.
There is some prior art here, Starlette checks if the provided callable is async like this, which works for both regular async functions and async callable objects:
defis_async_callable(obj: typing.Any) ->typing.Any:
whileisinstance(obj, functools.partial):
obj=obj.funcreturninspect.iscoroutinefunction(obj) or (callable(obj) andinspect.iscoroutinefunction(obj.__call__))
Would you be open to accepting a pull request with a similar implementation?
Thank you!
The text was updated successfully, but these errors were encountered:
Hi there,
I am running into an issue when attempting to use callable objects with FastMCP.
Description / Reproducible Example
Regular, synchronous callable objects work (mostly) as expected, with the exception of having to set
self.__name__
:However, making the
__call__
method async breaks things:Simple Fix
I tracked this down to this line in
Tool.from_function
, which does not work properly for async callable objects:I know this use-case is slightly out-of-the-ordinary, but it would be extremely helpful if we could improve this to work properly for callable objects as well.
There is some prior art here, Starlette checks if the provided callable is async like this, which works for both regular async functions and async callable objects:
Would you be open to accepting a pull request with a similar implementation?
Thank you!
The text was updated successfully, but these errors were encountered: