update bug

This commit is contained in:
2025-08-26 02:50:40 +09:00
parent f1f5ad04f1
commit de0a146eb1
6 changed files with 485 additions and 199 deletions

249
diagnostic.py Normal file
View File

@@ -0,0 +1,249 @@
"""
Test script to diagnose FLUX.1 Edit MCP Server issues
"""
import sys
import os
import asyncio
import logging
from pathlib import Path
# Add src to path
sys.path.insert(0, str(Path(__file__).parent / 'src'))
def test_imports():
"""Test all required imports"""
print("🔍 Testing imports...")
# Test standard library imports
try:
import json
import logging
import asyncio
print("✅ Standard library imports OK")
except ImportError as e:
print(f"❌ Standard library import failed: {e}")
return False
# Test third-party dependencies
deps = {
'aiohttp': '3.11.7',
'httpx': '0.28.1',
'mcp': '1.1.0+',
'PIL': 'Pillow 11.0.0',
'dotenv': 'python-dotenv 1.0.1',
'pydantic': '2.10.3'
}
for module, expected in deps.items():
try:
__import__(module)
print(f"{module} ({expected}) OK")
except ImportError as e:
print(f"{module} missing: {e}")
return False
# Test MCP specific imports
try:
import mcp.types as types
import mcp.server
from mcp.server import Server
from mcp.server.stdio import stdio_server
print("✅ MCP imports OK")
except ImportError as e:
print(f"❌ MCP import failed: {e}")
return False
# Test local module imports
try:
from src.connector import Config
print("✅ Config import OK")
except ImportError as e:
print(f"❌ Config import failed: {e}")
return False
try:
from src.server.models import TOOL_DEFINITIONS, ToolName
print("✅ Models import OK")
except ImportError as e:
print(f"❌ Models import failed: {e}")
return False
try:
from src.server.handlers import ToolHandlers
print("✅ Handlers import OK")
except ImportError as e:
print(f"❌ Handlers import failed: {e}")
return False
try:
from src.utils import validate_edit_parameters
print("✅ Utils import OK")
except ImportError as e:
print(f"❌ Utils import failed: {e}")
return False
return True
def test_config():
"""Test configuration loading"""
print("\n🔍 Testing configuration...")
try:
from src.connector import Config
config = Config()
print(f"✅ Config loaded")
print(f" - API key: {'***' + config.api_key[-4:] if config.api_key else 'Not Set'}")
print(f" - Input path: {config.input_path}")
print(f" - Output path: {config.generated_images_path}")
# Test config validation
if config.validate():
print("✅ Config validation passed")
else:
print("❌ Config validation failed")
return False
return True
except Exception as e:
print(f"❌ Config test failed: {e}")
return False
def test_mcp_server_creation():
"""Test MCP server creation"""
print("\n🔍 Testing MCP server creation...")
try:
from src.server.mcp_server import FluxEditMCPServer
server = FluxEditMCPServer()
print("✅ MCP server created successfully")
# Test tool definitions
from src.server.models import TOOL_DEFINITIONS
print(f"✅ Tool definitions loaded: {len(TOOL_DEFINITIONS)} tools")
for tool_name in TOOL_DEFINITIONS:
print(f" - {tool_name}")
return True
except Exception as e:
print(f"❌ MCP server creation failed: {e}")
import traceback
traceback.print_exc()
return False
async def test_mcp_server_init():
"""Test MCP server initialization"""
print("\n🔍 Testing MCP server initialization...")
try:
from src.server.mcp_server import create_server
server = create_server()
print("✅ MCP server initialized")
# Test configuration validation
if server.validate_config():
print("✅ Server config validation passed")
else:
print("❌ Server config validation failed")
return False
return True
except Exception as e:
print(f"❌ MCP server initialization failed: {e}")
import traceback
traceback.print_exc()
return False
def test_directories():
"""Test directory structure"""
print("\n🔍 Testing directory structure...")
base_path = Path(__file__).parent
required_dirs = [
'src',
'src/connector',
'src/server',
'src/utils',
'input_images',
'generated_images'
]
for dir_path in required_dirs:
full_path = base_path / dir_path
if full_path.exists():
print(f"{dir_path}/")
else:
print(f"{dir_path}/ (missing)")
try:
full_path.mkdir(parents=True, exist_ok=True)
print(f"✅ Created {dir_path}/")
except Exception as e:
print(f"❌ Failed to create {dir_path}/: {e}")
return False
return True
def main():
"""Main test function"""
print("🚀 FLUX.1 Edit MCP Server Diagnostic Tool")
print("=" * 50)
tests = [
("Directory Structure", test_directories),
("Import Dependencies", test_imports),
("Configuration", test_config),
("MCP Server Creation", test_mcp_server_creation),
("MCP Server Initialization", lambda: asyncio.run(test_mcp_server_init())),
]
results = []
for test_name, test_func in tests:
print(f"\n📋 Running {test_name}...")
try:
result = test_func()
results.append((test_name, result))
if result:
print(f"{test_name} PASSED")
else:
print(f"{test_name} FAILED")
except Exception as e:
print(f"{test_name} FAILED with exception: {e}")
results.append((test_name, False))
# Summary
print("\n" + "=" * 50)
print("📊 DIAGNOSTIC SUMMARY")
print("=" * 50)
passed = sum(1 for _, result in results if result)
total = len(results)
for test_name, result in results:
status = "✅ PASS" if result else "❌ FAIL"
print(f"{status} {test_name}")
print(f"\n🎯 Results: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! Server should work correctly.")
else:
print("🔧 Some tests failed. Please fix the issues above.")
return passed == total
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)

