Spaces:
Sleeping
Sleeping
import gradio as gr | |
import base64 | |
import json | |
import requests | |
from io import BytesIO | |
from PIL import Image | |
import traceback | |
from gradio_client import Client | |
from typing import Optional, Tuple, Dict, Any | |
class MCPImageAnalyzer: | |
def __init__(self, space_url: str = "https://chris4k-mcp-images.hf.space"): | |
"""Initialize the MCP Image Analyzer client.""" | |
self.space_url = space_url.rstrip('/') | |
self.client = None | |
self.connection_status = "Disconnected" | |
def connect(self) -> Tuple[str, str]: | |
"""Connect to the MCP server.""" | |
try: | |
self.client = Client(self.space_url) | |
# Test connection by checking if we can get the client info | |
self.connection_status = "Connected β " | |
return f"β Successfully connected to {self.space_url}", "success" | |
except Exception as e: | |
self.connection_status = "Connection Failed β" | |
return f"β Failed to connect to {self.space_url}: {str(e)}", "error" | |
def analyze_image(self, image: Image.Image) -> Dict[str, Any]: | |
"""Analyze an image using the MCP server.""" | |
if not self.client: | |
return {"error": "Not connected to MCP server. Please connect first."} | |
if image is None: | |
return {"error": "No image provided"} | |
try: | |
result = self.client.predict( | |
image=image, | |
api_name="/analyze_image" | |
) | |
return json.loads(result) if isinstance(result, str) else result | |
except Exception as e: | |
return {"error": f"Analysis failed: {str(e)}"} | |
def get_orientation(self, image: Image.Image) -> str: | |
"""Get image orientation using the MCP server.""" | |
if not self.client: | |
return "β Not connected to MCP server" | |
if image is None: | |
return "β No image provided" | |
try: | |
result = self.client.predict( | |
image=image, | |
api_name="/get_image_orientation" | |
) | |
return f"π Orientation: {result}" | |
except Exception as e: | |
return f"β Error: {str(e)}" | |
def analyze_colors(self, image: Image.Image) -> str: | |
"""Analyze colors using the MCP server.""" | |
if not self.client: | |
return "β Not connected to MCP server" | |
if image is None: | |
return "β No image provided" | |
try: | |
result = self.client.predict( | |
image=image, | |
api_name="/count_colors" | |
) | |
return f"π¨ Color Analysis:\n{result}" | |
except Exception as e: | |
return f"β Error: {str(e)}" | |
def extract_text_info(self, image: Image.Image) -> Dict[str, Any]: | |
"""Extract text info using the MCP server.""" | |
if not self.client: | |
return {"error": "Not connected to MCP server"} | |
if image is None: | |
return {"error": "No image provided"} | |
try: | |
result = self.client.predict( | |
image=image, | |
api_name="/extract_text_info" | |
) | |
return json.loads(result) if isinstance(result, str) else result | |
except Exception as e: | |
return {"error": f"Text analysis failed: {str(e)}"} | |
# Initialize the analyzer | |
analyzer = MCPImageAnalyzer() | |
def create_sample_images(): | |
"""Create sample test images.""" | |
samples = {} | |
# Red rectangle | |
img1 = Image.new('RGB', (400, 300), color='red') | |
samples["Red Rectangle (400x300)"] = img1 | |
# Blue square | |
img2 = Image.new('RGB', (300, 300), color='blue') | |
samples["Blue Square (300x300)"] = img2 | |
# Colorful gradient | |
img3 = Image.new('RGB', (200, 400)) | |
pixels = img3.load() | |
for i in range(200): | |
for j in range(400): | |
pixels[i, j] = (i % 256, j % 256, (i + j) % 256) | |
samples["Colorful Gradient (200x400)"] = img3 | |
# Simple pattern | |
img4 = Image.new('RGB', (100, 100), color='white') | |
pixels = img4.load() | |
for i in range(100): | |
for j in range(100): | |
if (i // 10 + j // 10) % 2: | |
pixels[i, j] = (0, 0, 0) | |
samples["Checkerboard Pattern (100x100)"] = img4 | |
return samples | |
def connect_to_server(): | |
"""Connect to the MCP server.""" | |
status, status_type = analyzer.connect() | |
if status_type == "success": | |
return status, gr.update(variant="primary"), gr.update(visible=True) | |
else: | |
return status, gr.update(variant="stop"), gr.update(visible=False) | |
def run_comprehensive_analysis(image): | |
"""Run all analysis functions on the uploaded image.""" | |
if image is None: | |
return "β Please upload an image first", "", "", "" | |
# Run all analyses | |
analysis = analyzer.analyze_image(image) | |
orientation = analyzer.get_orientation(image) | |
colors = analyzer.analyze_colors(image) | |
text_info = analyzer.extract_text_info(image) | |
# Format results | |
analysis_result = json.dumps(analysis, indent=2) if isinstance(analysis, dict) else str(analysis) | |
text_result = json.dumps(text_info, indent=2) if isinstance(text_info, dict) else str(text_info) | |
return analysis_result, orientation, colors, text_result | |
def load_sample_image(sample_name): | |
"""Load a sample image.""" | |
samples = create_sample_images() | |
return samples.get(sample_name, None) | |
# Create the Gradio interface | |
with gr.Blocks(title="MCP Image Analysis Test Client", theme=gr.themes.Soft()) as demo: | |
gr.HTML(""" | |
<div style="text-align: center; padding: 20px;"> | |
<h1>πΌοΈ MCP Image Analysis Test Client</h1> | |
<p>Test your Gradio MCP Image Analysis server with this interactive client</p> | |
<p><strong>Server:</strong> <code>https://chris4k-mcp-images.hf.space</code></p> | |
</div> | |
""") | |
# Connection section | |
with gr.Row(): | |
with gr.Column(): | |
gr.Markdown("## π Connection") | |
connect_btn = gr.Button("Connect to MCP Server", variant="primary", size="lg") | |
connection_status = gr.Textbox( | |
label="Connection Status", | |
value="Not connected", | |
interactive=False | |
) | |
# Main testing interface (initially hidden) | |
main_interface = gr.Column(visible=False) | |
with main_interface: | |
gr.Markdown("## π§ͺ Image Analysis Testing") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gr.Markdown("### π€ Upload Image") | |
image_input = gr.Image( | |
label="Upload Image for Analysis", | |
type="pil", | |
height=300 | |
) | |
gr.Markdown("### π― Quick Test Samples") | |
sample_dropdown = gr.Dropdown( | |
choices=list(create_sample_images().keys()), | |
label="Load Sample Image", | |
value=None | |
) | |
load_sample_btn = gr.Button("Load Sample", size="sm") | |
gr.Markdown("### π Run Analysis") | |
analyze_btn = gr.Button("Analyze Image", variant="primary", size="lg") | |
with gr.Column(scale=2): | |
gr.Markdown("### π Analysis Results") | |
with gr.Tabs(): | |
with gr.Tab("π Comprehensive Analysis"): | |
analysis_output = gr.Code( | |
label="Full Image Analysis", | |
language="json", | |
lines=15 | |
) | |
with gr.Tab("π Orientation"): | |
orientation_output = gr.Textbox( | |
label="Image Orientation", | |
lines=3 | |
) | |
with gr.Tab("π¨ Color Analysis"): | |
color_output = gr.Textbox( | |
label="Color Information", | |
lines=10 | |
) | |
with gr.Tab("π Text Detection"): | |
text_output = gr.Code( | |
label="Text Analysis", | |
language="json", | |
lines=10 | |
) | |
# Individual tool testing section | |
gr.Markdown("## π§ Individual Tool Testing") | |
with gr.Row(): | |
with gr.Column(): | |
gr.Markdown("### Single Tool Tests") | |
single_image = gr.Image(label="Image for Single Tool Test", type="pil", height=200) | |
with gr.Row(): | |
orient_btn = gr.Button("Check Orientation", size="sm") | |
color_btn = gr.Button("Analyze Colors", size="sm") | |
single_result = gr.Textbox( | |
label="Single Tool Result", | |
lines=5 | |
) | |
# Usage examples and help | |
with gr.Accordion("π Usage Guide & Examples", open=False): | |
gr.Markdown(""" | |
## How to Use This Test Client | |
1. **Connect**: Click "Connect to MCP Server" to establish connection | |
2. **Upload Image**: Use the image upload area or load a sample image | |
3. **Analyze**: Click "Analyze Image" to run all analysis tools | |
4. **Review Results**: Check different tabs for specific analysis results | |
## Available Analysis Tools | |
- **π Comprehensive Analysis**: Complete image metadata (dimensions, format, colors, etc.) | |
- **π Orientation Detection**: Portrait, Landscape, or Square | |
- **π¨ Color Analysis**: Dominant colors and color count | |
- **π Text Detection**: Basic text presence analysis | |
## Sample Images | |
Try the built-in sample images to test different scenarios: | |
- Different orientations (portrait vs landscape) | |
- Various color schemes | |
- Different dimensions and formats | |
## Testing with Claude Desktop | |
This same MCP server can be used with Claude Desktop by adding this configuration: | |
```json | |
{ | |
"mcpServers": { | |
"image-analysis": { | |
"url": "https://chris4k-mcp-images.hf.space/gradio_api/mcp/sse" | |
} | |
} | |
} | |
``` | |
""") | |
# Event handlers | |
connect_btn.click( | |
connect_to_server, | |
outputs=[connection_status, connect_btn, main_interface] | |
) | |
load_sample_btn.click( | |
load_sample_image, | |
inputs=[sample_dropdown], | |
outputs=[image_input] | |
) | |
analyze_btn.click( | |
run_comprehensive_analysis, | |
inputs=[image_input], | |
outputs=[analysis_output, orientation_output, color_output, text_output] | |
) | |
# Individual tool tests | |
orient_btn.click( | |
analyzer.get_orientation, | |
inputs=[single_image], | |
outputs=[single_result] | |
) | |
color_btn.click( | |
analyzer.analyze_colors, | |
inputs=[single_image], | |
outputs=[single_result] | |
) | |
# Launch the app | |
if __name__ == "__main__": | |
demo.launch( | |
debug=True, | |
share=True, | |
show_error=True | |
) |