#!/usr/bin/env python3
"""
Customer Feedback MCP Server
A simple server for collecting and analyzing customer feedback
"""
import json
import asyncio
from datetime import datetime
from typing import Any, Dict, List
# MCP SDK imports
from mcp.server.models import InitializationOptions
from mcp.server import NotificationOptions, Server
from mcp.server.stdio import stdio_server
from mcp.types import Resource, Tool, TextContent
class FeedbackServer:
def __init__(self):
self.server = Server("customer-feedback")
self.feedback_list = []
self.setup_handlers()
def setup_handlers(self):
"""Set up all the server handlers"""
@self.server.list_resources()
async def handle_list_resources() -> List[Resource]:
"""List available resources"""
return [
Resource(
uri="feedback://recent",
name="Recent Feedback",
description="View recent customer feedback",
mimeType="application/json"
),
Resource(
uri="feedback://summary",
name="Feedback Summary",
description="Get a summary of all feedback",
mimeType="text/plain"
)
]
@self.server.read_resource()
async def handle_read_resource(uri: str) -> str:
"""Read a specific resource"""
if uri == "feedback://recent":
# Return last 5 feedback entries
recent = self.feedback_list[-5:] if self.feedback_list else []
return json.dumps(recent, indent=2)
elif uri == "feedback://summary":
# Generate summary
if not self.feedback_list:
return "No feedback collected yet."
total = len(self.feedback_list)
sentiments = {"positive": 0, "neutral": 0, "negative": 0}
for feedback in self.feedback_list:
sentiments[feedback["sentiment"]] += 1
return f"""
Feedback Summary
================
Total Feedback: {total}
Positive: {sentiments['positive']} ({sentiments['positive']/total*100:.1f}%)
Neutral: {sentiments['neutral']} ({sentiments['neutral']/total*100:.1f}%)
Negative: {sentiments['negative']} ({sentiments['negative']/total*100:.1f}%)
"""
raise ValueError(f"Unknown resource: {uri}")
@self.server.list_tools()
async def handle_list_tools() -> List[Tool]:
"""List available tools"""
return [
Tool(
name="collect_feedback",
description="Collect new customer feedback",
inputSchema={
"type": "object",
"properties": {
"customer_name": {
"type": "string",
"description": "Name of the customer"
},
"feedback": {
"type": "string",
"description": "The feedback text"
},
"rating": {
"type": "integer",
"description": "Rating from 1-5",
"minimum": 1,
"maximum": 5
}
},
"required": ["customer_name", "feedback", "rating"]
}
),
Tool(
name="analyze_sentiment",
description="Analyze sentiment of feedback text",
inputSchema={
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to analyze"
}
},
"required": ["text"]
}
)
]
@self.server.call_tool()
async def handle_call_tool(
name: str,
arguments: Dict[str, Any]
) -> List[TextContent]:
"""Handle tool calls"""
if name == "collect_feedback":
# Analyze sentiment based on rating
rating = arguments["rating"]
if rating >= 4:
sentiment = "positive"
elif rating == 3:
sentiment = "neutral"
else:
sentiment = "negative"
# Store feedback
feedback_entry = {
"id": len(self.feedback_list) + 1,
"timestamp": datetime.now().isoformat(),
"customer_name": arguments["customer_name"],
"feedback": arguments["feedback"],
"rating": rating,
"sentiment": sentiment
}
self.feedback_list.append(feedback_entry)
return [TextContent(
type="text",
text=f"Feedback collected successfully! ID: {feedback_entry['id']}"
)]
elif name == "analyze_sentiment":
text = arguments["text"].lower()
# Simple sentiment analysis
positive_words = ["great", "excellent", "love", "amazing", "wonderful"]
negative_words = ["bad", "terrible", "hate", "awful", "horrible"]
positive_count = sum(1 for word in positive_words if word in text)
negative_count = sum(1 for word in negative_words if word in text)
if positive_count > negative_count:
sentiment = "positive"
elif negative_count > positive_count:
sentiment = "negative"
else:
sentiment = "neutral"
return [TextContent(
type="text",
text=f"Sentiment: {sentiment}"
)]
raise ValueError(f"Unknown tool: {name}")
async def run(self):
"""Run the server"""
async with stdio_server() as (read_stream, write_stream):
await self.server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="customer-feedback",
server_version="0.1.0",
capabilities=self.server.get_capabilities(
notification_options=NotificationOptions(),
experimental_capabilities={}
)
)
)
# Main entry point
async def main():
server = FeedbackServer()
await server.run()
if __name__ == "__main__":
asyncio.run(main())