119
main.py
View File

@@ -1,123 +1,30 @@
"""Main entry point for FLUX.1 Edit MCP Server"""
import asyncio
import logging
import sys
import traceback
from pathlib import Path
# Add src to path for imports
sys.path.insert(0, str(Path(__file__).parent / 'src'))
def setup_logging():
"""Setup logging configuration"""
# Only log to file, not stdout to avoid JSON parsing issues
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('flux1-edit.log', mode='a', encoding='utf-8')
]
)
# Set specific loggers
logging.getLogger('aiohttp').setLevel(logging.WARNING)
logging.getLogger('PIL').setLevel(logging.WARNING)
def check_dependencies():
"""Check if all required dependencies are available - silently check for MCP compatibility"""
missing_deps = []
try:
import aiohttp
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"aiohttp: {e}")
try:
import httpx
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"httpx: {e}")
try:
import mcp
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"mcp: {e}")
try:
from PIL import Image
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"Pillow: {e}")
try:
import dotenv
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"python-dotenv: {e}")
try:
import pydantic
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
missing_deps.append(f"pydantic: {e}")
if missing_deps:
# Log to file instead of print to avoid JSON parsing issues
logger = logging.getLogger(__name__)
logger.error(f"Missing dependencies: {missing_deps}")
return False
return True
def check_local_imports():
"""Check if local modules can be imported - silently check for MCP compatibility"""
logger = logging.getLogger(__name__)
try:
from src.connector import Config
# Silent check - no print to avoid JSON parsing issues
except ImportError as e:
logger.error(f"Failed to import local Config: {e}")
return False
try:
from src.server import main
# Silent check - no print to avoid JSON parsing issues
return True
except ImportError as e:
logger.error(f"Failed to import local server main: {e}", exc_info=True)
return False
if __name__ == "__main__":
setup_logging()
logger = logging.getLogger(__name__)
# Check dependencies first - silently for MCP compatibility
if not check_dependencies():
logger.error("Dependencies check failed")
sys.exit(1)
# Check local imports - silently for MCP compatibility
if not check_local_imports():
logger.error("Local imports check failed")
sys.exit(1)
# Start the MCP server without console output to avoid JSON parsing issues
try:
# Import main function after checks
from src.server import main
logger.info("Starting FLUX.1 Edit MCP Server...")
# Import and run the main server function
from src.server.mcp_server import main
asyncio.run(main())
except KeyboardInterrupt:
logger.info("Server stopped by user")
sys.exit(0)
except Exception as e:
logger.error(f"Server error: {e}", exc_info=True)
# Log to stderr for debugging, but avoid stdout pollution for MCP
import logging
logging.basicConfig(
level=logging.ERROR,
format='%(asctime)s [%(name)s] %(levelname)s: %(message)s',
handlers=[
logging.FileHandler('flux1-edit.log', mode='a', encoding='utf-8')
]
)
logger = logging.getLogger(__name__)
logger.error(f"Fatal error: {e}", exc_info=True)
sys.exit(1)

View File

@@ -1,7 +1,7 @@
# FLUX.1 Edit MCP Server Dependencies
# Core MCP Server
mcp==1.1.0
# Core MCP Server - Updated version
mcp==1.2.0
# HTTP Client for FLUX API
httpx==0.28.1

126
simple_test.py Normal file
View File

