#!/usr/bin/env python3 """Verify MCP Office Tools installation and basic functionality.""" import asyncio import sys import tempfile import os from pathlib import Path # Add the package to Python path for local testing sys.path.insert(0, str(Path(__file__).parent.parent / "src")) def create_sample_csv(): """Create a sample CSV file for testing.""" temp_file = tempfile.NamedTemporaryFile(suffix='.csv', delete=False, mode='w') temp_file.write("""Name,Age,Department,Salary John Smith,30,Engineering,75000 Jane Doe,25,Marketing,65000 Bob Johnson,35,Sales,70000 Alice Brown,28,Engineering,80000 Charlie Wilson,32,HR,60000""") temp_file.close() return temp_file.name def test_import(): """Test that the package can be imported.""" print("šŸ” Testing package import...") try: import mcp_office_tools print(f"āœ… Package imported successfully - Version: {mcp_office_tools.__version__}") # Test server import from mcp_office_tools.server import app print("āœ… Server module imported successfully") # Test utils import from mcp_office_tools.utils import OfficeFileError, get_supported_extensions print("āœ… Utils module imported successfully") # Test supported extensions extensions = get_supported_extensions() print(f"āœ… Supported extensions: {', '.join(extensions)}") return True except Exception as e: print(f"āŒ Import failed: {e}") import traceback traceback.print_exc() return False async def test_utils(): """Test utility functions.""" print("\nšŸ”§ Testing utility functions...") try: from mcp_office_tools.utils import ( detect_file_format, validate_office_path, OfficeFileError ) # Test format detection with a CSV file csv_file = create_sample_csv() try: # Test file path validation validated_path = validate_office_path(csv_file) print(f"āœ… File path validation successful: {os.path.basename(validated_path)}") # Test format detection format_info = detect_file_format(csv_file) print(f"āœ… Format detection successful: {format_info['format_name']}") print(f"šŸ“‚ Category: {format_info['category']}") print(f"šŸ“Š File size: {format_info['file_size']} bytes") # Test invalid file handling try: validate_office_path("/nonexistent/file.docx") print("āŒ Should have raised error for nonexistent file") return False except OfficeFileError: print("āœ… Correctly handles nonexistent files") return True finally: os.unlink(csv_file) except Exception as e: print(f"āŒ Utils test failed: {e}") import traceback traceback.print_exc() return False def test_server_structure(): """Test server structure and tools.""" print("\nšŸ–„ļø Testing server structure...") try: from mcp_office_tools.server import app # Check that app has tools if hasattr(app, '_tools'): tools = app._tools print(f"āœ… Server has {len(tools)} tools registered") # List tool names tool_names = list(tools.keys()) if isinstance(tools, dict) else [str(tool) for tool in tools] print(f"šŸ”§ Available tools: {', '.join(tool_names[:5])}...") # Show first 5 else: print("āš ļø Cannot access tool registry (FastMCP internal structure)") # Test that the app can be created print("āœ… FastMCP app structure is valid") return True except Exception as e: print(f"āŒ Server structure test failed: {e}") import traceback traceback.print_exc() return False async def test_caching(): """Test caching functionality.""" print("\nšŸ“¦ Testing caching functionality...") try: from mcp_office_tools.utils.caching import OfficeFileCache, get_cache # Test cache creation cache = get_cache() print("āœ… Cache instance created successfully") # Test cache stats stats = cache.get_cache_stats() print(f"āœ… Cache stats: {stats['total_files']} files, {stats['total_size_mb']} MB") # Test URL validation from mcp_office_tools.utils.validation import is_url assert is_url("https://example.com/file.docx") assert not is_url("/local/path/file.docx") print("āœ… URL validation working correctly") return True except Exception as e: print(f"āŒ Caching test failed: {e}") import traceback traceback.print_exc() return False def test_dependencies(): """Test that key dependencies are available.""" print("\nšŸ“š Testing dependencies...") dependencies = [ ("fastmcp", "FastMCP framework"), ("docx", "python-docx for Word documents"), ("openpyxl", "openpyxl for Excel files"), ("pptx", "python-pptx for PowerPoint files"), ("pandas", "pandas for data processing"), ("aiohttp", "aiohttp for async HTTP"), ("aiofiles", "aiofiles for async file operations"), ("PIL", "Pillow for image processing") ] success_count = 0 for module_name, description in dependencies: try: __import__(module_name) print(f"āœ… {description}") success_count += 1 except ImportError: print(f"āŒ {description} - NOT AVAILABLE") optional_dependencies = [ ("magic", "python-magic for MIME detection (optional)"), ("olefile", "olefile for legacy Office formats"), ("mammoth", "mammoth for enhanced Word processing"), ("xlrd", "xlrd for legacy Excel files") ] for module_name, description in optional_dependencies: try: __import__(module_name) print(f"āœ… {description}") except ImportError: print(f"āš ļø {description} - OPTIONAL") return success_count == len(dependencies) async def main(): """Main verification function.""" print("šŸš€ MCP Office Tools - Installation Verification") print("=" * 60) success_count = 0 total_tests = 0 # Test import total_tests += 1 if test_import(): success_count += 1 # Test utilities total_tests += 1 if await test_utils(): success_count += 1 # Test server structure total_tests += 1 if test_server_structure(): success_count += 1 # Test caching total_tests += 1 if await test_caching(): success_count += 1 # Test dependencies total_tests += 1 if test_dependencies(): success_count += 1 # Summary print("\n" + "=" * 60) print(f"šŸ“Š Verification Results: {success_count}/{total_tests} tests passed") if success_count == total_tests: print("šŸŽ‰ Installation verified successfully!") print("āœ… MCP Office Tools is ready to use.") print("\nšŸš€ Next steps:") print(" 1. Run the MCP server: uv run mcp-office-tools") print(" 2. Add to Claude Desktop config") print(" 3. Test with Office documents") return 0 else: print("āš ļø Some verification tests failed.") print("šŸ“ Check the output above for details.") return 1 if __name__ == "__main__": exit_code = asyncio.run(main())