├── example.txt ├── requirements.txt ├── .gitignore ├── pyproject.toml ├── .env.example ├── start_mcp_server.sh ├── README.md ├── kokoro_service.py ├── mcp_client.py ├── LICENSE ├── mcp-tts.py └── uv.lock /example.txt: -------------------------------------------------------------------------------- 1 | This is an example text file for testing the Kokoro TTS service. The text-to-speech system will convert this text into spoken audio. -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.2.3 2 | flask-cors==3.0.10 3 | werkzeug==3.1.3 4 | soundfile==0.12.1 5 | numpy>=1.26.0 6 | kokoro_onnx 7 | boto3==1.37.18 8 | fastMCP==0.1.0 9 | python-dotenv==0.21.0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | mp3/ 9 | kokoro-v1.0.onnx 10 | voices-v1.0.bin 11 | frontend/node_modules/ 12 | # Virtual environments 13 | .venv 14 | settings.py 15 | .env -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "kokoro-tts-mcp" 3 | version = "0.1.0" 4 | description = "Kokoro Text to Speech (TTS) MCP Server" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "kokoro-onnx>=0.4.5", 9 | "soundfile>=0.13.1", 10 | "boto3>=1.37.18", 11 | "fastMCP==0.1.0", 12 | "python-dotenv==0.21.0", 13 | "flask==2.2.3", 14 | "flask-cors==3.0.10", 15 | "werkzeug==3.1.3", 16 | "numpy>=1.26.0", 17 | ] 18 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # MCP TTS Server Environment Variables 2 | 3 | # AWS/S3 Settings - These are just placeholders, replace with real values if needed 4 | AWS_ACCESS_KEY_ID=your_access_key_here 5 | AWS_SECRET_ACCESS_KEY=your_secret_key_here 6 | AWS_S3_BUCKET_NAME=your_bucket_name 7 | AWS_S3_REGION=us-east-1 8 | AWS_S3_FOLDER=mp3 9 | # AWS_S3_ENDPOINT_URL=optional_custom_endpoint_url 10 | 11 | # Server Settings 12 | # Note: 0.0.0.0 means "listen on all interfaces" 13 | MCP_HOST=0.0.0.0 14 | MCP_PORT=9876 15 | 16 | # Client Settings - use localhost or 127.0.0.1 to connect to a local server 17 | MCP_CLIENT_HOST=localhost 18 | 19 | # TTS Client Settings 20 | TTS_VOICE=af_heart 21 | TTS_SPEED=1.0 22 | TTS_LANGUAGE=en-us 23 | 24 | # MP3 File Settings 25 | # Path to store MP3 files (default is 'mp3' folder in script directory) 26 | MP3_FOLDER=mp3 27 | # Number of days to keep MP3 files before deletion (optional) 28 | MP3_RETENTION_DAYS=30 29 | # Whether to delete local files after successful S3 upload (optional) 30 | DELETE_LOCAL_AFTER_S3_UPLOAD=false 31 | 32 | # S3 Settings 33 | # Enable or disable S3 uploads (overrides settings.py) 34 | S3_ENABLED=false 35 | # Alternatively, you can disable S3 with DISABLE_S3=true 36 | 37 | # Debug Settings 38 | DEBUG=true -------------------------------------------------------------------------------- /start_mcp_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to start the MCP TTS server 3 | 4 | # Determine the Python command to use 5 | if command -v python3 &>/dev/null; then 6 | PYTHON_CMD="python3" 7 | elif command -v python &>/dev/null; then 8 | PYTHON_CMD="python" 9 | else 10 | echo "Error: No python or python3 command found in PATH" 11 | exit 1 12 | fi 13 | 14 | # Default port 15 | PORT=${MCP_PORT:-9876} 16 | HOST=${MCP_HOST:-0.0.0.0} 17 | DEBUG="" 18 | S3_FLAGS="" 19 | 20 | # Display help message 21 | function show_help() { 22 | echo "Usage: $0 [options]" 23 | echo "" 24 | echo "Options:" 25 | echo " -h, --help Show this help message" 26 | echo " -p, --port PORT Set the server port (default: 9876)" 27 | echo " -b, --bind HOST Set the bind address (default: 0.0.0.0)" 28 | echo " -d, --debug Enable debug mode with additional logging" 29 | echo " --disable-s3 Disable S3 uploads regardless of settings" 30 | echo " --s3-access-key KEY Override S3 access key ID" 31 | echo " --s3-secret-key KEY Override S3 secret access key" 32 | echo " --s3-bucket NAME Override S3 bucket name" 33 | echo " --s3-region REGION Override S3 region" 34 | echo "" 35 | } 36 | 37 | # Parse command line arguments 38 | while [[ $# -gt 0 ]]; do 39 | case "$1" in 40 | -h|--help) 41 | show_help 42 | exit 0 43 | ;; 44 | -p|--port) 45 | PORT="$2" 46 | shift 2 47 | ;; 48 | -b|--bind) 49 | HOST="$2" 50 | shift 2 51 | ;; 52 | -d|--debug) 53 | DEBUG="--debug" 54 | shift 55 | ;; 56 | --disable-s3) 57 | S3_FLAGS="$S3_FLAGS --disable-s3" 58 | shift 59 | ;; 60 | --s3-access-key) 61 | S3_FLAGS="$S3_FLAGS --s3-access-key $2" 62 | shift 2 63 | ;; 64 | --s3-secret-key) 65 | S3_FLAGS="$S3_FLAGS --s3-secret-key $2" 66 | shift 2 67 | ;; 68 | --s3-bucket) 69 | S3_FLAGS="$S3_FLAGS --s3-bucket $2" 70 | shift 2 71 | ;; 72 | --s3-region) 73 | S3_FLAGS="$S3_FLAGS --s3-region $2" 74 | shift 2 75 | ;; 76 | *) 77 | echo "Unknown option: $1" 78 | show_help 79 | exit 1 80 | ;; 81 | esac 82 | done 83 | 84 | echo "Starting MCP TTS Server..." 85 | echo "Using Python: $PYTHON_CMD" 86 | echo "Host: $HOST" 87 | echo "Port: $PORT" 88 | if [ -n "$DEBUG" ]; then 89 | echo "Debug mode: enabled" 90 | fi 91 | 92 | # Start the server 93 | $PYTHON_CMD mcp_tts_server.py --host "$HOST" --port "$PORT" $DEBUG $S3_FLAGS 94 | 95 | # Check exit code 96 | if [ $? -ne 0 ]; then 97 | echo "Error: MCP TTS Server failed to start" 98 | exit 1 99 | fi 100 | 101 | # If the server process exits, print a message 102 | echo "MCP TTS Server stopped." -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Kokoro Text to Speech Server MCP server 3 | 4 | 5 | ## Kokoro Text to Speech (TTS) MCP Server 6 | 7 | Kokoro Text to Speech MCP server that generates .mp3 files with option to upload to S3. 8 | 9 | Uses: https://huggingface.co/spaces/hexgrad/Kokoro-TTS 10 | 11 | ## Configuration 12 | 13 | * Clone to a local repo. 14 | * Download the [Kokoro Onnx Weights](https://github.com/thewh1teagle/kokoro-onnx) for [kokoro-v1.0.onnx](https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx) and [voices-v1.0.bin](https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/voices-v1.0.bin) and store in the same repo. 15 | 16 | Add the following to your MCP configs. Update with your own values. 17 | 18 | ``` 19 | "kokoro-tts-mcp": { 20 | "command": "uv", 21 | "args": [ 22 | "--directory", 23 | "/path/toyourlocal/kokoro-tts-mcp", 24 | "run", 25 | "mcp-tts.py" 26 | ], 27 | "env": { 28 | "TTS_VOICE": "af_heart", 29 | "TTS_SPEED": "1.0", 30 | "TTS_LANGUAGE": "en-us", 31 | "AWS_ACCESS_KEY_ID": "", 32 | "AWS_SECRET_ACCESS_KEY": "", 33 | "AWS_REGION": "us-east-1", 34 | "AWS_S3_FOLDER": "mp3", 35 | "S3_ENABLED": "true", 36 | "MP3_FOLDER": "/path/to/mp3" 37 | } 38 | } 39 | ``` 40 | 41 | ### Install ffmmeg 42 | 43 | This is needed to convert .wav to .mp3 files 44 | 45 | For mac: 46 | 47 | ``` 48 | brew install ffmpeg 49 | ``` 50 | 51 | To run locally add these to your .env file. See env.example and copy to .env and modify with your own values. 52 | 53 | ### Supported Environment Variables 54 | 55 | - `AWS_ACCESS_KEY_ID`: Your AWS access key ID 56 | - `AWS_SECRET_ACCESS_KEY`: Your AWS secret access key 57 | - `AWS_S3_BUCKET_NAME`: S3 bucket name 58 | - `AWS_S3_REGION`: S3 region (e.g., us-east-1) 59 | - `AWS_S3_FOLDER`: Folder path within the S3 bucket 60 | - `AWS_S3_ENDPOINT_URL`: Optional custom endpoint URL for S3-compatible storage 61 | - `MCP_HOST`: Host to bind the server to (default: 0.0.0.0) 62 | - `MCP_PORT`: Port to listen on (default: 9876) 63 | - `MCP_CLIENT_HOST`: Hostname for client connections to the server (default: localhost) 64 | - `DEBUG`: Enable debug mode (set to "true" or "1") 65 | - `S3_ENABLED`: Enable S3 uploads (set to "true" or "1") 66 | - `MP3_FOLDER`: Path to store MP3 files (default is 'mp3' folder in script directory) 67 | - `MP3_RETENTION_DAYS`: Number of days to keep MP3 files before automatic deletion 68 | - `DELETE_LOCAL_AFTER_S3_UPLOAD`: Whether to delete local MP3 files after successful S3 upload (set to "true" or "1") 69 | - `TTS_VOICE`: Default voice for the TTS client (default: af_heart) 70 | - `TTS_SPEED`: Default speed for the TTS client (default: 1.0) 71 | - `TTS_LANGUAGE`: Default language for the TTS client (default: en-us) 72 | 73 | ## Running the Server Locally 74 | 75 | Preferred method use UV 76 | ``` 77 | uv run mcp-tts.py 78 | ``` 79 | 80 | 81 | ## Using the TTS Client 82 | 83 | The `mcp_client.py` script allows you to send TTS requests to the server. It can be used as follows: 84 | 85 | ### Connection Settings 86 | 87 | When running the server and client on the same machine: 88 | - Server should bind to `0.0.0.0` (all interfaces) or `127.0.0.1` (localhost only) 89 | - Client should connect to `localhost` or `127.0.0.1` 90 | 91 | 92 | ### Basic Usage 93 | 94 | ```bash 95 | python mcp_client.py --text "Hello, world!" 96 | ``` 97 | 98 | ### Reading Text from a File 99 | 100 | ```bash 101 | python mcp_client.py --file my_text.txt 102 | ``` 103 | 104 | ### Customizing Voice and Speed 105 | 106 | ```bash 107 | python mcp_client.py --text "Hello, world!" --voice "en_female" --speed 1.2 108 | ``` 109 | 110 | ### Disabling S3 Upload 111 | 112 | ```bash 113 | python mcp_client.py --text "Hello, world!" --no-s3 114 | ``` 115 | 116 | ### Command-line Options 117 | 118 | ```bash 119 | python mcp_client.py --help 120 | ``` 121 | 122 | ## MP3 File Management 123 | 124 | The TTS server generates MP3 files that are stored locally and optionally uploaded to S3. You can configure how these files are managed: 125 | 126 | ### Local Storage 127 | 128 | - Set `MP3_FOLDER` in your `.env` file to specify where MP3 files are stored 129 | - Files are kept in this folder unless automatically deleted 130 | 131 | ### Automatic Cleanup 132 | 133 | - Set `MP3_RETENTION_DAYS=30` (or any number) to automatically delete files older than that number of days 134 | - Set `DELETE_LOCAL_AFTER_S3_UPLOAD=true` to delete local files immediately after successful S3 upload 135 | 136 | ### S3 Integration 137 | 138 | - Enable/disable S3 uploads with `S3_ENABLED=true` or `DISABLE_S3=true` 139 | - Configure AWS credentials and bucket settings in the `.env` file 140 | - S3 uploads can be disabled per-request using the client's `--no-s3` option 141 | -------------------------------------------------------------------------------- /kokoro_service.py: -------------------------------------------------------------------------------- 1 | import soundfile as sf 2 | from kokoro_onnx import Kokoro 3 | import re 4 | import os 5 | import subprocess 6 | from dotenv import load_dotenv 7 | 8 | load_dotenv() 9 | 10 | class KokoroTTSService: 11 | def __init__(self, model_path="kokoro-v1.0.onnx", voices_path="voices-v1.0.bin"): 12 | """Initialize the Kokoro TTS service.""" 13 | try: 14 | self.kokoro = Kokoro(model_path, voices_path) 15 | self.available = True 16 | except Exception as e: 17 | print(f"Error initializing Kokoro TTS: {e}") 18 | self.available = False 19 | 20 | def get_voices(self): 21 | """Return a list of available voices.""" 22 | if self.available: 23 | return self.kokoro.get_voices() 24 | else: 25 | # Return default voices if Kokoro is not available 26 | return ["af_heart", "en_us_male", "en_us_female"] 27 | 28 | def generate_audio(self, text, voice="af_heart", speed=1.0, lang="en-us", 29 | output_file="audio.mp3", output_dir="mp3"): 30 | """Generate audio from text using Kokoro TTS.""" 31 | # Clean up the text (remove markdown links) 32 | text = self._remove_markdown_links(text) 33 | 34 | # Create output directory if it doesn't exist 35 | os.makedirs(output_dir, exist_ok=True) 36 | 37 | # Ensure output filename has the correct extension 38 | if not output_file.lower().endswith('.mp3'): 39 | output_file = f"{os.path.splitext(output_file)[0]}.mp3" 40 | 41 | if not self.available: 42 | # Use fallback TTS method 43 | return self._generate_with_fallback(text, output_file, output_dir) 44 | 45 | try: 46 | # Create full file paths 47 | base_filename = os.path.splitext(output_file)[0] 48 | wav_file = os.path.join(output_dir, f"{base_filename}.wav") 49 | mp3_file = os.path.join(output_dir, output_file) 50 | 51 | # Generate audio 52 | samples, sample_rate = self.kokoro.create( 53 | text, voice=voice, speed=speed, lang=lang 54 | ) 55 | 56 | # Write audio to WAV file first 57 | sf.write(wav_file, samples, sample_rate) 58 | 59 | # Convert WAV to MP3 60 | success = self._convert_wav_to_mp3(wav_file, mp3_file) 61 | 62 | # Clean up the WAV file 63 | if success and os.path.exists(wav_file): 64 | os.remove(wav_file) 65 | 66 | return { 67 | "success": success, 68 | "mp3_file": mp3_file if success else None 69 | } 70 | 71 | except Exception as e: 72 | print(f"Error generating audio with Kokoro: {e}") 73 | return self._generate_with_fallback(text, output_file, output_dir) 74 | 75 | def _generate_with_fallback(self, text, output_file, output_dir): 76 | """Use system TTS as a fallback method.""" 77 | try: 78 | # Create full file paths 79 | base_filename = os.path.splitext(output_file)[0] 80 | wav_file = os.path.join(output_dir, f"{base_filename}.wav") 81 | mp3_file = os.path.join(output_dir, output_file) 82 | 83 | # Use macOS 'say' command or other system TTS 84 | cmd = ['say', '-o', wav_file, text] 85 | subprocess.run(cmd, check=True, capture_output=True, text=True) 86 | 87 | # Convert to MP3 88 | success = self._convert_wav_to_mp3(wav_file, mp3_file) 89 | 90 | # Clean up WAV file 91 | if success and os.path.exists(wav_file): 92 | os.remove(wav_file) 93 | 94 | return { 95 | "success": success, 96 | "mp3_file": mp3_file if success else None 97 | } 98 | 99 | except Exception as e: 100 | print(f"Error with fallback TTS: {e}") 101 | return { 102 | "success": False, 103 | "mp3_file": None 104 | } 105 | 106 | def _remove_markdown_links(self, text): 107 | """Remove markdown links from text.""" 108 | # Remove inline links like [text](url) 109 | text = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', text) 110 | # Remove reference-style links like [text][ref] 111 | text = re.sub(r'\[([^\]]+)\]\[[^\]]*\]', r'\1', text) 112 | # Remove reference link definitions like [ref]: url 113 | text = re.sub(r'^\s*\[[^\]]+\]:\s*.*$', '', text, flags=re.MULTILINE) 114 | return text 115 | 116 | def _convert_wav_to_mp3(self, wav_file, mp3_file): 117 | """Convert WAV file to MP3 using ffmpeg.""" 118 | try: 119 | cmd = ['ffmpeg', '-y', '-i', wav_file, '-codec:a', 'libmp3lame', '-qscale:a', '2', mp3_file] 120 | subprocess.run(cmd, check=True, capture_output=True, text=True) 121 | return True 122 | except Exception as e: 123 | print(f"Error converting to MP3: {e}") 124 | return False -------------------------------------------------------------------------------- /mcp_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import asyncio 5 | import json 6 | import os 7 | import sys 8 | import time 9 | from dotenv import load_dotenv 10 | 11 | # Load environment variables from .env file 12 | load_dotenv() 13 | 14 | async def send_tts_request(host, port, text, voice, speed, language, filename, upload_to_s3=True): 15 | """Send a TTS request to the MCP server""" 16 | try: 17 | # Connect to the server 18 | reader, writer = await asyncio.open_connection(host, port) 19 | 20 | # Create the request 21 | request = { 22 | "text": text, 23 | "voice": voice, 24 | "speed": speed, 25 | "lang": language, 26 | "upload_to_s3": upload_to_s3 27 | } 28 | 29 | # Add filename if provided 30 | if filename: 31 | request["filename"] = filename 32 | 33 | # Encode the request as JSON 34 | request_json = json.dumps(request) 35 | 36 | # Send the request 37 | print(f"Sending request to {host}:{port}...") 38 | print(f"Request: {request_json}") 39 | writer.write(request_json.encode('utf-8')) 40 | await writer.drain() 41 | 42 | # Read the response 43 | print("Waiting for response...") 44 | data = await reader.read(4096) 45 | response = json.loads(data.decode('utf-8')) 46 | 47 | # Close the connection 48 | writer.close() 49 | await writer.wait_closed() 50 | 51 | # Return the response 52 | return response 53 | 54 | except ConnectionRefusedError: 55 | print(f"Error: Could not connect to MCP TTS Server at {host}:{port}") 56 | print("Please make sure the server is running.") 57 | return None 58 | except Exception as e: 59 | print(f"Error: {str(e)}") 60 | return None 61 | 62 | def print_response(response): 63 | """Print the server response in a human-readable format""" 64 | if response is None: 65 | return 66 | 67 | print("\n=== TTS Response ===") 68 | if response.get("success", False): 69 | print("✅ Success: Audio generated successfully") 70 | print(f"📁 Filename: {response.get('filename', 'Unknown')}") 71 | print(f"📊 File size: {response.get('file_size', 0)} bytes") 72 | 73 | if response.get("s3_uploaded", False): 74 | print("☁️ S3 Upload: Success") 75 | print(f"🔗 S3 URL: {response.get('s3_url', 'Not available')}") 76 | elif "s3_uploaded" in response and not response["s3_uploaded"]: 77 | print("☁️ S3 Upload: Failed") 78 | print(f"❌ Error: {response.get('s3_error', 'Unknown error')}") 79 | else: 80 | print("☁️ S3 Upload: Not requested") 81 | else: 82 | print("❌ Error: TTS generation failed") 83 | print(f"Error message: {response.get('error', 'Unknown error')}") 84 | 85 | print("=====================\n") 86 | 87 | def read_text_file(file_path): 88 | """Read text from a file""" 89 | try: 90 | with open(file_path, 'r', encoding='utf-8') as file: 91 | return file.read() 92 | except Exception as e: 93 | print(f"Error reading file {file_path}: {str(e)}") 94 | sys.exit(1) 95 | 96 | def main(): 97 | # Parse command line arguments 98 | parser = argparse.ArgumentParser(description="MCP TTS Client") 99 | 100 | # Server connection - Important: for connecting to a local server, use "localhost" or "127.0.0.1", not "0.0.0.0" 101 | parser.add_argument("--host", default=os.environ.get("MCP_CLIENT_HOST", "localhost"), 102 | help="MCP server hostname (default: localhost or MCP_CLIENT_HOST env var)") 103 | parser.add_argument("--port", type=int, default=int(os.environ.get("MCP_PORT", "9876")), 104 | help="MCP server port (default: 9876 or MCP_PORT env var)") 105 | 106 | # TTS parameters 107 | parser.add_argument("--text", default=None, 108 | help="Text to synthesize") 109 | parser.add_argument("--file", default=None, 110 | help="Text file to read content from") 111 | parser.add_argument("--voice", default=os.environ.get("TTS_VOICE", "af_heart"), 112 | help="Voice to use (default: af_heart or TTS_VOICE env var)") 113 | parser.add_argument("--speed", type=float, default=float(os.environ.get("TTS_SPEED", "1.0")), 114 | help="Speech speed (default: 1.0 or TTS_SPEED env var)") 115 | parser.add_argument("--language", default=os.environ.get("TTS_LANGUAGE", "en-us"), 116 | help="Language code (default: en-us or TTS_LANGUAGE env var)") 117 | parser.add_argument("--filename", default=None, 118 | help="Output filename (default: auto-generated)") 119 | 120 | # S3 options 121 | parser.add_argument("--no-s3", action="store_true", 122 | help="Disable S3 upload (enabled by default)") 123 | 124 | # Debug options 125 | parser.add_argument("--raw", action="store_true", 126 | help="Print raw JSON response") 127 | 128 | args = parser.parse_args() 129 | 130 | # Check for text input 131 | if args.text is None and args.file is None: 132 | parser.error("Either --text or --file is required") 133 | 134 | # Read text from file if specified 135 | if args.file: 136 | text = read_text_file(args.file) 137 | else: 138 | text = args.text 139 | 140 | # Run the request 141 | response = asyncio.run(send_tts_request( 142 | host=args.host, 143 | port=args.port, 144 | text=text, 145 | voice=args.voice, 146 | speed=args.speed, 147 | language=args.language, 148 | filename=args.filename, 149 | upload_to_s3=not args.no_s3 150 | )) 151 | 152 | # Print the response 153 | if response: 154 | if args.raw: 155 | print(json.dumps(response, indent=2)) 156 | else: 157 | print_response(response) 158 | 159 | if __name__ == "__main__": 160 | main() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /mcp-tts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import time 4 | import json 5 | import asyncio 6 | from werkzeug.utils import secure_filename 7 | import boto3 8 | from botocore.exceptions import ClientError 9 | import argparse 10 | import uuid 11 | from dotenv import load_dotenv 12 | import datetime 13 | import shutil 14 | 15 | # Load environment variables from .env file 16 | load_dotenv() 17 | 18 | # Create default settings object to replace settings.py 19 | class Settings: 20 | def __init__(self): 21 | self.S3_SETTINGS = { 22 | "enabled": False, # Default to disabled 23 | "bucket_name": None, 24 | "region": None, 25 | "folder": "mp3", 26 | "access_key_id": None, 27 | "secret_access_key": None, 28 | "endpoint_url": None 29 | } 30 | 31 | # Initialize settings object 32 | settings = Settings() 33 | 34 | # Function to check if running on Claude Desktop and load config 35 | def load_claude_desktop_config(): 36 | """ 37 | Check if running on Claude Desktop and load config from claude_desktop_config.json 38 | Returns True if config was loaded from Claude Desktop, False otherwise 39 | """ 40 | # Check if we're running on Claude Desktop (you might need to adjust this check) 41 | claude_desktop_config_path = os.path.expanduser("~/claude_desktop_config.json") 42 | 43 | if os.path.exists(claude_desktop_config_path): 44 | try: 45 | print(f"Claude Desktop config found at {claude_desktop_config_path}, loading...") 46 | with open(claude_desktop_config_path, 'r') as config_file: 47 | config = json.load(config_file) 48 | 49 | # Load environment variables from the config 50 | if 'environment' in config: 51 | for key, value in config['environment'].items(): 52 | os.environ[key] = str(value) 53 | print(f"Loaded environment variable from Claude Desktop config: {key}") 54 | 55 | return True 56 | except Exception as e: 57 | print(f"Error loading Claude Desktop config: {e}") 58 | 59 | return False 60 | 61 | # Try to load config from Claude Desktop first, fall back to .env if not found 62 | if not load_claude_desktop_config(): 63 | # Load environment variables from .env file 64 | print("Loading environment variables from .env file") 65 | load_dotenv() 66 | 67 | # Import the fastMCP SDK (make sure it's installed and on your PYTHONPATH) 68 | from mcp.server.fastmcp import FastMCP 69 | 70 | # Only attempt to import the KokoroTTSService if it's available 71 | try: 72 | from kokoro_service import KokoroTTSService 73 | # Initialize TTS service 74 | tts_service = KokoroTTSService() 75 | TTS_AVAILABLE = True 76 | except ImportError: 77 | print("WARNING: kokoro_service module not found. TTS functionality will be disabled.") 78 | tts_service = None 79 | TTS_AVAILABLE = False 80 | 81 | # Configure paths 82 | ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) 83 | MP3_FOLDER = os.environ.get('MP3_FOLDER', os.path.join(ROOT_DIR, 'mp3')) 84 | os.makedirs(MP3_FOLDER, exist_ok=True) 85 | 86 | class MCPTTSServer: 87 | """ 88 | Model Context Protocol (MCP) server for Kokoro TTS service. 89 | Processes JSON requests with text-to-speech parameters. 90 | 91 | Expected JSON request example: 92 | { 93 | "text": "Text to convert to speech", 94 | "voice": "voice_id", # Optional; default: "af_heart" 95 | "speed": 1.0, # Optional; default: 1.0 96 | "lang": "en-us", # Optional; default: "en-us" 97 | "filename": "output.mp3", # Optional; a UUID will be generated if not provided 98 | "upload_to_s3": true # Optional; defaults to true if S3 is enabled 99 | } 100 | 101 | The response will include file details and (if enabled) an S3 URL. 102 | """ 103 | def __init__(self, host='0.0.0.0', port=9876): 104 | self.host = host 105 | self.port = port 106 | 107 | # Validate S3 settings at startup 108 | self.s3_enabled = False 109 | self.s3_client = None 110 | self.validate_s3_settings() 111 | 112 | # Clean up old MP3 files if retention period is set 113 | self.cleanup_old_mp3_files() 114 | 115 | def cleanup_old_mp3_files(self): 116 | """Clean up MP3 files older than the retention period.""" 117 | retention_days_str = os.environ.get('MP3_RETENTION_DAYS') 118 | if not retention_days_str: 119 | return 120 | 121 | try: 122 | retention_days = int(retention_days_str) 123 | if retention_days <= 0: 124 | print(f"MP3 file retention disabled (MP3_RETENTION_DAYS={retention_days})") 125 | return 126 | 127 | print(f"Cleaning up MP3 files older than {retention_days} days...") 128 | now = datetime.datetime.now() 129 | cutoff_date = now - datetime.timedelta(days=retention_days) 130 | 131 | files_removed = 0 132 | for filename in os.listdir(MP3_FOLDER): 133 | if not filename.endswith('.mp3'): 134 | continue 135 | 136 | file_path = os.path.join(MP3_FOLDER, filename) 137 | file_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(file_path)) 138 | 139 | if file_mtime < cutoff_date: 140 | try: 141 | os.remove(file_path) 142 | files_removed += 1 143 | except Exception as e: 144 | print(f"Error removing old MP3 file {file_path}: {e}") 145 | 146 | if files_removed > 0: 147 | print(f"Removed {files_removed} MP3 files older than {retention_days} days") 148 | else: 149 | print(f"No MP3 files older than {retention_days} days found") 150 | 151 | except ValueError: 152 | print(f"Invalid MP3_RETENTION_DAYS value: {retention_days_str}") 153 | except Exception as e: 154 | print(f"Error during MP3 cleanup: {e}") 155 | 156 | def validate_s3_settings(self): 157 | """Validate S3 settings and create client if enabled.""" 158 | try: 159 | # Check if S3 is explicitly disabled via environment variable 160 | if os.environ.get('DISABLE_S3', '').lower() in ('true', '1', 'yes'): 161 | print("S3 uploads are disabled via DISABLE_S3 environment variable") 162 | return 163 | 164 | # Check if S3 is explicitly enabled via environment variable 165 | s3_enabled_env = os.environ.get('S3_ENABLED', '').lower() 166 | if s3_enabled_env in ('false', '0', 'no'): 167 | print("S3 uploads are disabled via S3_ENABLED environment variable") 168 | return 169 | 170 | # If S3_ENABLED is not explicitly set to true, disable S3 171 | if not (s3_enabled_env in ('true', '1', 'yes')): 172 | print("S3 uploads are disabled (S3_ENABLED not set to true)") 173 | return 174 | 175 | print("Validating S3 settings...") 176 | # Get settings from environment variables 177 | bucket_name = os.environ.get('AWS_S3_BUCKET_NAME') 178 | region = os.environ.get('AWS_S3_REGION') 179 | folder = os.environ.get('AWS_S3_FOLDER', 'mp3') 180 | endpoint_url = os.environ.get('AWS_S3_ENDPOINT_URL') 181 | 182 | if not bucket_name: 183 | print("ERROR: S3 bucket name is not configured (AWS_S3_BUCKET_NAME)") 184 | return 185 | 186 | if not region: 187 | print("ERROR: S3 region is not configured (AWS_S3_REGION)") 188 | return 189 | 190 | try: 191 | # Get AWS credentials from environment variables 192 | aws_access_key_id = os.environ.get('AWS_ACCESS_KEY_ID') 193 | if not aws_access_key_id: 194 | print("ERROR: AWS_ACCESS_KEY_ID not found in environment (.env)") 195 | return 196 | else: 197 | print("Using AWS access key from environment variables (.env)") 198 | 199 | aws_secret_access_key = os.environ.get('AWS_SECRET_ACCESS_KEY') 200 | if not aws_secret_access_key: 201 | print("ERROR: AWS_SECRET_ACCESS_KEY not found in environment (.env)") 202 | return 203 | else: 204 | print("Using AWS secret key from environment variables (.env)") 205 | 206 | print(f"Creating S3 client with: region={region}, endpoint_url={endpoint_url}") 207 | session = boto3.Session( 208 | aws_access_key_id=aws_access_key_id, 209 | aws_secret_access_key=aws_secret_access_key, 210 | region_name=region 211 | ) 212 | 213 | self.s3_client = session.client( 214 | 's3', 215 | endpoint_url=endpoint_url 216 | ) 217 | 218 | print(f"Testing S3 connection to bucket '{bucket_name}'...") 219 | self.s3_client.head_bucket(Bucket=bucket_name) 220 | 221 | print("✅ S3 connection validated successfully") 222 | self.s3_enabled = True 223 | print(f"S3 uploads enabled to bucket: {bucket_name}") 224 | print(f"S3 folder: {folder}") 225 | 226 | except ClientError as e: 227 | error_code = e.response.get('Error', {}).get('Code') 228 | if error_code == '403': 229 | print(f"ERROR: No permission to access S3 bucket '{bucket_name}'") 230 | elif error_code == '404': 231 | print(f"ERROR: S3 bucket '{bucket_name}' does not exist") 232 | else: 233 | print(f"ERROR: S3 client failed: {str(e)}") 234 | import traceback 235 | traceback.print_exc() 236 | return 237 | 238 | except Exception as e: 239 | print(f"ERROR initializing S3 settings: {str(e)}") 240 | import traceback 241 | traceback.print_exc() 242 | 243 | def upload_to_s3(self, file_path, object_name=None): 244 | """Upload a file to the S3 bucket and return the file's URL.""" 245 | print(f"Starting S3 upload process for {file_path}") 246 | if not self.s3_enabled or not self.s3_client: 247 | print("S3 uploads are disabled or failed to initialize") 248 | return None 249 | 250 | if object_name is None: 251 | object_name = os.path.basename(file_path) 252 | 253 | # Get settings from environment variables 254 | bucket_name = os.environ.get('AWS_S3_BUCKET_NAME') 255 | folder = os.environ.get('AWS_S3_FOLDER', 'mp3') 256 | 257 | if folder and not folder.endswith('/'): 258 | folder += '/' 259 | 260 | s3_path = folder + object_name 261 | print(f"Uploading to S3: bucket={bucket_name}, key={s3_path}") 262 | 263 | try: 264 | print(f"Uploading file {file_path} to S3...") 265 | self.s3_client.upload_file(file_path, bucket_name, s3_path) 266 | print("✅ File successfully uploaded to S3") 267 | 268 | # Get endpoint URL and region from environment variables 269 | endpoint = os.environ.get('AWS_S3_ENDPOINT_URL') 270 | region = os.environ.get('AWS_S3_REGION') 271 | 272 | if endpoint: 273 | s3_url = f"{endpoint}/{bucket_name}/{s3_path}" 274 | else: 275 | s3_url = f"https://{bucket_name}.s3.{region}.amazonaws.com/{s3_path}" 276 | 277 | print(f"Generated S3 URL: {s3_url}") 278 | return s3_url 279 | 280 | except ClientError as e: 281 | print(f"ERROR: S3 upload failed: {str(e)}") 282 | import traceback 283 | traceback.print_exc() 284 | return None 285 | 286 | async def process_tts_request(self, request_data): 287 | """Process a TTS request and return a JSON response.""" 288 | try: 289 | if not TTS_AVAILABLE: 290 | return { 291 | "success": False, 292 | "error": "TTS service is not available. Missing required modules." 293 | } 294 | 295 | text = request_data.get('text', '') 296 | voice = request_data.get('voice', os.environ.get('TTS_VOICE', 'af_heart')) 297 | speed = float(request_data.get('speed', 1.0)) 298 | lang = request_data.get('lang', 'en-us') 299 | filename = request_data.get('filename', None) 300 | upload_to_s3_flag = request_data.get('upload_to_s3', True) 301 | 302 | if not text: 303 | return {"success": False, "error": "No text provided"} 304 | 305 | if not filename: 306 | filename = str(uuid.uuid4()) 307 | 308 | if not filename.endswith('.mp3'): 309 | filename += '.mp3' 310 | 311 | filename = secure_filename(filename) 312 | os.makedirs(MP3_FOLDER, exist_ok=True) 313 | mp3_path = os.path.join(MP3_FOLDER, filename) 314 | mp3_filename = os.path.basename(mp3_path) 315 | 316 | print(f"Generating audio for: {text[:50]}{'...' if len(text) > 50 else ''}") 317 | print(f"Using voice: {voice}, speed: {speed}, language: {lang}") 318 | print(f"Output file: {mp3_path}") 319 | 320 | loop = asyncio.get_running_loop() 321 | 322 | try: 323 | # Attempt primary parameter format 324 | result = await loop.run_in_executor( 325 | None, 326 | lambda: tts_service.generate_audio( 327 | text=text, 328 | output_file=mp3_path, 329 | voice=voice, 330 | speed=speed, 331 | lang=lang 332 | ) 333 | ) 334 | 335 | if isinstance(result, dict) and not result.get('success', True): 336 | print(f"TTS service returned an error: {result}") # Log the result for debugging 337 | return { 338 | "success": False, 339 | "error": result.get('error', 'Unknown TTS generation error'), 340 | "tts_result": result, # Include full TTS service response 341 | "request_params": { 342 | "text": text, 343 | "voice": voice, 344 | "speed": speed, 345 | "lang": lang, 346 | "filename": filename 347 | }, 348 | "timestamp": datetime.datetime.now().isoformat() 349 | } 350 | 351 | except TypeError as e: 352 | print(f"TypeError in TTS service call: {e}") 353 | print("Trying alternative parameter format...") 354 | result = await loop.run_in_executor( 355 | None, 356 | lambda: tts_service.generate_audio( 357 | text, 358 | mp3_path, 359 | voice=voice, 360 | speed=speed 361 | ) 362 | ) 363 | 364 | if not os.path.exists(mp3_path): 365 | return { 366 | "success": False, 367 | "error": "Failed to generate audio file" 368 | } 369 | 370 | file_size = os.path.getsize(mp3_path) 371 | print(f"Audio generated successfully. File size: {file_size} bytes") 372 | 373 | response_data = { 374 | "success": True, 375 | "message": "Audio generated successfully", 376 | "filename": mp3_filename, 377 | "file_size": file_size, 378 | "path": mp3_path, 379 | "s3_uploaded": False 380 | } 381 | 382 | if upload_to_s3_flag: 383 | print(f"Uploading {mp3_filename} to S3...") 384 | s3_url = self.upload_to_s3(mp3_path, mp3_filename) 385 | if s3_url: 386 | response_data["s3_uploaded"] = True 387 | response_data["s3_url"] = s3_url 388 | 389 | # Delete local file if configured to do so 390 | if os.environ.get('DELETE_LOCAL_AFTER_S3_UPLOAD', '').lower() in ('true', '1', 'yes'): 391 | try: 392 | print(f"Removing local file {mp3_path} after successful S3 upload") 393 | os.remove(mp3_path) 394 | response_data["local_file_kept"] = False 395 | except Exception as e: 396 | print(f"Error removing local file after S3 upload: {e}") 397 | response_data["local_file_kept"] = True 398 | else: 399 | response_data["local_file_kept"] = True 400 | else: 401 | response_data["s3_uploaded"] = False 402 | response_data["s3_error"] = "S3 upload failed" 403 | 404 | return response_data 405 | 406 | except Exception as e: 407 | print(f"Error processing TTS request: {str(e)}") 408 | import traceback 409 | traceback.print_exc() 410 | return { 411 | "success": False, 412 | "error": str(e) 413 | } 414 | 415 | def main(): 416 | parser = argparse.ArgumentParser(description="MCP TTS Server") 417 | parser.add_argument("--host", default=os.environ.get('MCP_HOST', '0.0.0.0'), 418 | help="Host to bind the server to (default: 0.0.0.0)") 419 | parser.add_argument("--port", type=int, default=int(os.environ.get('MCP_PORT', 9876)), 420 | help="Port to listen on (default: 9876)") 421 | parser.add_argument("--debug", action="store_true", 422 | help="Enable debug mode with additional logging") 423 | parser.add_argument("--disable-s3", action="store_true", 424 | help="Disable S3 uploads regardless of settings") 425 | parser.add_argument("--s3-access-key", 426 | help="Override S3 access key ID") 427 | parser.add_argument("--s3-secret-key", 428 | help="Override S3 secret access key") 429 | parser.add_argument("--s3-bucket", 430 | help="Override S3 bucket name") 431 | parser.add_argument("--s3-region", 432 | help="Override S3 region") 433 | parser.add_argument("--claude-desktop-config", type=str, 434 | help="Path to claude_desktop_config.json if not in default location") 435 | 436 | args = parser.parse_args() 437 | 438 | # If a custom claude desktop config path was provided, try to load it 439 | if args.claude_desktop_config and os.path.exists(args.claude_desktop_config): 440 | try: 441 | print(f"Loading custom Claude Desktop config from: {args.claude_desktop_config}") 442 | with open(args.claude_desktop_config, 'r') as config_file: 443 | config = json.load(config_file) 444 | 445 | # Load environment variables from the config 446 | if 'environment' in config: 447 | for key, value in config['environment'].items(): 448 | os.environ[key] = str(value) 449 | print(f"Loaded environment variable from custom Claude Desktop config: {key}") 450 | except Exception as e: 451 | print(f"Error loading custom Claude Desktop config: {e}") 452 | 453 | # Check for DISABLE_S3 environment variable 454 | if os.environ.get('DISABLE_S3') == 'true' or os.environ.get('DISABLE_S3') == '1': 455 | os.environ['S3_ENABLED'] = 'false' 456 | print("S3 uploads disabled by environment variable") 457 | elif args.disable_s3: 458 | os.environ['S3_ENABLED'] = 'false' 459 | print("S3 uploads disabled by command line argument") 460 | 461 | # Command line args override environment variables 462 | if args.s3_access_key: 463 | os.environ['AWS_ACCESS_KEY_ID'] = args.s3_access_key 464 | print("Using S3 access key from command line") 465 | 466 | if args.s3_secret_key: 467 | os.environ['AWS_SECRET_ACCESS_KEY'] = args.s3_secret_key 468 | print("Using S3 secret key from command line") 469 | 470 | if args.s3_bucket: 471 | os.environ['AWS_S3_BUCKET_NAME'] = args.s3_bucket 472 | print(f"Using S3 bucket from command line: {args.s3_bucket}") 473 | 474 | if args.s3_region: 475 | os.environ['AWS_S3_REGION'] = args.s3_region 476 | print(f"Using S3 region from command line: {args.s3_region}") 477 | 478 | # Print debug information about loaded environment variables if debug mode is enabled 479 | if args.debug or os.environ.get('DEBUG') == 'true' or os.environ.get('DEBUG') == '1': 480 | print("Debug mode enabled") 481 | print("Environment variables:") 482 | for var in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_S3_BUCKET_NAME', 'AWS_S3_REGION', 'AWS_S3_FOLDER', 'AWS_S3_ENDPOINT_URL']: 483 | if os.environ.get(var): 484 | print(f" {var}: {'*' * 10 if 'KEY' in var or 'SECRET' in var else os.environ.get(var)}") 485 | else: 486 | print(f" {var}: Not set") 487 | 488 | # Instantiate our TTS server (which handles S3 validation and TTS generation) 489 | mcp_tts_server = MCPTTSServer(host=args.host, port=args.port) 490 | 491 | # Create and configure the FastMCP server 492 | mcp = FastMCP("Kokoro TTS Server") 493 | 494 | # Register our TTS tool using the decorator syntax 495 | @mcp.tool() 496 | async def text_to_speech(text: str, voice: str = os.environ.get('TTS_VOICE', 'af_heart'), 497 | speed: float = float(os.environ.get('TTS_SPEED', 1.0)), 498 | lang: str = os.environ.get('TTS_LANGUAGE', 'en-us'), 499 | filename: str = None, 500 | upload_to_s3: bool = os.environ.get('S3_ENABLED', 'true').lower() == 'true') -> dict: 501 | """ 502 | Convert text to speech using the Kokoro TTS service. 503 | 504 | Args: 505 | text: The text to convert to speech 506 | voice: Voice ID to use (default: af_heart) 507 | speed: Speech speed (default: 1.0) 508 | lang: Language code (default: en-us) 509 | filename: Optional filename for the MP3 (default: auto-generated UUID) 510 | upload_to_s3: Whether to upload to S3 if enabled (default: True) 511 | 512 | Returns: 513 | A dictionary with information about the generated audio file 514 | """ 515 | request_data = { 516 | "text": text, 517 | "voice": voice, 518 | "speed": speed, 519 | "lang": lang, 520 | "filename": filename, 521 | "upload_to_s3": upload_to_s3 522 | } 523 | 524 | return await mcp_tts_server.process_tts_request(request_data) 525 | 526 | print(f"Starting MCP TTS Server on {args.host}:{args.port}") 527 | print(f"MP3 files will be stored in: {MP3_FOLDER}") 528 | 529 | try: 530 | # Run the server 531 | mcp.run() 532 | except KeyboardInterrupt: 533 | print("Server stopped by user") 534 | except Exception as e: 535 | print(f"Server error: {e}") 536 | if args.debug: 537 | import traceback 538 | traceback.print_exc() 539 | 540 | if __name__ == "__main__": 541 | main() -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.12" 4 | 5 | [[package]] 6 | name = "annotated-types" 7 | version = "0.7.0" 8 | source = { registry = "https://pypi.org/simple" } 9 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } 10 | wheels = [ 11 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, 12 | ] 13 | 14 | [[package]] 15 | name = "anyio" 16 | version = "4.9.0" 17 | source = { registry = "https://pypi.org/simple" } 18 | dependencies = [ 19 | { name = "idna" }, 20 | { name = "sniffio" }, 21 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 22 | ] 23 | sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } 24 | wheels = [ 25 | { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, 26 | ] 27 | 28 | [[package]] 29 | name = "attrs" 30 | version = "25.3.0" 31 | source = { registry = "https://pypi.org/simple" } 32 | sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032 } 33 | wheels = [ 34 | { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815 }, 35 | ] 36 | 37 | [[package]] 38 | name = "babel" 39 | version = "2.17.0" 40 | source = { registry = "https://pypi.org/simple" } 41 | sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852 } 42 | wheels = [ 43 | { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537 }, 44 | ] 45 | 46 | [[package]] 47 | name = "boto3" 48 | version = "1.37.18" 49 | source = { registry = "https://pypi.org/simple" } 50 | dependencies = [ 51 | { name = "botocore" }, 52 | { name = "jmespath" }, 53 | { name = "s3transfer" }, 54 | ] 55 | sdist = { url = "https://files.pythonhosted.org/packages/87/42/2b102f999c76614e55afd8a8c2392c35ce2f390cdeb78007aba029cd1171/boto3-1.37.18.tar.gz", hash = "sha256:9b272268794172b0b8bb9fb1f3c470c3b6c0ffb92fbd4882465cc740e40fbdcd", size = 111358 } 56 | wheels = [ 57 | { url = "https://files.pythonhosted.org/packages/12/94/dccc4dd874cf455c8ea6dfb4c43a224632c03c3f503438aa99021759a097/boto3-1.37.18-py3-none-any.whl", hash = "sha256:1545c943f36db41853cdfdb6ff09c4eda9220dd95bd2fae76fc73091603525d1", size = 139561 }, 58 | ] 59 | 60 | [[package]] 61 | name = "botocore" 62 | version = "1.37.18" 63 | source = { registry = "https://pypi.org/simple" } 64 | dependencies = [ 65 | { name = "jmespath" }, 66 | { name = "python-dateutil" }, 67 | { name = "urllib3" }, 68 | ] 69 | sdist = { url = "https://files.pythonhosted.org/packages/2c/fa/a176046c74032ca3bda68c71ad544602a69be21d7ee3b199f4f2099fe4bf/botocore-1.37.18.tar.gz", hash = "sha256:99e8eefd5df6347ead15df07ce55f4e62a51ea7b54de1127522a08597923b726", size = 13667977 } 70 | wheels = [ 71 | { url = "https://files.pythonhosted.org/packages/a9/fd/059e57de7405b1ba93117c1b79a6daa45d6865f557b892f3cc7645836f3b/botocore-1.37.18-py3-none-any.whl", hash = "sha256:a8b97d217d82b3c4f6bcc906e264df7ebb51e2c6a62b3548a97cd173fb8759a1", size = 13428387 }, 72 | ] 73 | 74 | [[package]] 75 | name = "certifi" 76 | version = "2025.1.31" 77 | source = { registry = "https://pypi.org/simple" } 78 | sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } 79 | wheels = [ 80 | { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, 81 | ] 82 | 83 | [[package]] 84 | name = "cffi" 85 | version = "1.17.1" 86 | source = { registry = "https://pypi.org/simple" } 87 | dependencies = [ 88 | { name = "pycparser" }, 89 | ] 90 | sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } 91 | wheels = [ 92 | { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, 93 | { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, 94 | { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, 95 | { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, 96 | { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, 97 | { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, 98 | { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, 99 | { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, 100 | { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, 101 | { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, 102 | { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, 103 | { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, 104 | { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, 105 | { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, 106 | { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, 107 | { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, 108 | { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, 109 | { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, 110 | { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, 111 | { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, 112 | { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, 113 | { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, 114 | ] 115 | 116 | [[package]] 117 | name = "charset-normalizer" 118 | version = "3.4.1" 119 | source = { registry = "https://pypi.org/simple" } 120 | sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } 121 | wheels = [ 122 | { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, 123 | { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, 124 | { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, 125 | { url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 }, 126 | { url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 }, 127 | { url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 }, 128 | { url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 }, 129 | { url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 }, 130 | { url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 }, 131 | { url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 }, 132 | { url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 }, 133 | { url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 }, 134 | { url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 }, 135 | { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 }, 136 | { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 }, 137 | { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 }, 138 | { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 }, 139 | { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 }, 140 | { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 }, 141 | { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 }, 142 | { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 }, 143 | { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 }, 144 | { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 }, 145 | { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 }, 146 | { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 }, 147 | { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 }, 148 | { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, 149 | ] 150 | 151 | [[package]] 152 | name = "click" 153 | version = "8.1.8" 154 | source = { registry = "https://pypi.org/simple" } 155 | dependencies = [ 156 | { name = "colorama", marker = "sys_platform == 'win32'" }, 157 | ] 158 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } 159 | wheels = [ 160 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, 161 | ] 162 | 163 | [[package]] 164 | name = "colorama" 165 | version = "0.4.6" 166 | source = { registry = "https://pypi.org/simple" } 167 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 168 | wheels = [ 169 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, 170 | ] 171 | 172 | [[package]] 173 | name = "coloredlogs" 174 | version = "15.0.1" 175 | source = { registry = "https://pypi.org/simple" } 176 | dependencies = [ 177 | { name = "humanfriendly" }, 178 | ] 179 | sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520 } 180 | wheels = [ 181 | { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 }, 182 | ] 183 | 184 | [[package]] 185 | name = "colorlog" 186 | version = "6.9.0" 187 | source = { registry = "https://pypi.org/simple" } 188 | dependencies = [ 189 | { name = "colorama", marker = "sys_platform == 'win32'" }, 190 | ] 191 | sdist = { url = "https://files.pythonhosted.org/packages/d3/7a/359f4d5df2353f26172b3cc39ea32daa39af8de522205f512f458923e677/colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2", size = 16624 } 192 | wheels = [ 193 | { url = "https://files.pythonhosted.org/packages/e3/51/9b208e85196941db2f0654ad0357ca6388ab3ed67efdbfc799f35d1f83aa/colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff", size = 11424 }, 194 | ] 195 | 196 | [[package]] 197 | name = "csvw" 198 | version = "3.5.1" 199 | source = { registry = "https://pypi.org/simple" } 200 | dependencies = [ 201 | { name = "attrs" }, 202 | { name = "babel" }, 203 | { name = "colorama" }, 204 | { name = "isodate" }, 205 | { name = "jsonschema" }, 206 | { name = "language-tags" }, 207 | { name = "python-dateutil" }, 208 | { name = "rdflib" }, 209 | { name = "requests" }, 210 | { name = "rfc3986" }, 211 | { name = "uritemplate" }, 212 | ] 213 | sdist = { url = "https://files.pythonhosted.org/packages/5b/f0/1f76b07f2ddedc0e3b3b6e746c820de7028c6ac44416876a3ddc8243beb0/csvw-3.5.1.tar.gz", hash = "sha256:e13dfcbf56a51f66bd4c6b442b8b32b3fee4b615dcd9436149832b41572938f3", size = 73493 } 214 | wheels = [ 215 | { url = "https://files.pythonhosted.org/packages/13/84/069db1325f5a6dd034524c0099da3978de8fdb6242ce63223ead188da940/csvw-3.5.1-py2.py3-none-any.whl", hash = "sha256:8dd3864aae51bfd943713a62ec2c6688d3f406a9627b5f16de2479b1281febe5", size = 59881 }, 216 | ] 217 | 218 | [[package]] 219 | name = "dlinfo" 220 | version = "2.0.0" 221 | source = { registry = "https://pypi.org/simple" } 222 | sdist = { url = "https://files.pythonhosted.org/packages/85/8e/8f2f94cd40af1b51e8e371a83b385d622170d42f98776441a6118f4dd682/dlinfo-2.0.0.tar.gz", hash = "sha256:88a2bc04f51d01bc604cdc9eb1c3cc0bde89057532ca6a3e71a41f6235433e17", size = 12727 } 223 | wheels = [ 224 | { url = "https://files.pythonhosted.org/packages/da/90/022c79d6e5e6f843268c10b84d4a021ee3afba0621d3c176d3ff2024bfc8/dlinfo-2.0.0-py3-none-any.whl", hash = "sha256:b32cc18e3ea67c0ca9ca409e5b41eed863bd1363dbc9dd3de90fedf11b61e7bc", size = 3654 }, 225 | ] 226 | 227 | [[package]] 228 | name = "espeakng-loader" 229 | version = "0.2.4" 230 | source = { registry = "https://pypi.org/simple" } 231 | wheels = [ 232 | { url = "https://files.pythonhosted.org/packages/f8/92/f44ed7f531143c3c6c97d56e2b0f9be8728dc05e18b96d46eb539230ed46/espeakng_loader-0.2.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b77477ae2ddf62a748e04e49714eabb2f3a24f344166200b00539083bd669904", size = 9938387 }, 233 | { url = "https://files.pythonhosted.org/packages/a8/26/258c0cd43b9bc1043301c5f61767d6a6c3b679df82790c9cb43a3277b865/espeakng_loader-0.2.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d27cdca31112226e7299d8562e889d3e38a1e48055c9ee381b45d669072ee59f", size = 9892565 }, 234 | { url = "https://files.pythonhosted.org/packages/de/1e/25ec5ab07528c0fbb215a61800a38eca05c8a99445515a02d7fa5debcb32/espeakng_loader-0.2.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08721baf27d13d461f6be6eed9a65277e70d68234ff484fd8b9897b222cdcb6d", size = 10078484 }, 235 | { url = "https://files.pythonhosted.org/packages/d9/ad/1b768d8daffc2996e07bbcb6f534d8de3202cd75fce1f1c45eced1ce6465/espeakng_loader-0.2.4-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:d1e798141b46a050cdb75fcf3c17db969bb2c40394f3f4a48910655d547508b9", size = 10037736 }, 236 | { url = "https://files.pythonhosted.org/packages/9d/ed/a3d872fbad4f3a3f3db0e8c31768ab14e77cd77306de16b8b20b1e1df7ea/espeakng_loader-0.2.4-py3-none-win_amd64.whl", hash = "sha256:41f1e08ac9deda2efd1ea9de0b81dab9f5ae3c4b24284f76533d0a7b1dd7abd7", size = 9437292 }, 237 | { url = "https://files.pythonhosted.org/packages/29/64/0b75bc50ec53b4e000bac913625511215aa96124adf5dba8c4baa17c02cd/espeakng_loader-0.2.4-py3-none-win_arm64.whl", hash = "sha256:d7a2928843eaeb2df82f99a370f44e8a630f59b02f9b0d1f168a03c4eeb76b89", size = 9426841 }, 238 | ] 239 | 240 | [[package]] 241 | name = "fastmcp" 242 | version = "0.1.0" 243 | source = { registry = "https://pypi.org/simple" } 244 | dependencies = [ 245 | { name = "httpx" }, 246 | { name = "mcp" }, 247 | { name = "pydantic" }, 248 | { name = "pydantic-settings" }, 249 | { name = "typer" }, 250 | ] 251 | sdist = { url = "https://files.pythonhosted.org/packages/71/ef/351d0f953de706adb89c21f0fac150955eda2eb240196f5dca1c569a5053/fastmcp-0.1.0.tar.gz", hash = "sha256:5c18220961e717eb8cec30e12c5ebd9f240d4c830dc53a8404752bee777d064b", size = 54997 } 252 | wheels = [ 253 | { url = "https://files.pythonhosted.org/packages/f5/07/bc69e65b45d638822190bce0defb497a50d240291b8467cb79078d0064b7/fastmcp-0.1.0-py3-none-any.whl", hash = "sha256:55d4af4dcbd6543fd4df45ac6c82b148126f1883772ba66c2d25616ad0305db2", size = 14055 }, 254 | ] 255 | 256 | [[package]] 257 | name = "flask" 258 | version = "2.2.3" 259 | source = { registry = "https://pypi.org/simple" } 260 | dependencies = [ 261 | { name = "click" }, 262 | { name = "itsdangerous" }, 263 | { name = "jinja2" }, 264 | { name = "werkzeug" }, 265 | ] 266 | sdist = { url = "https://files.pythonhosted.org/packages/e8/5c/ff9047989bd995b1098d14b03013f160225db2282925b517bb4a967752ee/Flask-2.2.3.tar.gz", hash = "sha256:7eb373984bf1c770023fce9db164ed0c3353cd0b53f130f4693da0ca756a2e6d", size = 697599 } 267 | wheels = [ 268 | { url = "https://files.pythonhosted.org/packages/95/9c/a3542594ce4973786236a1b7b702b8ca81dbf40ea270f0f96284f0c27348/Flask-2.2.3-py3-none-any.whl", hash = "sha256:c0bec9477df1cb867e5a67c9e1ab758de9cb4a3e52dd70681f59fa40a62b3f2d", size = 101839 }, 269 | ] 270 | 271 | [[package]] 272 | name = "flask-cors" 273 | version = "3.0.10" 274 | source = { registry = "https://pypi.org/simple" } 275 | dependencies = [ 276 | { name = "flask" }, 277 | { name = "six" }, 278 | ] 279 | sdist = { url = "https://files.pythonhosted.org/packages/cf/25/e3b2553d22ed542be807739556c69621ad2ab276ae8d5d2560f4ed20f652/Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de", size = 30867 } 280 | wheels = [ 281 | { url = "https://files.pythonhosted.org/packages/db/84/901e700de86604b1c4ef4b57110d4e947c218b9997adf5d38fa7da493bce/Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438", size = 14067 }, 282 | ] 283 | 284 | [[package]] 285 | name = "flatbuffers" 286 | version = "25.2.10" 287 | source = { registry = "https://pypi.org/simple" } 288 | sdist = { url = "https://files.pythonhosted.org/packages/e4/30/eb5dce7994fc71a2f685d98ec33cc660c0a5887db5610137e60d8cbc4489/flatbuffers-25.2.10.tar.gz", hash = "sha256:97e451377a41262f8d9bd4295cc836133415cc03d8cb966410a4af92eb00d26e", size = 22170 } 289 | wheels = [ 290 | { url = "https://files.pythonhosted.org/packages/b8/25/155f9f080d5e4bc0082edfda032ea2bc2b8fab3f4d25d46c1e9dd22a1a89/flatbuffers-25.2.10-py2.py3-none-any.whl", hash = "sha256:ebba5f4d5ea615af3f7fd70fc310636fbb2bbd1f566ac0a23d98dd412de50051", size = 30953 }, 291 | ] 292 | 293 | [[package]] 294 | name = "h11" 295 | version = "0.14.0" 296 | source = { registry = "https://pypi.org/simple" } 297 | sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } 298 | wheels = [ 299 | { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, 300 | ] 301 | 302 | [[package]] 303 | name = "httpcore" 304 | version = "1.0.7" 305 | source = { registry = "https://pypi.org/simple" } 306 | dependencies = [ 307 | { name = "certifi" }, 308 | { name = "h11" }, 309 | ] 310 | sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } 311 | wheels = [ 312 | { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, 313 | ] 314 | 315 | [[package]] 316 | name = "httpx" 317 | version = "0.28.1" 318 | source = { registry = "https://pypi.org/simple" } 319 | dependencies = [ 320 | { name = "anyio" }, 321 | { name = "certifi" }, 322 | { name = "httpcore" }, 323 | { name = "idna" }, 324 | ] 325 | sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } 326 | wheels = [ 327 | { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, 328 | ] 329 | 330 | [[package]] 331 | name = "httpx-sse" 332 | version = "0.4.0" 333 | source = { registry = "https://pypi.org/simple" } 334 | sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 } 335 | wheels = [ 336 | { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 }, 337 | ] 338 | 339 | [[package]] 340 | name = "humanfriendly" 341 | version = "10.0" 342 | source = { registry = "https://pypi.org/simple" } 343 | dependencies = [ 344 | { name = "pyreadline3", marker = "sys_platform == 'win32'" }, 345 | ] 346 | sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 } 347 | wheels = [ 348 | { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 }, 349 | ] 350 | 351 | [[package]] 352 | name = "idna" 353 | version = "3.10" 354 | source = { registry = "https://pypi.org/simple" } 355 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } 356 | wheels = [ 357 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, 358 | ] 359 | 360 | [[package]] 361 | name = "isodate" 362 | version = "0.7.2" 363 | source = { registry = "https://pypi.org/simple" } 364 | sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705 } 365 | wheels = [ 366 | { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320 }, 367 | ] 368 | 369 | [[package]] 370 | name = "itsdangerous" 371 | version = "2.2.0" 372 | source = { registry = "https://pypi.org/simple" } 373 | sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } 374 | wheels = [ 375 | { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, 376 | ] 377 | 378 | [[package]] 379 | name = "jinja2" 380 | version = "3.1.6" 381 | source = { registry = "https://pypi.org/simple" } 382 | dependencies = [ 383 | { name = "markupsafe" }, 384 | ] 385 | sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } 386 | wheels = [ 387 | { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, 388 | ] 389 | 390 | [[package]] 391 | name = "jmespath" 392 | version = "1.0.1" 393 | source = { registry = "https://pypi.org/simple" } 394 | sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843 } 395 | wheels = [ 396 | { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256 }, 397 | ] 398 | 399 | [[package]] 400 | name = "joblib" 401 | version = "1.4.2" 402 | source = { registry = "https://pypi.org/simple" } 403 | sdist = { url = "https://files.pythonhosted.org/packages/64/33/60135848598c076ce4b231e1b1895170f45fbcaeaa2c9d5e38b04db70c35/joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e", size = 2116621 } 404 | wheels = [ 405 | { url = "https://files.pythonhosted.org/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6", size = 301817 }, 406 | ] 407 | 408 | [[package]] 409 | name = "jsonschema" 410 | version = "4.23.0" 411 | source = { registry = "https://pypi.org/simple" } 412 | dependencies = [ 413 | { name = "attrs" }, 414 | { name = "jsonschema-specifications" }, 415 | { name = "referencing" }, 416 | { name = "rpds-py" }, 417 | ] 418 | sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 } 419 | wheels = [ 420 | { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, 421 | ] 422 | 423 | [[package]] 424 | name = "jsonschema-specifications" 425 | version = "2024.10.1" 426 | source = { registry = "https://pypi.org/simple" } 427 | dependencies = [ 428 | { name = "referencing" }, 429 | ] 430 | sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } 431 | wheels = [ 432 | { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, 433 | ] 434 | 435 | [[package]] 436 | name = "kokoro-onnx" 437 | version = "0.4.5" 438 | source = { registry = "https://pypi.org/simple" } 439 | dependencies = [ 440 | { name = "colorlog" }, 441 | { name = "espeakng-loader" }, 442 | { name = "numpy" }, 443 | { name = "onnxruntime" }, 444 | { name = "phonemizer-fork" }, 445 | ] 446 | sdist = { url = "https://files.pythonhosted.org/packages/ed/c3/8a0e7106759393e1ee22752cd255b10b2ba2804803afe221e8fef1e4faba/kokoro_onnx-0.4.5.tar.gz", hash = "sha256:d6173cdf8957cd648969382b33eb7b274367a65743ccacd546d41032ddb23e62", size = 90537 } 447 | wheels = [ 448 | { url = "https://files.pythonhosted.org/packages/cd/ef/df373e151af2086379804974b03c1b053874655d3432302006d75c6be0cf/kokoro_onnx-0.4.5-py3-none-any.whl", hash = "sha256:6e9a049b2a84f791780b8ec390ee618f5d5c025722f430b076036168b546f042", size = 17861 }, 449 | ] 450 | 451 | [[package]] 452 | name = "kokoro-tts-mcp" 453 | version = "0.1.0" 454 | source = { virtual = "." } 455 | dependencies = [ 456 | { name = "boto3" }, 457 | { name = "fastmcp" }, 458 | { name = "flask" }, 459 | { name = "flask-cors" }, 460 | { name = "kokoro-onnx" }, 461 | { name = "numpy" }, 462 | { name = "python-dotenv" }, 463 | { name = "soundfile" }, 464 | { name = "werkzeug" }, 465 | ] 466 | 467 | [package.metadata] 468 | requires-dist = [ 469 | { name = "boto3", specifier = ">=1.37.18" }, 470 | { name = "fastmcp", specifier = "==0.1.0" }, 471 | { name = "flask", specifier = "==2.2.3" }, 472 | { name = "flask-cors", specifier = "==3.0.10" }, 473 | { name = "kokoro-onnx", specifier = ">=0.4.5" }, 474 | { name = "numpy", specifier = ">=1.26.0" }, 475 | { name = "python-dotenv", specifier = "==0.21.0" }, 476 | { name = "soundfile", specifier = ">=0.13.1" }, 477 | { name = "werkzeug", specifier = "==3.1.3" }, 478 | ] 479 | 480 | [[package]] 481 | name = "language-tags" 482 | version = "1.2.0" 483 | source = { registry = "https://pypi.org/simple" } 484 | sdist = { url = "https://files.pythonhosted.org/packages/e0/7e/b6a0efe4fee11e9742c1baaedf7c574084238a70b03c1d8eb2761383848f/language_tags-1.2.0.tar.gz", hash = "sha256:e934acba3e3dc85f867703eca421847a9ab7b7679b11b5d5cfd096febbf8bde6", size = 207901 } 485 | wheels = [ 486 | { url = "https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl", hash = "sha256:d815604622242fdfbbfd747b40c31213617fd03734a267f2e39ee4bd73c88722", size = 213449 }, 487 | ] 488 | 489 | [[package]] 490 | name = "markdown-it-py" 491 | version = "3.0.0" 492 | source = { registry = "https://pypi.org/simple" } 493 | dependencies = [ 494 | { name = "mdurl" }, 495 | ] 496 | sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } 497 | wheels = [ 498 | { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, 499 | ] 500 | 501 | [[package]] 502 | name = "markupsafe" 503 | version = "3.0.2" 504 | source = { registry = "https://pypi.org/simple" } 505 | sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } 506 | wheels = [ 507 | { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, 508 | { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, 509 | { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, 510 | { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, 511 | { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, 512 | { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, 513 | { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, 514 | { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, 515 | { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, 516 | { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, 517 | { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, 518 | { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, 519 | { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, 520 | { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, 521 | { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, 522 | { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, 523 | { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, 524 | { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, 525 | { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, 526 | { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, 527 | { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, 528 | { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, 529 | { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, 530 | { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, 531 | { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, 532 | { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, 533 | { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, 534 | { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, 535 | { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, 536 | { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, 537 | ] 538 | 539 | [[package]] 540 | name = "mcp" 541 | version = "1.5.0" 542 | source = { registry = "https://pypi.org/simple" } 543 | dependencies = [ 544 | { name = "anyio" }, 545 | { name = "httpx" }, 546 | { name = "httpx-sse" }, 547 | { name = "pydantic" }, 548 | { name = "pydantic-settings" }, 549 | { name = "sse-starlette" }, 550 | { name = "starlette" }, 551 | { name = "uvicorn" }, 552 | ] 553 | sdist = { url = "https://files.pythonhosted.org/packages/6d/c9/c55764824e893fdebe777ac7223200986a275c3191dba9169f8eb6d7c978/mcp-1.5.0.tar.gz", hash = "sha256:5b2766c05e68e01a2034875e250139839498c61792163a7b221fc170c12f5aa9", size = 159128 } 554 | wheels = [ 555 | { url = "https://files.pythonhosted.org/packages/c1/d1/3ff566ecf322077d861f1a68a1ff025cad337417bd66ad22a7c6f7dfcfaf/mcp-1.5.0-py3-none-any.whl", hash = "sha256:51c3f35ce93cb702f7513c12406bbea9665ef75a08db909200b07da9db641527", size = 73734 }, 556 | ] 557 | 558 | [[package]] 559 | name = "mdurl" 560 | version = "0.1.2" 561 | source = { registry = "https://pypi.org/simple" } 562 | sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } 563 | wheels = [ 564 | { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, 565 | ] 566 | 567 | [[package]] 568 | name = "mpmath" 569 | version = "1.3.0" 570 | source = { registry = "https://pypi.org/simple" } 571 | sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 } 572 | wheels = [ 573 | { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, 574 | ] 575 | 576 | [[package]] 577 | name = "numpy" 578 | version = "2.2.4" 579 | source = { registry = "https://pypi.org/simple" } 580 | sdist = { url = "https://files.pythonhosted.org/packages/e1/78/31103410a57bc2c2b93a3597340a8119588571f6a4539067546cb9a0bfac/numpy-2.2.4.tar.gz", hash = "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", size = 20270701 } 581 | wheels = [ 582 | { url = "https://files.pythonhosted.org/packages/a2/30/182db21d4f2a95904cec1a6f779479ea1ac07c0647f064dea454ec650c42/numpy-2.2.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4", size = 20947156 }, 583 | { url = "https://files.pythonhosted.org/packages/24/6d/9483566acfbda6c62c6bc74b6e981c777229d2af93c8eb2469b26ac1b7bc/numpy-2.2.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854", size = 14133092 }, 584 | { url = "https://files.pythonhosted.org/packages/27/f6/dba8a258acbf9d2bed2525cdcbb9493ef9bae5199d7a9cb92ee7e9b2aea6/numpy-2.2.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24", size = 5163515 }, 585 | { url = "https://files.pythonhosted.org/packages/62/30/82116199d1c249446723c68f2c9da40d7f062551036f50b8c4caa42ae252/numpy-2.2.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee", size = 6696558 }, 586 | { url = "https://files.pythonhosted.org/packages/0e/b2/54122b3c6df5df3e87582b2e9430f1bdb63af4023c739ba300164c9ae503/numpy-2.2.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba", size = 14084742 }, 587 | { url = "https://files.pythonhosted.org/packages/02/e2/e2cbb8d634151aab9528ef7b8bab52ee4ab10e076509285602c2a3a686e0/numpy-2.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592", size = 16134051 }, 588 | { url = "https://files.pythonhosted.org/packages/8e/21/efd47800e4affc993e8be50c1b768de038363dd88865920439ef7b422c60/numpy-2.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb", size = 15578972 }, 589 | { url = "https://files.pythonhosted.org/packages/04/1e/f8bb88f6157045dd5d9b27ccf433d016981032690969aa5c19e332b138c0/numpy-2.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f", size = 17898106 }, 590 | { url = "https://files.pythonhosted.org/packages/2b/93/df59a5a3897c1f036ae8ff845e45f4081bb06943039ae28a3c1c7c780f22/numpy-2.2.4-cp312-cp312-win32.whl", hash = "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00", size = 6311190 }, 591 | { url = "https://files.pythonhosted.org/packages/46/69/8c4f928741c2a8efa255fdc7e9097527c6dc4e4df147e3cadc5d9357ce85/numpy-2.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146", size = 12644305 }, 592 | { url = "https://files.pythonhosted.org/packages/2a/d0/bd5ad792e78017f5decfb2ecc947422a3669a34f775679a76317af671ffc/numpy-2.2.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7", size = 20933623 }, 593 | { url = "https://files.pythonhosted.org/packages/c3/bc/2b3545766337b95409868f8e62053135bdc7fa2ce630aba983a2aa60b559/numpy-2.2.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0", size = 14148681 }, 594 | { url = "https://files.pythonhosted.org/packages/6a/70/67b24d68a56551d43a6ec9fe8c5f91b526d4c1a46a6387b956bf2d64744e/numpy-2.2.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392", size = 5148759 }, 595 | { url = "https://files.pythonhosted.org/packages/1c/8b/e2fc8a75fcb7be12d90b31477c9356c0cbb44abce7ffb36be39a0017afad/numpy-2.2.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc", size = 6683092 }, 596 | { url = "https://files.pythonhosted.org/packages/13/73/41b7b27f169ecf368b52533edb72e56a133f9e86256e809e169362553b49/numpy-2.2.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", size = 14081422 }, 597 | { url = "https://files.pythonhosted.org/packages/4b/04/e208ff3ae3ddfbafc05910f89546382f15a3f10186b1f56bd99f159689c2/numpy-2.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", size = 16132202 }, 598 | { url = "https://files.pythonhosted.org/packages/fe/bc/2218160574d862d5e55f803d88ddcad88beff94791f9c5f86d67bd8fbf1c/numpy-2.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", size = 15573131 }, 599 | { url = "https://files.pythonhosted.org/packages/a5/78/97c775bc4f05abc8a8426436b7cb1be806a02a2994b195945600855e3a25/numpy-2.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", size = 17894270 }, 600 | { url = "https://files.pythonhosted.org/packages/b9/eb/38c06217a5f6de27dcb41524ca95a44e395e6a1decdc0c99fec0832ce6ae/numpy-2.2.4-cp313-cp313-win32.whl", hash = "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", size = 6308141 }, 601 | { url = "https://files.pythonhosted.org/packages/52/17/d0dd10ab6d125c6d11ffb6dfa3423c3571befab8358d4f85cd4471964fcd/numpy-2.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", size = 12636885 }, 602 | { url = "https://files.pythonhosted.org/packages/fa/e2/793288ede17a0fdc921172916efb40f3cbc2aa97e76c5c84aba6dc7e8747/numpy-2.2.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8", size = 20961829 }, 603 | { url = "https://files.pythonhosted.org/packages/3a/75/bb4573f6c462afd1ea5cbedcc362fe3e9bdbcc57aefd37c681be1155fbaa/numpy-2.2.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39", size = 14161419 }, 604 | { url = "https://files.pythonhosted.org/packages/03/68/07b4cd01090ca46c7a336958b413cdbe75002286295f2addea767b7f16c9/numpy-2.2.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd", size = 5196414 }, 605 | { url = "https://files.pythonhosted.org/packages/a5/fd/d4a29478d622fedff5c4b4b4cedfc37a00691079623c0575978d2446db9e/numpy-2.2.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0", size = 6709379 }, 606 | { url = "https://files.pythonhosted.org/packages/41/78/96dddb75bb9be730b87c72f30ffdd62611aba234e4e460576a068c98eff6/numpy-2.2.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", size = 14051725 }, 607 | { url = "https://files.pythonhosted.org/packages/00/06/5306b8199bffac2a29d9119c11f457f6c7d41115a335b78d3f86fad4dbe8/numpy-2.2.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", size = 16101638 }, 608 | { url = "https://files.pythonhosted.org/packages/fa/03/74c5b631ee1ded596945c12027649e6344614144369fd3ec1aaced782882/numpy-2.2.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", size = 15571717 }, 609 | { url = "https://files.pythonhosted.org/packages/cb/dc/4fc7c0283abe0981e3b89f9b332a134e237dd476b0c018e1e21083310c31/numpy-2.2.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", size = 17879998 }, 610 | { url = "https://files.pythonhosted.org/packages/e5/2b/878576190c5cfa29ed896b518cc516aecc7c98a919e20706c12480465f43/numpy-2.2.4-cp313-cp313t-win32.whl", hash = "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", size = 6366896 }, 611 | { url = "https://files.pythonhosted.org/packages/3e/05/eb7eec66b95cf697f08c754ef26c3549d03ebd682819f794cb039574a0a6/numpy-2.2.4-cp313-cp313t-win_amd64.whl", hash = "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", size = 12739119 }, 612 | ] 613 | 614 | [[package]] 615 | name = "onnxruntime" 616 | version = "1.21.0" 617 | source = { registry = "https://pypi.org/simple" } 618 | dependencies = [ 619 | { name = "coloredlogs" }, 620 | { name = "flatbuffers" }, 621 | { name = "numpy" }, 622 | { name = "packaging" }, 623 | { name = "protobuf" }, 624 | { name = "sympy" }, 625 | ] 626 | wheels = [ 627 | { url = "https://files.pythonhosted.org/packages/ff/21/593c9bc56002a6d1ea7c2236f4a648e081ec37c8d51db2383a9e83a63325/onnxruntime-1.21.0-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:893d67c68ca9e7a58202fa8d96061ed86a5815b0925b5a97aef27b8ba246a20b", size = 33658780 }, 628 | { url = "https://files.pythonhosted.org/packages/4a/b4/33ec675a8ac150478091262824413e5d4acc359e029af87f9152e7c1c092/onnxruntime-1.21.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:37b7445c920a96271a8dfa16855e258dc5599235b41c7bbde0d262d55bcc105f", size = 14159975 }, 629 | { url = "https://files.pythonhosted.org/packages/8b/08/eead6895ed83b56711ca6c0d31d82f109401b9937558b425509e497d6fb4/onnxruntime-1.21.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a04aafb802c1e5573ba4552f8babcb5021b041eb4cfa802c9b7644ca3510eca", size = 16019285 }, 630 | { url = "https://files.pythonhosted.org/packages/77/39/e83d56e3c215713b5263cb4d4f0c69e3964bba11634233d8ae04fc7e6bf3/onnxruntime-1.21.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f801318476cd7003d636a5b392f7a37c08b6c8d2f829773f3c3887029e03f32", size = 11760975 }, 631 | { url = "https://files.pythonhosted.org/packages/f2/25/93f65617b06c741a58eeac9e373c99df443b02a774f4cb6511889757c0da/onnxruntime-1.21.0-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:85718cbde1c2912d3a03e3b3dc181b1480258a229c32378408cace7c450f7f23", size = 33659581 }, 632 | { url = "https://files.pythonhosted.org/packages/f9/03/6b6829ee8344490ab5197f39a6824499ed097d1fc8c85b1f91c0e6767819/onnxruntime-1.21.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94dff3a61538f3b7b0ea9a06bc99e1410e90509c76e3a746f039e417802a12ae", size = 14160534 }, 633 | { url = "https://files.pythonhosted.org/packages/a6/81/e280ddf05f83ad5e0d066ef08e31515b17bd50bb52ef2ea713d9e455e67a/onnxruntime-1.21.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1e704b0eda5f2bbbe84182437315eaec89a450b08854b5a7762c85d04a28a0a", size = 16018947 }, 634 | { url = "https://files.pythonhosted.org/packages/d3/ea/011dfc2536e46e2ea984d2c0256dc585ebb1352366dffdd98764f1f44ee4/onnxruntime-1.21.0-cp313-cp313-win_amd64.whl", hash = "sha256:19b630c6a8956ef97fb7c94948b17691167aa1aaf07b5f214fa66c3e4136c108", size = 11760731 }, 635 | { url = "https://files.pythonhosted.org/packages/47/6b/a00f31322e91c610c7825377ef0cad884483c30d1370b896d57e7032e912/onnxruntime-1.21.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3995c4a2d81719623c58697b9510f8de9fa42a1da6b4474052797b0d712324fe", size = 14172215 }, 636 | { url = "https://files.pythonhosted.org/packages/58/4b/98214f13ac1cd675dfc2713ba47b5722f55ce4fba526d2b2826f2682a42e/onnxruntime-1.21.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36b18b8f39c0f84e783902112a0dd3c102466897f96d73bb83f6a6bff283a423", size = 15990612 }, 637 | ] 638 | 639 | [[package]] 640 | name = "packaging" 641 | version = "24.2" 642 | source = { registry = "https://pypi.org/simple" } 643 | sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } 644 | wheels = [ 645 | { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, 646 | ] 647 | 648 | [[package]] 649 | name = "phonemizer-fork" 650 | version = "3.3.1" 651 | source = { registry = "https://pypi.org/simple" } 652 | dependencies = [ 653 | { name = "attrs" }, 654 | { name = "dlinfo" }, 655 | { name = "joblib" }, 656 | { name = "segments" }, 657 | { name = "typing-extensions" }, 658 | ] 659 | sdist = { url = "https://files.pythonhosted.org/packages/42/bc/6d626024573810fdf54925670f4798456ef56c764878f50cf3bc397085bd/phonemizer_fork-3.3.1.tar.gz", hash = "sha256:483a2751ea435b9859e2ddca7d4ec817e54a82f3d2ad5ad2fd8fbd40e3bdf89e", size = 210609 } 660 | wheels = [ 661 | { url = "https://files.pythonhosted.org/packages/1c/36/b6700c86bd268ab867c3d0ee4b905fbd3f1954fbfa5cb991c12289727bb8/phonemizer_fork-3.3.1-py3-none-any.whl", hash = "sha256:452e4b3f4fe4724a4c46c55eb6926c2b0a7abefd72a893549de139f80874162c", size = 82533 }, 662 | ] 663 | 664 | [[package]] 665 | name = "protobuf" 666 | version = "6.30.1" 667 | source = { registry = "https://pypi.org/simple" } 668 | sdist = { url = "https://files.pythonhosted.org/packages/55/de/8216061897a67b2ffe302fd51aaa76bbf613001f01cd96e2416a4955dd2b/protobuf-6.30.1.tar.gz", hash = "sha256:535fb4e44d0236893d5cf1263a0f706f1160b689a7ab962e9da8a9ce4050b780", size = 429304 } 669 | wheels = [ 670 | { url = "https://files.pythonhosted.org/packages/83/f6/28460c49a8a93229e2264cd35fd147153fb524cbd944789db6b6f3cc9b13/protobuf-6.30.1-cp310-abi3-win32.whl", hash = "sha256:ba0706f948d0195f5cac504da156d88174e03218d9364ab40d903788c1903d7e", size = 419150 }, 671 | { url = "https://files.pythonhosted.org/packages/96/82/7045f5b3f3e338a8ab5852d22ce9c31e0a40d8b0f150a3735dc494be769a/protobuf-6.30.1-cp310-abi3-win_amd64.whl", hash = "sha256:ed484f9ddd47f0f1bf0648806cccdb4fe2fb6b19820f9b79a5adf5dcfd1b8c5f", size = 431007 }, 672 | { url = "https://files.pythonhosted.org/packages/b0/b6/732d04d0cdf457d05b7cba83ae73735d91ceced2439735b4500e311c44a5/protobuf-6.30.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aa4f7dfaed0d840b03d08d14bfdb41348feaee06a828a8c455698234135b4075", size = 417579 }, 673 | { url = "https://files.pythonhosted.org/packages/fc/22/29dd085f6e828ab0424e73f1bae9dbb9e8bb4087cba5a9e6f21dc614694e/protobuf-6.30.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:47cd320b7db63e8c9ac35f5596ea1c1e61491d8a8eb6d8b45edc44760b53a4f6", size = 317319 }, 674 | { url = "https://files.pythonhosted.org/packages/26/10/8863ba4baa4660e3f50ad9ae974c47fb63fa6d4089b15f7db82164b1c879/protobuf-6.30.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3083660225fa94748ac2e407f09a899e6a28bf9c0e70c75def8d15706bf85fc", size = 316213 }, 675 | { url = "https://files.pythonhosted.org/packages/a1/d6/683a3d470398e45b4ad9b6c95b7cbabc32f9a8daf454754f0e3df1edffa6/protobuf-6.30.1-py3-none-any.whl", hash = "sha256:3c25e51e1359f1f5fa3b298faa6016e650d148f214db2e47671131b9063c53be", size = 167064 }, 676 | ] 677 | 678 | [[package]] 679 | name = "pycparser" 680 | version = "2.22" 681 | source = { registry = "https://pypi.org/simple" } 682 | sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } 683 | wheels = [ 684 | { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, 685 | ] 686 | 687 | [[package]] 688 | name = "pydantic" 689 | version = "2.10.6" 690 | source = { registry = "https://pypi.org/simple" } 691 | dependencies = [ 692 | { name = "annotated-types" }, 693 | { name = "pydantic-core" }, 694 | { name = "typing-extensions" }, 695 | ] 696 | sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } 697 | wheels = [ 698 | { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, 699 | ] 700 | 701 | [[package]] 702 | name = "pydantic-core" 703 | version = "2.27.2" 704 | source = { registry = "https://pypi.org/simple" } 705 | dependencies = [ 706 | { name = "typing-extensions" }, 707 | ] 708 | sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } 709 | wheels = [ 710 | { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, 711 | { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, 712 | { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, 713 | { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, 714 | { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, 715 | { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, 716 | { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, 717 | { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, 718 | { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, 719 | { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, 720 | { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, 721 | { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, 722 | { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, 723 | { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, 724 | { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, 725 | { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, 726 | { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, 727 | { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, 728 | { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, 729 | { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, 730 | { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, 731 | { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, 732 | { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, 733 | { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, 734 | { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, 735 | { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, 736 | { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, 737 | { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, 738 | ] 739 | 740 | [[package]] 741 | name = "pydantic-settings" 742 | version = "2.8.1" 743 | source = { registry = "https://pypi.org/simple" } 744 | dependencies = [ 745 | { name = "pydantic" }, 746 | { name = "python-dotenv" }, 747 | ] 748 | sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 } 749 | wheels = [ 750 | { url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 }, 751 | ] 752 | 753 | [[package]] 754 | name = "pygments" 755 | version = "2.19.1" 756 | source = { registry = "https://pypi.org/simple" } 757 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } 758 | wheels = [ 759 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, 760 | ] 761 | 762 | [[package]] 763 | name = "pyparsing" 764 | version = "3.2.1" 765 | source = { registry = "https://pypi.org/simple" } 766 | sdist = { url = "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694 } 767 | wheels = [ 768 | { url = "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716 }, 769 | ] 770 | 771 | [[package]] 772 | name = "pyreadline3" 773 | version = "3.5.4" 774 | source = { registry = "https://pypi.org/simple" } 775 | sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 } 776 | wheels = [ 777 | { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, 778 | ] 779 | 780 | [[package]] 781 | name = "python-dateutil" 782 | version = "2.9.0.post0" 783 | source = { registry = "https://pypi.org/simple" } 784 | dependencies = [ 785 | { name = "six" }, 786 | ] 787 | sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } 788 | wheels = [ 789 | { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, 790 | ] 791 | 792 | [[package]] 793 | name = "python-dotenv" 794 | version = "0.21.0" 795 | source = { registry = "https://pypi.org/simple" } 796 | sdist = { url = "https://files.pythonhosted.org/packages/87/8d/ab7352188f605e3f663f34692b2ed7457da5985857e9e4c2335cd12fb3c9/python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045", size = 34984 } 797 | wheels = [ 798 | { url = "https://files.pythonhosted.org/packages/2d/10/ff4f2f5b2a420fd09e1331d63cc87cf4367c5745c0a4ce99cea92b1cbacb/python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5", size = 18818 }, 799 | ] 800 | 801 | [[package]] 802 | name = "rdflib" 803 | version = "7.1.3" 804 | source = { registry = "https://pypi.org/simple" } 805 | dependencies = [ 806 | { name = "pyparsing" }, 807 | ] 808 | sdist = { url = "https://files.pythonhosted.org/packages/96/12/f43307e7b1f871ed5424fc6eff1fb8c85637dbaed6a401748c2b72c97d7a/rdflib-7.1.3.tar.gz", hash = "sha256:f3dcb4c106a8cd9e060d92f43d593d09ebc3d07adc244f4c7315856a12e383ee", size = 4867170 } 809 | wheels = [ 810 | { url = "https://files.pythonhosted.org/packages/9c/3c/f508a9b346078ea0bd49c8261430204fcfb4150352d51fa2a54a4d9eacda/rdflib-7.1.3-py3-none-any.whl", hash = "sha256:5402310a9f0f3c07d453d73fd0ad6ba35616286fe95d3670db2b725f3f539673", size = 564909 }, 811 | ] 812 | 813 | [[package]] 814 | name = "referencing" 815 | version = "0.36.2" 816 | source = { registry = "https://pypi.org/simple" } 817 | dependencies = [ 818 | { name = "attrs" }, 819 | { name = "rpds-py" }, 820 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 821 | ] 822 | sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744 } 823 | wheels = [ 824 | { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775 }, 825 | ] 826 | 827 | [[package]] 828 | name = "regex" 829 | version = "2024.11.6" 830 | source = { registry = "https://pypi.org/simple" } 831 | sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 } 832 | wheels = [ 833 | { url = "https://files.pythonhosted.org/packages/ba/30/9a87ce8336b172cc232a0db89a3af97929d06c11ceaa19d97d84fa90a8f8/regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a", size = 483781 }, 834 | { url = "https://files.pythonhosted.org/packages/01/e8/00008ad4ff4be8b1844786ba6636035f7ef926db5686e4c0f98093612add/regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9", size = 288455 }, 835 | { url = "https://files.pythonhosted.org/packages/60/85/cebcc0aff603ea0a201667b203f13ba75d9fc8668fab917ac5b2de3967bc/regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2", size = 284759 }, 836 | { url = "https://files.pythonhosted.org/packages/94/2b/701a4b0585cb05472a4da28ee28fdfe155f3638f5e1ec92306d924e5faf0/regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4", size = 794976 }, 837 | { url = "https://files.pythonhosted.org/packages/4b/bf/fa87e563bf5fee75db8915f7352e1887b1249126a1be4813837f5dbec965/regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577", size = 833077 }, 838 | { url = "https://files.pythonhosted.org/packages/a1/56/7295e6bad94b047f4d0834e4779491b81216583c00c288252ef625c01d23/regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3", size = 823160 }, 839 | { url = "https://files.pythonhosted.org/packages/fb/13/e3b075031a738c9598c51cfbc4c7879e26729c53aa9cca59211c44235314/regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e", size = 796896 }, 840 | { url = "https://files.pythonhosted.org/packages/24/56/0b3f1b66d592be6efec23a795b37732682520b47c53da5a32c33ed7d84e3/regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe", size = 783997 }, 841 | { url = "https://files.pythonhosted.org/packages/f9/a1/eb378dada8b91c0e4c5f08ffb56f25fcae47bf52ad18f9b2f33b83e6d498/regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e", size = 781725 }, 842 | { url = "https://files.pythonhosted.org/packages/83/f2/033e7dec0cfd6dda93390089864732a3409246ffe8b042e9554afa9bff4e/regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29", size = 789481 }, 843 | { url = "https://files.pythonhosted.org/packages/83/23/15d4552ea28990a74e7696780c438aadd73a20318c47e527b47a4a5a596d/regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39", size = 852896 }, 844 | { url = "https://files.pythonhosted.org/packages/e3/39/ed4416bc90deedbfdada2568b2cb0bc1fdb98efe11f5378d9892b2a88f8f/regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51", size = 860138 }, 845 | { url = "https://files.pythonhosted.org/packages/93/2d/dd56bb76bd8e95bbce684326302f287455b56242a4f9c61f1bc76e28360e/regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad", size = 787692 }, 846 | { url = "https://files.pythonhosted.org/packages/0b/55/31877a249ab7a5156758246b9c59539abbeba22461b7d8adc9e8475ff73e/regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54", size = 262135 }, 847 | { url = "https://files.pythonhosted.org/packages/38/ec/ad2d7de49a600cdb8dd78434a1aeffe28b9d6fc42eb36afab4a27ad23384/regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b", size = 273567 }, 848 | { url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525 }, 849 | { url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324 }, 850 | { url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617 }, 851 | { url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023 }, 852 | { url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072 }, 853 | { url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130 }, 854 | { url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857 }, 855 | { url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006 }, 856 | { url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650 }, 857 | { url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545 }, 858 | { url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045 }, 859 | { url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182 }, 860 | { url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733 }, 861 | { url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122 }, 862 | { url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545 }, 863 | ] 864 | 865 | [[package]] 866 | name = "requests" 867 | version = "2.32.3" 868 | source = { registry = "https://pypi.org/simple" } 869 | dependencies = [ 870 | { name = "certifi" }, 871 | { name = "charset-normalizer" }, 872 | { name = "idna" }, 873 | { name = "urllib3" }, 874 | ] 875 | sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } 876 | wheels = [ 877 | { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, 878 | ] 879 | 880 | [[package]] 881 | name = "rfc3986" 882 | version = "1.5.0" 883 | source = { registry = "https://pypi.org/simple" } 884 | sdist = { url = "https://files.pythonhosted.org/packages/79/30/5b1b6c28c105629cc12b33bdcbb0b11b5bb1880c6cfbd955f9e792921aa8/rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", size = 49378 } 885 | wheels = [ 886 | { url = "https://files.pythonhosted.org/packages/c4/e5/63ca2c4edf4e00657584608bee1001302bbf8c5f569340b78304f2f446cb/rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97", size = 31976 }, 887 | ] 888 | 889 | [[package]] 890 | name = "rich" 891 | version = "13.9.4" 892 | source = { registry = "https://pypi.org/simple" } 893 | dependencies = [ 894 | { name = "markdown-it-py" }, 895 | { name = "pygments" }, 896 | ] 897 | sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } 898 | wheels = [ 899 | { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, 900 | ] 901 | 902 | [[package]] 903 | name = "rpds-py" 904 | version = "0.23.1" 905 | source = { registry = "https://pypi.org/simple" } 906 | sdist = { url = "https://files.pythonhosted.org/packages/0a/79/2ce611b18c4fd83d9e3aecb5cba93e1917c050f556db39842889fa69b79f/rpds_py-0.23.1.tar.gz", hash = "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707", size = 26806 } 907 | wheels = [ 908 | { url = "https://files.pythonhosted.org/packages/f3/8c/d17efccb9f5b9137ddea706664aebae694384ae1d5997c0202093e37185a/rpds_py-0.23.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c", size = 364369 }, 909 | { url = "https://files.pythonhosted.org/packages/6e/c0/ab030f696b5c573107115a88d8d73d80f03309e60952b64c584c70c659af/rpds_py-0.23.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba", size = 349965 }, 910 | { url = "https://files.pythonhosted.org/packages/b3/55/b40170f5a079c4fb0b6a82b299689e66e744edca3c3375a8b160fb797660/rpds_py-0.23.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31", size = 389064 }, 911 | { url = "https://files.pythonhosted.org/packages/ab/1c/b03a912c59ec7c1e16b26e587b9dfa8ddff3b07851e781e8c46e908a365a/rpds_py-0.23.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149", size = 397741 }, 912 | { url = "https://files.pythonhosted.org/packages/52/6f/151b90792b62fb6f87099bcc9044c626881fdd54e31bf98541f830b15cea/rpds_py-0.23.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c", size = 448784 }, 913 | { url = "https://files.pythonhosted.org/packages/71/2a/6de67c0c97ec7857e0e9e5cd7c52405af931b303eb1e5b9eff6c50fd9a2e/rpds_py-0.23.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5", size = 440203 }, 914 | { url = "https://files.pythonhosted.org/packages/db/5e/e759cd1c276d98a4b1f464b17a9bf66c65d29f8f85754e27e1467feaa7c3/rpds_py-0.23.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc", size = 391611 }, 915 | { url = "https://files.pythonhosted.org/packages/1c/1e/2900358efcc0d9408c7289769cba4c0974d9db314aa884028ed7f7364f61/rpds_py-0.23.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35", size = 423306 }, 916 | { url = "https://files.pythonhosted.org/packages/23/07/6c177e6d059f5d39689352d6c69a926ee4805ffdb6f06203570234d3d8f7/rpds_py-0.23.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b", size = 562323 }, 917 | { url = "https://files.pythonhosted.org/packages/70/e4/f9097fd1c02b516fff9850792161eb9fc20a2fd54762f3c69eae0bdb67cb/rpds_py-0.23.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef", size = 588351 }, 918 | { url = "https://files.pythonhosted.org/packages/87/39/5db3c6f326bfbe4576ae2af6435bd7555867d20ae690c786ff33659f293b/rpds_py-0.23.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad", size = 557252 }, 919 | { url = "https://files.pythonhosted.org/packages/fd/14/2d5ad292f144fa79bafb78d2eb5b8a3a91c358b6065443cb9c49b5d1fedf/rpds_py-0.23.1-cp312-cp312-win32.whl", hash = "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057", size = 222181 }, 920 | { url = "https://files.pythonhosted.org/packages/a3/4f/0fce63e0f5cdd658e71e21abd17ac1bc9312741ebb8b3f74eeed2ebdf771/rpds_py-0.23.1-cp312-cp312-win_amd64.whl", hash = "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165", size = 237426 }, 921 | { url = "https://files.pythonhosted.org/packages/13/9d/b8b2c0edffb0bed15be17b6d5ab06216f2f47f9ee49259c7e96a3ad4ca42/rpds_py-0.23.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935", size = 363672 }, 922 | { url = "https://files.pythonhosted.org/packages/bd/c2/5056fa29e6894144d7ba4c938b9b0445f75836b87d2dd00ed4999dc45a8c/rpds_py-0.23.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4", size = 349602 }, 923 | { url = "https://files.pythonhosted.org/packages/b0/bc/33779a1bb0ee32d8d706b173825aab75c628521d23ce72a7c1e6a6852f86/rpds_py-0.23.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6", size = 388746 }, 924 | { url = "https://files.pythonhosted.org/packages/62/0b/71db3e36b7780a619698ec82a9c87ab44ad7ca7f5480913e8a59ff76f050/rpds_py-0.23.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10", size = 397076 }, 925 | { url = "https://files.pythonhosted.org/packages/bb/2e/494398f613edf77ba10a916b1ddea2acce42ab0e3b62e2c70ffc0757ce00/rpds_py-0.23.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122", size = 448399 }, 926 | { url = "https://files.pythonhosted.org/packages/dd/53/4bd7f5779b1f463243ee5fdc83da04dd58a08f86e639dbffa7a35f969a84/rpds_py-0.23.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4", size = 439764 }, 927 | { url = "https://files.pythonhosted.org/packages/f6/55/b3c18c04a460d951bf8e91f2abf46ce5b6426fb69784166a6a25827cb90a/rpds_py-0.23.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013", size = 390662 }, 928 | { url = "https://files.pythonhosted.org/packages/2a/65/cc463044a3cbd616029b2aa87a651cdee8288d2fdd7780b2244845e934c1/rpds_py-0.23.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64", size = 422680 }, 929 | { url = "https://files.pythonhosted.org/packages/fa/8e/1fa52990c7836d72e8d70cd7753f2362c72fbb0a49c1462e8c60e7176d0b/rpds_py-0.23.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8", size = 561792 }, 930 | { url = "https://files.pythonhosted.org/packages/57/b8/fe3b612979b1a29d0c77f8585903d8b3a292604b26d4b300e228b8ac6360/rpds_py-0.23.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957", size = 588127 }, 931 | { url = "https://files.pythonhosted.org/packages/44/2d/fde474de516bbc4b9b230f43c98e7f8acc5da7fc50ceed8e7af27553d346/rpds_py-0.23.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93", size = 556981 }, 932 | { url = "https://files.pythonhosted.org/packages/18/57/767deeb27b81370bbab8f74ef6e68d26c4ea99018f3c71a570e506fede85/rpds_py-0.23.1-cp313-cp313-win32.whl", hash = "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd", size = 221936 }, 933 | { url = "https://files.pythonhosted.org/packages/7d/6c/3474cfdd3cafe243f97ab8474ea8949236eb2a1a341ca55e75ce00cd03da/rpds_py-0.23.1-cp313-cp313-win_amd64.whl", hash = "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70", size = 237145 }, 934 | { url = "https://files.pythonhosted.org/packages/ec/77/e985064c624230f61efa0423759bb066da56ebe40c654f8b5ba225bd5d63/rpds_py-0.23.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731", size = 359623 }, 935 | { url = "https://files.pythonhosted.org/packages/62/d9/a33dcbf62b29e40559e012d525bae7d516757cf042cc9234bd34ca4b6aeb/rpds_py-0.23.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5", size = 345900 }, 936 | { url = "https://files.pythonhosted.org/packages/92/eb/f81a4be6397861adb2cb868bb6a28a33292c2dcac567d1dc575226055e55/rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a", size = 386426 }, 937 | { url = "https://files.pythonhosted.org/packages/09/47/1f810c9b5e83be005341201b5389f1d240dfa440346ea7189f9b3fd6961d/rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e", size = 392314 }, 938 | { url = "https://files.pythonhosted.org/packages/83/bd/bc95831432fd6c46ed8001f01af26de0763a059d6d7e6d69e3c5bf02917a/rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f", size = 447706 }, 939 | { url = "https://files.pythonhosted.org/packages/19/3e/567c04c226b1802dc6dc82cad3d53e1fa0a773258571c74ac5d8fbde97ed/rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219", size = 437060 }, 940 | { url = "https://files.pythonhosted.org/packages/fe/77/a77d2c6afe27ae7d0d55fc32f6841502648070dc8d549fcc1e6d47ff8975/rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722", size = 389347 }, 941 | { url = "https://files.pythonhosted.org/packages/3f/47/6b256ff20a74cfebeac790ab05586e0ac91f88e331125d4740a6c86fc26f/rpds_py-0.23.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e", size = 415554 }, 942 | { url = "https://files.pythonhosted.org/packages/fc/29/d4572469a245bc9fc81e35166dca19fc5298d5c43e1a6dd64bf145045193/rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6", size = 557418 }, 943 | { url = "https://files.pythonhosted.org/packages/9c/0a/68cf7228895b1a3f6f39f51b15830e62456795e61193d2c8b87fd48c60db/rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b", size = 583033 }, 944 | { url = "https://files.pythonhosted.org/packages/14/18/017ab41dcd6649ad5db7d00155b4c212b31ab05bd857d5ba73a1617984eb/rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5", size = 554880 }, 945 | { url = "https://files.pythonhosted.org/packages/2e/dd/17de89431268da8819d8d51ce67beac28d9b22fccf437bc5d6d2bcd1acdb/rpds_py-0.23.1-cp313-cp313t-win32.whl", hash = "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7", size = 219743 }, 946 | { url = "https://files.pythonhosted.org/packages/68/15/6d22d07e063ce5e9bfbd96db9ec2fbb4693591b4503e3a76996639474d02/rpds_py-0.23.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d", size = 235415 }, 947 | ] 948 | 949 | [[package]] 950 | name = "s3transfer" 951 | version = "0.11.4" 952 | source = { registry = "https://pypi.org/simple" } 953 | dependencies = [ 954 | { name = "botocore" }, 955 | ] 956 | sdist = { url = "https://files.pythonhosted.org/packages/0f/ec/aa1a215e5c126fe5decbee2e107468f51d9ce190b9763cb649f76bb45938/s3transfer-0.11.4.tar.gz", hash = "sha256:559f161658e1cf0a911f45940552c696735f5c74e64362e515f333ebed87d679", size = 148419 } 957 | wheels = [ 958 | { url = "https://files.pythonhosted.org/packages/86/62/8d3fc3ec6640161a5649b2cddbbf2b9fa39c92541225b33f117c37c5a2eb/s3transfer-0.11.4-py3-none-any.whl", hash = "sha256:ac265fa68318763a03bf2dc4f39d5cbd6a9e178d81cc9483ad27da33637e320d", size = 84412 }, 959 | ] 960 | 961 | [[package]] 962 | name = "segments" 963 | version = "2.3.0" 964 | source = { registry = "https://pypi.org/simple" } 965 | dependencies = [ 966 | { name = "csvw" }, 967 | { name = "regex" }, 968 | ] 969 | sdist = { url = "https://files.pythonhosted.org/packages/9b/4c/25e499df952528004ff3f7f8e1e63d20773ed30141ed17c285adb5446f55/segments-2.3.0.tar.gz", hash = "sha256:381143f66f59eaf45398f5bb57f899d6501be011048ec5f92754c9b24b181615", size = 18193 } 970 | wheels = [ 971 | { url = "https://files.pythonhosted.org/packages/11/18/cb614939ccd46d336013cab705f1e11540ec9c68b08ecbb854ab893fc480/segments-2.3.0-py2.py3-none-any.whl", hash = "sha256:30a5656787071430cd22422e04713b2a9beabe1a97d2ebf37f716a56f90577a3", size = 15705 }, 972 | ] 973 | 974 | [[package]] 975 | name = "shellingham" 976 | version = "1.5.4" 977 | source = { registry = "https://pypi.org/simple" } 978 | sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } 979 | wheels = [ 980 | { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, 981 | ] 982 | 983 | [[package]] 984 | name = "six" 985 | version = "1.17.0" 986 | source = { registry = "https://pypi.org/simple" } 987 | sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } 988 | wheels = [ 989 | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, 990 | ] 991 | 992 | [[package]] 993 | name = "sniffio" 994 | version = "1.3.1" 995 | source = { registry = "https://pypi.org/simple" } 996 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } 997 | wheels = [ 998 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, 999 | ] 1000 | 1001 | [[package]] 1002 | name = "soundfile" 1003 | version = "0.13.1" 1004 | source = { registry = "https://pypi.org/simple" } 1005 | dependencies = [ 1006 | { name = "cffi" }, 1007 | { name = "numpy" }, 1008 | ] 1009 | sdist = { url = "https://files.pythonhosted.org/packages/e1/41/9b873a8c055582859b239be17902a85339bec6a30ad162f98c9b0288a2cc/soundfile-0.13.1.tar.gz", hash = "sha256:b2c68dab1e30297317080a5b43df57e302584c49e2942defdde0acccc53f0e5b", size = 46156 } 1010 | wheels = [ 1011 | { url = "https://files.pythonhosted.org/packages/64/28/e2a36573ccbcf3d57c00626a21fe51989380636e821b341d36ccca0c1c3a/soundfile-0.13.1-py2.py3-none-any.whl", hash = "sha256:a23c717560da2cf4c7b5ae1142514e0fd82d6bbd9dfc93a50423447142f2c445", size = 25751 }, 1012 | { url = "https://files.pythonhosted.org/packages/ea/ab/73e97a5b3cc46bba7ff8650a1504348fa1863a6f9d57d7001c6b67c5f20e/soundfile-0.13.1-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:82dc664d19831933fe59adad199bf3945ad06d84bc111a5b4c0d3089a5b9ec33", size = 1142250 }, 1013 | { url = "https://files.pythonhosted.org/packages/a0/e5/58fd1a8d7b26fc113af244f966ee3aecf03cb9293cb935daaddc1e455e18/soundfile-0.13.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:743f12c12c4054921e15736c6be09ac26b3b3d603aef6fd69f9dde68748f2593", size = 1101406 }, 1014 | { url = "https://files.pythonhosted.org/packages/58/ae/c0e4a53d77cf6e9a04179535766b3321b0b9ced5f70522e4caf9329f0046/soundfile-0.13.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9c9e855f5a4d06ce4213f31918653ab7de0c5a8d8107cd2427e44b42df547deb", size = 1235729 }, 1015 | { url = "https://files.pythonhosted.org/packages/57/5e/70bdd9579b35003a489fc850b5047beeda26328053ebadc1fb60f320f7db/soundfile-0.13.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:03267c4e493315294834a0870f31dbb3b28a95561b80b134f0bd3cf2d5f0e618", size = 1313646 }, 1016 | { url = "https://files.pythonhosted.org/packages/fe/df/8c11dc4dfceda14e3003bb81a0d0edcaaf0796dd7b4f826ea3e532146bba/soundfile-0.13.1-py2.py3-none-win32.whl", hash = "sha256:c734564fab7c5ddf8e9be5bf70bab68042cd17e9c214c06e365e20d64f9a69d5", size = 899881 }, 1017 | { url = "https://files.pythonhosted.org/packages/14/e9/6b761de83277f2f02ded7e7ea6f07828ec78e4b229b80e4ca55dd205b9dc/soundfile-0.13.1-py2.py3-none-win_amd64.whl", hash = "sha256:1e70a05a0626524a69e9f0f4dd2ec174b4e9567f4d8b6c11d38b5c289be36ee9", size = 1019162 }, 1018 | ] 1019 | 1020 | [[package]] 1021 | name = "sse-starlette" 1022 | version = "2.2.1" 1023 | source = { registry = "https://pypi.org/simple" } 1024 | dependencies = [ 1025 | { name = "anyio" }, 1026 | { name = "starlette" }, 1027 | ] 1028 | sdist = { url = "https://files.pythonhosted.org/packages/71/a4/80d2a11af59fe75b48230846989e93979c892d3a20016b42bb44edb9e398/sse_starlette-2.2.1.tar.gz", hash = "sha256:54470d5f19274aeed6b2d473430b08b4b379ea851d953b11d7f1c4a2c118b419", size = 17376 } 1029 | wheels = [ 1030 | { url = "https://files.pythonhosted.org/packages/d9/e0/5b8bd393f27f4a62461c5cf2479c75a2cc2ffa330976f9f00f5f6e4f50eb/sse_starlette-2.2.1-py3-none-any.whl", hash = "sha256:6410a3d3ba0c89e7675d4c273a301d64649c03a5ef1ca101f10b47f895fd0e99", size = 10120 }, 1031 | ] 1032 | 1033 | [[package]] 1034 | name = "starlette" 1035 | version = "0.46.1" 1036 | source = { registry = "https://pypi.org/simple" } 1037 | dependencies = [ 1038 | { name = "anyio" }, 1039 | ] 1040 | sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 } 1041 | wheels = [ 1042 | { url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 }, 1043 | ] 1044 | 1045 | [[package]] 1046 | name = "sympy" 1047 | version = "1.13.3" 1048 | source = { registry = "https://pypi.org/simple" } 1049 | dependencies = [ 1050 | { name = "mpmath" }, 1051 | ] 1052 | sdist = { url = "https://files.pythonhosted.org/packages/11/8a/5a7fd6284fa8caac23a26c9ddf9c30485a48169344b4bd3b0f02fef1890f/sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9", size = 7533196 } 1053 | wheels = [ 1054 | { url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 }, 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "typer" 1059 | version = "0.15.2" 1060 | source = { registry = "https://pypi.org/simple" } 1061 | dependencies = [ 1062 | { name = "click" }, 1063 | { name = "rich" }, 1064 | { name = "shellingham" }, 1065 | { name = "typing-extensions" }, 1066 | ] 1067 | sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 } 1068 | wheels = [ 1069 | { url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 }, 1070 | ] 1071 | 1072 | [[package]] 1073 | name = "typing-extensions" 1074 | version = "4.12.2" 1075 | source = { registry = "https://pypi.org/simple" } 1076 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } 1077 | wheels = [ 1078 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "uritemplate" 1083 | version = "4.1.1" 1084 | source = { registry = "https://pypi.org/simple" } 1085 | sdist = { url = "https://files.pythonhosted.org/packages/d2/5a/4742fdba39cd02a56226815abfa72fe0aa81c33bed16ed045647d6000eba/uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", size = 273898 } 1086 | wheels = [ 1087 | { url = "https://files.pythonhosted.org/packages/81/c0/7461b49cd25aeece13766f02ee576d1db528f1c37ce69aee300e075b485b/uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e", size = 10356 }, 1088 | ] 1089 | 1090 | [[package]] 1091 | name = "urllib3" 1092 | version = "2.3.0" 1093 | source = { registry = "https://pypi.org/simple" } 1094 | sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } 1095 | wheels = [ 1096 | { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "uvicorn" 1101 | version = "0.34.0" 1102 | source = { registry = "https://pypi.org/simple" } 1103 | dependencies = [ 1104 | { name = "click" }, 1105 | { name = "h11" }, 1106 | ] 1107 | sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } 1108 | wheels = [ 1109 | { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, 1110 | ] 1111 | 1112 | [[package]] 1113 | name = "werkzeug" 1114 | version = "3.1.3" 1115 | source = { registry = "https://pypi.org/simple" } 1116 | dependencies = [ 1117 | { name = "markupsafe" }, 1118 | ] 1119 | sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } 1120 | wheels = [ 1121 | { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, 1122 | ] 1123 | --------------------------------------------------------------------------------