Rename server

This commit is contained in:
Jeremiah Lowin 2024-11-29 17:59:44 -05:00
commit ead41caa0d
7 changed files with 60 additions and 23 deletions

View file

@ -7,10 +7,10 @@ A simple example that exposes the desktop directory as a resource.
import asyncio
from pathlib import Path
from fastmcp.server import FastMCPServer
from fastmcp.server import FastMCP
# Create server
app = FastMCPServer("desktop")
app = FastMCP("desktop")
# Add desktop as a directory resource
desktop = Path.home() / "Desktop"
@ -24,7 +24,7 @@ app.add_dir_resource(
def main123():
# Run the server
asyncio.run(FastMCPServer.run_stdio(app))
asyncio.run(FastMCP.run_stdio(app))
if __name__ == "__main__":

View file

@ -5,7 +5,7 @@ FastMCP Weather Server Example
import os
import httpx
from pydantic import BaseModel, Field
from fastmcp.server import FastMCPServer
from fastmcp.server import FastMCP
# Load env vars
API_KEY = os.getenv("OPENWEATHER_API_KEY")
@ -32,7 +32,7 @@ class AlertParams(BaseModel):
# Create server
app = FastMCPServer("weather-service")
app = FastMCP("weather-service")
# Tools using Pydantic models
@ -126,7 +126,7 @@ def main():
)
# Run the server
asyncio.run(FastMCPServer.run_stdio(app))
asyncio.run(FastMCP.run_stdio(app))
if __name__ == "__main__":

1
src/fastmcp/__init__.py Normal file
View file

@ -0,0 +1 @@
from .server import FastMCP

View file

@ -1,13 +1,16 @@
"""FastMCP - A more ergonomic interface for MCP servers."""
import asyncio
import base64
import functools
import json
import logging
from dataclasses import dataclass
from typing import Any, Callable, Dict, Optional, Sequence, Union, Literal
from mcp.server import Server as MCPServer
from mcp.server.stdio import stdio_server
from mcp.server.sse import SseServerTransport
from mcp.types import Resource as MCPResource
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
from pydantic import BaseModel
@ -16,9 +19,9 @@ from pydantic_settings import BaseSettings
from .exceptions import ResourceError
from .resources import Resource, FunctionResource, ResourceManager
from .tools import ToolManager
from .utilities import get_logger, configure_logging
logger = logging.getLogger("fastmcp")
logger = get_logger(__name__)
class Settings(BaseSettings):
@ -45,10 +48,10 @@ class Settings(BaseSettings):
warn_on_duplicate_tools: bool = True
class FastMCPServer:
class FastMCP:
def __init__(self, name=None, **settings: Optional[Settings]):
self.settings = Settings(**settings)
self._mcp_server = MCPServer(name=name or "FastMCPServer")
self._mcp_server = MCPServer(name=name or "FastMCP")
self._tool_manager = ToolManager(
warn_on_duplicate_tools=self.settings.warn_on_duplicate_tools
)
@ -57,11 +60,7 @@ class FastMCPServer:
)
# Configure logging
logging.basicConfig(
level=getattr(logging, self.settings.log_level.upper()),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger.setLevel(getattr(logging, self.settings.log_level.upper()))
configure_logging(self.settings.log_level)
self._setup_handlers()
@ -297,7 +296,7 @@ class FastMCPServer:
await self._mcp_server.run(*args, **kwargs)
@classmethod
async def run_stdio(cls, app: "FastMCPServer") -> None:
async def run_stdio(cls, app: "FastMCP") -> None:
"""Run the server using stdio transport."""
async with stdio_server() as (read_stream, write_stream):
await app.run(
@ -309,7 +308,7 @@ class FastMCPServer:
@classmethod
async def run_sse(
cls,
app: "FastMCPServer",
app: "FastMCP",
) -> None:
"""Run the server using SSE transport."""
from mcp.server.sse import SseServerTransport

View file

@ -0,0 +1,4 @@
"""Utility functions for FastMCP."""
from .logging import get_logger, configure_logging
__all__ = ["get_logger", "configure_logging"]

View file

@ -0,0 +1,33 @@
"""Logging utilities for FastMCP."""
import logging
from typing import Optional
def get_logger(name: Optional[str] = None) -> logging.Logger:
"""Get a logger instance nested under the FastMCP namespace.
Args:
name: Optional name to append to the FastMCP namespace.
If provided, the logger will be named 'FastMCP.[name]'.
If not provided, returns the root FastMCP logger.
Returns:
A configured logger instance
"""
logger_name = "FastMCP"
if name:
logger_name = f"{logger_name}.{name}"
return logging.getLogger(logger_name)
def configure_logging(level: str = "INFO") -> None:
"""Configure the root FastMCP logger.
Args:
level: The log level to use. Defaults to INFO.
"""
logging.basicConfig(
level=getattr(logging, level.upper()),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
get_logger().setLevel(getattr(logging, level.upper()))

View file

@ -1,13 +1,13 @@
from mcp.shared.memory import (
create_connected_server_and_client_session as client_session,
)
from fastmcp.server import FastMCPServer
from fastmcp.server import FastMCP
class TestServer:
async def test_create_server(self):
server = FastMCPServer()
assert server.name == "FastMCPServer"
server = FastMCP()
assert server.name == "FastMCP"
def tool_fn(x: int, y: int) -> int:
@ -16,20 +16,20 @@ def tool_fn(x: int, y: int) -> int:
class TestServerTools:
async def test_add_tool(self):
server = FastMCPServer()
server = FastMCP()
server.add_tool(tool_fn)
server.add_tool(tool_fn)
assert len(server._tool_manager.list_tools()) == 1
async def test_list_tools(self):
server = FastMCPServer()
server = FastMCP()
server.add_tool(tool_fn)
async with client_session(server._mcp_server) as client:
tools = await client.list_tools()
assert len(tools.tools) == 1
async def test_call_tool(self):
server = FastMCPServer()
server = FastMCP()
server.add_tool(tool_fn)
async with client_session(server._mcp_server) as client:
result = await client.call_tool("my_tool", {"arg1": "value"})