Skip to main content
Glama

Auto Favicon MCP Server

by dh1011
server.py7.5 kB
#!/usr/bin/env python3 """ MCP FastMCP Server for Automatic Favicon Generation This server provides tools to generate favicons from PNG images or URLs. It creates a complete favicon set including various sizes and a manifest.json file. """ import asyncio import json import os import tempfile from pathlib import Path from typing import Any, Dict, List, Optional from urllib.parse import urlparse import aiohttp from PIL import Image from mcp.server.fastmcp import FastMCP mcp = FastMCP(name="favicon-generator") FAVICON_SIZES = [16, 32, 48, 64, 128, 256] ICO_SIZES = [16, 32, 48] APPLE_SIZES = [180, 152, 144, 120, 114, 76, 72, 60, 57] def validate_absolute_path(path: str, path_type: str) -> Path: """Validate that a path is absolute and exists (for files) or can be created (for directories).""" path_obj = Path(path) if not path_obj.is_absolute(): raise ValueError(f"{path_type} must be an absolute path: {path}") return path_obj def create_favicon_set(image_data: bytes, output_dir: str) -> Dict[str, Any]: """Create a complete favicon set from image data.""" # Write image data to a temp file with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file: temp_file.write(image_data) temp_file.flush() temp_path = temp_file.name try: with Image.open(temp_path) as img: # Convert to RGBA if needed if img.mode != 'RGBA': img = img.convert('RGBA') output_path = Path(output_dir) output_path.mkdir(parents=True, exist_ok=True) generated_files = [] # Generate PNG favicons for size in FAVICON_SIZES: resized = img.resize((size, size), Image.Resampling.LANCZOS) filename = f"favicon-{size}x{size}.png" filepath = output_path / filename resized.save(filepath, "PNG") generated_files.append(str(filepath)) # Generate ICO file ico_images = [img.resize((size, size), Image.Resampling.LANCZOS) for size in ICO_SIZES] ico_path = output_path / "favicon.ico" ico_images[0].save(ico_path, format='ICO', sizes=[(size, size) for size in ICO_SIZES]) generated_files.append(str(ico_path)) # Generate Apple touch icons for size in APPLE_SIZES: resized = img.resize((size, size), Image.Resampling.LANCZOS) filename = f"apple-touch-icon-{size}x{size}.png" filepath = output_path / filename resized.save(filepath, "PNG") generated_files.append(str(filepath)) # Generate manifest.json manifest = { "name": "Favicon App", "short_name": "Favicon", "description": "Generated favicon application", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#000000", "icons": [ { "src": f"favicon-{size}x{size}.png", "sizes": f"{size}x{size}", "type": "image/png" } for size in FAVICON_SIZES ] } manifest_path = output_path / "manifest.json" with open(manifest_path, 'w') as f: json.dump(manifest, f, indent=2) generated_files.append(str(manifest_path)) return { "generated_files": generated_files, "manifest": manifest, "output_directory": str(output_path) } finally: os.unlink(temp_path) @mcp.tool() async def generate_favicon_from_png(image_path: str, output_path: str) -> str: """ Generate a complete favicon set from a PNG image file. Args: image_path: Absolute path to the PNG image file. output_path: Absolute path to the directory where favicon files will be generated. Returns: A message describing the generated files and output directory. """ try: # Validate absolute paths image_path_obj = validate_absolute_path(image_path, "image_path") output_path_obj = validate_absolute_path(output_path, "output_path") # Check if image file exists if not image_path_obj.exists(): return f"Error: Image file does not exist: {image_path}" if not image_path_obj.is_file(): return f"Error: Path is not a file: {image_path}" # Check if output directory can be created try: output_path_obj.mkdir(parents=True, exist_ok=True) except Exception as e: return f"Error: Cannot create output directory {output_path}: {str(e)}" with open(image_path_obj, 'rb') as f: image_data = f.read() result = create_favicon_set(image_data, str(output_path_obj)) return ( f"Successfully generated favicon set!\n\n" f"Output directory: {result['output_directory']}\n" f"Generated files:\n" + "\n".join(f"- {f}" for f in result['generated_files']) ) except ValueError as e: return f"Error: {str(e)}" except Exception as e: return f"Error generating favicon: {str(e)}" @mcp.tool() async def generate_favicon_from_url(image_url: str, output_path: str) -> str: """ Download an image from a URL and generate a complete favicon set. Args: image_url: URL of the image to download. output_path: Absolute path to the directory where favicon files will be generated. Returns: A message describing the generated files and output directory. """ try: # Validate absolute path for output directory output_path_obj = validate_absolute_path(output_path, "output_path") # Check if output directory can be created try: output_path_obj.mkdir(parents=True, exist_ok=True) except Exception as e: return f"Error: Cannot create output directory {output_path}: {str(e)}" async with aiohttp.ClientSession() as session: async with session.get(image_url) as response: response.raise_for_status() image_data = await response.read() result = create_favicon_set(image_data, str(output_path_obj)) return ( f"Successfully downloaded image from {image_url} and generated favicon set!\n\n" f"Output directory: {result['output_directory']}\n" f"Generated files:\n" + "\n".join(f"- {f}" for f in result['generated_files']) ) except ValueError as e: return f"Error: {str(e)}" except Exception as e: return f"Error generating favicon from URL: {str(e)}" def main(): """MCP Auto Favicon Server - Automatic favicon generation functionality for MCP""" import argparse parser = argparse.ArgumentParser( description="Generate favicons from PNG images or URLs" ) parser.add_argument( "--output-dir", type=str, default="./favicons", help="Default output directory for generated favicons" ) args = parser.parse_args() # Initialize and run the server mcp.run(transport='stdio') if __name__ == "__main__": main()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dh1011/auto-favicon-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server