Spec Registry
Help your agents use open-source better. Learn more.
Find usage specs for your project’s dependencies
- Author
- tessl
- Last updated
- Spec files
pypi-fastmcp
Describes: pypi/fastmcp
- Description
- The fast, Pythonic way to build MCP servers and clients with minimal boilerplate code.
- Author
- tessl
- Last updated
utilities.md docs/
1# Utilities and Types23Helper classes and utility functions for enhanced functionality and type support. FastMCP provides a comprehensive set of utilities for common tasks, data handling, and system integration.45## Capabilities67### Media and File Types89Helper classes for returning rich media content from tools and resources.1011```python { .api }12class Image:13def __init__(14self,15data: bytes | str,16mime_type: str = "image/png"17):18"""19Image helper for returning image data from tools.2021Parameters:22- data: Image data as bytes or base64 string23- mime_type: MIME type of the image24"""2526class Audio:27def __init__(28self,29data: bytes | str,30mime_type: str = "audio/wav"31):32"""33Audio helper for returning audio data from tools.3435Parameters:36- data: Audio data as bytes or base64 string37- mime_type: MIME type of the audio38"""3940class File:41def __init__(42self,43data: bytes | str,44name: str,45mime_type: str | None = None46):47"""48File helper for returning file data from tools.4950Parameters:51- data: File content as bytes or string52- name: Filename53- mime_type: MIME type of the file54"""55```5657### Base Model Classes5859Base Pydantic models providing common functionality for FastMCP components.6061```python { .api }62class FastMCPBaseModel:63"""Base Pydantic model for FastMCP with common configurations."""6465class Config:66arbitrary_types_allowed = True67extra = "forbid"68validate_assignment = True6970def get_cached_typeadapter(type_hint: type) -> TypeAdapter:71"""72Get cached TypeAdapter for type validation.7374Parameters:75- type_hint: Type to create adapter for7677Returns:78Cached TypeAdapter instance79"""80```8182### Component System8384Base classes for creating reusable FastMCP components.8586```python { .api }87class FastMCPComponent:88"""Base class for FastMCP components with lifecycle management."""8990def __init__(self, name: str | None = None):91"""92Initialize component.9394Parameters:95- name: Component name for identification96"""9798async def initialize(self) -> None:99"""Initialize component resources."""100101async def cleanup(self) -> None:102"""Clean up component resources."""103104def get_name(self) -> str:105"""Get component name."""106```107108### Settings Management109110Comprehensive settings system for configuring FastMCP behavior.111112```python { .api }113class Settings:114"""Main settings class for FastMCP configuration."""115116# Logging settings117log_enabled: bool = True118log_level: str = "INFO"119enable_rich_tracebacks: bool = True120121# Development settings122test_mode: bool = False123debug_mode: bool = False124125# Feature flags126deprecation_warnings: bool = True127experimental_features: bool = False128129# Performance settings130max_connections: int = 100131request_timeout: float = 30.0132133# Security settings134allow_dangerous_tools: bool = False135require_auth: bool = False136137class ExperimentalSettings:138"""Settings for experimental features."""139140enable_async_tools: bool = False141enable_streaming: bool = False142enable_caching: bool = False143```144145### OpenAPI Integration146147Utilities for working with OpenAPI specifications and HTTP APIs.148149```python { .api }150class OpenAPIParser:151"""Parser for OpenAPI specifications."""152153def __init__(self, spec: dict | str):154"""155Initialize OpenAPI parser.156157Parameters:158- spec: OpenAPI specification as dict or JSON string159"""160161def parse_paths(self) -> list[HTTPRoute]:162"""Parse API paths into HTTPRoute objects."""163164def get_schemas(self) -> dict[str, dict]:165"""Get schema definitions from specification."""166167class HTTPRoute:168"""HTTP route representation."""169170def __init__(171self,172path: str,173method: str,174operation_id: str | None = None,175summary: str | None = None,176description: str | None = None,177parameters: list[dict] | None = None,178request_body: dict | None = None,179responses: dict | None = None180):181"""182HTTP route definition.183184Parameters:185- path: URL path with parameters186- method: HTTP method (GET, POST, etc.)187- operation_id: Unique operation identifier188- summary: Brief operation summary189- description: Detailed operation description190- parameters: Request parameters191- request_body: Request body schema192- responses: Response schemas193"""194```195196### MCP Configuration197198Configuration management for MCP server setups and client connections.199200```python { .api }201class MCPConfig:202"""MCP configuration format for server definitions."""203204def __init__(self, config: dict):205"""206Initialize MCP configuration.207208Parameters:209- config: Configuration dictionary210"""211212def get_servers(self) -> dict[str, dict]:213"""Get server configurations."""214215def validate(self) -> bool:216"""Validate configuration format."""217```218219### Testing Utilities220221Helper functions and classes for testing FastMCP servers and clients.222223```python { .api }224def create_test_server() -> FastMCP:225"""Create a FastMCP server configured for testing."""226227def create_test_client(server: FastMCP) -> Client:228"""Create a client connected to test server via in-memory transport."""229230async def assert_tool_exists(client: Client, tool_name: str) -> None:231"""Assert that a tool exists on the server."""232233async def assert_resource_exists(client: Client, resource_uri: str) -> None:234"""Assert that a resource exists on the server."""235```236237### JSON Schema Utilities238239Utilities for working with JSON schemas and type validation.240241```python { .api }242def generate_schema_from_function(func: Callable) -> dict:243"""244Generate JSON schema from function signature.245246Parameters:247- func: Function to analyze248249Returns:250JSON schema dictionary251"""252253def validate_against_schema(data: Any, schema: dict) -> bool:254"""255Validate data against JSON schema.256257Parameters:258- data: Data to validate259- schema: JSON schema260261Returns:262True if valid, False otherwise263"""264```265266### HTTP Utilities267268Utilities for HTTP operations and request handling.269270```python { .api }271async def make_http_request(272method: str,273url: str,274headers: dict | None = None,275data: Any | None = None,276timeout: float = 30.0277) -> dict:278"""279Make HTTP request with error handling.280281Parameters:282- method: HTTP method283- url: Target URL284- headers: Request headers285- data: Request data286- timeout: Request timeout287288Returns:289Response data290"""291292def parse_http_headers(headers: dict) -> dict[str, str]:293"""Parse and normalize HTTP headers."""294```295296## Usage Examples297298### Media Types Usage299300```python301from fastmcp import FastMCP302from fastmcp.utilities.types import Image, Audio, File303import base64304305mcp = FastMCP("Media Server")306307@mcp.tool308def create_chart() -> Image:309"""Create a chart and return as image."""310import matplotlib.pyplot as plt311import io312313# Create chart314plt.figure(figsize=(10, 6))315plt.plot([1, 2, 3, 4], [1, 4, 2, 3])316plt.title("Sample Chart")317318# Save to bytes319buffer = io.BytesIO()320plt.savefig(buffer, format='png')321buffer.seek(0)322323return Image(buffer.read(), mime_type="image/png")324325@mcp.tool326def generate_audio() -> Audio:327"""Generate audio data."""328import numpy as np329import wave330import io331332# Generate sine wave333sample_rate = 44100334duration = 1.0335frequency = 440.0336337t = np.linspace(0, duration, int(sample_rate * duration))338waveform = np.sin(2 * np.pi * frequency * t)339340# Convert to audio bytes341buffer = io.BytesIO()342with wave.open(buffer, 'wb') as wav_file:343wav_file.setnchannels(1)344wav_file.setsampwidth(2)345wav_file.setframerate(sample_rate)346wav_file.writeframes((waveform * 32767).astype(np.int16).tobytes())347348buffer.seek(0)349return Audio(buffer.read(), mime_type="audio/wav")350351@mcp.tool352def create_document(content: str, filename: str = "document.txt") -> File:353"""Create document file."""354return File(355data=content.encode('utf-8'),356name=filename,357mime_type="text/plain"358)359360@mcp.tool361def create_json_file(data: dict, filename: str = "data.json") -> File:362"""Create JSON file."""363import json364365json_content = json.dumps(data, indent=2)366367return File(368data=json_content,369name=filename,370mime_type="application/json"371)372```373374### Settings Configuration375376```python377from fastmcp import FastMCP, Settings378from fastmcp.utilities.logging import configure_logging379380# Create custom settings381settings = Settings()382settings.log_level = "DEBUG"383settings.debug_mode = True384settings.max_connections = 50385settings.request_timeout = 60.0386settings.allow_dangerous_tools = False387388# Configure logging389configure_logging(390level=settings.log_level,391enable_rich_tracebacks=settings.enable_rich_tracebacks392)393394# Create server with custom settings395mcp = FastMCP(396name="Configured Server",397settings=settings398)399400@mcp.tool401def debug_info() -> dict:402"""Get debug information."""403return {404"debug_mode": settings.debug_mode,405"log_level": settings.log_level,406"max_connections": settings.max_connections,407"request_timeout": settings.request_timeout408}409410mcp.run()411```412413### Component System Usage414415```python416from fastmcp import FastMCP417from fastmcp.utilities.components import FastMCPComponent418import asyncio419420class DatabaseComponent(FastMCPComponent):421"""Database connection component."""422423def __init__(self):424super().__init__("database")425self.connection = None426427async def initialize(self):428"""Initialize database connection."""429# Mock database connection430await asyncio.sleep(0.1)431self.connection = {"status": "connected", "pool_size": 10}432print(f"Component {self.get_name()} initialized")433434async def cleanup(self):435"""Clean up database connection."""436if self.connection:437self.connection = None438print(f"Component {self.get_name()} cleaned up")439440def query(self, sql: str) -> list[dict]:441"""Execute database query."""442if not self.connection:443raise RuntimeError("Database not connected")444445# Mock query result446return [{"id": 1, "name": "example", "sql": sql}]447448class CacheComponent(FastMCPComponent):449"""Cache component."""450451def __init__(self):452super().__init__("cache")453self.cache = {}454455async def initialize(self):456"""Initialize cache."""457self.cache = {}458print(f"Component {self.get_name()} initialized")459460async def cleanup(self):461"""Clean up cache."""462self.cache.clear()463print(f"Component {self.get_name()} cleaned up")464465def get(self, key: str) -> Any:466"""Get value from cache."""467return self.cache.get(key)468469def set(self, key: str, value: Any) -> None:470"""Set value in cache."""471self.cache[key] = value472473# Set up components474db_component = DatabaseComponent()475cache_component = CacheComponent()476477mcp = FastMCP("Component Server")478479@mcp.tool480async def query_with_cache(sql: str) -> list[dict]:481"""Query database with caching."""482# Check cache first483cached_result = cache_component.get(sql)484if cached_result:485return {"cached": True, "data": cached_result}486487# Query database488result = db_component.query(sql)489490# Cache result491cache_component.set(sql, result)492493return {"cached": False, "data": result}494495# Initialize components before running server496async def main():497await db_component.initialize()498await cache_component.initialize()499500try:501mcp.run()502finally:503await db_component.cleanup()504await cache_component.cleanup()505506if __name__ == "__main__":507asyncio.run(main())508```509510### OpenAPI Integration511512```python513from fastmcp import FastMCP514from fastmcp.utilities.openapi import OpenAPIParser, HTTPRoute515516# Load OpenAPI specification517openapi_spec = {518"openapi": "3.0.0",519"info": {"title": "Example API", "version": "1.0.0"},520"paths": {521"/users": {522"get": {523"operationId": "getUsers",524"summary": "Get all users",525"responses": {526"200": {527"description": "List of users",528"content": {529"application/json": {530"schema": {531"type": "array",532"items": {"$ref": "#/components/schemas/User"}533}534}535}536}537}538},539"post": {540"operationId": "createUser",541"summary": "Create new user",542"requestBody": {543"content": {544"application/json": {545"schema": {"$ref": "#/components/schemas/User"}546}547}548},549"responses": {550"201": {"description": "User created"}551}552}553}554},555"components": {556"schemas": {557"User": {558"type": "object",559"properties": {560"id": {"type": "integer"},561"name": {"type": "string"},562"email": {"type": "string"}563}564}565}566}567}568569# Parse OpenAPI spec570parser = OpenAPIParser(openapi_spec)571routes = parser.parse_paths()572schemas = parser.get_schemas()573574mcp = FastMCP("OpenAPI Server")575576# Create tools from OpenAPI routes577for route in routes:578if route.method == "GET" and route.path == "/users":579@mcp.tool580def get_users() -> list[dict]:581"""Get all users."""582return [583{"id": 1, "name": "Alice", "email": "alice@example.com"},584{"id": 2, "name": "Bob", "email": "bob@example.com"}585]586587elif route.method == "POST" and route.path == "/users":588@mcp.tool589def create_user(name: str, email: str) -> dict:590"""Create new user."""591return {592"id": 123,593"name": name,594"email": email,595"created": "2024-01-01T00:00:00Z"596}597598mcp.run()599```600601### Testing Utilities Usage602603```python604from fastmcp import FastMCP, Client605from fastmcp.utilities.tests import create_test_client, assert_tool_exists606import asyncio607608async def test_server():609"""Test FastMCP server functionality."""610# Create test server611mcp = FastMCP("Test Server")612613@mcp.tool614def add(a: int, b: int) -> int:615"""Add two numbers."""616return a + b617618@mcp.resource("config://test")619def get_test_config():620"""Get test configuration."""621return {"test": True, "env": "testing"}622623# Create test client624client = create_test_client(mcp)625626async with client:627# Test tool existence628await assert_tool_exists(client, "add")629630# Test tool functionality631result = await client.call_tool("add", {"a": 5, "b": 3})632assert result.text == "8", f"Expected 8, got {result.text}"633634# Test resource635await assert_resource_exists(client, "config://test")636resource = await client.read_resource("config://test")637assert "test" in resource.content638639print("All tests passed!")640641if __name__ == "__main__":642asyncio.run(test_server())643```644645### Custom Utility Functions646647```python648from fastmcp import FastMCP, Context649from fastmcp.utilities.types import Image650import json651import hashlib652from datetime import datetime653from typing import Any654655def serialize_for_logging(obj: Any) -> str:656"""Serialize object for logging with proper handling of complex types."""657if isinstance(obj, (str, int, float, bool, type(None))):658return str(obj)659elif isinstance(obj, (list, tuple)):660return f"[{len(obj)} items]"661elif isinstance(obj, dict):662return f"{{keys: {list(obj.keys())[:5]}...}}"663else:664return f"<{type(obj).__name__}>"665666def calculate_hash(data: str | bytes) -> str:667"""Calculate SHA-256 hash of data."""668if isinstance(data, str):669data = data.encode('utf-8')670return hashlib.sha256(data).hexdigest()671672def format_timestamp() -> str:673"""Get current timestamp in ISO format."""674return datetime.utcnow().isoformat() + "Z"675676mcp = FastMCP("Utility Demo Server")677678@mcp.tool679async def process_data(680data: dict,681operation: str = "analyze",682ctx: Context = None683) -> dict:684"""Process data with utility functions."""685await ctx.info(f"Processing data: {serialize_for_logging(data)}")686687# Calculate data hash for integrity688data_str = json.dumps(data, sort_keys=True)689data_hash = calculate_hash(data_str)690691await ctx.info(f"Data hash: {data_hash}")692693# Process based on operation694if operation == "analyze":695result = {696"analysis": f"Analyzed {len(data)} fields",697"keys": list(data.keys())[:10], # Limit for safety698"field_types": {k: type(v).__name__ for k, v in data.items()}699}700elif operation == "transform":701result = {702"transformed": {k: str(v).upper() if isinstance(v, str) else v703for k, v in data.items()},704"transformation": "uppercase_strings"705}706else:707result = {"error": f"Unknown operation: {operation}"}708709# Add metadata710result.update({711"data_hash": data_hash,712"processed_at": format_timestamp(),713"operation": operation,714"status": "completed"715})716717await ctx.info("Data processing completed")718return result719720@mcp.tool721def create_visualization(data: dict, chart_type: str = "bar") -> Image:722"""Create visualization from data."""723import matplotlib.pyplot as plt724import io725726# Extract data for plotting727if isinstance(data, dict) and all(isinstance(v, (int, float)) for v in data.values()):728keys = list(data.keys())729values = list(data.values())730else:731# Fallback data732keys = ["A", "B", "C", "D"]733values = [1, 3, 2, 4]734735# Create chart736plt.figure(figsize=(10, 6))737738if chart_type == "bar":739plt.bar(keys, values)740elif chart_type == "line":741plt.plot(keys, values, marker='o')742elif chart_type == "pie":743plt.pie(values, labels=keys, autopct='%1.1f%%')744else:745plt.bar(keys, values) # Default to bar746747plt.title(f"{chart_type.title()} Chart")748plt.tight_layout()749750# Save to bytes751buffer = io.BytesIO()752plt.savefig(buffer, format='png', dpi=150)753buffer.seek(0)754755return Image(buffer.read(), mime_type="image/png")756757mcp.run()758```759760## Type Aliases and Constants761762```python { .api }763# Common type aliases764ToolFunction = Callable[..., Any]765ResourceFunction = Callable[..., str | bytes | dict]766PromptFunction = Callable[..., str | list[dict]]767768# Transport types769TransportType = Literal["stdio", "sse", "http", "ws"]770771# Log levels772LOG_LEVEL = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]773774# Duplicate behavior options775DuplicateBehavior = Literal["error", "ignore", "replace"]776777# Component types778ComponentFn = Callable[..., Any]779```