@@ -0,0 +1,126 @@
"""
Simple test script for FLUX.1 Edit MCP Server
"""
import sys
import asyncio
import json
from pathlib import Path
# Add src to path
sys.path.insert(0, str(Path(__file__).parent / 'src'))
async def test_server_import():
"""Test if the server can be imported and initialized"""
print("🔍 Testing server import and initialization...")
try:
# Test imports
from src.server.mcp_server import create_server
from src.connector import Config
print("✅ Successfully imported server components")
# Test configuration
config = Config()
if config.validate():
print("✅ Configuration validation passed")
else:
print("❌ Configuration validation failed")
return False
# Test server creation
server = create_server()
print("✅ Server created successfully")
# Test server validation
if server.validate_config():
print("✅ Server configuration validated")
else:
print("❌ Server configuration validation failed")
return False
return True
except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
return False
async def test_mcp_protocol():
"""Test MCP protocol basics"""
print("\n🔍 Testing MCP protocol basics...")
try:
import mcp.types as types
from mcp.server import Server
from mcp.server.stdio import stdio_server
print("✅ MCP imports successful")
# Create a minimal server for testing
server = Server("test-server")
@server.list_tools()
async def list_tools():
return [
types.Tool(
name="test_tool",
description="Test tool",
inputSchema={
"type": "object",
"properties": {
"test_param": {
"type": "string",
"description": "Test parameter"
}
},
"required": ["test_param"]
}
)
]
print("✅ MCP server handlers configured")
return True
except Exception as e:
print(f"❌ MCP protocol test failed: {e}")
import traceback
traceback.print_exc()
return False
def main():
"""Main test function"""
print("🚀 FLUX.1 Edit MCP Server - Simple Test")
print("=" * 50)
# Run async tests
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
test1_result = loop.run_until_complete(test_server_import())
test2_result = loop.run_until_complete(test_mcp_protocol())
print("\n" + "=" * 50)
print("📊 TEST RESULTS")
print("=" * 50)
print(f"Server Import & Init: {'✅ PASS' if test1_result else '❌ FAIL'}")
print(f"MCP Protocol Basic: {'✅ PASS' if test2_result else '❌ FAIL'}")
if test1_result and test2_result:
print("\n🎉 All tests passed! Server should be ready.")
print("\n💡 Try running: python main.py")
return True
else:
print("\n🔧 Some tests failed. Check the errors above.")
return False
finally:
loop.close()
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)

View File

