Compare commits

...

1 commit

Author SHA1 Message Date
zzstoatzz
54a3c4a8f6 TestClient 2025-05-20 09:18:34 -05:00
4 changed files with 1012 additions and 2 deletions

View file

@ -0,0 +1,21 @@
from fastmcp import FastMCP
from fastmcp.testing import TestClient
server = FastMCP("test-server")
@server.tool()
def get_the_value_of_schleeb() -> int:
return 42
async def main():
async with TestClient(server) as client:
await client.say("What is the value of schleeb?")
await client.say("sorry can you repeat that?")
if __name__ == "__main__":
import asyncio
asyncio.run(main())

View file

@ -36,6 +36,9 @@ classifiers = [
"Typing :: Typed",
]
[project.optional-dependencies]
chat = ["marvin>=3.1.0"]
[dependency-groups]
dev = [
"copychat>=0.5.2",

37
src/fastmcp/testing.py Normal file
View file

@ -0,0 +1,37 @@
from contextlib import ExitStack
from types import ModuleType
from typing import Any
from typing_extensions import Self
from fastmcp import FastMCP
def _get_agent_framework_module() -> ModuleType:
try:
import marvin
except ImportError:
raise ImportError(
"please install `fastmcp[chat]` to use TestClient with chat tools"
)
return marvin
class TestClient:
def __init__(self, server: FastMCP, agent_options: dict[str, Any] | None = None):
self.server = server
self._agent_framework = _get_agent_framework_module()
self._agent_options = agent_options or {}
self._stack = ExitStack()
async def __aenter__(self) -> Self:
self._stack.enter_context(self._agent_framework.Thread())
return self
async def __aexit__(self, exc_type, exc_value, traceback):
pass
async def say(self, message: str) -> None:
await self._agent_framework.Agent(
mcp_servers=[self.server], **self._agent_options
).run_async(message)

953
uv.lock generated

File diff suppressed because it is too large Load diff