mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-21 21:14:17 +02:00
Improve methods on server and registration
This commit is contained in:
parent
8c30fc5f2c
commit
c032d0cb06
2 changed files with 72 additions and 56 deletions
|
|
@ -67,50 +67,54 @@ class FastMCP:
|
|||
|
||||
def _setup_handlers(self) -> None:
|
||||
"""Set up core MCP protocol handlers."""
|
||||
self._mcp_server.list_tools()(self.list_tools)
|
||||
self._mcp_server.call_tool()(self.call_tool)
|
||||
self._mcp_server.list_resources()(self.list_resources)
|
||||
self._mcp_server.read_resource()(self.read_resource)
|
||||
|
||||
@self._mcp_server.list_tools()
|
||||
async def handle_list_tools() -> list[Tool]:
|
||||
tools = self._tool_manager.list_tools()
|
||||
return [
|
||||
Tool(
|
||||
name=info.name,
|
||||
description=info.description,
|
||||
inputSchema=info.parameters,
|
||||
)
|
||||
for info in tools
|
||||
]
|
||||
async def list_tools(self) -> list[Tool]:
|
||||
"""List all available tools."""
|
||||
tools = self._tool_manager.list_tools()
|
||||
return [
|
||||
Tool(
|
||||
name=info.name,
|
||||
description=info.description,
|
||||
inputSchema=info.parameters,
|
||||
)
|
||||
for info in tools
|
||||
]
|
||||
|
||||
@self._mcp_server.call_tool()
|
||||
async def handle_call_tool(
|
||||
name: str, arguments: dict
|
||||
) -> Sequence[Union[TextContent, ImageContent, EmbeddedResource]]:
|
||||
result = await self._tool_manager.call_tool(name, arguments)
|
||||
return [self._convert_to_content(result)]
|
||||
async def call_tool(
|
||||
self, name: str, arguments: dict
|
||||
) -> Sequence[Union[TextContent, ImageContent, EmbeddedResource]]:
|
||||
"""Call a tool by name with arguments."""
|
||||
result = await self._tool_manager.call_tool(name, arguments)
|
||||
return [self._convert_to_content(result)]
|
||||
|
||||
@self._mcp_server.list_resources()
|
||||
async def handle_list_resources() -> list[MCPResource]:
|
||||
resources = self._resource_manager.list_resources()
|
||||
return [
|
||||
MCPResource(
|
||||
uri=resource.uri,
|
||||
name=resource.name,
|
||||
description=resource.description,
|
||||
mimeType=resource.mime_type,
|
||||
)
|
||||
for resource in resources
|
||||
]
|
||||
async def list_resources(self) -> list[MCPResource]:
|
||||
"""List all available resources."""
|
||||
resources = self._resource_manager.list_resources()
|
||||
return [
|
||||
MCPResource(
|
||||
uri=resource.uri,
|
||||
name=resource.name,
|
||||
description=resource.description,
|
||||
mimeType=resource.mime_type,
|
||||
)
|
||||
for resource in resources
|
||||
]
|
||||
|
||||
@self._mcp_server.read_resource()
|
||||
async def handle_read_resource(uri: str) -> Union[str, bytes]:
|
||||
resource = self._resource_manager.get_resource(uri)
|
||||
if not resource:
|
||||
raise ResourceError(f"Unknown resource: {uri}")
|
||||
async def read_resource(self, uri: str) -> Union[str, bytes]:
|
||||
"""Read a resource by URI."""
|
||||
resource = self._resource_manager.get_resource(uri)
|
||||
if not resource:
|
||||
raise ResourceError(f"Unknown resource: {uri}")
|
||||
|
||||
try:
|
||||
return await resource.read()
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading resource {uri}: {e}")
|
||||
raise ResourceError(str(e))
|
||||
try:
|
||||
return await resource.read()
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading resource {uri}: {e}")
|
||||
raise ResourceError(str(e))
|
||||
|
||||
def _convert_to_content(
|
||||
self, value: Any
|
||||
|
|
@ -143,6 +147,7 @@ class FastMCP:
|
|||
self, name: Optional[str] = None, description: Optional[str] = None
|
||||
) -> Callable:
|
||||
"""Decorator to register a tool."""
|
||||
breakpoint()
|
||||
|
||||
def decorator(func: Callable) -> Callable:
|
||||
self.add_tool(func, name=name, description=description)
|
||||
|
|
@ -308,7 +313,6 @@ class FastMCP:
|
|||
app: "FastMCP",
|
||||
) -> None:
|
||||
"""Run the server using SSE transport."""
|
||||
from mcp.server.sse import SseServerTransport
|
||||
from starlette.applications import Starlette
|
||||
from starlette.routing import Route
|
||||
import uvicorn
|
||||
|
|
|
|||
|
|
@ -1,13 +1,25 @@
|
|||
from mcp.shared.memory import (
|
||||
create_connected_server_and_client_session as client_session,
|
||||
)
|
||||
from fastmcp.server import FastMCP
|
||||
from fastmcp import FastMCP
|
||||
|
||||
|
||||
class TestServer:
|
||||
async def test_create_server(self):
|
||||
server = FastMCP()
|
||||
assert server.name == "FastMCP"
|
||||
mcp = FastMCP()
|
||||
assert mcp.name == "FastMCP"
|
||||
|
||||
async def test_add_tool_decorator(self):
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.tool
|
||||
def add(x: int, y: int) -> int:
|
||||
return x + y
|
||||
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
tools = await client.list_tools()
|
||||
assert len(tools.tools) == 1
|
||||
assert tools.tools[0].name == "add"
|
||||
|
||||
|
||||
def tool_fn(x: int, y: int) -> int:
|
||||
|
|
@ -16,22 +28,22 @@ def tool_fn(x: int, y: int) -> int:
|
|||
|
||||
class TestServerTools:
|
||||
async def test_add_tool(self):
|
||||
server = FastMCP()
|
||||
server.add_tool(tool_fn)
|
||||
server.add_tool(tool_fn)
|
||||
assert len(server._tool_manager.list_tools()) == 1
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
mcp.add_tool(tool_fn)
|
||||
assert len(mcp._tool_manager.list_tools()) == 1
|
||||
|
||||
async def test_list_tools(self):
|
||||
server = FastMCP()
|
||||
server.add_tool(tool_fn)
|
||||
async with client_session(server._mcp_server) as client:
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
tools = await client.list_tools()
|
||||
assert len(tools.tools) == 1
|
||||
|
||||
async def test_call_tool(self):
|
||||
server = FastMCP()
|
||||
server.add_tool(tool_fn)
|
||||
async with client_session(server._mcp_server) as client:
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
result = await client.call_tool("my_tool", {"arg1": "value"})
|
||||
assert "error" not in result
|
||||
assert len(result.content) > 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue