From 501b4eae772c9e0158ed93a166ecb4fed8bbcef9 Mon Sep 17 00:00:00 2001 From: Yena Yu Date: Sun, 23 Nov 2025 18:21:18 -0500 Subject: [PATCH 01/21] feat: Add Shopping Agent MCP Server Adds the Shopping Agent MCP server implementation, including: - Server code (shopping_agent.py) - Documentation (README.md, ARCHITECTURE.md, QUICKSTART.md) - Configuration (pyproject.toml, Dockerfile) - Helper scripts (test_server.sh) Signed-off-by: Yena Yu --- mcp/README.md | 287 +++++++++++++++++ mcp/shopping_agent/.gitignore | 58 ++++ mcp/shopping_agent/ARCHITECTURE.md | 462 +++++++++++++++++++++++++++ mcp/shopping_agent/Dockerfile | 28 ++ mcp/shopping_agent/QUICKSTART.md | 422 ++++++++++++++++++++++++ mcp/shopping_agent/README.md | 365 +++++++++++++++++++++ mcp/shopping_agent/__init__.py | 6 + mcp/shopping_agent/config.example | 24 ++ mcp/shopping_agent/pyproject.toml | 15 + mcp/shopping_agent/setup_env.sh | 49 +++ mcp/shopping_agent/shopping_agent.py | 263 +++++++++++++++ mcp/shopping_agent/test_server.sh | 38 +++ 12 files changed, 2017 insertions(+) create mode 100644 mcp/README.md create mode 100644 mcp/shopping_agent/.gitignore create mode 100644 mcp/shopping_agent/ARCHITECTURE.md create mode 100644 mcp/shopping_agent/Dockerfile create mode 100644 mcp/shopping_agent/QUICKSTART.md create mode 100644 mcp/shopping_agent/README.md create mode 100644 mcp/shopping_agent/__init__.py create mode 100644 mcp/shopping_agent/config.example create mode 100644 mcp/shopping_agent/pyproject.toml create mode 100755 mcp/shopping_agent/setup_env.sh create mode 100644 mcp/shopping_agent/shopping_agent.py create mode 100755 mcp/shopping_agent/test_server.sh diff --git a/mcp/README.md b/mcp/README.md new file mode 100644 index 0000000..34f0251 --- /dev/null +++ b/mcp/README.md @@ -0,0 +1,287 @@ +# MCP Tools + +This directory contains Model Context Protocol (MCP) tools that can be used by AI assistants and agents. + +## Available Tools + +### 1. Weather Tool (`weather_tool/`) + +Get weather information for any city. + +**Features**: +- Current weather data +- Temperature, wind speed, conditions +- Uses Open-Meteo API (no API key required) + +**Tools**: +- `get_weather(city: str)` - Get weather info for a city + +### 2. Movie Tool (`movie_tool/`) + +Get movie information and reviews from OMDb. + +**Features**: +- Movie details (plot, ratings, actors, awards) +- Full plot summaries +- Uses OMDb API + +**Tools**: +- `get_full_plot(movie_title: str)` - Get full plot summary +- `get_movie_details(movie_title: str)` - Get full movie details + +**Requirements**: +- OMDB_API_KEY environment variable + +### 3. Slack Tool (`slack_tool/`) + +Interact with Slack workspaces. + +**Features**: +- List channels +- Get channel history +- Optional fine-grained authorization + +**Tools**: +- `get_channels()` - Lists all public and private channels +- `get_channel_history(channel_id: str, limit: int)` - Fetches recent messages + +**Requirements**: +- SLACK_BOT_TOKEN environment variable +- Optional: ADMIN_SLACK_BOT_TOKEN for fine-grained auth + +### 4. GitHub Tool (`github_tool/`) + +Interact with GitHub repositories (written in Go). + +**Features**: +- Repository management +- Issue tracking +- Pull request operations + +**Requirements**: +- GitHub authentication token + +### 5. Shopping Agent (`shopping_agent/`) ⭐ NEW + +AI-powered shopping recommendations using LangChain, LangGraph, OpenAI, and SerpAPI. + +**Features**: +- Natural language query understanding +- Real-time product search across retailers +- AI-curated recommendations with reasoning +- Budget-aware suggestions +- Multi-step LangGraph workflow + +**Tools**: +- `recommend_products(query: str, maxResults: int)` - Get AI-powered product recommendations +- `search_products(query: str, maxResults: int)` - Raw product search + +**Requirements**: +- OPENAI_API_KEY environment variable +- SERPAPI_API_KEY environment variable + +**Example Usage**: +```bash +curl -X POST http://localhost:8000/tools/recommend_products \ + -H "Content-Type: application/json" \ + -d '{ + "query": "I want to buy a scarf for 40 dollars", + "maxResults": 5 + }' +``` + +**Technologies**: +- FastMCP - MCP server framework +- LangChain - LLM application framework +- LangGraph - Agent workflow orchestration +- OpenAI GPT-4o-mini - Natural language understanding/generation +- SerpAPI - Product search across retailers + +**Documentation**: +- [README.md](shopping_agent/README.md) - Full documentation +- [QUICKSTART.md](shopping_agent/QUICKSTART.md) - Quick start guide +- [ARCHITECTURE.md](shopping_agent/ARCHITECTURE.md) - Architecture details +- [VERIFICATION.md](shopping_agent/VERIFICATION.md) - Requirements verification + +## Getting Started + +### General Setup + +All MCP tools follow a similar pattern: + +1. **Install dependencies**: +```bash +cd +uv pip install -e . +``` + +2. **Configure environment variables**: +```bash +export API_KEY="your-api-key-here" +``` + +3. **Run the server**: +```bash +python .py +``` + +4. **Test the server**: +```bash +curl http://localhost:8000/health +``` + +### Docker Deployment + +Each tool includes a Dockerfile for containerized deployment: + +```bash +cd +docker build -t -mcp . +docker run -p 8000:8000 -e API_KEY="your-key" -mcp +``` + +## MCP Protocol + +All tools expose functionality via the Model Context Protocol (MCP), which allows AI assistants to discover and use these tools programmatically. + +### Key Features + +- **Tool Discovery**: Tools are self-describing with metadata +- **Type Safety**: Strong typing for parameters and returns +- **Documentation**: Built-in documentation for each tool +- **Error Handling**: Standardized error responses +- **Transport**: HTTP transport support (streamable HTTP optional) + +### Tool Annotations + +Tools use annotations to describe their behavior: +- `readOnlyHint`: Indicates if the tool only reads data +- `destructiveHint`: Warns if the tool modifies or deletes data +- `idempotentHint`: Indicates if repeated calls have the same effect + +## Framework Comparison + +| Tool | Language | Framework | Key Library | +|------|----------|-----------|-------------| +| Weather | Python | FastMCP | requests | +| Movie | Python | FastMCP | requests + OMDb | +| Slack | Python | FastMCP | slack_sdk | +| GitHub | Go | Custom | GitHub API | +| Shopping Agent | Python | FastMCP | LangChain + LangGraph | + +## Advanced Example: Shopping Agent Architecture + +The Shopping Agent demonstrates an advanced MCP tool with: + +``` +User Query + ↓ +Parse Query Node (OpenAI) + ↓ +Search Products Node (SerpAPI) + ↓ +Generate Recommendations Node (OpenAI) + ↓ +Structured Response +``` + +**Key Technologies**: +- **LangGraph**: Multi-node agent workflow with state management +- **LangChain**: LLM framework for tool integration +- **OpenAI**: Natural language understanding and generation +- **SerpAPI**: Real-time search across retailers + +See [shopping_agent/ARCHITECTURE.md](shopping_agent/ARCHITECTURE.md) for detailed architecture. + +## Creating Your Own MCP Tool + +### Basic Template + +```python +import os +from fastmcp import FastMCP + +mcp = FastMCP("My Tool") + +@mcp.tool(annotations={"readOnlyHint": True}) +def my_function(param: str) -> str: + """Tool description""" + # Your logic here + return result + +def run_server(): + transport = os.getenv("MCP_TRANSPORT", "http") + host = os.getenv("HOST", "0.0.0.0") + port = int(os.getenv("PORT", "8000")) + mcp.run(transport=transport, host=host, port=port) + +if __name__ == "__main__": + run_server() +``` + +### Best Practices + +1. **Environment Variables**: Use env vars for API keys and configuration +2. **Error Handling**: Return structured error responses +3. **Logging**: Use appropriate log levels +4. **Documentation**: Include docstrings for all tools +5. **Type Hints**: Use type hints for parameters and returns +6. **Testing**: Provide test clients or scripts +7. **Docker**: Include Dockerfile for deployment +8. **README**: Comprehensive documentation + +## Common Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| HOST | Server host address | 0.0.0.0 | +| PORT | Server port | 8000 | +| MCP_TRANSPORT | Transport protocol | http | +| LOG_LEVEL | Logging level | INFO | + +## Troubleshooting + +### Server Won't Start + +1. Check API keys are set +2. Verify port 8000 is available +3. Check Python version (3.10+) +4. Review logs for errors + +### Tool Returns Errors + +1. Verify API keys are valid +2. Check API quota limits +3. Review request parameters +4. Check network connectivity + +### Import Errors + +1. Install dependencies: `uv pip install -e .` +2. Verify Python version +3. Check for conflicting packages + +## Contributing + +When adding new MCP tools: + +1. Follow the existing structure +2. Use FastMCP framework (or document why not) +3. Include comprehensive README +4. Add Dockerfile +5. Provide test client +6. Document all tools and parameters +7. Use environment variables for secrets +8. Add logging and error handling + +## Resources + +- [FastMCP Documentation](https://github.com/jlowin/fastmcp) +- [Model Context Protocol Spec](https://modelcontextprotocol.io/) +- [LangChain Documentation](https://python.langchain.com/) +- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/) + +## License + +See the repository's LICENSE file for details. + diff --git a/mcp/shopping_agent/.gitignore b/mcp/shopping_agent/.gitignore new file mode 100644 index 0000000..fb88bd5 --- /dev/null +++ b/mcp/shopping_agent/.gitignore @@ -0,0 +1,58 @@ +# API Keys and Secrets - NEVER COMMIT THESE! +.env +.env.local +.env.*.local +config.sh +*.key +*.pem + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual Environments +venv/ +ENV/ +env/ +.venv + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Logs +*.log + +# Testing +.pytest_cache/ +.coverage +htmlcov/ + +# uv +uv.lock + diff --git a/mcp/shopping_agent/ARCHITECTURE.md b/mcp/shopping_agent/ARCHITECTURE.md new file mode 100644 index 0000000..7da49f8 --- /dev/null +++ b/mcp/shopping_agent/ARCHITECTURE.md @@ -0,0 +1,462 @@ +# Shopping Agent Architecture + +## System Overview + +The Shopping Agent is an MCP (Model Context Protocol) server that uses SerpAPI to provide product search capabilities. The server returns structured product data, and the calling agent (your AI) provides intelligent analysis and recommendations. + +## Design Philosophy + +**Separation of Concerns:** +- **MCP Server**: Provides data (product search results) +- **AI Agent**: Provides intelligence (analysis and recommendations) + +This architecture follows the principle that MCP servers should be lightweight data providers, while AI agents handle complex reasoning and decision-making. + +## High-Level Architecture + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ Client Application │ +│ (Any MCP-compatible client) │ +└────────────────────────────────┬────────────────────────────────────┘ + │ HTTP/MCP Protocol + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ Shopping Agent MCP Server │ +│ (FastMCP Framework) │ +├─────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────┐ ┌──────────────────┐ │ +│ │ recommend_products│ │ search_products │ │ +│ │ @mcp.tool │ │ @mcp.tool │ │ +│ └─────────┬─────────┘ └─────────┬────────┘ │ +│ │ │ │ +│ └──────────────┬───────────────┘ │ +│ ▼ │ +│ ┌──────────────────────────┐ │ +│ │ SerpAPI Integration │ │ +│ │ (Product Search Only) │ │ +│ └──────────┬───────────────┘ │ +│ │ │ +└───────────────────────┼──────────────────────────────────────────────┘ + │ + ▼ + ┌─────────┐ + │ SerpAPI │ + │ API │ + └─────────┘ + + ↓ + Returns structured product data to agent + ↓ +┌─────────────────────────────────────────────────────────────────────┐ +│ AI Agent (Your Client) │ +│ Analyzes data & provides reasoning │ +│ │ +│ • Evaluates products against user requirements │ +│ • Considers budget constraints │ +│ • Provides recommendation scores │ +│ • Explains reasoning for each recommendation │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +## Component Details + +### 1. FastMCP Server Layer + +**Purpose**: Exposes product search tools via Model Context Protocol + +**Components**: +- `FastMCP("Shopping Agent")`: MCP server instance +- Tool decorators with proper annotations +- HTTP transport support (MCP Inspector compatible) +- Environment-based configuration + +**Key Features**: +- RESTful API endpoints for tools +- Tool metadata and documentation +- Error handling and validation +- Logging and monitoring + +### 2. Tool Implementations + +#### recommend_products Tool + +``` +Input: "I want to buy a scarf for 40 dollars" + ↓ + [SerpAPI Search] + ↓ + [Parse Results] + ↓ +Output: Structured product data (JSON) +``` + +**Process**: +1. Receives natural language query +2. Constructs optimized search query for shopping +3. Queries SerpAPI for product listings +4. Parses raw results into structured format +5. Returns JSON with product names, prices, descriptions, URLs + +**No AI reasoning at this level** - just data retrieval and structuring. + +#### search_products Tool + +``` +Input: "wireless headphones" + ↓ + [SerpAPI Search] + ↓ +Output: Raw search results +``` + +**Process**: +1. Receives search query +2. Queries SerpAPI +3. Returns raw results for lower-level access + +## Data Flow + +### Request Flow + +``` +1. User asks AI agent for product recommendations + ↓ +2. AI agent calls recommend_products MCP tool + ↓ +3. MCP server validates parameters + ↓ +4. MCP server searches SerpAPI + ↓ +5. MCP server parses results into structured format + ↓ +6. MCP server returns JSON with product data + ↓ +7. AI agent receives product data + ↓ +8. AI agent analyzes products: + - Evaluates match to user requirements + - Considers budget constraints + - Compares features and value + - Generates reasoning for each product + - Ranks products by suitability + ↓ +9. AI agent presents recommendations to user with reasoning +``` + +### Example Data Flow + +**User Query:** +``` +"I want to buy a scarf for 40 dollars" +``` + +**MCP Server Response:** +```json +{ + "query": "I want to buy a scarf for 40 dollars", + "products": [ + { + "name": "Winter Wool Scarf", + "price": "$38.99", + "description": "100% merino wool, various colors", + "url": "https://example.com/product1" + }, + { + "name": "Cashmere Blend Scarf", + "price": "$35.99", + "description": "Soft cashmere blend, multiple patterns", + "url": "https://example.com/product2" + } + ], + "count": 2, + "note": "These are search results. The agent should analyze and provide reasoning." +} +``` + +**AI Agent Analysis & Response to User:** +``` +I found 2 great scarves within your $40 budget: + +1. **Winter Wool Scarf - $38.99** ⭐ Score: 9/10 + This is an excellent choice. The 100% merino wool provides superior warmth + and quality. At $38.99, it's well within your budget and offers great value. + Merino wool is naturally breathable and soft against skin. + +2. **Cashmere Blend Scarf - $35.99** ⭐ Score: 8/10 + A more affordable luxury option. The cashmere blend provides softness and + warmth at a lower price point ($35.99). The multiple pattern options give + you style flexibility. Great value if you want a touch of cashmere without + the high price. + +My top recommendation is the Winter Wool Scarf for its superior quality and warmth. +``` + +## Integration Points + +### External APIs + +#### SerpAPI +- **Usage**: Real-time product search across retailers +- **Calls per request**: 1 +- **Authentication**: API key via environment variable +- **Results**: Aggregated product listings + +### LangChain Components + +``` +langchain_community.utilities.SerpAPIWrapper + ├── Search query optimization + ├── Result parsing + └── API key management +``` + +## Error Handling + +### Error Flow + +``` +Try: + Validate input parameters + ↓ + Execute SerpAPI search + ↓ + Parse results + ↓ + Return structured data +Except APIError: + Log error + Return {"error": "API error message"} +Except ValidationError: + Log error + Return {"error": "Validation error message"} +Except Exception: + Log with traceback + Return {"error": "Generic error message"} +``` + +### Error Types + +1. **API Key Errors**: Missing or invalid SERPAPI_API_KEY +2. **API Quota Errors**: SerpAPI rate limits exceeded +3. **Network Errors**: Connection failures +4. **Parsing Errors**: Invalid search results format +5. **Validation Errors**: Invalid parameters (maxResults bounds, etc.) + +## Performance Characteristics + +### Latency Breakdown + +``` +Total Request Time: ~2-4 seconds + ├── Search Products: ~2-3 seconds (SerpAPI) + └── Parse Results: ~0.5-1 second (local processing) +``` + +**Note**: The AI agent's analysis time is additional and depends on the agent's LLM speed. + +### Optimization Strategies + +1. **Efficient Parsing**: Lightweight result parsing +2. **Result Limiting**: maxResults parameter (default 10, max 20 for recommend_products) +3. **Simple Processing**: No complex AI processing on server side +4. **Stateless Design**: No session management overhead + +## Scalability + +### Horizontal Scaling + +``` +Load Balancer + ↓ +┌───────────┬───────────┬───────────┐ +│ Instance 1│ Instance 2│ Instance 3│ +└───────────┴───────────┴───────────┘ +``` + +### Considerations + +- Stateless design (no session storage) +- Independent request processing +- External API rate limits (SerpAPI) +- Docker containerization for easy deployment +- Lightweight processing (no AI model loading) + +## Security + +### API Key Management + +``` +Environment Variables + └── SERPAPI_API_KEY (required) + • Never logged or exposed + • Loaded from environment only + • Validated at startup +``` + +### Input Validation + +- Query length limits +- maxResults bounds checking (10 default, 20 max for recommend_products, 100 max for search_products) +- Parameter type validation +- Error message sanitization + +## Monitoring and Logging + +### Log Levels + +``` +DEBUG: Detailed execution flow +INFO: Search queries and result counts +WARNING: API issues or parsing problems +ERROR: Failures and exceptions +``` + +### Key Metrics + +- Request count +- Response times +- SerpAPI call counts +- Error rates +- Search result quality + +## Deployment Architecture + +### Docker Deployment + +``` +Docker Container + ├── Python 3.10+ + ├── uv package manager + ├── Application code + ├── Dependencies (FastMCP, LangChain Community, SerpAPI) + └── Environment configuration + +Exposed: + └── Port 8000 (HTTP) + +Environment: + ├── SERPAPI_API_KEY (required) + ├── HOST (default: 0.0.0.0) + ├── PORT (default: 8000) + ├── MCP_TRANSPORT (default: http) + ├── MCP_JSON_RESPONSE (default: true) + └── LOG_LEVEL (default: INFO) +``` + +### Production Setup + +``` +┌─────────────────┐ +│ Load Balancer │ +└────────┬────────┘ + │ + ┌────┴────┬────────┐ + ▼ ▼ ▼ +┌────────┐ ┌────────┐ ┌────────┐ +│Container│ │Container│ │Container│ +│ #1 │ │ #2 │ │ #3 │ +└────────┘ └────────┘ └────────┘ +``` + +## Agent Integration Guide + +### Recommended System Prompt for AI Agents + +When using this MCP server, configure your AI agent with a system prompt like: + +``` +When users ask for product recommendations: + +1. Use the recommend_products tool to search for products based on their query +2. Analyze each returned product considering: + - How well it matches the user's specific requirements + - Whether the price fits within their stated budget + - The value proposition (quality vs. price) + - Any specific features or constraints mentioned + - Availability and retailer reputation + +3. For each relevant product, provide: + - A clear explanation of why it's a good match + - A recommendation score (1-10 scale) + - Any important caveats or considerations + - Comparison with other options + +4. Rank products by how well they meet the user's needs +5. Present the top 3-5 recommendations with detailed reasoning +6. Provide direct purchase links for convenience + +Always explain your reasoning transparently so users understand why you're +recommending specific products. +``` + +### Example Agent Conversation Flow + +``` +User: "I need wireless headphones under $100" + +Agent: [Calls recommend_products MCP tool] + +MCP Server: [Returns 5 product results with names, prices, descriptions, URLs] + +Agent: [Analyzes products and responds to user with]: + "I found several great options for wireless headphones under $100: + + 1. Sony WH-CH710N - $89.99 ⭐ 9/10 + [Detailed reasoning about features, value, fit to requirements] + + 2. JBL Tune 760NC - $79.99 ⭐ 8/10 + [Reasoning] + + 3. Anker Soundcore Q30 - $69.99 ⭐ 8/10 + [Reasoning] + + My top pick is the Sony WH-CH710N because [explanation]..." +``` + +## Future Enhancements + +### Planned Features + +1. **Caching Layer**: Redis for common searches +2. **Advanced Filtering**: Price ranges, categories, ratings in query parsing +3. **Multiple Providers**: Add more search providers beyond SerpAPI +4. **Structured Query Parameters**: Optional structured input format +5. **Result Enrichment**: Add more metadata (reviews, ratings, shipping info) +6. **Price Tracking**: Historical price data +7. **Image URLs**: Include product image URLs when available + +### Architectural Improvements + +1. **Async/Await**: Non-blocking SerpAPI calls +2. **Parallel Searches**: Query multiple providers simultaneously +3. **Enhanced Parsing**: Better extraction of product details +4. **Rate Limiting**: Built-in rate limiting for API protection +5. **Result Caching**: Cache recent searches to reduce API calls + +## Technology Stack Summary + +| Layer | Technology | Purpose | +|-------|-----------|---------| +| **Protocol** | FastMCP | MCP server framework | +| **Search** | SerpAPI | Product search across retailers | +| **Integration** | LangChain Community | SerpAPI wrapper utilities | +| **Runtime** | Python 3.10+ | Application runtime | +| **Package Manager** | uv | Fast Python package management | +| **Containerization** | Docker | Deployment and isolation | + +## Conclusion + +The Shopping Agent represents a clean, lightweight MCP server implementation: +- ✅ Focused responsibility (data retrieval only) +- ✅ Fast response times (no LLM processing) +- ✅ Simple deployment and scaling +- ✅ Clear separation of concerns +- ✅ Agent-friendly architecture +- ✅ Production-ready error handling + +The server does one thing well: searches for products and returns structured data. +Your AI agent does what it does best: intelligent analysis and recommendations. + +Ready for deployment and real-world use! 🚀 diff --git a/mcp/shopping_agent/Dockerfile b/mcp/shopping_agent/Dockerfile new file mode 100644 index 0000000..e23c9e8 --- /dev/null +++ b/mcp/shopping_agent/Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Install uv +RUN pip install uv + +# Copy project files +COPY pyproject.toml . +COPY shopping_agent.py . +COPY __init__.py . +COPY README.md . + +# Install dependencies +RUN uv pip install --system -e . + +# Environment variables (can be overridden at runtime) +ENV HOST=0.0.0.0 +ENV PORT=8000 +ENV MCP_TRANSPORT=http +ENV LOG_LEVEL=INFO + +# Expose the port +EXPOSE 8000 + +# Run the server +CMD ["python", "shopping_agent.py"] + diff --git a/mcp/shopping_agent/QUICKSTART.md b/mcp/shopping_agent/QUICKSTART.md new file mode 100644 index 0000000..754c1b6 --- /dev/null +++ b/mcp/shopping_agent/QUICKSTART.md @@ -0,0 +1,422 @@ +# Shopping Agent - Quick Start Guide + +This guide will help you get the Shopping Agent MCP server up and running quickly. + +## What You'll Need + +1. **SerpAPI Key** - Get it from [SerpAPI Dashboard](https://serpapi.com/manage-api-key) +2. **Python 3.10+** - Check with `python --version` +3. **uv package manager** - Install from [Astral UV](https://docs.astral.sh/uv/) + +## Installation Steps + +### Step 1: Set Up API Key + +```bash +# Export your SerpAPI key +export SERPAPI_API_KEY="your-serpapi-key-here" +``` + +**Tip**: Add this to your `~/.bashrc` or `~/.zshrc` to persist it: +```bash +echo 'export SERPAPI_API_KEY="your-key"' >> ~/.zshrc +source ~/.zshrc +``` + +### Step 2: Install Dependencies + +```bash +cd mcp/shopping_agent +uv pip install -e . +``` + +### Step 3: Start the Server + +```bash +python shopping_agent.py +``` + +You should see: +``` +INFO: Starting Shopping Agent MCP Server with SerpAPI +INFO: Note: This server provides search results. The calling agent provides reasoning. +INFO: Server running on http://0.0.0.0:8000 +``` + +### Step 4: Test the Server + +In a new terminal: + +```bash +# Test with the provided test script +python simple_test.py + +# Or test manually with curl +curl -X POST http://localhost:8000/mcp/tools/recommend_products \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{ + "query": "I want to buy a scarf for 40 dollars", + "maxResults": 5 + }' +``` + +## MCP Inspector Demo (HTTP Transport) + +Use the MCP Inspector UI to explore the server interactively: + +1. Start the shopping agent with explicit port/transport: + ```bash + cd mcp/shopping_agent + export SERPAPI_API_KEY="your-key" + MCP_TRANSPORT=http PORT=8001 python shopping_agent.py + ``` +2. In a separate terminal (Node.js ≥18 required) launch the inspector: + ```bash + npx @modelcontextprotocol/inspector + ``` +3. When the browser opens, choose **Add server** and fill in: + - Name: `Shopping Agent` + - Transport: `HTTP` (use `Streamable HTTP` if that is the option offered) + - URL: `http://localhost:8001` +4. Connect and explore the `recommend_products` and `search_products` tools from the **Tools** tab. The response JSON renders in the inspector panel. + +To compare behavior with the movie MCP server, repeat the steps with `PORT=8002 MCP_TRANSPORT=http python ../movie_tool/movie_tool.py` and add it as a second server in the inspector. + +## Usage Examples + +### Example 1: Shopping for Scarves + +```bash +curl -X POST http://localhost:8000/mcp/tools/recommend_products \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{ + "query": "I want to buy a scarf for 40 dollars", + "maxResults": 5 + }' +``` + +**Expected Response** (MCP server returns structured product data): +```json +{ + "query": "I want to buy a scarf for 40 dollars", + "products": [ + { + "name": "Winter Wool Scarf", + "price": "$38.99", + "description": "Soft merino wool scarf in multiple colors...", + "url": "https://example.com/product1", + "thumbnail": "https://example.com/image.jpg", + "source": "Amazon", + "rating": 4.5, + "reviews": 120 + }, + { + "name": "Cashmere Blend Scarf", + "price": "$35.99", + "description": "Luxury cashmere blend, various patterns...", + "url": "https://example.com/product2", + "thumbnail": "https://example.com/image2.jpg", + "source": "Etsy" + } + ], + "count": 2 +} +``` + +**Your AI agent should then analyze these products and add reasoning.** + +### Example 2: Finding Headphones + +```bash +curl -X POST http://localhost:8000/mcp/tools/recommend_products \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{ + "query": "wireless headphones under $100 with noise cancellation", + "maxResults": 5 + }' +``` + +### Example 3: Using Python Client + +```python +import requests +import json + +response = requests.post( + "http://localhost:8000/mcp/tools/recommend_products", + headers={ + "Content-Type": "application/json", + "Accept": "application/json, text/event-stream" + }, + json={ + "query": "best laptop under $800 for programming", + "maxResults": 5 + } +) + +products = response.json() +print(json.dumps(products, indent=2)) + +# Your AI agent would then analyze these products and provide recommendations +``` + +## Architecture Overview + +The Shopping Agent uses a simple, efficient architecture: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ User Query │ +│ "I want to buy a scarf for $40" │ +└─────────────────┬───────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ AI Agent (Your Client) │ +│ Calls recommend_products MCP tool │ +└─────────────────┬───────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Shopping Agent MCP Server │ +│ Search Products (SerpAPI) │ +│ Parse Results │ +│ Return Structured Data │ +└─────────────────┬───────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ AI Agent (Your Client) │ +│ Analyzes products and provides reasoning │ +│ • Evaluates match to requirements │ +│ • Considers budget constraints │ +│ • Ranks by suitability │ +│ • Explains reasoning │ +└─────────────────┬───────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Return to User │ +│ Recommendations with names, prices, links, and reasoning │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Technologies Used + +| Technology | Purpose | +|------------|---------| +| **FastMCP** | MCP server framework for tool exposure | +| **LangChain Community** | SerpAPI wrapper utilities | +| **SerpAPI** | Real-time product search across retailers | + +## Configuring Your AI Agent + +When using this MCP server, configure your AI agent with a system prompt like: + +``` +When users ask for product recommendations: + +1. Use the recommend_products tool to search for products +2. Analyze each product considering: + - How well it matches the user's requirements + - Whether it fits within their budget + - The value proposition (quality vs. price) + - Any specific features mentioned + +3. For each product, provide: + - A brief explanation of why it's a good match + - A recommendation score (1-10) + - Any caveats or considerations + +4. Rank products by how well they match the user's needs +5. Present the top 3-5 recommendations with your reasoning +``` + +## Example Agent Conversation + +**User**: "I want to buy a scarf for 40 dollars" + +**AI Agent**: *[Calls recommend_products MCP tool]* + +**MCP Server**: *[Returns structured product data]* + +**AI Agent Response to User**: +``` +I found 2 great scarves within your $40 budget: + +1. Winter Wool Scarf - $38.99 ⭐ Score: 9/10 + This is an excellent choice within your budget. The 100% merino wool + provides superior warmth and quality, making it great value at this + price point. Available in multiple colors. + +2. Cashmere Blend Scarf - $35.99 ⭐ Score: 8/10 + A more affordable luxury option. The cashmere blend provides softness + and warmth at a lower price. The various patterns give you style + flexibility. + +My top recommendation is the Winter Wool Scarf for its superior quality +and durability. +``` + +## Troubleshooting + +### Server Won't Start + +**Problem**: Server fails to start with API key errors + +**Solution**: +```bash +# Verify your key is set +echo $SERPAPI_API_KEY + +# If empty, export it again +export SERPAPI_API_KEY="your-key" +``` + +### Import Errors + +**Problem**: `ModuleNotFoundError` when starting + +**Solution**: +```bash +# Reinstall dependencies +uv pip install --force-reinstall -e . +``` + +### No Results Returned + +**Problem**: Server runs but returns no products + +**Solution**: +1. Check your SerpAPI quota at https://serpapi.com/dashboard +2. Verify the query is specific enough +3. Check server logs: `LOG_LEVEL=DEBUG python shopping_agent.py` + +### Connection Refused + +**Problem**: `Connection refused` when testing + +**Solution**: +```bash +# Check if server is running +ps aux | grep shopping_agent + +# If not, start the server +python shopping_agent.py +``` + +## Docker Deployment + +### Build and Run + +```bash +# Build the Docker image +docker build -t shopping-agent-mcp . + +# Run with API key +docker run -p 8000:8000 \ + -e SERPAPI_API_KEY="your-serpapi-key" \ + shopping-agent-mcp +``` + +### Docker Compose + +Create `docker-compose.yml`: + +```yaml +version: '3.8' +services: + shopping-agent: + build: . + ports: + - "8000:8000" + environment: + - SERPAPI_API_KEY=${SERPAPI_API_KEY} + - LOG_LEVEL=INFO +``` + +Run with: +```bash +docker-compose up +``` + +## API Reference + +### Tool: `recommend_products` + +**Description**: Search for products and return structured data for your AI agent to analyze + +**Request**: +```json +{ + "query": "string (required) - Natural language product request", + "maxResults": "integer (optional) - Max results (default: 10, max: 20)" +} +``` + +**Response**: +```json +{ + "query": "string - Original query", + "products": [ + { + "name": "string - Product name", + "price": "string - Price", + "description": "string - Product description", + "url": "string - Purchase link" + } + ], + "count": "integer - Number of products", + "note": "string - Reminder that agent should provide reasoning" +} +``` + +### Tool: `search_products` + +**Description**: Raw product search (lower-level tool) + +**Request**: +```json +{ + "query": "string (required) - Search query", + "maxResults": "integer (optional) - Max results (default: 10, max: 100)" +} +``` + +**Response**: +```json +{ + "query": "string - Search query", + "results": "string - Raw search results", + "note": "string - Usage note" +} +``` + +## Next Steps + +1. **Integrate with Your Agent**: Connect your AI agent (Claude, GPT-4, etc.) to use this MCP server +2. **Configure System Prompt**: Use the suggested prompt above to guide your agent's analysis +3. **Test**: Try various product queries and refine your agent's reasoning +4. **Monitor**: Add logging and monitoring for production use +5. **Scale**: Deploy with Docker and load balancing for high traffic + +## Support + +- Check logs with `LOG_LEVEL=DEBUG python shopping_agent.py` +- Review the [README.md](README.md) for detailed documentation +- Review the [ARCHITECTURE.md](ARCHITECTURE.md) for architecture details +- Verify API key has sufficient quota at https://serpapi.com/dashboard +- Test with the provided `simple_test.py` script + +## Summary + +✅ You've created a lightweight Shopping Agent MCP server +✅ It uses SerpAPI for real-time product search +✅ It returns structured data for your AI agent to analyze +✅ It follows MCP best practices with clear separation of concerns +✅ It's ready for production deployment with Docker + +Your AI agent does the smart analysis and recommendations! 🛍️ diff --git a/mcp/shopping_agent/README.md b/mcp/shopping_agent/README.md new file mode 100644 index 0000000..e2cc5cc --- /dev/null +++ b/mcp/shopping_agent/README.md @@ -0,0 +1,365 @@ +# Shopping Agent MCP Tool + +A Model Context Protocol (MCP) server that provides product search capabilities using SerpAPI. The server returns structured product data, and the calling agent provides intelligent reasoning and recommendations. + +## Features + +- **Product Search**: Leverages SerpAPI (Google Shopping) to search across multiple retailers +- **Structured Data**: Returns rich product info including titles, prices, descriptions, thumbnails, ratings, and reviews +- **Agent-Driven Analysis**: The MCP server returns raw data; your AI agent analyzes and provides reasoning +- **Budget Awareness**: Product data includes prices for the agent to consider constraints +- **Configurable Results**: Limit search results (default 10, max 20) based on your needs + +## Tools + +### 1. `recommend_products` + +Searches for products based on a natural language query and returns structured product data. The calling agent should analyze this data and provide intelligent reasoning. + +**Parameters:** +- `query` (string, required): Natural language product request (e.g., "I want to buy a scarf for 40 dollars") +- `maxResults` (integer, optional): Maximum number of results (default: 10, max: 20) + +**Returns:** +```json +{ + "query": "I want to buy a scarf for 40 dollars", + "products": [ + { + "name": "Cashmere Blend Scarf", + "price": "$35.99", + "description": "Soft and warm cashmere blend scarf in multiple colors...", + "url": "https://example.com/product", + "thumbnail": "https://example.com/image.jpg", + "source": "Amazon", + "rating": 4.5, + "reviews": 120 + } + ], + "count": 5 +} +``` + +**Features:** +- Returns rich structured product data including thumbnails and ratings +- The calling agent should analyze products and provide reasoning +- Products include names, prices, descriptions, and purchase URLs +- Only requires `SERPAPI_API_KEY` to function + +### 2. `search_products` + +Search for products across retailers (lower-level tool for raw search results). + +**Parameters:** +- `query` (string, required): Product search query +- `maxResults` (integer, optional): Maximum results to return (default: 10, max: 100) + +**Returns:** +Raw search results from SerpAPI. + +## Setup + +### Prerequisites + +- Python 3.10 or higher +- [uv](https://docs.astral.sh/uv/) package manager +- SerpAPI key (required for product search) + +### Installation + +1. **Get API Key:** + - SerpAPI key: https://serpapi.com/manage-api-key + +2. **Install Dependencies:** + +```bash +cd mcp/shopping_agent +uv pip install -e . +``` + +### Configuration + +Set the required environment variable: + +```bash +export SERPAPI_API_KEY="your-serpapi-key" +``` + +Optional configuration: +```bash +export HOST="0.0.0.0" # Server host (default: 0.0.0.0) +export PORT="8000" # Server port (default: 8000) +export MCP_TRANSPORT="http" # Transport type (default: http, Inspector-ready) +export MCP_JSON_RESPONSE="1" # Force JSON responses (default: enabled) +export LOG_LEVEL="INFO" # Logging level (default: INFO) +``` + +## Running the Server + +### Development Mode + +```bash +cd mcp/shopping_agent +export SERPAPI_API_KEY="your-serpapi-key" +python shopping_agent.py +``` + +The server will start on `http://0.0.0.0:8000` by default and will return structured product data for your agent to analyze. + +### Command-line options + +You can override server behaviour with CLI flags: + +```bash +uv run shopping_agent.py --json-response --port 8020 +``` + +- `--json-response` / `--no-json-response`: toggle JSON responses without touching `MCP_JSON_RESPONSE` +- `--stateless-http` / `--stateful-http`: control FastMCP stateless HTTP mode +- `--host`, `--port`, `--transport`: override bind settings (fall back to environment variables when omitted) + +### MCP Inspector Demo (HTTP Transport) + +Follow these steps to debug the shopping agent with the official MCP Inspector UI: + +1. Start the server on its own port using HTTP transport: + ```bash + cd mcp/shopping_agent + export SERPAPI_API_KEY="your-key" + MCP_TRANSPORT=http PORT=8001 python shopping_agent.py + ``` +2. In a new terminal (requires Node.js ≥18), launch the inspector: + ```bash + npx @modelcontextprotocol/inspector + ``` +3. In the Inspector UI choose **Add server**, then supply: + - Name: `Shopping Agent (HTTP)` + - Transport: `HTTP` (or `Streamable HTTP` on older Inspector releases) + - URL: `http://localhost:8001` +4. Click **Connect**, open the **Tools** tab, and invoke `recommend_products` or `search_products`. Responses stream in the right-hand panel. + +Tip: run the `movie_tool` server on a different port (for example `PORT=8002 MCP_TRANSPORT=http python ../movie_tool/movie_tool.py`) to compare both MCP servers side by side inside the inspector. + +### Using Docker + +```bash +cd mcp/shopping_agent + +# Build the image +docker build -t shopping-agent-mcp . + +# Run the container +docker run -p 8000:8000 \ + -e SERPAPI_API_KEY="your-serpapi-key" \ + shopping-agent-mcp +``` + +## Architecture + +The shopping agent MCP server provides product search data. The calling agent (your AI) provides reasoning and recommendations: + +``` +User Query → [MCP Tool] Search Products → Return Structured Data → [Your Agent] Analyze & Recommend +``` + +### Workflow + +1. **MCP Server**: Receives query, searches SerpAPI, returns structured product data (no reasoning) +2. **Your Agent** (e.g., Claude, GPT-4): Analyzes the product data and provides intelligent reasoning for recommendations + +### Suggested Agent System Prompt + +When using this MCP server, configure your agent with a system prompt like this: + +``` +When users ask for product recommendations: +1. Use the recommend_products tool to search for products +2. Analyze each product considering: + - How well it matches the user's requirements + - Whether it fits within their budget + - The value proposition (quality vs. price) + - Any specific features mentioned in the query +3. For each product, provide: + - A brief explanation of why it's a good match + - A recommendation score (1-10) + - Any caveats or considerations +4. Rank products by how well they match the user's needs +5. Present the top 3-5 recommendations with your reasoning +``` + +### Technologies Used + +- **FastMCP**: MCP server framework +- **LangChain Community**: SerpAPI wrapper for product search +- **SerpAPI**: Real-time product search across retailers + +## Usage Examples + +### Example 1: Basic Product Search + +```python +# Query +"I want to buy a scarf for 40 dollars" + +# MCP Server Response (raw product data) +{ + "query": "I want to buy a scarf for 40 dollars", + "products": [ + { + "name": "Winter Wool Scarf", + "price": "$38.99", + "description": "100% merino wool...", + "url": "https://example.com/product", + "thumbnail": "https://...", + "source": "Retailer A" + }, + { + "name": "Cashmere Blend Scarf", + "price": "$35.99", + "description": "Soft cashmere blend...", + "url": "https://example.com/product2", + "thumbnail": "https://...", + "source": "Retailer B" + } + ], + "count": 2 +} + +# Your Agent should then analyze these products and provide reasoning: +# "Here are my top recommendations: +# +# 1. Winter Wool Scarf ($38.99) - Score: 9/10 +# This is an excellent choice within your $40 budget. The 100% merino wool +# provides superior warmth and quality, making it great value at this price point. +# +# 2. Cashmere Blend Scarf ($35.99) - Score: 8/10 +# A more affordable option that still offers luxury with its cashmere blend..." +``` + +### Example 2: Specific Requirements + +```python +# Query +"Find me wireless headphones under $100 with good noise cancellation" + +# MCP Server Response (raw product data) +{ + "query": "wireless headphones under $100 with good noise cancellation", + "products": [ + { + "name": "Sony WH-CH710N Wireless Headphones", + "price": "$89.99", + "description": "Active noise canceling...", + "url": "https://example.com/sony-headphones", + "rating": 4.4, + "reviews": 8500 + } + ], + "count": 1 +} + +# Your Agent analyzes and recommends: +# "I found the Sony WH-CH710N Wireless Headphones at $89.99 - this is an excellent +# match for your requirements: +# - ✅ Wireless Bluetooth connectivity +# - ✅ Active noise cancellation feature +# - ✅ Well under your $100 budget ($89.99) +# - ✅ Bonus: 35-hour battery life +# +# Recommendation Score: 9/10 +# This product checks all your boxes and comes from Sony, a trusted brand in audio..." +``` + +## Testing + +### Using Python Test Script + +Test the shopping agent MCP server: + +```bash +cd mcp/shopping_agent +export SERPAPI_API_KEY="your-serpapi-key" +python simple_test.py +``` + +This will test the product search functionality and show the structured data returned by the server. + +### Using curl + +You can also test the MCP server tools using curl: + +```bash +# Test recommend_products tool (returns structured product data) +curl -X POST http://localhost:8000/mcp/tools/recommend_products \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{ + "query": "I want to buy a scarf for 40 dollars", + "maxResults": 5 + }' +``` + +## Troubleshooting + +### API Key Issues + +**SerpAPI Key Issues:** +If you see "SERPAPI_API_KEY not configured" errors: +1. Get your key from https://serpapi.com/manage-api-key +2. Export it: `export SERPAPI_API_KEY="your-key"` +3. Restart the server + +**General API Key Tips:** +1. Verify your API key is set correctly +2. Check that the environment variable is exported in the same shell session +3. Restart the server after setting environment variables + +### No Results Returned + +If searches return no results: +1. Try a more specific query with product name and budget +2. Check your SerpAPI quota at https://serpapi.com/dashboard +3. Review server logs for detailed error messages + +### Import Errors + +If you encounter import errors: +1. Ensure all dependencies are installed: `uv pip install -e .` +2. Check Python version is 3.10 or higher +3. Try reinstalling with `uv pip install --force-reinstall -e .` + +## Development + +### Project Structure + +``` +shopping_agent/ +├── shopping_agent.py # Main MCP server with SerpAPI integration +├── simple_test.py # Test script for product search +├── pyproject.toml # Dependencies and project metadata +├── README.md # This file +├── Dockerfile # Container configuration +└── __init__.py # Package initialization +``` + +### Contributing + +When contributing, ensure: +1. Code follows the existing style +2. All API keys are handled via environment variables +3. Error handling is comprehensive +4. Logging is informative but not excessive +5. Tests pass (if applicable) + +## License + +See the repository's LICENSE file for details. + +## Support + +For issues or questions: +1. Check the troubleshooting section above +2. Review server logs for detailed error messages +3. Ensure all API keys are valid and have sufficient quota +4. Open an issue in the repository with relevant logs + diff --git a/mcp/shopping_agent/__init__.py b/mcp/shopping_agent/__init__.py new file mode 100644 index 0000000..4c44d91 --- /dev/null +++ b/mcp/shopping_agent/__init__.py @@ -0,0 +1,6 @@ +"""Shopping Agent MCP Tool""" + +from .shopping_agent import recommend_products, search_products, run_server + +__all__ = ["recommend_products", "search_products", "run_server"] + diff --git a/mcp/shopping_agent/config.example b/mcp/shopping_agent/config.example new file mode 100644 index 0000000..7f7a2f8 --- /dev/null +++ b/mcp/shopping_agent/config.example @@ -0,0 +1,24 @@ +# Shopping Agent MCP Server Configuration Example +# Copy this file to .env or export these variables in your shell + +# Required: OpenAI API Key +# Get your key from: https://platform.openai.com/api-keys +export OPENAI_API_KEY="sk-your-openai-api-key-here" + +# Required: SerpAPI Key +# Get your key from: https://serpapi.com/manage-api-key +export SERPAPI_API_KEY="your-serpapi-key-here" + +# Optional: Server Configuration +# Host address (default: 0.0.0.0) +export HOST="0.0.0.0" + +# Server port (default: 8000) +export PORT="8000" + +# MCP transport type (default: http) +export MCP_TRANSPORT="http" + +# Logging level (default: INFO) +# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL +export LOG_LEVEL="INFO" diff --git a/mcp/shopping_agent/pyproject.toml b/mcp/shopping_agent/pyproject.toml new file mode 100644 index 0000000..ca58abd --- /dev/null +++ b/mcp/shopping_agent/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "shopping_agent" +version = "0.1.0" +description = "Shopping Agent MCP Tool using SerpAPI for product search" +readme = "README.md" +requires-python = ">=3.10" +dependencies = [ + "fastmcp>=2.11.0", + "google-search-results>=2.4.2", + "requests>=2.32.3", +] + +[tool.setuptools] +py-modules = ["shopping_agent"] + diff --git a/mcp/shopping_agent/setup_env.sh b/mcp/shopping_agent/setup_env.sh new file mode 100755 index 0000000..1d83c35 --- /dev/null +++ b/mcp/shopping_agent/setup_env.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Helper script to set up your API keys +# +# Usage: +# 1. Run this script once: ./setup_env.sh +# 2. It will create a .env.local file for you to edit +# 3. Then run: source .env.local && python shopping_agent.py + +echo "🛍️ Shopping Agent Environment Setup" +echo "=====================================" +echo "" + +if [ -f ".env.local" ]; then + echo "ℹ️ .env.local already exists" + echo "" + read -p "Do you want to overwrite it? (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Keeping existing .env.local" + exit 0 + fi +fi + +echo "Creating .env.local template..." +cat > .env.local << 'EOF' +# Shopping Agent MCP Server - Local Environment Configuration +# Load this file: source .env.local + +# Required: OpenAI API Key (https://platform.openai.com/api-keys) +export OPENAI_API_KEY="your-openai-api-key-here" + +# Required: SerpAPI Key (https://serpapi.com/manage-api-key) +export SERPAPI_API_KEY="your-serpapi-api-key-here" + +# Optional: Server Configuration +export HOST="0.0.0.0" +export PORT="8000" +export MCP_TRANSPORT="http" +export LOG_LEVEL="INFO" +EOF + +echo "✓ Created .env.local" +echo "" +echo "📝 Next steps:" +echo " 1. Edit .env.local and add your actual API keys" +echo " 2. Load the environment: source .env.local" +echo " 3. Run the server: python3 shopping_agent.py" +echo " 4. Test the server: python3 test_client.py (in another terminal)" + diff --git a/mcp/shopping_agent/shopping_agent.py b/mcp/shopping_agent/shopping_agent.py new file mode 100644 index 0000000..5f3efe0 --- /dev/null +++ b/mcp/shopping_agent/shopping_agent.py @@ -0,0 +1,263 @@ +"""Shopping Agent MCP Tool - Uses SerpAPI for product search""" + +import argparse +import os +import sys +import json +import logging +from typing import Dict, Any, List +from fastmcp import FastMCP +from serpapi import GoogleSearch + +logger = logging.getLogger(__name__) +logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"), stream=sys.stdout, format='%(levelname)s: %(message)s') + + +def _env_flag(name: str, default: str = "false") -> bool: + """Parse environment flag strings like 1/true/on into booleans.""" + value = os.getenv(name) + if value is None: + value = default + return value.strip().lower() in {"1", "true", "yes", "on"} + +# Environment variable for API key +SERPAPI_API_KEY = os.getenv("SERPAPI_API_KEY") + +# Initialize FastMCP +mcp = FastMCP("Shopping Agent") + + +@mcp.tool(annotations={"readOnlyHint": True, "destructiveHint": False, "idempotentHint": True}) +def recommend_products(query: str, maxResults: int = 10) -> str: + """ + Recommend products based on natural language query (e.g., "good curtains under $40") + + This tool searches Google Shopping via SerpAPI and returns structured product data + including titles, prices, and descriptions. + + Args: + query: Natural language product request + maxResults: Maximum number of product recommendations to return (default 10, max 20) + + Returns: + JSON string containing product search results with names, prices, descriptions, and links. + """ + logger.info(f"Searching products for query: '{query}'") + + if not SERPAPI_API_KEY: + return json.dumps({"error": "SERPAPI_API_KEY not configured"}) + + # Limit maxResults + maxResults = min(maxResults, 20) + + try: + # Configure SerpAPI Google Shopping search + params = { + "api_key": SERPAPI_API_KEY, + "engine": "google_shopping", + "q": query, + "google_domain": "google.com", + "gl": "us", + "hl": "en", + "num": maxResults + } + + logger.debug(f"Searching with params: {json.dumps(params, default=str)}") + search = GoogleSearch(params) + results = search.get_dict() + + if "error" in results: + return json.dumps({"error": results["error"]}) + + shopping_results = results.get("shopping_results", []) + + # Format products + products = [] + for item in shopping_results: + product = { + "name": item.get("title"), + "price": item.get("price"), + "description": item.get("snippet") or item.get("description") or "No description available", + "url": item.get("link"), + "thumbnail": item.get("thumbnail"), + "source": item.get("source"), + "rating": item.get("rating"), + "reviews": item.get("reviews") + } + products.append(product) + + # Fallback to regular search if no shopping results found + if not products and "organic_results" in results: + logger.info("No shopping results found, falling back to organic results") + # This might happen if we switch engine to 'google' or if shopping has no results + # But with engine='google_shopping', we should get shopping_results + pass + + return json.dumps({ + "query": query, + "products": products[:maxResults], + "count": len(products[:maxResults]) + }, indent=2) + + except Exception as e: + logger.error(f"Error in recommend_products: {e}", exc_info=True) + return json.dumps({"error": str(e)}) + + +@mcp.tool(annotations={"readOnlyHint": True, "destructiveHint": False, "idempotentHint": True}) +def search_products(query: str, maxResults: int = 10) -> str: + """ + Search for products using standard Google Search (internal tool) + + Args: + query: Product search query + maxResults: Maximum number of results to return (default 10, max 100) + + Returns: + JSON string containing search results + """ + logger.info(f"Searching products for query: '{query}'") + + if not SERPAPI_API_KEY: + return json.dumps({"error": "SERPAPI_API_KEY not configured"}) + + # Limit maxResults + maxResults = min(maxResults, 100) + + try: + # Use standard Google Search for broader context + params = { + "api_key": SERPAPI_API_KEY, + "engine": "google", + "q": query, + "google_domain": "google.com", + "gl": "us", + "hl": "en", + "num": maxResults + } + + search = GoogleSearch(params) + results = search.get_dict() + + if "error" in results: + return json.dumps({"error": results["error"]}) + + return json.dumps({ + "query": query, + "organic_results": results.get("organic_results", [])[:maxResults], + "shopping_results": results.get("shopping_results", [])[:maxResults] + }, indent=2) + + except Exception as e: + logger.error(f"Error in search_products: {e}", exc_info=True) + return json.dumps({"error": str(e)}) + + +def run_server( + transport: str | None = None, + host: str | None = None, + port: int | str | None = None, + json_response: bool | None = None, + stateless_http: bool | None = None, +) -> None: + """Run the MCP server with optional overrides from CLI or environment.""" + if transport is None: + transport = os.getenv("MCP_TRANSPORT", "http") + if host is None: + host = os.getenv("HOST", "0.0.0.0") + if port is None: + port = int(os.getenv("PORT", "8000")) + else: + port = int(port) + if json_response is None: + json_response = _env_flag("MCP_JSON_RESPONSE", "true") + if stateless_http is None: + stateless_http = _env_flag("MCP_STATELESS_HTTP", "false") + + logger.info( + "Starting MCP server transport=%s host=%s port=%s json_response=%s stateless_http=%s", + transport, + host, + port, + json_response, + stateless_http, + ) + mcp.run( + transport=transport, + host=host, + port=port, + json_response=json_response, + stateless_http=stateless_http, + ) + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Shopping Agent MCP Server") + parser.add_argument( + "--transport", + dest="transport", + default=None, + help="Transport to use for FastMCP (default: env MCP_TRANSPORT or http)", + ) + parser.add_argument( + "--host", + dest="host", + default=None, + help="Host interface to bind (default: env HOST or 0.0.0.0)", + ) + parser.add_argument( + "--port", + dest="port", + type=int, + default=None, + help="Port to bind (default: env PORT or 8000)", + ) + parser.add_argument( + "--json-response", + dest="json_response", + action="store_true", + help="Force JSON responses (overrides env MCP_JSON_RESPONSE)", + ) + parser.add_argument( + "--no-json-response", + dest="json_response", + action="store_false", + help="Disable JSON responses (overrides env MCP_JSON_RESPONSE)", + ) + parser.add_argument( + "--stateless-http", + dest="stateless_http", + action="store_true", + help="Enable stateless HTTP transport mode", + ) + parser.add_argument( + "--stateful-http", + dest="stateless_http", + action="store_false", + help="Disable stateless HTTP transport mode", + ) + parser.set_defaults(json_response=None, stateless_http=None) + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + + if SERPAPI_API_KEY is None: + logger.error("Please configure the SERPAPI_API_KEY environment variable before running the server") + return 1 + + logger.info("Starting Shopping Agent MCP Server with SerpAPI") + logger.info("Note: This server provides search results. The calling agent provides reasoning.") + run_server( + transport=args.transport, + host=args.host, + port=args.port, + json_response=args.json_response, + stateless_http=args.stateless_http, + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/mcp/shopping_agent/test_server.sh b/mcp/shopping_agent/test_server.sh new file mode 100755 index 0000000..71ec42c --- /dev/null +++ b/mcp/shopping_agent/test_server.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +echo "🧪 Testing Shopping Agent MCP Server" +echo "====================================" +echo "" + +# Test 1: Check if server is running +echo "Test 1: Server Health Check" +echo "----------------------------" +response=$(curl -s -w "\n%{http_code}" http://localhost:8000/health 2>&1) +echo "Response: $response" +echo "" + +# Test 2: List MCP capabilities (using SSE endpoint) +echo "Test 2: Initialize MCP Connection" +echo "----------------------------------" +curl -X POST http://localhost:8000/mcp \ + -H "Content-Type: application/json" \ + -H "Accept: text/event-stream" \ + -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}}}' \ + 2>&1 | head -20 +echo "" +echo "" + +# Test 3: Call the recommend_products tool directly (if using standard REST) +echo "Test 3: Test recommend_products tool" +echo "-------------------------------------" +echo "Note: This requires proper MCP protocol - use MCP Inspector for full testing" +echo "" + +echo "✅ If you see responses above, your server is working!" +echo "" +echo "To properly test the server, use the MCP Inspector:" +echo " 1. Keep your server running on port 8000" +echo " 2. Run: npx @modelcontextprotocol/inspector" +echo " 3. Add server with URL: http://localhost:8000" +echo " 4. Connect and test the tools" + From 8419c1bac663d68e4117591a38edec389ffa1182 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:06:53 -0500 Subject: [PATCH 02/21] Update mcp/shopping_agent/QUICKSTART.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/QUICKSTART.md | 1 - 1 file changed, 1 deletion(-) diff --git a/mcp/shopping_agent/QUICKSTART.md b/mcp/shopping_agent/QUICKSTART.md index 754c1b6..6c2392b 100644 --- a/mcp/shopping_agent/QUICKSTART.md +++ b/mcp/shopping_agent/QUICKSTART.md @@ -409,7 +409,6 @@ docker-compose up - Review the [README.md](README.md) for detailed documentation - Review the [ARCHITECTURE.md](ARCHITECTURE.md) for architecture details - Verify API key has sufficient quota at https://serpapi.com/dashboard -- Test with the provided `simple_test.py` script ## Summary From fa8638fe701db6c78387052ce2f2caa6a88cce8a Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:07:14 -0500 Subject: [PATCH 03/21] Update mcp/shopping_agent/shopping_agent.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/shopping_agent.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mcp/shopping_agent/shopping_agent.py b/mcp/shopping_agent/shopping_agent.py index 5f3efe0..759711b 100644 --- a/mcp/shopping_agent/shopping_agent.py +++ b/mcp/shopping_agent/shopping_agent.py @@ -62,7 +62,8 @@ def recommend_products(query: str, maxResults: int = 10) -> str: "num": maxResults } - logger.debug(f"Searching with params: {json.dumps(params, default=str)}") + safe_params = {k: v for k, v in params.items() if k != "api_key"} + logger.debug(f"Searching with params: {json.dumps(safe_params, default=str)}") search = GoogleSearch(params) results = search.get_dict() From 5c86cb962d60bd1d1fbdfe626dd91154ac5e7095 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:12:45 -0500 Subject: [PATCH 04/21] Update mcp/shopping_agent/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mcp/shopping_agent/README.md b/mcp/shopping_agent/README.md index e2cc5cc..d9c7b69 100644 --- a/mcp/shopping_agent/README.md +++ b/mcp/shopping_agent/README.md @@ -190,9 +190,7 @@ When users ask for product recommendations: ### Technologies Used - **FastMCP**: MCP server framework -- **LangChain Community**: SerpAPI wrapper for product search -- **SerpAPI**: Real-time product search across retailers - +- **SerpAPI Python Client (`google-search-results`)**: Direct integration for real-time product search across retailers ## Usage Examples ### Example 1: Basic Product Search From ab08bbda338aa4ade986bb18315cab1b2831e1b4 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:12:55 -0500 Subject: [PATCH 05/21] Update mcp/shopping_agent/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/mcp/shopping_agent/README.md b/mcp/shopping_agent/README.md index d9c7b69..bfd2022 100644 --- a/mcp/shopping_agent/README.md +++ b/mcp/shopping_agent/README.md @@ -333,7 +333,6 @@ If you encounter import errors: ``` shopping_agent/ ├── shopping_agent.py # Main MCP server with SerpAPI integration -├── simple_test.py # Test script for product search ├── pyproject.toml # Dependencies and project metadata ├── README.md # This file ├── Dockerfile # Container configuration From 6dc7fec960973ecbf3769be7245b2572f6b0f856 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:13:03 -0500 Subject: [PATCH 06/21] Update mcp/shopping_agent/ARCHITECTURE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/ARCHITECTURE.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mcp/shopping_agent/ARCHITECTURE.md b/mcp/shopping_agent/ARCHITECTURE.md index 7da49f8..443e038 100644 --- a/mcp/shopping_agent/ARCHITECTURE.md +++ b/mcp/shopping_agent/ARCHITECTURE.md @@ -203,14 +203,6 @@ My top recommendation is the Winter Wool Scarf for its superior quality and warm - **Authentication**: API key via environment variable - **Results**: Aggregated product listings -### LangChain Components - -``` -langchain_community.utilities.SerpAPIWrapper - ├── Search query optimization - ├── Result parsing - └── API key management -``` ## Error Handling From 567777b9e4a120b39196a98fc58eb0723351d876 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:13:17 -0500 Subject: [PATCH 07/21] Update mcp/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/README.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index 34f0251..2e83c45 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -176,23 +176,9 @@ The Shopping Agent demonstrates an advanced MCP tool with: ``` User Query ↓ -Parse Query Node (OpenAI) - ↓ -Search Products Node (SerpAPI) - ↓ -Generate Recommendations Node (OpenAI) +SerpAPI Search ↓ Structured Response -``` - -**Key Technologies**: -- **LangGraph**: Multi-node agent workflow with state management -- **LangChain**: LLM framework for tool integration -- **OpenAI**: Natural language understanding and generation -- **SerpAPI**: Real-time search across retailers - -See [shopping_agent/ARCHITECTURE.md](shopping_agent/ARCHITECTURE.md) for detailed architecture. - ## Creating Your Own MCP Tool ### Basic Template From 7413e9bbfff24c55fbc84f1d40fcd3f57ad41648 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:13:27 -0500 Subject: [PATCH 08/21] Update mcp/shopping_agent/setup_env.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_agent/setup_env.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/mcp/shopping_agent/setup_env.sh b/mcp/shopping_agent/setup_env.sh index 1d83c35..9142a36 100755 --- a/mcp/shopping_agent/setup_env.sh +++ b/mcp/shopping_agent/setup_env.sh @@ -26,9 +26,6 @@ cat > .env.local << 'EOF' # Shopping Agent MCP Server - Local Environment Configuration # Load this file: source .env.local -# Required: OpenAI API Key (https://platform.openai.com/api-keys) -export OPENAI_API_KEY="your-openai-api-key-here" - # Required: SerpAPI Key (https://serpapi.com/manage-api-key) export SERPAPI_API_KEY="your-serpapi-api-key-here" From b8963a48ae0395a37b0eba9c14ff74850f671e15 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:13:35 -0500 Subject: [PATCH 09/21] Update mcp/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/mcp/README.md b/mcp/README.md index 2e83c45..749738a 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -101,7 +101,6 @@ curl -X POST http://localhost:8000/tools/recommend_products \ - [README.md](shopping_agent/README.md) - Full documentation - [QUICKSTART.md](shopping_agent/QUICKSTART.md) - Quick start guide - [ARCHITECTURE.md](shopping_agent/ARCHITECTURE.md) - Architecture details -- [VERIFICATION.md](shopping_agent/VERIFICATION.md) - Requirements verification ## Getting Started From 72bdd2654c7e256658076f720d423f79a43f1eb5 Mon Sep 17 00:00:00 2001 From: Yena Yu Date: Wed, 10 Dec 2025 11:21:42 -0500 Subject: [PATCH 10/21] Signed-off-by: Yena Yu modified from the github copilot Signed-off-by: Yena Yu --- mcp/shopping_agent/test_server.sh | 38 ----------------- .../.gitignore | 0 .../ARCHITECTURE.md | 7 ++-- .../Dockerfile | 0 .../QUICKSTART.md | 15 +++---- .../README.md | 32 +++++---------- .../__init__.py | 0 .../config.example | 3 -- .../pyproject.toml | 0 .../setup_env.sh | 3 ++ .../shopping_agent.py | 41 +++++++++++-------- 11 files changed, 49 insertions(+), 90 deletions(-) delete mode 100755 mcp/shopping_agent/test_server.sh rename mcp/{shopping_agent => shopping_tool}/.gitignore (100%) rename mcp/{shopping_agent => shopping_tool}/ARCHITECTURE.md (98%) rename mcp/{shopping_agent => shopping_tool}/Dockerfile (100%) rename mcp/{shopping_agent => shopping_tool}/QUICKSTART.md (97%) rename mcp/{shopping_agent => shopping_tool}/README.md (93%) rename mcp/{shopping_agent => shopping_tool}/__init__.py (100%) rename mcp/{shopping_agent => shopping_tool}/config.example (80%) rename mcp/{shopping_agent => shopping_tool}/pyproject.toml (100%) rename mcp/{shopping_agent => shopping_tool}/setup_env.sh (91%) rename mcp/{shopping_agent => shopping_tool}/shopping_agent.py (88%) diff --git a/mcp/shopping_agent/test_server.sh b/mcp/shopping_agent/test_server.sh deleted file mode 100755 index 71ec42c..0000000 --- a/mcp/shopping_agent/test_server.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -echo "🧪 Testing Shopping Agent MCP Server" -echo "====================================" -echo "" - -# Test 1: Check if server is running -echo "Test 1: Server Health Check" -echo "----------------------------" -response=$(curl -s -w "\n%{http_code}" http://localhost:8000/health 2>&1) -echo "Response: $response" -echo "" - -# Test 2: List MCP capabilities (using SSE endpoint) -echo "Test 2: Initialize MCP Connection" -echo "----------------------------------" -curl -X POST http://localhost:8000/mcp \ - -H "Content-Type: application/json" \ - -H "Accept: text/event-stream" \ - -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}}}' \ - 2>&1 | head -20 -echo "" -echo "" - -# Test 3: Call the recommend_products tool directly (if using standard REST) -echo "Test 3: Test recommend_products tool" -echo "-------------------------------------" -echo "Note: This requires proper MCP protocol - use MCP Inspector for full testing" -echo "" - -echo "✅ If you see responses above, your server is working!" -echo "" -echo "To properly test the server, use the MCP Inspector:" -echo " 1. Keep your server running on port 8000" -echo " 2. Run: npx @modelcontextprotocol/inspector" -echo " 3. Add server with URL: http://localhost:8000" -echo " 4. Connect and test the tools" - diff --git a/mcp/shopping_agent/.gitignore b/mcp/shopping_tool/.gitignore similarity index 100% rename from mcp/shopping_agent/.gitignore rename to mcp/shopping_tool/.gitignore diff --git a/mcp/shopping_agent/ARCHITECTURE.md b/mcp/shopping_tool/ARCHITECTURE.md similarity index 98% rename from mcp/shopping_agent/ARCHITECTURE.md rename to mcp/shopping_tool/ARCHITECTURE.md index 443e038..cc3ad7f 100644 --- a/mcp/shopping_agent/ARCHITECTURE.md +++ b/mcp/shopping_tool/ARCHITECTURE.md @@ -204,6 +204,7 @@ My top recommendation is the Winter Wool Scarf for its superior quality and warm - **Results**: Aggregated product listings + ## Error Handling ### Error Flow @@ -234,7 +235,7 @@ Except Exception: 2. **API Quota Errors**: SerpAPI rate limits exceeded 3. **Network Errors**: Connection failures 4. **Parsing Errors**: Invalid search results format -5. **Validation Errors**: Invalid parameters (maxResults bounds, etc.) +5. **Validation Errors**: Invalid parameters (max_results bounds, etc.) ## Performance Characteristics @@ -251,7 +252,7 @@ Total Request Time: ~2-4 seconds ### Optimization Strategies 1. **Efficient Parsing**: Lightweight result parsing -2. **Result Limiting**: maxResults parameter (default 10, max 20 for recommend_products) +2. **Result Limiting**: max_results parameter (default 10, max 20 for recommend_products) 3. **Simple Processing**: No complex AI processing on server side 4. **Stateless Design**: No session management overhead @@ -290,7 +291,7 @@ Environment Variables ### Input Validation - Query length limits -- maxResults bounds checking (10 default, 20 max for recommend_products, 100 max for search_products) +- max_results bounds checking (10 default, 20 max for recommend_products, 100 max for search_products) - Parameter type validation - Error message sanitization diff --git a/mcp/shopping_agent/Dockerfile b/mcp/shopping_tool/Dockerfile similarity index 100% rename from mcp/shopping_agent/Dockerfile rename to mcp/shopping_tool/Dockerfile diff --git a/mcp/shopping_agent/QUICKSTART.md b/mcp/shopping_tool/QUICKSTART.md similarity index 97% rename from mcp/shopping_agent/QUICKSTART.md rename to mcp/shopping_tool/QUICKSTART.md index 6c2392b..d8ce099 100644 --- a/mcp/shopping_agent/QUICKSTART.md +++ b/mcp/shopping_tool/QUICKSTART.md @@ -26,7 +26,7 @@ source ~/.zshrc ### Step 2: Install Dependencies ```bash -cd mcp/shopping_agent +cd mcp/shopping_tool uv pip install -e . ``` @@ -57,7 +57,7 @@ curl -X POST http://localhost:8000/mcp/tools/recommend_products \ -H "Accept: application/json, text/event-stream" \ -d '{ "query": "I want to buy a scarf for 40 dollars", - "maxResults": 5 + "max_results": 5 }' ``` @@ -67,7 +67,7 @@ Use the MCP Inspector UI to explore the server interactively: 1. Start the shopping agent with explicit port/transport: ```bash - cd mcp/shopping_agent + cd mcp/shopping_tool export SERPAPI_API_KEY="your-key" MCP_TRANSPORT=http PORT=8001 python shopping_agent.py ``` @@ -93,7 +93,7 @@ curl -X POST http://localhost:8000/mcp/tools/recommend_products \ -H "Accept: application/json, text/event-stream" \ -d '{ "query": "I want to buy a scarf for 40 dollars", - "maxResults": 5 + "max_results": 5 }' ``` @@ -153,7 +153,7 @@ response = requests.post( }, json={ "query": "best laptop under $800 for programming", - "maxResults": 5 + "max_results": 5 } ) @@ -353,7 +353,7 @@ docker-compose up ```json { "query": "string (required) - Natural language product request", - "maxResults": "integer (optional) - Max results (default: 10, max: 20)" + "max_results": "integer (optional) - Max results (default: 10, max: 20)" } ``` @@ -382,7 +382,7 @@ docker-compose up ```json { "query": "string (required) - Search query", - "maxResults": "integer (optional) - Max results (default: 10, max: 100)" + "max_results": "integer (optional) - Max results (default: 10, max: 100)" } ``` @@ -409,6 +409,7 @@ docker-compose up - Review the [README.md](README.md) for detailed documentation - Review the [ARCHITECTURE.md](ARCHITECTURE.md) for architecture details - Verify API key has sufficient quota at https://serpapi.com/dashboard +- Test with the provided `simple_test.py` script ## Summary diff --git a/mcp/shopping_agent/README.md b/mcp/shopping_tool/README.md similarity index 93% rename from mcp/shopping_agent/README.md rename to mcp/shopping_tool/README.md index bfd2022..4fdaf2f 100644 --- a/mcp/shopping_agent/README.md +++ b/mcp/shopping_tool/README.md @@ -18,7 +18,7 @@ Searches for products based on a natural language query and returns structured p **Parameters:** - `query` (string, required): Natural language product request (e.g., "I want to buy a scarf for 40 dollars") -- `maxResults` (integer, optional): Maximum number of results (default: 10, max: 20) +- `max_results` (integer, optional): Maximum number of results (default: 10, max: 20) **Returns:** ```json @@ -52,7 +52,7 @@ Search for products across retailers (lower-level tool for raw search results). **Parameters:** - `query` (string, required): Product search query -- `maxResults` (integer, optional): Maximum results to return (default: 10, max: 100) +- `max_results` (integer, optional): Maximum results to return (default: 10, max: 100) **Returns:** Raw search results from SerpAPI. @@ -73,7 +73,7 @@ Raw search results from SerpAPI. 2. **Install Dependencies:** ```bash -cd mcp/shopping_agent +cd mcp/shopping_tool uv pip install -e . ``` @@ -99,7 +99,7 @@ export LOG_LEVEL="INFO" # Logging level (default: INFO) ### Development Mode ```bash -cd mcp/shopping_agent +cd mcp/shopping_tool export SERPAPI_API_KEY="your-serpapi-key" python shopping_agent.py ``` @@ -124,7 +124,7 @@ Follow these steps to debug the shopping agent with the official MCP Inspector U 1. Start the server on its own port using HTTP transport: ```bash - cd mcp/shopping_agent + cd mcp/shopping_tool export SERPAPI_API_KEY="your-key" MCP_TRANSPORT=http PORT=8001 python shopping_agent.py ``` @@ -190,7 +190,9 @@ When users ask for product recommendations: ### Technologies Used - **FastMCP**: MCP server framework -- **SerpAPI Python Client (`google-search-results`)**: Direct integration for real-time product search across retailers +- **LangChain Community**: SerpAPI wrapper for product search +- **SerpAPI**: Real-time product search across retailers + ## Usage Examples ### Example 1: Basic Product Search @@ -268,19 +270,6 @@ When users ask for product recommendations: # This product checks all your boxes and comes from Sony, a trusted brand in audio..." ``` -## Testing - -### Using Python Test Script - -Test the shopping agent MCP server: - -```bash -cd mcp/shopping_agent -export SERPAPI_API_KEY="your-serpapi-key" -python simple_test.py -``` - -This will test the product search functionality and show the structured data returned by the server. ### Using curl @@ -293,7 +282,7 @@ curl -X POST http://localhost:8000/mcp/tools/recommend_products \ -H "Accept: application/json, text/event-stream" \ -d '{ "query": "I want to buy a scarf for 40 dollars", - "maxResults": 5 + "max_results": 5 }' ``` @@ -331,8 +320,9 @@ If you encounter import errors: ### Project Structure ``` -shopping_agent/ +shopping_tool/ ├── shopping_agent.py # Main MCP server with SerpAPI integration +├── simple_test.py # Test script for product search ├── pyproject.toml # Dependencies and project metadata ├── README.md # This file ├── Dockerfile # Container configuration diff --git a/mcp/shopping_agent/__init__.py b/mcp/shopping_tool/__init__.py similarity index 100% rename from mcp/shopping_agent/__init__.py rename to mcp/shopping_tool/__init__.py diff --git a/mcp/shopping_agent/config.example b/mcp/shopping_tool/config.example similarity index 80% rename from mcp/shopping_agent/config.example rename to mcp/shopping_tool/config.example index 7f7a2f8..cb38047 100644 --- a/mcp/shopping_agent/config.example +++ b/mcp/shopping_tool/config.example @@ -1,9 +1,6 @@ # Shopping Agent MCP Server Configuration Example # Copy this file to .env or export these variables in your shell -# Required: OpenAI API Key -# Get your key from: https://platform.openai.com/api-keys -export OPENAI_API_KEY="sk-your-openai-api-key-here" # Required: SerpAPI Key # Get your key from: https://serpapi.com/manage-api-key diff --git a/mcp/shopping_agent/pyproject.toml b/mcp/shopping_tool/pyproject.toml similarity index 100% rename from mcp/shopping_agent/pyproject.toml rename to mcp/shopping_tool/pyproject.toml diff --git a/mcp/shopping_agent/setup_env.sh b/mcp/shopping_tool/setup_env.sh similarity index 91% rename from mcp/shopping_agent/setup_env.sh rename to mcp/shopping_tool/setup_env.sh index 9142a36..1d83c35 100755 --- a/mcp/shopping_agent/setup_env.sh +++ b/mcp/shopping_tool/setup_env.sh @@ -26,6 +26,9 @@ cat > .env.local << 'EOF' # Shopping Agent MCP Server - Local Environment Configuration # Load this file: source .env.local +# Required: OpenAI API Key (https://platform.openai.com/api-keys) +export OPENAI_API_KEY="your-openai-api-key-here" + # Required: SerpAPI Key (https://serpapi.com/manage-api-key) export SERPAPI_API_KEY="your-serpapi-api-key-here" diff --git a/mcp/shopping_agent/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py similarity index 88% rename from mcp/shopping_agent/shopping_agent.py rename to mcp/shopping_tool/shopping_agent.py index 759711b..b068f18 100644 --- a/mcp/shopping_agent/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -10,7 +10,6 @@ from serpapi import GoogleSearch logger = logging.getLogger(__name__) -logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"), stream=sys.stdout, format='%(levelname)s: %(message)s') def _env_flag(name: str, default: str = "false") -> bool: @@ -28,7 +27,7 @@ def _env_flag(name: str, default: str = "false") -> bool: @mcp.tool(annotations={"readOnlyHint": True, "destructiveHint": False, "idempotentHint": True}) -def recommend_products(query: str, maxResults: int = 10) -> str: +def recommend_products(query: str, max_results: int = 10) -> str: """ Recommend products based on natural language query (e.g., "good curtains under $40") @@ -37,7 +36,7 @@ def recommend_products(query: str, maxResults: int = 10) -> str: Args: query: Natural language product request - maxResults: Maximum number of product recommendations to return (default 10, max 20) + max_results: Maximum number of product recommendations to return (default 10, max 20) Returns: JSON string containing product search results with names, prices, descriptions, and links. @@ -47,8 +46,8 @@ def recommend_products(query: str, maxResults: int = 10) -> str: if not SERPAPI_API_KEY: return json.dumps({"error": "SERPAPI_API_KEY not configured"}) - # Limit maxResults - maxResults = min(maxResults, 20) + # Limit max_results + max_results = min(max_results, 20) try: # Configure SerpAPI Google Shopping search @@ -59,11 +58,10 @@ def recommend_products(query: str, maxResults: int = 10) -> str: "google_domain": "google.com", "gl": "us", "hl": "en", - "num": maxResults + "num": max_results } - safe_params = {k: v for k, v in params.items() if k != "api_key"} - logger.debug(f"Searching with params: {json.dumps(safe_params, default=str)}") + logger.debug(f"Searching with params: {json.dumps(params, default=str)}") search = GoogleSearch(params) results = search.get_dict() @@ -96,8 +94,8 @@ def recommend_products(query: str, maxResults: int = 10) -> str: return json.dumps({ "query": query, - "products": products[:maxResults], - "count": len(products[:maxResults]) + "products": products[:max_results], + "count": len(products[:max_results]) }, indent=2) except Exception as e: @@ -106,13 +104,13 @@ def recommend_products(query: str, maxResults: int = 10) -> str: @mcp.tool(annotations={"readOnlyHint": True, "destructiveHint": False, "idempotentHint": True}) -def search_products(query: str, maxResults: int = 10) -> str: +def search_products(query: str, max_results: int = 10) -> str: """ Search for products using standard Google Search (internal tool) Args: query: Product search query - maxResults: Maximum number of results to return (default 10, max 100) + max_results: Maximum number of results to return (default 10, max 100) Returns: JSON string containing search results @@ -122,8 +120,8 @@ def search_products(query: str, maxResults: int = 10) -> str: if not SERPAPI_API_KEY: return json.dumps({"error": "SERPAPI_API_KEY not configured"}) - # Limit maxResults - maxResults = min(maxResults, 100) + # Limit max_results + max_results = min(max_results, 100) try: # Use standard Google Search for broader context @@ -134,7 +132,7 @@ def search_products(query: str, maxResults: int = 10) -> str: "google_domain": "google.com", "gl": "us", "hl": "en", - "num": maxResults + "num": max_results } search = GoogleSearch(params) @@ -143,10 +141,10 @@ def search_products(query: str, maxResults: int = 10) -> str: if "error" in results: return json.dumps({"error": results["error"]}) - return json.dumps({ + return json.dumps({ "query": query, - "organic_results": results.get("organic_results", [])[:maxResults], - "shopping_results": results.get("shopping_results", [])[:maxResults] + "organic_results": results.get("organic_results", [])[:max_results], + "shopping_results": results.get("shopping_results", [])[:max_results] }, indent=2) except Exception as e: @@ -242,6 +240,13 @@ def _parse_args() -> argparse.Namespace: def main() -> int: + # Configure logging only when run as a script, not on import + logging.basicConfig( + level=os.getenv("LOG_LEVEL", "INFO"), + stream=sys.stdout, + format="%(levelname)s: %(message)s", + ) + args = _parse_args() if SERPAPI_API_KEY is None: From 17fb95a44cf490d4fd5436cda1132c81844ae7f7 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:50:23 -0500 Subject: [PATCH 11/21] Update mcp/shopping_tool/shopping_agent.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/shopping_agent.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcp/shopping_tool/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py index b068f18..c7317bb 100644 --- a/mcp/shopping_tool/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -115,6 +115,11 @@ def search_products(query: str, max_results: int = 10) -> str: Returns: JSON string containing search results """ + # Validate query input + if not isinstance(query, str) or not query.strip(): + return json.dumps({"error": "Query parameter must be a non-empty string."}) + if len(query) > 256: + return json.dumps({"error": "Query parameter is too long (max 256 characters)."}) logger.info(f"Searching products for query: '{query}'") if not SERPAPI_API_KEY: From cd388756aac1b4dece514b3a2c09d30f8cffab51 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:51:01 -0500 Subject: [PATCH 12/21] removed LangGraph/LangChain on README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index 749738a..bbc4d26 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -92,8 +92,6 @@ curl -X POST http://localhost:8000/tools/recommend_products \ **Technologies**: - FastMCP - MCP server framework -- LangChain - LLM application framework -- LangGraph - Agent workflow orchestration - OpenAI GPT-4o-mini - Natural language understanding/generation - SerpAPI - Product search across retailers From 825de6d75ff7e6a51d966b944230339624bdb0cf Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:51:12 -0500 Subject: [PATCH 13/21] Update mcp/shopping_tool/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/shopping_tool/README.md b/mcp/shopping_tool/README.md index 4fdaf2f..e6191df 100644 --- a/mcp/shopping_tool/README.md +++ b/mcp/shopping_tool/README.md @@ -143,7 +143,7 @@ Tip: run the `movie_tool` server on a different port (for example `PORT=8002 MCP ### Using Docker ```bash -cd mcp/shopping_agent +cd mcp/shopping_tool # Build the image docker build -t shopping-agent-mcp . From cf12707e5405651fb51704195971056c2065af41 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:51:55 -0500 Subject: [PATCH 14/21] Update mcp/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/README.md b/mcp/README.md index bbc4d26..59d2d54 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -61,7 +61,7 @@ Interact with GitHub repositories (written in Go). **Requirements**: - GitHub authentication token -### 5. Shopping Agent (`shopping_agent/`) ⭐ NEW +### 5. Shopping Agent (`shopping_tool/`) ⭐ NEW AI-powered shopping recommendations using LangChain, LangGraph, OpenAI, and SerpAPI. From 78ac702cd95034970f61f8c4e0f5f86c3c45c158 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:52:09 -0500 Subject: [PATCH 15/21] Update mcp/shopping_tool/shopping_agent.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/shopping_agent.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcp/shopping_tool/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py index c7317bb..9e9e82f 100644 --- a/mcp/shopping_tool/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -41,6 +41,11 @@ def recommend_products(query: str, max_results: int = 10) -> str: Returns: JSON string containing product search results with names, prices, descriptions, and links. """ + # Validate query input + if not isinstance(query, str) or not query.strip(): + return json.dumps({"error": "Query must not be empty."}) + if len(query) > 256: + return json.dumps({"error": "Query is too long (max 256 characters)."}) logger.info(f"Searching products for query: '{query}'") if not SERPAPI_API_KEY: From ac41e32c0a5f6671b8fd4ad1c5f18f24236f33fe Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:52:20 -0500 Subject: [PATCH 16/21] Update mcp/shopping_tool/shopping_agent.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/shopping_agent.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mcp/shopping_tool/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py index 9e9e82f..966fc4d 100644 --- a/mcp/shopping_tool/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -5,7 +5,6 @@ import sys import json import logging -from typing import Dict, Any, List from fastmcp import FastMCP from serpapi import GoogleSearch From d2dbb37caa9429fb54ccec3ef6df57a0cb80f340 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:52:33 -0500 Subject: [PATCH 17/21] Update mcp/shopping_tool/QUICKSTART.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/QUICKSTART.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/shopping_tool/QUICKSTART.md b/mcp/shopping_tool/QUICKSTART.md index d8ce099..f902919 100644 --- a/mcp/shopping_tool/QUICKSTART.md +++ b/mcp/shopping_tool/QUICKSTART.md @@ -135,7 +135,7 @@ curl -X POST http://localhost:8000/mcp/tools/recommend_products \ -H "Accept: application/json, text/event-stream" \ -d '{ "query": "wireless headphones under $100 with noise cancellation", - "maxResults": 5 + "max_results": 5 }' ``` From 98b7e0b36c500da356dd0d2847553c1fd2392660 Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:52:44 -0500 Subject: [PATCH 18/21] Update mcp/shopping_tool/ARCHITECTURE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/shopping_tool/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/shopping_tool/ARCHITECTURE.md b/mcp/shopping_tool/ARCHITECTURE.md index cc3ad7f..b0865f7 100644 --- a/mcp/shopping_tool/ARCHITECTURE.md +++ b/mcp/shopping_tool/ARCHITECTURE.md @@ -434,7 +434,7 @@ Agent: [Analyzes products and responds to user with]: |-------|-----------|---------| | **Protocol** | FastMCP | MCP server framework | | **Search** | SerpAPI | Product search across retailers | -| **Integration** | LangChain Community | SerpAPI wrapper utilities | +| **Integration** | SerpAPI Python Client | Direct SerpAPI integration | | **Runtime** | Python 3.10+ | Application runtime | | **Package Manager** | uv | Fast Python package management | | **Containerization** | Docker | Deployment and isolation | From 1cfc2bac5576ac8a45e27cf3ac8c8dc8d89e148e Mon Sep 17 00:00:00 2001 From: Yena Yu <160572629+yenayuu@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:52:52 -0500 Subject: [PATCH 19/21] Update mcp/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Yena Yu --- mcp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/README.md b/mcp/README.md index 59d2d54..2d36871 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -164,7 +164,7 @@ Tools use annotations to describe their behavior: | Movie | Python | FastMCP | requests + OMDb | | Slack | Python | FastMCP | slack_sdk | | GitHub | Go | Custom | GitHub API | -| Shopping Agent | Python | FastMCP | LangChain + LangGraph | +| Shopping Agent | Python | FastMCP | SerpAPI | ## Advanced Example: Shopping Agent Architecture From 694e198e2909e9e2ec455f90876ccc4d1762796c Mon Sep 17 00:00:00 2001 From: Yena Yu Date: Sat, 13 Dec 2025 15:59:22 -0500 Subject: [PATCH 20/21] Apply local changes to shopping agent Signed-off-by: Yena Yu --- mcp/github_tool/README.md | 2 +- mcp/shopping_tool/shopping_agent.py | 45 +++++++++++++++++++++++++---- sample-environments.yaml | 12 ++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/mcp/github_tool/README.md b/mcp/github_tool/README.md index ed62880..bde8f80 100644 --- a/mcp/github_tool/README.md +++ b/mcp/github_tool/README.md @@ -137,7 +137,7 @@ After adding the new env vars, apply to Kagenti using `kubectl apply -n team1 -f Now that the environment variables are available, start an instance of the tool - Browse to http://kagenti-ui.localtest.me:8080/Import_New_Tool -- Select namespace (e.g. `team1`) +- Select namespace - Set the Target Port to 9090 - Specify Subfolder `mcp/github_tool` - Click "Build & Deploy New Tool" to deploy. diff --git a/mcp/shopping_tool/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py index 966fc4d..cb4d4a1 100644 --- a/mcp/shopping_tool/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -24,6 +24,27 @@ def _env_flag(name: str, default: str = "false") -> bool: # Initialize FastMCP mcp = FastMCP("Shopping Agent") +# Public agent card for A2A discovery +AGENT_CARD = { + "name": "shopping-agent", + "version": "1.0.0", + "description": "Shopping MCP tool using SerpAPI for product search", + "capabilities": { + "mcp": { + # Using cluster DNS; adjust if you front this with ingress + "endpoints": [ + { + "type": "http", + "url": os.getenv( + "AGENT_CARD_MCP_URL", + "http://shopping-agent:8000/mcp", + ), + } + ] + } + }, +} + @mcp.tool(annotations={"readOnlyHint": True, "destructiveHint": False, "idempotentHint": True}) def recommend_products(query: str, max_results: int = 10) -> str: @@ -149,12 +170,15 @@ def search_products(query: str, max_results: int = 10) -> str: if "error" in results: return json.dumps({"error": results["error"]}) - - return json.dumps({ - "query": query, - "organic_results": results.get("organic_results", [])[:max_results], - "shopping_results": results.get("shopping_results", [])[:max_results] - }, indent=2) + + return json.dumps( + { + "query": query, + "organic_results": results.get("organic_results", [])[:max_results], + "shopping_results": results.get("shopping_results", [])[:max_results], + }, + indent=2, + ) except Exception as e: logger.error(f"Error in search_products: {e}", exc_info=True) @@ -199,6 +223,14 @@ def run_server( ) +# Attach agent card route if FastMCP exposes the FastAPI app +app = getattr(mcp, "app", None) +if app: + @app.get("/.well-known/agent.json") + def agent_card() -> Dict[str, Any]: + return AGENT_CARD + + def _parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Shopping Agent MCP Server") parser.add_argument( @@ -264,6 +296,7 @@ def main() -> int: logger.info("Starting Shopping Agent MCP Server with SerpAPI") logger.info("Note: This server provides search results. The calling agent provides reasoning.") + run_server( transport=args.transport, host=args.host, diff --git a/sample-environments.yaml b/sample-environments.yaml index a49e297..fb69bea 100644 --- a/sample-environments.yaml +++ b/sample-environments.yaml @@ -38,6 +38,18 @@ data: "valueFrom": {"secretKeyRef": {"name": "slack-secret", "key": "bot-token"}} } ] + # mcp shopping uses http transport + mcp-shopping: | + [ + {"name": "MCP_URL", "value": "http://shopping-tool:8000/mcp"} + ] + mcp-shopping-config: | + [ + { + "name": "SERPAPI_API_KEY", + "valueFrom": {"secretKeyRef": {"name": "shopping-secret", "key": "serpapi-key"}} + } + ] slack-researcher-config: | [ {"name": "TASK_MODEL_ID", "value": "granite3.3:8b"}, From bf0e4729f67102238874cf7e0b4885a627b437e1 Mon Sep 17 00:00:00 2001 From: Yena Yu Date: Tue, 20 Jan 2026 13:50:14 -0500 Subject: [PATCH 21/21] Fixed syntax error Signed-off-by: Yena Yu --- mcp/shopping_tool/shopping_agent.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mcp/shopping_tool/shopping_agent.py b/mcp/shopping_tool/shopping_agent.py index cb4d4a1..2c98baa 100644 --- a/mcp/shopping_tool/shopping_agent.py +++ b/mcp/shopping_tool/shopping_agent.py @@ -5,6 +5,7 @@ import sys import json import logging +from typing import Any, Dict, Optional, Union from fastmcp import FastMCP from serpapi import GoogleSearch @@ -186,11 +187,11 @@ def search_products(query: str, max_results: int = 10) -> str: def run_server( - transport: str | None = None, - host: str | None = None, - port: int | str | None = None, - json_response: bool | None = None, - stateless_http: bool | None = None, + transport: Optional[str] = None, + host: Optional[str] = None, + port: Optional[Union[int, str]] = None, + json_response: Optional[bool] = None, + stateless_http: Optional[bool] = None, ) -> None: """Run the MCP server with optional overrides from CLI or environment.""" if transport is None: