#!/usr/bin/env python3
"""
Web Client for Amazon Product Search MCP Server
This creates a REST API that interfaces with your MCP server.
"""
import asyncio
import json
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
import uvicorn
app = FastAPI(title="Amazon Product Search API", description="Web interface for MCP Amazon search server")
class ProductSearchRequest(BaseModel):
product: str
specific_features: str = ""
min_price: float = 1.0
max_price: float = 999999.0
class ProductSearchResponse(BaseModel):
success: bool
recommendation: str
error: str = None
async def call_mcp_server(product: str, features: str, min_price: float, max_price: float):
"""Call the MCP server with the given parameters."""
server_params = StdioServerParameters(
command="python",
args=["-m", "server.buy"],
env=None,
)
try:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(
"getdata",
arguments={
"prod": product,
"specific_features": features,
"minp": min_price,
"maxp": max_price
}
)
return result.content[0].text if result.content else "No result"
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/", response_class=HTMLResponse)
async def get_home():
"""Serve a simple HTML interface."""
html_content = """
<!DOCTYPE html>
<html>
<head>
<title>Amazon Product Search</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background-color: #0056b3; }
.result { margin-top: 20px; padding: 15px; border: 1px solid #ddd; border-radius: 4px; background-color: #f9f9f9; }
.loading { display: none; }
</style>
</head>
<body>
<h1>🛒 Amazon Product Search</h1>
<form id="searchForm">
<div class="form-group">
<label for="product">Product:</label>
<input type="text" id="product" name="product" required placeholder="e.g., laptop, smartphone, headphones">
</div>
<div class="form-group">
<label for="features">Specific Features:</label>
<textarea id="features" name="features" rows="3" placeholder="e.g., 8GB RAM, good camera, long battery life"></textarea>
</div>
<div class="form-group">
<label for="minPrice">Minimum Price (₹):</label>
<input type="number" id="minPrice" name="minPrice" value="1" min="1">
</div>
<div class="form-group">
<label for="maxPrice">Maximum Price (₹):</label>
<input type="number" id="maxPrice" name="maxPrice" value="999999" min="1">
</div>
<button type="submit">🔍 Search Products</button>
</form>
<div id="loading" class="loading">
<p>🔄 Searching for products...</p>
</div>
<div id="result" class="result" style="display: none;">
<h3>Recommendation:</h3>
<pre id="recommendationText"></pre>
</div>
<script>
document.getElementById('searchForm').addEventListener('submit', async function(e) {
e.preventDefault();
const loadingDiv = document.getElementById('loading');
const resultDiv = document.getElementById('result');
const recommendationText = document.getElementById('recommendationText');
loadingDiv.style.display = 'block';
resultDiv.style.display = 'none';
const formData = new FormData(e.target);
const data = {
product: formData.get('product'),
specific_features: formData.get('features'),
min_price: parseFloat(formData.get('minPrice')),
max_price: parseFloat(formData.get('maxPrice'))
};
try {
const response = await fetch('/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
loadingDiv.style.display = 'none';
if (result.success) {
recommendationText.textContent = result.recommendation;
resultDiv.style.display = 'block';
} else {
alert('Error: ' + (result.error || 'Unknown error'));
}
} catch (error) {
loadingDiv.style.display = 'none';
alert('Network error: ' + error.message);
}
});
</script>
</body>
</html>
"""
return html_content
@app.post("/search", response_model=ProductSearchResponse)
async def search_products(request: ProductSearchRequest):
"""Search for products using the MCP server."""
try:
recommendation = await call_mcp_server(
request.product,
request.specific_features,
request.min_price,
request.max_price
)
return ProductSearchResponse(
success=True,
recommendation=recommendation
)
except Exception as e:
return ProductSearchResponse(
success=False,
recommendation="",
error=str(e)
)
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {"status": "healthy", "message": "Amazon Product Search API is running"}
if __name__ == "__main__":
print("🌐 Starting Web Client for Amazon Product Search...")
print("Open http://localhost:8000 in your browser")
uvicorn.run(app, host="127.0.0.1", port=8000)