### Setup Pre-commit Hooks Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/CLAUDE.md Install the pre-commit framework and its associated hooks into the local repository. ```bash pre-commit install ``` -------------------------------- ### Local Development Setup with .env Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/0-INDEX.md Sets up the local development environment by copying an example .env file and then using dotenv-cli to load environment variables. Ensure to edit the .env file with your specific API key and audio directory path. ```bash cp .env.example .env # Edit .env with your OpenAI API key and audio directory path bunx dotenv-cli -- claude ``` -------------------------------- ### Local Development Setup with Claude Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Set up your local environment for Claude by copying the example .env file, editing it with your API keys and audio paths, and then launching Claude with dotenv-cli. ```bash # 1. Create .env file cp .env.example .env # 2. Edit .env with your values # OPENAI_API_KEY=sk-your-key # AUDIO_FILES_PATH=/path/to/audio # 3. Launch Claude with environment variables loaded bunx dotenv-cli -- claude ``` -------------------------------- ### Create and Configure Environment File Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/README.md Copy the example environment file and edit it with your specific API keys and file paths. ```bash cp .env.example .env ``` ```dotenv OPENAI_API_KEY=your_openai_api_key AUDIO_FILES_PATH=/path/to/your/audio/files ``` -------------------------------- ### Example: Get Latest Audio File Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/2-api-reference-tools.md Demonstrates how to call `get_latest_audio` and print its returned file metadata. Requires `FilePathSupportParams` model. ```python from mcp_server_whisper.models import FilePathSupportParams result = await get_latest_audio() print(f"File: {result.file_name}") print(f"Size: {result.size_bytes} bytes") print(f"Duration: {result.duration_seconds} seconds") print(f"Format: {result.format}") print(f"Transcription Support: {result.transcription_support}") print(f"Chat Support: {result.chat_support}") ``` -------------------------------- ### Install MCP Server Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Install the created MCP server script using the mcp command. ```bash mcp install server.py ``` -------------------------------- ### Install MCP with CLI Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Install the MCP package with command-line interface support using uv. ```bash uv add "mcp[cli]" ``` -------------------------------- ### Example .env File Content Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md This is an example of the content expected in the .env file for configuring OpenAI API keys and audio file paths. ```dotenv # OpenAI Configuration OPENAI_API_KEY=sk-proj-xxxxx # Audio Files Directory AUDIO_FILES_PATH=/Users/user/audio_files ``` -------------------------------- ### Handle ConfigurationError in Python Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/5-errors.md Example of how to catch and handle a ConfigurationError when loading configuration. This demonstrates a common pattern for dealing with setup issues. ```python from mcp_server_whisper.config import get_config from mcp_server_whisper.exceptions import ConfigurationError try: config = get_config() except ConfigurationError as e: print(f"Configuration error: {e}") ``` -------------------------------- ### Install MCP (Alternative) Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Install the MCP package using pip. ```bash pip install mcp ``` -------------------------------- ### Install MCP Server Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/CLAUDE.md Install the MCP server, specifying the main server script located at `src/mcp_server_whisper/server.py`. ```bash mcp install src/mcp_server_whisper/server.py ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/README.md Clone the mcp-server-whisper repository and install project dependencies using uv. ```bash git clone https://github.com/arcaputo3/mcp-server-whisper.git cd mcp-server-whisper # Using uv uv sync # Set up pre-commit hooks uv run pre-commit install ``` -------------------------------- ### Create an Echo Server with Resources, Tools, and Prompts Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md This example demonstrates creating an MCP server that can handle messages as resources, tools, and prompts. It requires importing FastMCP from mcp.server.fastmcp. ```python from mcp.server.fastmcp import FastMCP mcp = FastMCP("Echo") @mcp.resource("echo://{message}") def echo_resource(message: str) -> str: """Echo a message as a resource""" return f"Resource echo: {message}" @mcp.tool() def echo_tool(message: str) -> str: """Echo a message as a tool""" return f"Tool echo: {message}" @mcp.prompt() def echo_prompt(message: str) -> str: """Create an echo prompt""" return f"Please process this message: {message}" ``` -------------------------------- ### Set Up FastMCP Server Instance and Main Entry Point Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/9-module-structure.md Initializes the FastMCP server with specified dependencies and defines the main function to register tools and run the server. Use this to start the MCP server. ```python from mcp.server.fastmcp import FastMCP mcp = FastMCP("whisper", dependencies=["openai", "pydub", "aiofiles"]) def main() -> None: """Run main entrypoint.""" from .tools import register_all_tools register_all_tools(mcp) mcp.run() ``` -------------------------------- ### Install MCP Server into Claude Desktop Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Install your server into Claude Desktop using the 'mcp install' command. You can specify a custom name with '--name' or load environment variables from a file using '-f'. ```bash mcp install server.py ``` ```bash mcp install server.py --name "My Analytics Server" ``` ```bash mcp install server.py -v API_KEY=abc123 -v DB_URL=postgres://... ``` ```bash mcp install server.py -f .env ``` -------------------------------- ### Common Audio Files Paths Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Examples of AUDIO_FILES_PATH configurations for different operating systems and common application paths. ```bash # Mac - Screen Recorder by Omi AUDIO_FILES_PATH=/Users/username/Movies/Omi Screen Recorder ``` ```bash # Linux AUDIO_FILES_PATH=/home/username/audio ``` ```bash # Windows AUDIO_FILES_PATH=C:\Users\username\audio ``` -------------------------------- ### Create an SQLite Explorer Server Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md This example shows how to build an MCP server that interacts with an SQLite database. It includes a resource to fetch the schema and a tool to execute SQL queries safely. Ensure you have an 'database.db' file. ```python from mcp.server.fastmcp import FastMCP import sqlite3 mcp = FastMCP("SQLite Explorer") @mcp.resource("schema://main") def get_schema() -> str: """Provide the database schema as a resource""" conn = sqlite3.connect("database.db") schema = conn.execute( "SELECT sql FROM sqlite_master WHERE type='table'" ).fetchall() return "\n".join(sql[0] for sql in schema if sql[0]) @mcp.tool() def query_data(sql: str) -> str: """Execute SQL queries safely""" conn = sqlite3.connect("database.db") try: result = conn.execute(sql).fetchall() return "\n".join(str(row) for row in result) except Exception as e: return f"Error: {str(e)}" ``` -------------------------------- ### Example Usage of apply_all_filters Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/8-domain-layer.md Demonstrates how to use the apply_all_filters method to check if a file matches size and duration criteria. It also shows how files with missing duration information are handled. ```python from mcp_server_whisper.domain import FileFilterSorter sorter = FileFilterSorter() # File matches all filters matches = sorter.apply_all_filters( file_info, min_size_bytes=1_000_000, max_duration_seconds=600 ) # File with duration=None won't match duration filter file_no_duration = FilePathSupportParams( file_name="silent.mp3", duration_seconds=None, ... ) # apply_all_filters with min_duration_seconds will skip this file ``` -------------------------------- ### Run MCP Server in Development Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/CLAUDE.md Start the MCP server in development mode, pointing to the main server script in `src/mcp_server_whisper/server.py`. ```bash mcp dev src/mcp_server_whisper/server.py ``` -------------------------------- ### Example Usage of sort_files Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/8-domain-layer.md Illustrates how to use the sort_files method to sort a list of files by name, size (descending), and duration. ```python from mcp_server_whisper.domain import FileFilterSorter from mcp_server_whisper.constants import SortBy sorter = FileFilterSorter() # Sort by file name ascending sorted_files = sorter.sort_files(files, SortBy.NAME) # Sort by size descending sorted_files = sorter.sort_files(files, SortBy.SIZE, reverse=True) # Sort by duration ascending sorted_files = sorter.sort_files(files, SortBy.DURATION) ``` -------------------------------- ### Initialize and Use pyttsx3 for Text-to-Speech Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/openai-realtime.md This snippet initializes the pyttsx3 TTS engine, sets speaking rate and volume, and speaks the provided assistant reply. It uses the system's default voice and requires the pyttsx3 library to be installed. ```python import pyttsx3 # Initialize TTS engine tts_engine = pyttsx3.init() tts_engine.setProperty('rate', 180) # speaking rate (words per minute) tts_engine.setProperty('volume', 1.0) # volume (0.0 to 1.0) # Speak the assistant's reply tts_engine.say(assistant_reply) tts_engine.runAndWait() ``` -------------------------------- ### MCP Client Session with Stdio Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Connect to MCP servers using the high-level client interface via stdio. Demonstrates initializing the connection, listing prompts, getting prompts, and calling tools. ```python from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client import mcp.types as types # Create server parameters for stdio connection server_params = StdioServerParameters( command="python", # Executable args=["example_server.py"], # Optional command line arguments env=None # Optional environment variables ) # Optional: create a sampling callback async def handle_sampling_message(message: types.CreateMessageRequestParams) -> types.CreateMessageResult: return types.CreateMessageResult( role="assistant", content=types.TextContent( type="text", text="Hello, world! from model", ), model="gpt-3.5-turbo", stopReason="endTurn", ) async def run(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write, sampling_callback=handle_sampling_message) as session: # Initialize the connection await session.initialize() # List available prompts prompts = await session.list_prompts() # Get a prompt prompt = await session.get_prompt("example-prompt", arguments={"arg1": "value"}) # List available resources resources = await session.list_resources() # List available tools tools = await session.list_tools() # Read a resource content, mime_type = await session.read_resource("file://some/path") # Call a tool result = await session.call_tool("tool-name", arguments={"arg1": "value"}) if __name__ == "__main__": import asyncio asyncio.run(run()) ``` -------------------------------- ### Example: List and Filter Audio Files Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/2-api-reference-tools.md Shows how to use `list_audio_files` to find MP3 files larger than 10MB, modified after a specific date, and sorted by size. Requires `SortBy` enum and `FilePathSupportParams` model. ```python from mcp_server_whisper.constants import SortBy from mcp_server_whisper.models import FilePathSupportParams # Find all MP3 files larger than 10MB modified after Jan 1, 2024 files = await list_audio_files( pattern=".*\\.mp3$", min_size_bytes=10_000_000, min_modified_time=1704067200.0, # Jan 1, 2024 UTC format="mp3", sort_by=SortBy.SIZE, reverse=True ) for file_info in files: print(f"{file_info.file_name} ({file_info.size_bytes} bytes, {file_info.duration_seconds}s)") ``` -------------------------------- ### FastMCP Context for Tools and Resources Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Access MCP capabilities within tools and resources using the `Context` object. This example shows how to log information, report progress, and read resources. ```python from mcp.server.fastmcp import FastMCP, Context @mcp.tool() async def long_task(files: list[str], ctx: Context) -> str: """Process multiple files with progress tracking""" for i, file in enumerate(files): ctx.info(f"Processing {file}") await ctx.report_progress(i, len(files)) data, mime_type = await ctx.read_resource(f"file://{file}") return "Processing complete" ``` -------------------------------- ### Register File Tools Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/9-module-structure.md Defines and registers file-related tools with the MCPServer. Includes functions to get the latest audio file and list audio files. ```python def create_file_tools(mcp: MCPServer) -> None: @mcp.tool() async def get_latest_audio() -> FilePathSupportParams: ... @mcp.tool() async def list_audio_files(...) -> list[FilePathSupportParams]: ... ``` -------------------------------- ### Get Application Configuration (Cached Singleton) Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Retrieves the application configuration as a cached singleton. Raises ConfigurationError if essential environment variables are missing or invalid. Uses @lru_cache for efficiency. ```python from mcp_server_whisper.config import get_config from mcp_server_whisper.exceptions import ConfigurationError @lru_cache def get_config() -> WhisperConfig: """Get the application configuration (cached singleton).""" try: return WhisperConfig() except Exception as e: raise ConfigurationError(f"Failed to load configuration: {e}") from e ``` ```python from mcp_server_whisper.config import get_config try: config = get_config() print(f"API Key: {config.openai_api_key[:10]}...") print(f"Audio Path: {config.audio_files_path}") except ConfigurationError as e: print(f"Configuration error: {e}") exit(1) ``` -------------------------------- ### Get Application Configuration Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Retrieves the application configuration. It uses LRU caching to ensure a single instance is returned on repeated calls. Requires OPENAI_API_KEY and AUDIO_FILES_PATH environment variables. ```python from functools import lru_cache from pathlib import Path from src.mcp_server_whisper.config import WhisperConfig, ConfigurationError @lru_cache def get_config() -> WhisperConfig: """Get the application configuration (cached singleton).""" # ... implementation details ... pass ``` -------------------------------- ### Check and Get Audio Path (Legacy) Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Checks if the AUDIO_FILES_PATH environment variable is set and if the path exists. This function is for backward compatibility; use get_config().audio_files_path for new code. Raises ValueError if the variable is not set or the path does not exist. ```python def check_and_get_audio_path() -> Path: """Check if the audio path environment variable is set and exists.""" audio_path_str = os.getenv("AUDIO_FILES_PATH") if not audio_path_str: raise ValueError("AUDIO_FILES_PATH environment variable not set") audio_path = Path(audio_path_str).resolve() if not audio_path.exists(): raise ValueError(f"Audio path does not exist: {audio_path}") return audio_path ``` -------------------------------- ### Load and Verify Configuration Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md This snippet demonstrates how to load and verify the application's configuration, including checking for the API key and audio path validity. It catches specific ConfigurationError and general exceptions. ```python import os from mcp_server_whisper.config import get_config from mcp_server_whisper.exceptions import ConfigurationError # Verify configuration try: config = get_config() print(f"✓ Configuration loaded successfully") print(f"✓ API Key: {config.openai_api_key[:20]}...") print(f"✓ Audio Path: {config.audio_files_path}") # Verify directory is readable files = list(config.audio_files_path.iterdir())[:5] print(f"✓ Found {len(files)} files in audio directory") except ConfigurationError as e: print(f"✗ Configuration error: {e}") except Exception as e: print(f"✗ Unexpected error: {e}") ``` -------------------------------- ### FileSystemRepository Constructor Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Initializes the FileSystemRepository with the path to the audio files directory. ```APIDOC ## FileSystemRepository Constructor ### Description Initializes the FileSystemRepository with the path to the audio files directory. ### Parameters - `audio_files_path` (Path) - Required - Path to directory containing audio files ``` -------------------------------- ### FastMCP Server Initialization Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Demonstrates how to create and configure a FastMCP server instance, including dependency management and lifespan support. ```APIDOC ## FastMCP Server Initialization ### Description Initialize a FastMCP server with a name and optional dependencies. Supports strong typing for application lifespan management during startup and shutdown. ### Method ```python FastMCP(name: str, dependencies: list[str] | None = None, lifespan: Callable[..., AsyncIterator[AppContext]] | None = None) ``` ### Parameters - **name** (str) - Required - The name of the MCP application. - **dependencies** (list[str], optional) - A list of string names for dependencies. - **lifespan** (Callable[..., AsyncIterator[AppContext]], optional) - An asynchronous context manager for managing application lifecycle. ### Request Example ```python # Create a named server mcp = FastMCP("My App") # Specify dependencies for deployment and development mcp = FastMCP("My App", dependencies=["pandas", "numpy"]) # Pass lifespan to server mcp = FastMCP("My App", lifespan=app_lifespan) ``` ``` -------------------------------- ### Get Global Cache Information Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Retrieves statistics about the global cache, including hits and misses. ```python def get_global_cache_info() -> dict[str, int]: """Get cache statistics.""" # ... implementation details ... pass ``` -------------------------------- ### Create and Edit .env File Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Instructions on how to create a .env file from a template and edit it with your specific configuration values. ```bash # Copy from template cp .env.example .env # Edit with your values # Set: # - OPENAI_API_KEY=your_api_key # - AUDIO_FILES_PATH=/path/to/audio ``` -------------------------------- ### Get Relative Filename from Path Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Extracts just the filename from a given path, stripping all directory components. ```python def get_relative_name(self, path: Path) -> str ``` -------------------------------- ### Get File Size Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Retrieves the size of a file in bytes. Raises AudioFileError on stat errors. ```python async def get_file_size(self, file_path: Path) -> int ``` -------------------------------- ### Resource Definition Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Defines how to expose data to LLMs using resources, similar to GET endpoints in a REST API. ```APIDOC ## Resource Definition ### Description Expose data to LLMs using resources. These are intended for retrieving data and should not perform significant computation or have side effects. ### Method ```python @mcp.resource(resource_path: str) def resource_function() -> Any ``` ### Parameters - **resource_path** (str) - Required - The path for the resource, e.g., `"config://app"` or `"users://{user_id}/profile"`. ### Request Example ```python @mcp.resource("config://app") def get_config() -> str: """Static configuration data""" return "App configuration here" @mcp.resource("users://{user_id}/profile") def get_user_profile(user_id: str) -> str: """Dynamic user data""" return f"Profile data for user {user_id}" ``` ``` -------------------------------- ### TranscribeAudioInputParams Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/1-api-reference-models.md Parameters for transcribing audio, extending base parameters with an optional custom prompt for guiding the transcription process. ```APIDOC ## TranscribeAudioInputParams ### Description Parameters for transcribing audio with optional custom prompt. Extends `TranscribeAudioInputParamsBase`. ### Fields - **input_file_path** (Path) - Required - Path to the input audio file to process - **model** (AudioModel) - Optional - Default: "gpt-4o-mini-transcribe" - The transcription model to use - **response_format** (AudioResponseFormat) - Optional - Default: "text" - The response format - **timestamp_granularities** (Optional[list[Literal["word", "segment"]]]) - Optional - Default: None - The timestamp granularities to populate - **prompt** (Optional[str]) - Optional - Default: None - Optional prompt to guide the transcription. Can correct specific words/acronyms, maintain context, enforce punctuation, preserve filler words, or set writing style ``` -------------------------------- ### Create a Simple MCP Server Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md This Python code creates a basic MCP server named 'Demo' using FastMCP, exposing an addition tool and a dynamic greeting resource. ```python # server.py from mcp.server.fastmcp import FastMCP # Create an MCP server mcp = FastMCP("Demo") # Add an addition tool @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b # Add a dynamic greeting resource @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" ``` -------------------------------- ### Initialize Package and Export Main Function Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/9-module-structure.md Defines the package entry point and exports the main server function and version. Used for importing the server's main entry point. ```python from .server import main __version__ = "1.1.0" __all__ = ["main"] ``` -------------------------------- ### Handle TranscriptionAPIError Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/5-errors.md Example of how to catch and handle a TranscriptionAPIError when transcribing audio. This demonstrates checking the error message for specific failure reasons. ```python from mcp_server_whisper.tools.transcription_tools import transcribe_audio from mcp_server_whisper.exceptions import TranscriptionAPIError try: result = await transcribe_audio(input_file_name="meeting.mp3") except TranscriptionAPIError as e: print(f"Transcription failed: {e}") # Check error message for specific issue: # - "API key" → invalid credentials # - "rate limit" → quota exceeded # - "deprecated" → model no longer available ``` -------------------------------- ### TranscribeAudioInputParams Model Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/1-api-reference-models.md Parameters for transcribing audio with an optional custom prompt. Extends TranscribeAudioInputParamsBase and adds a prompt field for guiding transcription. ```python class TranscribeAudioInputParams(TranscribeAudioInputParamsBase): prompt: str | None = None ``` -------------------------------- ### Example Usage of SortBy Enum Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/7-types.md Demonstrates how to use the `SortBy` enum when calling the `list_audio_files` function. The `reverse` parameter can be used for descending order. ```python from mcp_server_whisper.constants import SortBy # Sort by size, descending files = await list_audio_files(sort_by=SortBy.SIZE, reverse=True) # Sort by modification time, ascending files = await list_audio_files(sort_by=SortBy.MODIFIED_TIME) ``` -------------------------------- ### Get Configuration Object Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/0-INDEX.md Retrieves the configuration object for the MCP Server Whisper project. This function provides a cached singleton instance of the configuration. ```python from mcp_server_whisper.config import get_config config = get_config() # Cached singleton # config.openai_api_key # config.audio_files_path ``` -------------------------------- ### FastMCP Server Initialization with Lifespan Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Initialize a FastMCP server with a name and optional dependencies. Supports lifespan management for startup and shutdown tasks, with type-safe context for application resources. ```python from dataclasses import dataclass from typing import AsyncIterator from mcp.server.fastmcp import FastMCP # Create a named server mcp = FastMCP("My App") # Specify dependencies for deployment and development mcp = FastMCP("My App", dependencies=["pandas", "numpy"]) @dataclass class AppContext: db: Database # Replace with your actual DB type @asynccontextmanager async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]: """Manage application lifecycle with type-safe context""" try: # Initialize on startup await db.connect() yield AppContext(db=db) finally: # Cleanup on shutdown await db.disconnect() # Pass lifespan to server mcp = FastMCP("My App", lifespan=app_lifespan) # Access type-safe lifespan context in tools @mcp.tool() def query_db(ctx: Context) -> str: """Tool that uses initialized resources""" db = ctx.request_context.lifespan_context["db"] return db.query() ``` -------------------------------- ### Handle TTS API Errors Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/5-errors.md Example of how to catch a TTSAPIError when creating audio. This pattern is useful for providing user-friendly feedback on TTS generation failures. ```python from mcp_server_whisper.tools.tts_tools import create_audio from mcp_server_whisper.exceptions import TTSAPIError try: result = await create_audio( text_prompt="Hello world", voice="shimmer", speed=1.0 ) except TTSAPIError as e: print(f"TTS generation failed: {e}") ``` -------------------------------- ### Get Latest Audio File Metadata Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/2-api-reference-tools.md Retrieves metadata for the most recently modified audio file. Ensure audio files are present in the designated directory. ```python async def get_latest_audio() -> FilePathSupportParams: pass ``` -------------------------------- ### OpenAIClientWrapper Constructor Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Initializes the OpenAIClientWrapper. It can optionally take an API key, otherwise it defaults to using the environment variable. ```APIDOC ## OpenAIClientWrapper Constructor ### Description Initializes the OpenAIClientWrapper. It can optionally take an API key, otherwise it defaults to using the environment variable. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response None ### Constructor Signature ```python OpenAIClientWrapper(api_key: Optional[str] = None) ``` ### Parameters - **api_key** (Optional[str]) - OpenAI API key. If None, uses environment variable. ``` -------------------------------- ### FastMCP Image Handling Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Utilize the `Image` class for automatic handling of image data within FastMCP tools. This example demonstrates creating a thumbnail from an image file. ```python from mcp.server.fastmcp import FastMCP, Image from PIL import Image as PILImage @mcp.tool() def create_thumbnail(image_path: str) -> Image: """Create a thumbnail from an image""" img = PILImage.open(image_path) img.thumbnail((100, 100)) return Image(data=img.tobytes(), format="png") ``` -------------------------------- ### Define FastMCP Resources Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Expose data to LLMs using resources, similar to GET endpoints. Resources should provide data without significant computation or side effects. ```python @mcp.resource("config://app") def get_config() -> str: """Static configuration data""" return "App configuration here" @mcp.resource("users://{user_id}/profile") def get_user_profile(user_id: str) -> str: """Dynamic user data""" return f"Profile data for user {user_id}" ``` -------------------------------- ### Connect MCP Client to Local Server via StdIO Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-overview.md Use async context managers to connect an MCP client to a local server process. `stdio_client` launches the server and provides streams, while `ClientSession` handles the protocol handshake. Ensures proper resource cleanup. ```python from mcp.client.stdio import stdio_client from mcp import ClientSession # Launch a local MCP server process (e.g., running example_server.py) server_params = StdioServerParameters(command="python", args=["example_server.py"]) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() print("Available tools:", tools) ``` -------------------------------- ### get_config() Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/6-configuration.md Retrieves the application configuration as a cached singleton. It validates essential environment variables like OPENAI_API_KEY and AUDIO_FILES_PATH, and ensures the audio path is a valid directory. Uses LRU caching to return the same configuration instance on repeated calls. ```APIDOC ## get_config() ### Description Get the application configuration as a cached singleton. This function validates critical environment variables and ensures the audio path is correctly set and accessible. ### Method ```python get_config() ``` ### Returns `WhisperConfig` — A validated configuration object. The same instance is returned on repeated calls due to caching. ### Raises `ConfigurationError` — Raised if `OPENAI_API_KEY` or `AUDIO_FILES_PATH` environment variables are missing, if `AUDIO_FILES_PATH` does not exist, if it's not a directory, or if Pydantic validation fails. ### Caching This function utilizes `@lru_cache` to ensure that only one instance of the configuration object is created and reused across all calls. ### Usage Example ```python from mcp_server_whisper.config import get_config from mcp_server_whisper.exceptions import ConfigurationError try: config = get_config() print(f"API Key: {config.openai_api_key[:10]}...") print(f"Audio Path: {config.audio_files_path}") except ConfigurationError as e: print(f"Configuration error: {e}") exit(1) ``` ``` -------------------------------- ### Run MCP Server Directly Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md After setting up the server script, you can run it using either 'python server.py' or 'mcp run server.py'. ```bash python server.py ``` ```bash mcp run server.py ``` -------------------------------- ### Load Audio from Path Method Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/8-domain-layer.md Loads an audio file from disk into memory as an AudioSegment. Runs file reading in a thread pool and detects format from the file extension. ```python @staticmethod async def load_audio_from_path(file_path: Path) -> AudioSegment ``` -------------------------------- ### Define Enhancement Prompts Dictionary Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/7-types.md A dictionary mapping `EnhancementType` to specific prompt strings used for enhancing transcriptions. These prompts guide the AI in generating different styles of transcripts. ```python ENHANCEMENT_PROMPTS: dict[EnhancementType, str] = { "detailed": "The following is a detailed transcript that includes all verbal and non-verbal elements...", "storytelling": "The following is a natural conversation with proper punctuation and flow...", "professional": "The following is a clear, professional transcript with proper capitalization...", "analytical": "The following is a precise technical transcript that preserves speech patterns...", } ``` -------------------------------- ### Claude Desktop Configuration (UVX) Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/README.md Add this JSON configuration to your 'claude_desktop_config.json' for production use with Claude Desktop via UVX. Ensure you replace placeholders for API keys and audio file paths. ```json { "mcpServers": { "whisper": { "command": "uvx", "args": ["mcp-server-whisper"], "env": { "OPENAI_API_KEY": "your_openai_api_key", "AUDIO_FILES_PATH": "/path/to/your/audio/files" } } } } ``` -------------------------------- ### Check and Get Audio Path Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Validates that the AUDIO_FILES_PATH environment variable is set and that the specified directory exists. This function is for backward compatibility and validates the path without full configuration validation. ```python from pathlib import Path def check_and_get_audio_path() -> Path: """Check if audio path environment variable is set and exists.""" # ... implementation details ... pass ``` -------------------------------- ### Low-Level MCP Server Implementation Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-readme.md Directly use the low-level server implementation for full protocol control. Define handlers for listing prompts and retrieving prompt details. ```python from mcp.server.lowlevel import Server, NotificationOptions from mcp.server.models import InitializationOptions import mcp.server.stdio import mcp.types as types # Create a server instance server = Server("example-server") @server.list_prompts() async def handle_list_prompts() -> list[types.Prompt]: return [ types.Prompt( name="example-prompt", description="An example prompt template", arguments=[ types.PromptArgument( name="arg1", description="Example argument", required=True ) ] ) ] @server.get_prompt() async def handle_get_prompt( name: str, arguments: dict[str, str] | None ) -> types.GetPromptResult: if name != "example-prompt": raise ValueError(f"Unknown prompt: {name}") return types.GetPromptResult( description="Example prompt", messages=[ types.PromptMessage( role="user", content=types.TextContent( type="text", text="Example prompt text" ) ) ] ) async def run(): async with mcp.server.stdio.stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, InitializationOptions( server_name="example", server_version="1.0.0", capabilities=server.get_capabilities( notification_options=NotificationOptions(), experimental_capabilities={}, ) ) ) if __name__ == "__main__": import asyncio asyncio.run(run()) ``` -------------------------------- ### Run All Pre-commit Checks Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/CLAUDE.md Execute all configured pre-commit hooks on all files in the repository to ensure code quality and consistency. ```bash pre-commit run --all-files ``` -------------------------------- ### Services Package Export (__init__.py) Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/9-module-structure.md Exports key service classes from the services package, making them available for import. ```python from .audio_service import AudioService from .file_service import FileService from .transcription_service import TranscriptionService from .tts_service import TTSService __all__ = ["AudioService", "FileService", "TranscriptionService", "TTSService"] ``` -------------------------------- ### Transcribe Audio with Custom Prompt Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/0-INDEX.md Transcribes an audio file using a specified model and a custom prompt to guide the transcription of technical content. Ensure the audio file exists and the model is available. ```python result = await transcribe_audio( input_file_name="technical_discussion.mp3", model="gpt-4o-mini-transcribe", prompt="Preserve all technical terms and acronyms exactly as spoken. " "This is a discussion about machine learning, cloud computing, and APIs." ) print(result.text) ``` -------------------------------- ### TranscriptionService Constructor Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/3-api-reference-services.md Initializes the TranscriptionService with necessary repositories and clients. Requires FileSystemRepository, OpenAIClientWrapper, and SecurePathResolver. ```python class TranscriptionService: def __init__( self, file_repo: FileSystemRepository, openai_client: OpenAIClientWrapper, path_resolver: SecurePathResolver ) ``` -------------------------------- ### Format Code with Ruff Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/CLAUDE.md Format the `src` directory according to project style guidelines using `uv` and `ruff format`. ```bash uv run ruff format src ``` -------------------------------- ### transcribe_audio Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/3-api-reference-services.md Transcribes an audio file using OpenAI's transcription API. It supports various models, response formats, and optional prompts for guiding the transcription process. It also allows for specifying timestamp granularities. ```APIDOC ## transcribe_audio ### Description Transcribe audio file using OpenAI's transcription API. ### Method Asynchronous function call (Python) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **filename** (str) - Required - Name of the audio file - **model** (str) - Optional - Default: "gpt-4o-mini-transcribe" - Transcription model - **response_format** (str) - Optional - Default: "text" - Response format (text, json, verbose_json) - **prompt** (Optional[str]) - Optional - None - Optional prompt to guide transcription - **timestamp_granularities** (Optional[list[Literal["word", "segment"]]]) - Optional - None - Timestamp granularities (word, segment) ### Returns `TranscriptionResult` — Transcription with typed fields. ### Raises `TranscriptionAPIError` — If API call fails. ``` -------------------------------- ### Import MCP Utilities Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/mcp-overview.md Import necessary classes from the MCP SDK for server and client implementations. Ensure 'mcp' is added to your project's dependencies. ```python from mcp.server.fastmcp import FastMCP ``` ```python from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client ``` -------------------------------- ### get_config() Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/4-api-reference-infrastructure.md Retrieves the application configuration. This function uses caching to return a singleton instance, ensuring efficiency. It requires specific environment variables to be set for validation. ```APIDOC ## get_config() ### Description Get the application configuration (cached singleton). ### Returns `WhisperConfig` — Validated configuration object. ### Raises `ConfigurationError` — If configuration is invalid or missing. ### Environment Variables - `OPENAI_API_KEY` — OpenAI API key (required) - `AUDIO_FILES_PATH` — Path to audio files directory (required) ### Caching Uses `@lru_cache` to return same instance on repeated calls. ``` -------------------------------- ### Define List Audio Files Input Parameters Model Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/1-api-reference-models.md Parameters for listing and filtering audio files with comprehensive filtering and sorting options. ```python class ListAudioFilesInputParams(BaseModel): pattern: Optional[str] = None min_size_bytes: Optional[int] = None max_size_bytes: Optional[int] = None min_duration_seconds: Optional[float] = None max_duration_seconds: Optional[float] = None min_modified_time: Optional[float] = None max_modified_time: Optional[float] = None format: Optional[str] = None sort_by: SortBy = SortBy.NAME reverse: bool = False ``` -------------------------------- ### FileSystemRepository Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/9-module-structure.md Handles file system I/O operations, including reading, writing, and retrieving metadata for audio files. ```APIDOC ## Class FileSystemRepository ### Description Provides methods for interacting with the file system, specifically for audio files. It supports operations like reading, writing, checking file support, and retrieving file information. ### Methods - `__init__(self, audio_files_path: Path)`: Initializes the FileSystemRepository with a base path for audio files. - `get_audio_file_support(self, file_path: Path) -> FilePathSupportParams`: Checks if a given file path is supported for audio processing. - `get_latest_audio_file(self) -> FilePathSupportParams`: Retrieves information about the most recently added audio file. - `list_audio_files(self, ...) -> list[Path]`: Lists all audio files within the configured directory. - `read_audio_file(self, file_path: Path) -> bytes`: Reads the content of an audio file. - `write_audio_file(self, file_path: Path, content: bytes) -> None`: Writes content to an audio file. - `get_file_size(self, file_path: Path) -> int`: Gets the size of a specified file. ``` -------------------------------- ### Send Text to GPT-4 ChatCompletion API Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/docs/openai-realtime.md Appends user text to conversation history and calls the GPT-4 ChatCompletion API to get a response. Stores the assistant's reply for future context. Use when a full response is acceptable before proceeding. ```python conversation.append({"role": "user", "content": user_text}) response = openai.ChatCompletion.create( model="gpt-4", # or the appropriate GPT-4 model name messages=conversation, temperature=0.7, # adjust as needed max_tokens=500, # limit the response length stream=False # we will demonstrate streaming below ) assistant_reply = response['choices'][0]['message']['content'] conversation.append({"role": "assistant", "content": assistant_reply}) print("🤖 GPT-4:", assistant_reply) ``` -------------------------------- ### Chat with Audio using GPT-4o Models Source: https://github.com/arcaputo3/mcp-server-whisper/blob/main/_autodocs/2-api-reference-tools.md Engage in conversational analysis with audio files using GPT-4o audio models. Supports mp3 and wav formats. You can provide system and user prompts to guide the conversation. Requires `ChatResult` model. ```python async def chat_with_audio( input_file_name: str, model: AudioChatModel = "gpt-4o-audio-preview-2024-12-17", system_prompt: Optional[str] = None, user_prompt: Optional[str] = None, ) -> ChatResult ``` ```python from mcp_server_whisper.models import ChatResult result = await chat_with_audio( input_file_name="podcast.mp3", model="gpt-4o-audio-preview-2024-12-17", system_prompt="You are a podcast analyst. Summarize the key points.", user_prompt="What are the main topics discussed?" ) print(f"Response: {result.text}") ```