Skip to main content

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:

  1. Database Indexing: The schema includes optimized indexes for common queries
  2. Connection Pooling: Adjust DB_POOL_MAX_SIZE for high-concurrency scenarios
  3. Similarity Threshold: Higher thresholds reduce computation but may miss relevant results
  4. 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

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run the test suite
  5. Submit a pull request

License

[Add your license information here]

Support

For issues and questions:

  1. Check the troubleshooting section above
  2. Review the test files for usage examples
  3. Open an issue on the repository

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wine_semantic_search-0.1.0.tar.gz (38.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wine_semantic_search-0.1.0-py3-none-any.whl (24.2 kB view details)

Uploaded Python 3

File details

Details for the file wine_semantic_search-0.1.0.tar.gz.

File metadata

  • Download URL: wine_semantic_search-0.1.0.tar.gz
  • Upload date:
  • Size: 38.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for wine_semantic_search-0.1.0.tar.gz
Algorithm Hash digest
SHA256 164cac7219c23eec967c90b2e9ff4c6e8b04601d82a9e4580a18bb79a3a31a84
MD5 422677b7a975d6bafd710e08fef96bc1
BLAKE2b-256 40472ff3d6d2b84bda9ef5de8ed443d50d636b8f47787d2e08e588d48359404b

See more details on using hashes here.

File details

Details for the file wine_semantic_search-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for wine_semantic_search-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1c5bd8bb3785c44560a749fc4364c8108e721670f02eb09292f6a4d9aae7c92
MD5 46f2b4b04a1d8c59c9ff9247b1d96a34
BLAKE2b-256 0e9556819a311a627de36d1b2be03348e93662465b9a39ae99bce4cfd2347be9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page