A Model Context Protocol server for semantic wine search using PostgreSQL and OpenAI embeddings
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wine_semantic_search-0.1.1.tar.gz.
File metadata
- Download URL: wine_semantic_search-0.1.1.tar.gz
- Upload date:
- Size: 38.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f858ba0ffc00dd7d5e0a7e49bce4872b57cc01779e5d7483ea822f5a856e0ff6
|
|
| MD5 |
31800c2627f01913eeb31f8083287cfa
|
|
| BLAKE2b-256 |
eddd98ce1a55c5c534684181bbfdff743a2832174484cc91202665367c3fc01f
|
File details
Details for the file wine_semantic_search-0.1.1-py3-none-any.whl.
File metadata
- Download URL: wine_semantic_search-0.1.1-py3-none-any.whl
- Upload date:
- Size: 24.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
088917e81a64d91659e10212589a76795467a577a0e091beb8b930e5045b27bc
|
|
| MD5 |
907554347a0e9769e5fe2b6488c9657f
|
|
| BLAKE2b-256 |
ecfd56bd92cf4d23f1b2a60576cbb35feade24fa440f02aac057de6be6bacd68
|