Alko MCP Server
Uses Google Cloud Firestore for data storage and persistence of product catalog, store information, and enriched product data, with support for both production deployment and local emulator.
Retrieves wine ratings and reviews from Vivino by searching for wines by name or URL through web scraping.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Alko MCP Serverfind a good Finnish gin under 30 euros"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Alko MCP Server
A production-grade Model Context Protocol (MCP) server that provides AI assistants with access to the Alko.fi alcohol product catalog.
Features
Product Search: Search 11,900+ products by name, type, country, price range, alcohol %, and more
Product Details: Get detailed information including enriched data (taste profile, food pairings, certificates, serving suggestions)
Vivino Ratings: Get wine ratings from Vivino.com by name or URL
Store Hours: Check store opening hours with "open now" filtering
Store Availability: Check real-time stock availability at Alko stores (via web scraping)
Recommendations: Get product recommendations based on food pairings, occasions, and preferences
Store Listing: Browse 360+ Alko stores by city
All tools return compact JSON for efficient LLM token usage.
Related MCP server: MatMCP
Demo
Claude Desktop using Alko MCP to search products, check availability, and get recommendations.
MCP Tools
Tool | Description |
| Search products by name, type, country, price range, alcohol % |
| Get product details. Set |
| Get store opening hours. Filter by city, name, or |
| Check store stock for a product (scrapes alko.fi) |
| List Alko stores by city |
| Get personalized product recommendations |
| Get Vivino wine rating by name or URL (scrapes vivino.com) |
| Sync database with latest Alko price list |
| Check sync status and product count |
Quick Start
Prerequisites
Node.js 24+
Google Cloud Firestore (or emulator for local dev)
Playwright (auto-installed for web scraping)
Installation
# Clone the repository
git clone https://github.com/yourusername/alko-mcp.git
cd alko-mcp
# Install dependencies
npm install
# Install Playwright browsers
npx playwright install chromium
# Build
npm run buildLocal Development with Firestore Emulator
Step 1: Start Firestore Emulator (keep running in background)
gcloud emulators firestore start --host-port=localhost:8081Step 2: Start Claude Desktop (or other AI assistant)
The MCP server will automatically load bundled seed data (~12,000 products, ~360 stores) on first query if the emulator is empty. No manual sync required!
Note: The emulator doesn't persist data. After restarting the emulator, seed data will be auto-loaded again on first use.
Optional: Fresh Data Sync
If you need the latest product data from Alko.fi:
export FIRESTORE_EMULATOR_HOST=localhost:8081
# Sync fresh products from Excel (~30 seconds)
npm run sync-data
# Sync fresh stores from website (~2 minutes)
npm run sync-stores
# Export to seed file (for sharing with team)
npm run export-seedAI Assistant Configuration
Claude Desktop
Config file: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
Local development:
{
"mcpServers": {
"alko": {
"command": "node",
"args": ["/absolute/path/to/alko-mcp/dist/server.js"],
"env": {
"FIRESTORE_EMULATOR_HOST": "localhost:8081"
}
}
}
}Production (Cloud Run):
{
"mcpServers": {
"alko": {
"url": "https://YOUR-CLOUD-RUN-URL.run.app/mcp",
"transport": "streamable-http"
}
}
}ChatGPT Desktop
Config file: ~/.config/chatgpt/mcp.json (macOS/Linux) or %APPDATA%\chatgpt\mcp.json (Windows)
Local development:
{
"servers": {
"alko": {
"command": "node",
"args": ["/absolute/path/to/alko-mcp/dist/server.js"],
"env": {
"FIRESTORE_EMULATOR_HOST": "localhost:8081"
}
}
}
}Production (Cloud Run):
{
"servers": {
"alko": {
"url": "https://YOUR-CLOUD-RUN-URL.run.app/mcp",
"transport": "streamable-http"
}
}
}Google Gemini (AI Studio)
For Gemini, use HTTP transport. Start the server with:
MCP_TRANSPORT=http PORT=3000 node dist/server.jsThen configure in AI Studio with the MCP endpoint URL:
http://localhost:3000/mcpFor production, deploy to Cloud Run with API token authentication (see below).
Claude Code CLI
Add to your project's .mcp.json:
{
"mcpServers": {
"alko": {
"command": "node",
"args": ["./dist/server.js"],
"env": {
"FIRESTORE_EMULATOR_HOST": "localhost:8081"
}
}
}
}Example Prompts
🔍 Basic Search
Etsi minulle hyviä italialaisia punaviinejä alle 20 euroa
Searches for Italian red wines under €20
🍷 Wine Recommendations
Suosittele viiniä grillatulle lohelle. Budjetti noin 15-25 euroa.
Recommends wine for grilled salmon within budget
🥂 Champagne & Sparkling
Mitä samppanjoita Alkossa on saatavilla? Näytä 5 parasta vaihtoehtoa.
Lists champagne options
🍺 Craft Beer Search
Etsi IPA-oluita Suomesta tai muista Pohjoismaista
Searches for Nordic IPA beers
📊 Product Details
Kerro lisää tuotteesta numero 906458
Gets detailed product information with taste profile
🏪 Store Hours
Mitkä Alkon myymälät ovat auki nyt Helsingissä?
Lists Helsinki stores that are open now
📍 Store Availability
Onko Barolo-viiniä saatavilla Helsingin myymälöissä?
Checks product availability in Helsinki stores
🎁 Gift Recommendations
Etsi lahjaideoita viininystävälle. Budjetti 50-100 euroa.
Premium gift ideas for wine lovers
🧀 Food Pairing (uses Alko's official pairing data)
Suosittele viiniä äyriäisille / Recommend wine for seafood
Uses Alko's food symbol search to find products officially tagged for seafood pairing
Tarvitsen viinin juustolautaselle. Juustot: brie, manchego ja sinihomejuusto.
Wine for cheese platter - matches "miedot juustot" and "voimakkaat juustot"
🌍 Region-specific Search
Hae espanjalaisia punaviinejä Rioja-alueelta
Spanish wines from Rioja region
💰 Budget Shopping
Parhaat viinit alle 10 eurolla arki-iltoihin
Best budget wines for weeknight dinners
🍾 Special Occasions
Suosittele kuohuviiniä uudenvuoden juhliin 20 hengelle
Sparkling wine for New Year's party
⭐ Vivino Ratings
Etsi punaviinejä 15-25€ ja tarkista niiden Vivino-arvostelut
Searches for red wines and checks their Vivino ratings
🏆 Best Rated Wines
Mikä on Alkon parhaiten arvioitu Barolo Vivinossa?
Finds Barolo wines and compares their Vivino ratings
📈 Wine Comparison
Vertaile näiden viinien Vivino-arvosanoja: Amarone, Brunello di Montalcino
Compares Vivino ratings for premium Italian wines
Data Sources
Product Catalog
Source: Alko's public Excel price list
URL:
https://www.alko.fi/INTERSHOP/static/WFS/Alko-OnlineShop-Site/-/Alko-OnlineShop/fi_FI/Alkon%20Hinnasto%20Tekstitiedostona/alkon-hinnasto-tekstitiedostona.xlsxProducts: ~11,900
Update: Run
npm run sync-data
Store Data
Source: Scraped from alko.fi store finder
Stores: ~360
Includes: Name, address, opening hours (today/tomorrow)
Update: Run
npm run sync-stores
Enriched Product Data
Source: Scraped from individual product pages
Includes: Taste profile, usage tips, serving suggestions, food pairings, certificates, ingredients
Cached: Persisted to Firestore after first scrape
Product Fields
Field | Description |
| Product ID (e.g., "004246") |
| Product name |
| Producer/manufacturer |
| Price in EUR |
| Price per liter |
| Volume (e.g., "0.75 l") |
| Category (punaviinit, valkoviinit, oluet, etc.) |
| Flavor profile (e.g., "Mehevä & Hilloinen") |
| Country of origin |
| Wine region |
| Alcohol % |
| Taste description from Excel |
| Detailed taste (enriched, scraped) |
| Usage suggestions (enriched) |
| Serving temperature (enriched) |
| Food pairing symbols (enriched) |
| Certification labels: Luomu, Vegaani, etc. (enriched) |
| Producer declared ingredients (enriched) |
| vakiovalikoima, tilausvalikoima, etc. |
Development
npm run build # Compile TypeScript
npm run dev # Run with tsx watch mode
npm run test # Run tests in watch mode
npm run test:run # Run tests once (232 tests)
npm run typecheck # Type check
npm run sync-data # Sync products from Excel
npm run sync-stores # Scrape stores from website
npm run export-seed # Export data to seed file (with diff)Logs
tail -f /tmp/alko-mcp.logDeployment to Google Cloud Run
The server can be deployed to Cloud Run with public access (no authentication) for compatibility with ChatGPT and other MCP clients.
# Enable APIs
gcloud services enable run.googleapis.com firestore.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com
# Create Firestore database
gcloud firestore databases create --location=europe-north1
# Deploy using Cloud Build
gcloud builds submit --config=cloudbuild.yaml
# Or deploy directly from source
gcloud run deploy alko-mcp \
--source . \
--region europe-north1 \
--memory 2Gi \
--cpu 2 \
--execution-environment gen2 \
--set-env-vars="MCP_TRANSPORT=http" \
--allow-unauthenticatedTest the endpoint:
curl -X POST https://alko-mcp-xxx.a.run.app/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'See DEPLOYMENT.md for API token authentication and other options.
Legal Disclaimer
The Alko price list is publicly available data
Web scraping respects rate limits (2s between requests)
This is an unofficial project not affiliated with Alko Oy
Alcohol products can only be purchased by persons 18+ in Finland
License
MIT License
Available Tools
9 toolsget_availabilityCheck Product StockARead-onlyIdempotent
Check real-time product availability at Alko stores. Returns store names with stock quantities. Filter by city. Scrapes alko.fi for live data.
| Name | Required | Description | Default |
|---|---|---|---|
| productId | Yes | The Alko product ID (e.g., "906458") | |
| city | No | Filter by city name (e.g., "Helsinki", "Tampere") | |
| forceRefresh | No | Force a fresh scrape instead of using cached data |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=true, and idempotentHint=true, covering safety and idempotency. The description adds valuable behavioral context beyond annotations: it discloses the data source ('Scrapes alko.fi for live data'), real-time nature, and caching behavior ('Force a fresh scrape instead of using cached data'), which are not captured in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence, followed by return details, filtering, and data source. Each sentence adds essential information without redundancy, making it efficient and well-structured for quick comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 parameters, no output schema), the description is mostly complete. It covers purpose, data source, and key behaviors. However, it lacks details on output format (e.g., structure of returned store names and quantities) and error handling, which would be helpful since there's no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with clear descriptions for all parameters (productId, city, forceRefresh). The description adds minimal semantic value beyond the schema, only implying filtering by city and caching behavior, which are already covered in parameter descriptions. Baseline 3 is appropriate given high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Check real-time product availability'), resource ('at Alko stores'), and scope ('Returns store names with stock quantities'). It distinguishes from siblings like 'get_product' (product details), 'list_stores' (store listings), and 'search_products' (product search) by focusing on stock availability with store-level granularity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool ('Check real-time product availability at Alko stores') and mentions filtering capability ('Filter by city'). However, it does not explicitly state when NOT to use it or name specific alternatives among the sibling tools, such as 'get_product' for product details without stock data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_productGet Product by IDARead-onlyIdempotent
Retrieve detailed product info by Alko product ID. Optional: includeEnrichedData=true adds taste profile, food pairings, serving tips (slower, scrapes alko.fi).
| Name | Required | Description | Default |
|---|---|---|---|
| productId | Yes | The Alko product ID (e.g., "906458") | |
| includeEnrichedData | No | If true, scrapes additional data from product page: taste profile, usage tips, serving suggestions, and food pairings. This is slower but provides more detailed information. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, and open-world behavior, but the description adds valuable context beyond this: it discloses that includeEnrichedData=true triggers web scraping ('scrapes alko.fi') and impacts performance ('slower'). This provides practical behavioral insights not captured in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: the first states the core purpose, and the second explains the optional parameter with its benefits and trade-offs. Every word adds value, with no redundancy or fluff, making it efficiently front-loaded and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (2 parameters, no output schema), the description is nearly complete: it covers purpose, parameter usage, and behavioral nuances. However, without an output schema, it could briefly hint at the return structure (e.g., 'detailed product info' is vague) to achieve full completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents both parameters. The description adds some semantic context for includeEnrichedData (e.g., 'taste profile, food pairings, serving tips'), but this largely overlaps with the schema's description. No new parameter details are introduced beyond what the schema provides, meeting the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Retrieve') and resource ('detailed product info'), specifies the key identifier ('by Alko product ID'), and distinguishes from siblings like 'search_products' by focusing on single-item lookup rather than search. This is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the optional parameter (includeEnrichedData=true for taste profiles, food pairings, etc.), including a performance trade-off ('slower, scrapes alko.fi'). However, it does not explicitly state when to choose this tool over alternatives like 'search_products' or 'get_recommendations', which would be needed for a score of 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recommendationsGet Wine/Drink RecommendationsARead-onlyIdempotent
Get personalized product recommendations. Specify occasion, food pairing (uses Alko official pairing data), price range, or preferences (organic, vegan). Supports 33 food categories.
| Name | Required | Description | Default |
|---|---|---|---|
| preferredTypes | No | Preferred product types (e.g., ["punaviinit", "viskit"]) | |
| priceRange | No | Price range for recommendations | |
| occasion | No | Occasion for the drink (e.g., "dinner party", "gift", "casual") | |
| foodPairing | No | Food to pair with. Uses Alko's official food pairing data. Supported categories (Finnish/English): Äyriäiset (seafood/shrimp/lobster/crab), Rasvainen kala (salmon/tuna/mackerel), Vähärasvainen kala (cod/halibut/white fish), Kana, kalkkuna (chicken/turkey/poultry), Nauta (beef/steak), Porsas (pork/ham/bacon), Lammas (lamb), Riista (game/venison/elk), Riistalinnut (duck/pheasant/goose), Sushi (sushi/sashimi/japanese), Pasta ja pizza (pasta/pizza/italian), Grilliruoka (grilled/bbq), Itämainen ruoka (asian/thai/chinese/indian), Tulinen ruoka (spicy/curry/chili), Salaatit, kasvisruoka (salad/vegetarian/vegan), Miedot juustot (mild cheese/brie/mozzarella), Voimakkaat juustot (strong cheese/blue cheese/parmesan), Simpukat ja osterit (mussels/oysters/clams), Sienet (mushrooms/truffle), Makea jälkiruoka (dessert/chocolate/cake), Aperitiivi (aperitif), Seurustelujuoma (social/party), Nautiskelujuoma (digestif/nightcap), Tapas ja antipasti (tapas/antipasti/mezze), Pikkusuolaiset (snacks/finger food), Keitot (soup/stew), Noutopöytä (buffet), Blinit (blini) | |
| preferOrganic | No | Prefer organic products | |
| preferVegan | No | Prefer vegan-suitable products | |
| country | No | Preferred country of origin | |
| limit | No | Number of recommendations |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a safe read operation (readOnlyHint: true, destructiveHint: false, idempotentHint: true). The description adds useful context about the food pairing data source ('Alko official pairing data') and the 33 food categories support, but doesn't disclose rate limits, authentication needs, or return format details beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured in two sentences: the first states the core purpose and key parameters, the second adds important context about the food pairing system. Every word earns its place with no redundancy or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only recommendation tool with comprehensive annotations and full schema coverage, the description provides adequate context about what the tool does and its key features. The main gap is the lack of output schema, so the description doesn't explain what the recommendations look like (e.g., format, fields returned), but this is partially mitigated by the tool's straightforward purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the schema already documents all 8 parameters thoroughly. The description adds marginal value by mentioning the same parameters (occasion, food pairing, price range, preferences) but doesn't provide additional syntax, format details, or usage examples beyond what's in the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('Get personalized product recommendations') and resources ('wine/drink'), distinguishing it from siblings like get_product (single product) or search_products (unfiltered search). It explicitly mentions the recommendation aspect and personalization criteria.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool ('personalized product recommendations') and lists specific filtering criteria (occasion, food pairing, price range, preferences). However, it doesn't explicitly state when NOT to use it or name alternatives like search_products for broader searches.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_store_hoursGet Store Opening HoursARead-onlyIdempotent
Get Alko store opening hours for today and tomorrow. Filter by store name, city, or openNow=true for currently open stores. Auto-refreshes stale data.
| Name | Required | Description | Default |
|---|---|---|---|
| storeId | No | Specific store ID to get hours for | |
| storeName | No | Search by store name (partial match, e.g., "Kamppi" or "Helsinki Arkadia") | |
| city | No | Filter by city name (e.g., "Helsinki", "Tampere") | |
| openNow | No | Filter to only show stores currently open | |
| limit | No | Maximum number of stores to return |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral context beyond what annotations provide: 'Auto-refreshes stale data' reveals a caching/refresh behavior not indicated by annotations. The annotations already cover read-only, open-world, idempotent, and non-destructive aspects, so the description appropriately supplements rather than contradicts them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured in two sentences that each earn their place: first establishes core purpose, second adds filtering details and behavioral nuance. No wasted words, front-loaded with essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, comprehensive annotations, and full parameter documentation, the description provides good contextual coverage. The main gap is the lack of output schema, so the description doesn't explain return format, but this is reasonable given the annotations and clear purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the input schema already documents all 5 parameters thoroughly. The description mentions filtering by store name, city, or openNow, which aligns with but doesn't add significant meaning beyond the schema. This meets the baseline expectation when schema coverage is complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Get Alko store opening hours'), resource ('Alko store'), scope ('for today and tomorrow'), and distinguishes from siblings by focusing on hours rather than availability, products, or store listings. It goes beyond just restating the name/title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context about when to use this tool (to get opening hours for today/tomorrow with filtering capabilities). However, it doesn't explicitly mention when NOT to use it or name specific alternatives among the sibling tools (e.g., when to use list_stores instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sync_statusGet Database StatusARead-onlyIdempotent
Check database health: product count, last sync timestamp, sync status. Use to verify data freshness before searches.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide strong behavioral hints (readOnly, non-destructive, idempotent, closed-world). The description adds value by explaining the tool's purpose in checking health metrics, but it doesn't disclose additional behavioral traits like potential rate limits, authentication needs, or what 'sync status' entails beyond what annotations cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is highly concise and well-structured: two sentences that efficiently convey the tool's purpose and usage guideline. Every sentence adds value without redundancy, making it easy to parse and understand quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (0 parameters, no output schema) and rich annotations, the description is reasonably complete. It explains what the tool does and when to use it, though it could be more comprehensive by detailing the return format or error conditions, which aren't covered by annotations or an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters with 100% coverage, so no parameter documentation is needed. The description appropriately doesn't discuss parameters, focusing instead on the tool's purpose and usage. This meets the baseline for tools with no parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Check database health' with specific metrics (product count, last sync timestamp, sync status). It uses a specific verb ('Check') and resource ('database health'), though it doesn't explicitly differentiate from sibling tools like 'get_availability' or 'sync_products' which might have related purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool: 'to verify data freshness before searches.' This gives a practical guideline, but it doesn't explicitly state when NOT to use it or mention alternatives among siblings (e.g., 'sync_products' for syncing data).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_vivino_ratingGet Vivino Wine RatingARead-onlyIdempotent
Look up wine ratings from Vivino.com. Search by wine name/winery or provide direct URL. Returns: average rating (1-5 stars), rating count, wine details. Results are cached.
| Name | Required | Description | Default |
|---|---|---|---|
| wineName | No | The wine name to search for on Vivino (e.g., "Chateau Margaux") | |
| winery | No | The winery/producer name to help narrow down the search | |
| vivinoUrl | No | Direct Vivino URL if known (e.g., "https://www.vivino.com/wines/1129971") |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral context beyond annotations by disclosing that 'results are cached', which is not covered by the annotations (readOnlyHint, openWorldHint, idempotentHint, destructiveHint). This informs the agent about performance and data freshness considerations. No contradictions with annotations exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, followed by usage details and return values, all in three concise sentences. Each sentence earns its place by providing essential information without redundancy, making it efficient and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, lack of output schema, and rich annotations, the description is mostly complete. It covers purpose, usage, return values, and caching behavior. However, it could improve by detailing output structure (e.g., format of 'wine details') or error handling, though annotations help mitigate some gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the input schema already fully documents the three parameters (wineName, winery, vivinoUrl). The description adds minimal semantic value by mentioning search methods but does not elaborate on parameter interactions or usage beyond what the schema provides, aligning with the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('look up', 'search') and resources ('wine ratings from Vivino.com'). It distinguishes itself from siblings by focusing on wine ratings rather than availability, products, recommendations, or store operations, making its unique function immediately apparent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use this tool by specifying search methods ('by wine name/winery or provide direct URL'). However, it does not explicitly state when not to use it or name alternatives among siblings, such as using 'search_products' for broader product searches instead of Vivino-specific ratings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_storesList Alko StoresARead-onlyIdempotent
List all ~360 Alko stores in Finland. Filter by city name. Returns: store id, name, address, city, postal code.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | Filter by city name (e.g., "Helsinki", "Tampere") | |
| limit | No | Maximum number of stores to return |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=false. The description adds valuable context beyond annotations by specifying the approximate dataset size (~360 stores), the geographic scope (Finland), and the return format (store id, name, address, city, postal code). It doesn't contradict annotations and provides useful operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise (two sentences) and front-loaded with the core purpose. Every word earns its place: the first sentence establishes scope and filtering, the second specifies return format. No wasted words or redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with comprehensive annotations and 100% schema coverage, the description provides good context about dataset size, geographic scope, and return format. The main gap is the lack of output schema, but the description compensates by explicitly listing return fields. It could be more complete by mentioning pagination behavior or result ordering.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both parameters (city and limit) fully documented in the schema. The description mentions filtering by city name but doesn't add any semantic details beyond what the schema already provides (e.g., city parameter examples or limit behavior). Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('List') and resource ('all ~360 Alko stores in Finland'), specifies the scope ('Filter by city name'), and distinguishes from siblings by focusing on store listings rather than availability, products, or other operations. It provides concrete details about the dataset size (~360 stores) and geographic context (Finland).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool ('Filter by city name'), providing clear context for its filtering capability. However, it doesn't mention when NOT to use it or name specific alternatives among the sibling tools (e.g., get_store_hours for hours information), leaving some room for improvement in distinguishing from closely related siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_productsSearch Alko ProductsARead-onlyIdempotent
Search Finnish Alko alcohol catalog (~12,000 products). Filter by name, type, country, price, alcohol%. Returns: id, name, price, type, country, alcohol%, producer.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Text search query for product name, producer, or description | |
| type | No | Product type (e.g., "punaviinit", "oluet", "viskit") | |
| country | No | Country of origin (e.g., "Ranska", "Italia", "Suomi") | |
| region | No | Region within country (e.g., "Bordeaux", "Toscana") | |
| minPrice | No | Minimum price in EUR | |
| maxPrice | No | Maximum price in EUR | |
| minAlcohol | No | Minimum alcohol percentage | |
| maxAlcohol | No | Maximum alcohol percentage | |
| assortment | No | Assortment type: vakiovalikoima (in stores), tilausvalikoima (order only) | |
| specialGroup | No | Special group (e.g., "Luomu", "Vegaaneille soveltuva tuote") | |
| beerType | No | Beer type for beer products (e.g., "ipa", "lager", "stout & porter") | |
| isNew | No | Filter for new products only | |
| isOrganic | No | Filter for organic products only | |
| isVegan | No | Filter for vegan-suitable products only | |
| minSmokiness | No | Minimum smokiness level (0-4, for whiskeys: 0=ei savuinen, 4=voimakkaan savuinen) | |
| maxSmokiness | No | Maximum smokiness level (0-4, for whiskeys: 0=ei savuinen, 4=voimakkaan savuinen) | |
| sortBy | No | Field to sort by | name |
| sortOrder | No | Sort order | asc |
| limit | No | Maximum number of results to return | |
| offset | No | Number of results to skip for pagination |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety and idempotency. The description adds valuable context by specifying the catalog size (~12,000 products) and listing return fields, which helps set expectations for result volume and format. No contradictions with annotations exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, dense sentence that efficiently conveys purpose, scope, filtering parameters, and return values without any wasted words. It's front-loaded with the core functionality and appropriately sized for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with rich annotations (read-only, idempotent) and 100% schema coverage, the description provides adequate context by detailing the catalog scope and return structure. However, without an output schema, it could benefit from mentioning pagination behavior or result limits, though the schema covers 'limit' and 'offset' parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with detailed parameter documentation in the schema itself. The description mentions filtering capabilities ('Filter by name, type, country, price, alcohol%') and return fields, but adds minimal semantic value beyond what the schema already provides. Baseline 3 is appropriate given the comprehensive schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Search'), resource ('Finnish Alko alcohol catalog'), and scope ('~12,000 products'). It distinguishes from siblings like 'get_product' (single product retrieval) and 'get_recommendations' (personalized suggestions) by emphasizing broad filtering capabilities.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through the mention of filtering parameters and return fields, suggesting it's for general catalog exploration. However, it doesn't explicitly state when to use this versus alternatives like 'get_product' for specific items or 'sync_products' for data updates, leaving some ambiguity about optimal use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_productsSync Product Database (Admin)AIdempotent
Admin: Download latest Alko price list and update product database. Takes 2-5 minutes. Updates ~12,000 products. Use get_sync_status to check progress.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral context beyond annotations: it discloses the execution time (2-5 minutes), the scale of updates (~12,000 products), and the need to monitor progress with another tool. While annotations cover safety (destructiveHint: false) and idempotency, the description provides practical operational details that help the agent understand what to expect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is perfectly concise and front-loaded: it starts with the core purpose, adds key operational details (time, scale), and ends with a usage tip. Every sentence earns its place by providing essential information without fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter mutation tool with good annotations but no output schema, the description is highly complete: it explains the action, time, scale, and monitoring method. The only minor gap is not explicitly stating the return value or success indicators, but given the annotations and sibling tool for status checking, this is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0 parameters and 100% schema description coverage, the baseline is 4. The description appropriately confirms there are no parameters by not mentioning any, and it adds context about what the tool does without needing to explain inputs. This is efficient and avoids redundancy.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Download latest Alko price list and update product database'), identifies the resource ('product database'), and distinguishes it from sibling tools by specifying it's an admin operation that updates ~12,000 products. It goes beyond the title by explaining the scope and scale of the operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool ('Admin: Download latest Alko price list and update product database') and when to use an alternative ('Use get_sync_status to check progress'). It also indicates the time commitment ('Takes 2-5 minutes'), helping the agent decide when to invoke it versus other read-only sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
9 tool updates
- First observed
get_availability - First observed
get_product - First observed
get_recommendations - First observed
get_store_hours - First observed
get_sync_status - First observed
get_vivino_rating - First observed
list_stores - First observed
search_products - First observed
sync_products
TDQS
Every tool has a clearly distinct purpose with no overlap. For example, get_availability checks stock, get_product retrieves product details, and get_recommendations provides personalized suggestions, each targeting different user needs. The descriptions reinforce this separation, making misselection unlikely.
All tool names follow a consistent verb_noun pattern using snake_case, such as get_availability, list_stores, and search_products. This predictability aids in agent navigation and understanding of tool functions without confusion from mixed conventions.
With 9 tools, the server is well-scoped for its domain of Alko product and store management. Each tool serves a specific role, from data retrieval to administrative tasks, avoiding bloat or thin coverage. This count supports comprehensive workflows without overwhelming complexity.
The toolset covers core operations like product search, availability checks, store information, and recommendations, with minor gaps such as missing update or delete operations for products or stores. However, these are likely intentional given the server's focus on read-only data access and synchronization from external sources.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Wine cellar manager: bottles, racks, drink windows, pairings and a shared wine registry.
AI-agent product catalog: search, lookup & purchase routing over verified merchant data.
Neutral verified-merchant index for AI shopping agents; regulated/alcohol-first; earned-trust only.
The media memory layer for AI agents and their humans. Your AI client gets 29 tools to search your collection, add items, update ratings, preview music, and find patterns across everything you've read, watched, and listened to.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to access the Open Food Facts database to query detailed food product information, nutritional data, and environmental scores. Supports product lookup by barcode, smart search with filtering, nutritional analysis, product comparison, and dietary recommendations to help users make informed food choices.51MIT
- FlicenseBqualityCmaintenanceEnables AI assistants to interact with Mathem.se, a Swedish online grocery store, allowing users to search for ingredients, add items to their shopping basket, and manage recipes through natural language.42-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Rohlik Group's online grocery delivery services across multiple European countries, supporting product search, shopping cart management, order history analysis, and personalized meal suggestions based on purchase patterns.563MIT
- AlicenseAqualityBmaintenanceEnables LLMs to search, profile, and compare Japanese sake using a flavor-space engine, including similarity recommendations and side-by-side comparisons.51MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/markusl/alko-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server