Wine Semantic Search MCP Server
A Model Context Protocol (MCP) server that enables semantic search capabilities over a PostgreSQL database containing wine listings and descriptions. The system uses vector embeddings to perform intelligent searches that understand the meaning and context of wine-related queries, returning relevant wine recommendations based on semantic similarity rather than just keyword matching.
Features
- Semantic Search: Uses OpenAI's text-embedding-3-small model for intelligent wine recommendations
- Vector Database: PostgreSQL with pgvector extension for efficient similarity search
- MCP Protocol: Full compliance with Model Context Protocol for AI assistant integration
- Configurable: Flexible search parameters and result limits
- Production Ready: Comprehensive error handling, logging, and connection management
- Type Safe: Full type annotations and validation using Pydantic
Requirements
- Python: 3.8 or higher
- PostgreSQL: 12+ with pgvector extension installed
- OpenAI API Key: For generating embeddings
Quick Start
1. Install Dependencies
# Clone the repository
git clone <repository-url>
cd wine-semantic-search
# Install the package
pip install -e .
# For development
pip install -e ".[dev]"
2. Database Setup
Install PostgreSQL and pgvector
Ubuntu/Debian:
sudo apt-get install postgresql postgresql-contrib
sudo apt-get install postgresql-14-pgvector # Adjust version as needed
macOS (using Homebrew):
brew install postgresql
brew install pgvector
Docker (Alternative):
docker run --name wine-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d pgvector/pgvector:pg16
Create Database and Schema
# Connect to PostgreSQL
psql -U postgres -h localhost
# Create database
CREATE DATABASE wine_database;
# Connect to the new database
\c wine_database
# Run the schema setup
\i database_schema.sql
Or use the provided schema file:
psql -U postgres -h localhost -d wine_database -f database_schema.sql
3. Configuration
Copy the example configuration file and customize it:
cp .env.example .env
Edit .env with your settings:
# Required settings
DATABASE_URL=postgresql://username:password@localhost:5432/wine_database
OPENAI_API_KEY=your_openai_api_key_here
# Optional settings
MAX_RESULTS=50
SIMILARITY_THRESHOLD=0.7
4. Load Wine Data (Optional)
If you have wine data to import, you can use the following format:
INSERT INTO wine (country, description, designation, points, price, province, region_1, region_2, variety, winery)
VALUES
('France', 'A rich, full-bodied Bordeaux with notes of blackcurrant and oak', 'Château Example 2020', 92, 45.99, 'Bordeaux', 'Left Bank', 'Pauillac', 'Cabernet Sauvignon', 'Château Example'),
-- Add more wine records...
Note: Embeddings will be generated automatically when you perform searches.
5. Run the Server
# Start the MCP server
wine-search-server
# Or run directly with Python
python -m wine_semantic_search.main
Usage
As an MCP Server
The server exposes a single tool called search_wines that can be used by any MCP-compatible client:
Tool Schema:
{
"name": "search_wines",
"description": "Search for wines using natural language descriptions",
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Natural language description of desired wine characteristics"
},
"limit": {
"type": "integer",
"description": "Maximum number of results to return (default: 10, max: 50)",
"minimum": 1,
"maximum": 50,
"default": 10
}
},
"required": ["query"]
}
}
Example Queries:
- "I want a full-bodied red wine from France under $30"
- "Light, crisp white wine perfect for seafood"
- "Bold Cabernet Sauvignon with high ratings"
- "Sweet dessert wine from Germany"
Testing the Installation
You can test your setup using the built-in health check:
# Test database connection and configuration
python -c "
from wine_semantic_search.main import test_setup
import asyncio
asyncio.run(test_setup())
"
Database Schema
The system uses two main tables:
wine table
Stores wine information including:
- Basic details (name, country, region, variety, winery)
- Ratings and pricing (points, price)
- Descriptive text (description)
wine_embeddings table
Stores vector embeddings for semantic search:
- 512-dimensional vectors generated by OpenAI
- Linked to wine records via foreign key
- Indexed for efficient similarity search
See database_schema.sql for the complete schema definition.
Configuration Options
| Environment Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | - | PostgreSQL connection string |
OPENAI_API_KEY |
Yes | - | OpenAI API key for embeddings |
MAX_RESULTS |
No | 50 | Maximum search results (1-50) |
SIMILARITY_THRESHOLD |
No | 0.7 | Minimum similarity score (0.0-1.0) |
Development
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=wine_semantic_search
# Run specific test categories
pytest tests/test_database.py # Database tests
pytest tests/test_embedding.py # Embedding tests
pytest tests/test_integration.py # Integration tests
Code Quality
# Format code
black wine_semantic_search/
isort wine_semantic_search/
# Type checking
mypy wine_semantic_search/
# Linting
flake8 wine_semantic_search/
Property-Based Testing
The project uses Hypothesis for property-based testing to ensure correctness across a wide range of inputs:
# Run property-based tests with verbose output
pytest tests/ -v --hypothesis-show-statistics
Troubleshooting
Common Issues
1. pgvector extension not found
ERROR: extension "vector" is not available
Solution: Install pgvector extension for your PostgreSQL version.
2. Database connection failed
ERROR: could not connect to server
Solution: Check your DATABASE_URL and ensure PostgreSQL is running.
3. OpenAI API errors
ERROR: Invalid API key
Solution: Verify your OPENAI_API_KEY is correct and has sufficient credits.
4. No search results
INFO: No wines found matching query
Solution: Check that your database contains wine records and try adjusting the SIMILARITY_THRESHOLD.
Logging
The server provides detailed logging for troubleshooting:
# Enable debug logging
export LOG_LEVEL=DEBUG
wine-search-server
Performance Tuning
For large datasets, consider:
- Database Indexing: The schema includes optimized indexes for common queries
- Connection Pooling: Adjust
DB_POOL_MAX_SIZEfor high-concurrency scenarios - Similarity Threshold: Higher thresholds reduce computation but may miss relevant results
- Result Limits: Lower limits improve response times
Architecture
The system follows a layered architecture:
- MCP Server Layer: Handles protocol communication and tool registration
- Service Layer: Business logic for embeddings and database operations
- Data Layer: PostgreSQL with pgvector for efficient vector operations
Contributing
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run the test suite
- Submit a pull request
License
[Add your license information here]
Support
For issues and questions:
- Check the troubleshooting section above
- Review the test files for usage examples
- Open an issue on the repository
Release files for wine-semantic-search 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wine_semantic_search-0.1.1.tar.gz | 38.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wine_semantic_search-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 63.1 kB
Release files / wine_semantic_search-0.1.1.tar.gz
| Download URL | wine_semantic_search-0.1.1.tar.gz |
|---|---|
| Size | 38.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f858ba0ffc00dd7d5e0a7e49bce4872b57cc01779e5d7483ea822f5a856e0ff6
|
|
BLAKE2b-256 checksum How to use checksums |
eddd98ce1a55c5c534684181bbfdff743a2832174484cc91202665367c3fc01f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / wine_semantic_search-0.1.1-py3-none-any.whl
| Download URL | wine_semantic_search-0.1.1-py3-none-any.whl |
|---|---|
| Size | 24.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
088917e81a64d91659e10212589a76795467a577a0e091beb8b930e5045b27bc
|
|
BLAKE2b-256 checksum How to use checksums |
ecfd56bd92cf4d23f1b2a60576cbb35feade24fa440f02aac057de6be6bacd68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|