@@ -5,9 +5,8 @@ import asyncio
from typing import Dict, Any, List
import mcp.types as types
from mcp import server
from mcp.server import Server
from mcp.server.models import InitializationOptions
from mcp.server.stdio import stdio_server
from ..connector import Config
from .models import TOOL_DEFINITIONS, ToolName
@@ -16,23 +15,44 @@ from .handlers import ToolHandlers
logger = logging.getLogger(__name__)
class FluxEditMCPServer:
"""FLUX.1 Edit MCP Server"""
async def main():
"""Main entry point for the MCP server"""
def __init__(self):
"""Initialize the MCP server"""
self.config = Config()
self.app = Server("flux1-edit")
self.handlers = ToolHandlers(self.config)
self._setup_handlers()
logger.info("FLUX.1 Edit MCP Server initialized")
# Setup logging with minimal output for MCP compatibility
logging.basicConfig(
level=logging.WARNING, # Only warnings and errors
format='%(asctime)s [%(name)s] %(levelname)s: %(message)s',
handlers=[
logging.FileHandler('flux1-edit.log', mode='a', encoding='utf-8')
]
)
def _setup_handlers(self):
"""Setup MCP server handlers"""
# Silence noisy loggers completely
logging.getLogger('aiohttp').setLevel(logging.ERROR)
logging.getLogger('PIL').setLevel(logging.ERROR)
logging.getLogger('httpx').setLevel(logging.ERROR)
logger = logging.getLogger(__name__)
try:
# Create configuration
config = Config()
# List tools handler
@self.app.list_tools()
# Validate configuration
if not config.validate():
logger.error("Configuration validation failed")
raise RuntimeError("Configuration validation failed")
# Create MCP server
server = Server("flux1-edit")
# Create tool handlers
handlers = ToolHandlers(config)
logger.info("Setting up MCP server handlers...")
# Set up list_tools handler
@server.list_tools()
async def list_tools() -> List[types.Tool]:
"""List available tools"""
tools = []
@@ -76,23 +96,32 @@ class FluxEditMCPServer:
logger.debug(f"Listed {len(tools)} tools")
return tools
# Call tool handler
@self.app.call_tool()
# Set up call_tool handler
@server.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]) -> List[types.TextContent | types.ImageContent]:
"""Handle tool calls"""
try:
logger.info(f"Tool call: {name}")
logger.debug(f"Arguments: {self._sanitize_args_for_logging(arguments)}")
# Sanitize arguments for logging
safe_args = arguments.copy()
if 'input_image_b64' in safe_args:
b64_data = safe_args['input_image_b64']
safe_args['input_image_b64'] = f"<base64 image data: {len(b64_data)} chars>"
if 'prompt' in safe_args and len(safe_args['prompt']) > 100:
safe_args['prompt'] = safe_args['prompt'][:100] + '...'
logger.debug(f"Arguments: {safe_args}")
# Route to appropriate handler
if name == ToolName.FLUX_EDIT_IMAGE:
return await self.handlers.handle_flux_edit_image(arguments)
return await handlers.handle_flux_edit_image(arguments)
elif name == ToolName.FLUX_EDIT_IMAGE_FROM_FILE:
return await self.handlers.handle_flux_edit_image_from_file(arguments)
return await handlers.handle_flux_edit_image_from_file(arguments)
elif name == ToolName.VALIDATE_IMAGE:
return await self.handlers.handle_validate_image(arguments)
return await handlers.handle_validate_image(arguments)
elif name == ToolName.MOVE_TEMP_TO_OUTPUT:
return await self.handlers.handle_move_temp_to_output(arguments)
return await handlers.handle_move_temp_to_output(arguments)
else:
return [types.TextContent(
type="text",
@@ -105,74 +134,39 @@ class FluxEditMCPServer:
type="text",
text=f"[ERROR] Tool execution error: {str(e)}"
)]
logger.info("Starting FLUX.1 Edit MCP Server...")
logger.info(f"API key configured: {'Yes' if config.api_key else 'No'}")
logger.info(f"Input directory: {config.input_path}")
logger.info(f"Output directory: {config.generated_images_path}")
# Run the server using stdio
await stdio_server(server)
except Exception as e:
logger.error(f"Server startup failed: {e}", exc_info=True)
raise
class FluxEditMCPServer:
"""Legacy wrapper class (kept for compatibility)"""
def _sanitize_args_for_logging(self, args: Dict[str, Any]) -> Dict[str, Any]:
"""
Remove sensitive data from arguments for logging
Args:
args: Original arguments
Returns:
dict: Sanitized arguments
"""
safe_args = args.copy()
# Don't log full base64 image data
if 'input_image_b64' in safe_args:
b64_data = safe_args['input_image_b64']
safe_args['input_image_b64'] = f"<base64 image data: {len(b64_data)} chars>"
# Truncate long prompts
if 'prompt' in safe_args and len(safe_args['prompt']) > 100:
safe_args['prompt'] = safe_args['prompt'][:100] + '...'
return safe_args
def __init__(self):
"""Initialize the MCP server"""
self.config = Config()
self.server = Server("flux1-edit")
self.handlers = ToolHandlers(self.config)
logger.info("FLUX.1 Edit MCP Server initialized")
def validate_config(self) -> bool:
"""Validate server configuration"""
return self.config.validate()
async def run(self):
"""Run the MCP server"""
if not self.validate_config():
logger.error("Configuration validation failed")
return False
logger.info("Starting FLUX.1 Edit MCP Server...")
logger.info(f"Configuration:\n{self.config}")
# Run the server
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await self.app.run(
read_stream,
write_stream,
InitializationOptions(
server_name="flux1-edit",
server_version="1.0.0"
)
)
# Server factory function
def create_server() -> FluxEditMCPServer:
"""Create and return a FLUX.1 Edit MCP Server instance"""
return FluxEditMCPServer()
# Main function for running the server
async def main():
"""Main entry point for the server"""
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Create and run server
server_instance = create_server()
await server_instance.run()
if __name__ == "__main__":
asyncio.run(main())

View File

@@ -2,24 +2,34 @@
echo FLUX.1 Edit MCP Server - Quick Start
echo ====================================
echo Checking dependencies first...
REM Set UTF-8 encoding to prevent Unicode errors
chcp 65001 >nul 2>&1
set PYTHONIOENCODING=utf-8
set PYTHONUTF8=1
python check_dependencies.py
echo Running simple test first...
python simple_test.py
if errorlevel 1 (
echo.
echo Dependencies check failed. Running installation...
call install_dependencies.bat
if errorlevel 1 (
echo Failed to install dependencies.
pause
exit /b 1
)
echo Simple test failed. Please check the errors above.
pause
exit /b 1
)
echo.
echo Dependencies OK! Running original startup script...
echo Simple test passed! Starting MCP server...
echo.
call run.bat
REM Start the main MCP server
python main.py
if errorlevel 1 (
echo.
echo Server failed to start. Check flux1-edit.log for details.
pause
exit /b 1
)
echo.
echo Server stopped.
pause