Skip to main content
Glama
elid-wine
by elid-wine

elid-wine-mcp

An MCP server for ELID, which gives wines readable IDs. It lets Claude and other MCP clients:

  • turn wine text such as a label or a wine-list line into ranked ELIDs

  • look up wines by name, ELID prefix or LWIN

  • get vintage fact sheets: alcohol, sugar, acidity, blend, soil, winemaking, aging, dosage, drinking window and food pairing

  • search observed retailer prices from Swiss-market shops

An ELID is written {CC}-{RRR}-{PPPP}{NN}[-{VINTAGE}]. For example, FR-CMP-DOMP01-2015 is the 2015 Dom Pérignon. The format is defined in the ELID specification.

Tools

Tool

What it does

elid_match_wine

Matches free text to ranked base-wine ELIDs, with LWINs and scores

elid_search_wines

Searches the catalog by name/ELID substring (q) or exact 7-digit lwin, with cursor pagination

elid_get_wine

Returns a wine's identity and vintage fact sheets. A full ELID such as …-2015 limits the facts to that vintage

elid_search_shop_prices

Searches Swiss-market shop prices by text, ELID and vintage, shop, or CHF range, with sorting

elid_list_shops

Lists covered shops with observation counts and date ranges

Every tool is read-only, and no API key or account is needed. Results include a wine_url (for example https://elid.wine/wine/FR-CMP-DOMP01#vintage-2015) that you can cite.

Related MCP server: MCP MySQL

Install

Node.js 20 or newer is required.

Claude Code

claude mcp add elid -- npx -y elid-wine-mcp

Claude Desktop, Cursor, Windsurf and other clients

Add this to your MCP config file (for Claude Desktop, claude_desktop_config.json):

{
  "mcpServers": {
    "elid": {
      "command": "npx",
      "args": ["-y", "elid-wine-mcp"]
    }
  }
}

Configuration

Variable

Default

Purpose

ELID_BASE_URL

https://elid.wine

Alternative deployment, e.g. https://elid-site.exe.xyz

Example

You: I'm looking at "Dom Perignon 2015" on a wine list. What's in it, and what does it cost in Swiss shops?

Claude calls:

  1. elid_match_wine({ "raw": "Dom Perignon 2015" }), which returns FR-CMP-DOMP01 (Dom Pérignon, Vintage, Champagne; LWIN 1082656).

  2. elid_get_wine({ "elid": "FR-CMP-DOMP01-2015" }), which returns the 2015 facts only: 12.5% ABV, 51% Pinot Noir / 49% Chardonnay, dosage 4.5 g/L, 100% malolactic, about 8 years on lees, disgorged 2023-01, drinking window 2023+.

  3. elid_search_shop_prices({ "elid": "FR-CMP-DOMP01-2015", "sort": "price" }), which returns observed shop listings with shop, bottle size, currency and observation date.

Then it answers with the ELID, cites https://elid.wine/wine/FR-CMP-DOMP01#vintage-2015, and labels each price as a dated observation, not a current offer.

Data notes

  • Don't mix vintages. elid_get_wine never applies one vintage's facts to another. If a vintage has no fact sheet, the tool says so.

  • Prices are observations. Shop rows keep the source currency, bottle size, case quantity and scraped_at date. Missing values are null. Shipping and taxes are not included, and a listed price does not mean the wine is in stock now.

  • Match scores rank candidates. They are not probabilities. An empty list means no accepted match.

  • The API does not include RRP, restaurant lists or critic reviews. For those, see the pages on elid.wine.

Development

npm install
npm run build
npm test                                  # unit tests (mocked HTTP)
npm run test:live                         # live tests against elid.wine
npm run inspect                           # MCP Inspector UI

Publishing

  1. Update version in package.json and in both places in server.json.

  2. Run npm publish. The prepublishOnly script builds and runs the tests first.

  3. Optionally, list the server in the MCP Registry: mcp-publisher login github && mcp-publisher publish.

You can also publish a GitHub release. .github/workflows/publish.yml then publishes to npm (this needs an NPM_TOKEN secret) and to the MCP Registry.

License

MIT. Data © ELID. The catalog comes partly from LWIN (CC BY 4.0); see elid.wine for provenance.

Available Tools

5 tools
elid_get_wineGet wine identity and vintage factsA
Read-only

Get one wine's catalog identity (producer, region, colour, type, classification, LWIN…) and its vintage fact sheets (alcohol, residual sugar, acidity, blend, soil, winemaking, aging, dosage, drinking window, food pairing…). Accepts a base ELID (FR-CMP-DOMP01) or a full ELID with vintage (FR-CMP-DOMP01-2015), which restricts facts to that vintage. Unknown fields are omitted. Does not include prices; use elid_search_shop_prices.

ParametersJSON Schema
NameRequiredDescriptionDefault
elidYesBase or full ELID, e.g. FR-CMP-DOMP01 or FR-CMP-DOMP01-2015.
vintageNoOptional vintage (year, NVXX, or edition) to restrict facts to. Overrides a suffix in elid.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint and openWorldHint, but the description adds concrete behaviors: 'Unknown fields are omitted' (partial result handling) and 'restricts facts to that vintage' (filtering scope). It also clarifies that prices are not included, which is non-obvious and prevents incorrect expectations. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences carry full content: the first lists the returned info and accepted input forms; the second notes unknown-field omission and the price exclusion with a sibling pointer. No filler, and the scope is front-loaded before the alternative. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential categories of returned data and the input variants. It does not enumerate every possible field, but given the openWorldHint and the absence of an output schema, the summarized list is sufficient for an agent to know what it will get. The alternative routing also covers the most likely separate use case. A slightly higher score would require explicit mention of response structure, but that is not necessary for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are documented. The description adds meaningful semantics beyond the schema: it explains the base vs full ELID usage and notes that the vintage parameter can override a suffix in elid. This interpretive guidance helps the agent construct valid calls without reading deeply into the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Get') and resource ('one wine's catalog identity and vintage fact sheets') and enumerates the types of fields (producer, region, colour, type, classification, LWIN…). It explicitly excludes prices and routes to a sibling tool, distinguishing it from the other ELID tools immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains how the elid parameter can be a base or full ELID and that a vintage suffix restricts facts to that vintage. It also provides an explicit 'use instead' alternative for prices (elid_search_shop_prices), giving a clear when-not-to-use criterion. The vintage parameter's override semantics are also disclosed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

elid_list_shopsList Swiss-market shopsA
Read-only

List the shops covered by elid_search_shop_prices, with observation counts and the oldest/newest observation dates.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, which cover the safety profile. The description adds value by specifying the data returned (observation counts, oldest/newest dates), which is beyond the annotations. It does not contradict any annotation and provides enough behavioral context for an agent to 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that is front-loaded with the core purpose and immediately specifies the return data. There is no fluff, and every word contributes to understanding. This is an exemplar of concise, well-structured tool documentation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that there are no parameters, no output schema, and the tool is a straightforward list operation, the description is sufficient. It explains what the tool returns and its relationship to a sibling tool. While it does not mention pagination or ordering, these are not critical for a simple listing tool, and the description covers all essential information an agent needs to decide when to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the description has nothing to add about parameters. The schema is empty (100% coverage trivially), and the description correctly omits any parameter details. With 0 parameters, the baseline is 4, and the description does not need to compensate for anything.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('List') and the resource ('shops'), and specifies the scope ('covered by elid_search_shop_prices'), which immediately distinguishes it from siblings like wine search or matching tools. The addition of what is included (observation counts, date ranges) further clarifies the exact output, leaving no ambiguity about the tool's function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by linking to elid_search_shop_prices, suggesting that this tool is meant to be used when one needs to know the available shops for price queries. While it does not explicitly state 'use this when' or exclude alternatives, the reference to the sibling tool provides strong implicit guidance. For a simple listing tool, this is adequate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

elid_match_wineMatch wine text to ELIDsA
Read-only

Match free wine text (e.g. 'Kanonkop Paul Sauer 2021', a label or a wine-list line) to ranked ELID base-wine identities. Returns elid, lwin, display_name, producer_name, wine and scores (for ranking only, not probabilities). An empty list means no accepted match. Vintages in the text are not part of the result: pass the vintage to elid_get_wine.

ParametersJSON Schema
NameRequiredDescriptionDefault
rawYesWine text to match, up to 500 characters.
top_nNoNumber of candidates, 1–20 (default 5).
producer_idNoOptional ELID producer code, e.g. ZA-KNKP.
country_codeNoOptional two-letter country code to restrict matching, e.g. ZA.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so safety is covered. The description goes further: it states scores are ranking-only, not probabilities, that an empty list means no accepted match, and that vintages are not in the result – all crucial behavioral details an agent needs to interpret output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with the purpose up front, then return contract and a caveat. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only matching tool with no output schema, the description covers what the result means (empty list, 'no accepted match'), what scores represent, and how vintages are handled. It also signals return fields, making agent interpretation complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (raw, top_n, producer_id, country_code) already documented. The description adds only an example for `raw`, not new parameter semantics, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the core function with a specific verb ('Match') and resource ('free wine text... to ranked ELID base-wine identities'). The example inputs and named return fields make the tool's purpose unambiguous and distinguish it from generic search tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a direct routing instruction: 'Vintages in the text are not part of the result: pass the vintage to elid_get_wine.' This tells the agent when to hand off to a sibling. It doesn't explicitly contrast with elid_search_wines, but the 'free wine text' scope and example clarify typical use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

elid_search_shop_pricesSearch Swiss-market shop pricesA
Read-only

Search observed retailer prices from ~26 Swiss-market shops (plus gute-weine.de). Filter by free text (q), exact base ELID (elid) and vintage, shop (site), and CHF price range. Rows keep the source currency, bottle size, case quantity and observation date (scraped_at); missing values are null. These are historical observations, not current offers; shipping and taxes are not included. Always report vintage, size, currency, shop and date.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoFree-text search, accent-insensitive, e.g. 'dom perignon 2015'.
maxNoMaximum per-bottle price in CHF.
minNoMinimum per-bottle price in CHF.
elidNoBase ELID (vintage suffix is stripped and used as vintage if not given).
siteNoShop domain, e.g. gute-weine.de. See elid_list_shops.
sortNoSort order (default recent).
limitNoRows per page, 1–100 (default 20).
offsetNoPagination offset.
vintageNoVintage year, e.g. 2015.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the readOnlyHint annotation by explaining that rows are historical observations, not current offers, that shipping/taxes are excluded, that missing values are null, and that source currency is preserved. This is critical behavioral context for interpreting results and avoiding misuse.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense, well-ordered sentences: scope and filters first, then output semantics and caveats, then a clear reporting instruction. Every sentence earns its place without repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by naming key row fields (source currency, bottle size, case quantity, scraped_at) and null behavior. It also clarifies interpretation and warns about non-included costs. Combined with the readOnlyHint and openWorldHint annotations, the agent has enough context to call the tool correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, and each parameter already has a meaningful description. The description restates filters such as 'CHF price range' and 'shop (site)' but adds little semantic value beyond the schema, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Search observed retailer prices from ~26 Swiss-market shops'. It clearly distinguishes this tool from wine-metadata siblings like elid_search_wines and elid_match_wine by focusing on retailer price observations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use the tool: searching historical Swiss shop prices, with explicit caveats that these are 'historical observations, not current offers' and that shipping/taxes are excluded. It does not explicitly name sibling alternatives, but the context strongly implies the intended niche.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

elid_search_winesSearch the ELID catalogA
Read-only

List ELID wine identities, ordered by ELID. Use q for a case-insensitive substring match on the name or ELID (e.g. 'kanonkop' or 'FR-CMP-DOMP'), or lwin for an exact seven-digit LWIN lookup. For free text such as a full label, prefer elid_match_wine. Paginate by passing next_cursor as after.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoSubstring of the wine name or ELID.
lwinNoExact seven-digit wine-level LWIN.
afterNonext_cursor from the previous page. Keep other filters unchanged.
limitNoResults per page, 1–200 (default 50).

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as read-only, and the description adds substantive behavioral detail: case-insensitive substring matching, exact seven-digit LWIN lookup, ordering, and cursor-based pagination. It does not describe the result shape, but that is less critical given the read-only annotation and search-oriented behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler. It front-loads the core purpose and ordering, then covers both query modes, sibling routing, and pagination efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only search tool, the description covers query modes, ordering, pagination, and sibling differentiation. A small gap is that it does not explicitly state whether q and lwin are mutually exclusive or what happens if both are supplied, and there is no mention of the returned identity fields since no output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds real meaning beyond the schema: it explains case-insensitivity, gives examples, clarifies the 'after' cursor semantics ('keep other filters unchanged'), and states the default limit. Every parameter is made actionable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('List ELID wine identities') and adds ordering ('ordered by ELID'). It also explicitly contrasts with elid_match_wine, so an agent can distinguish the tools without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states exactly when to use q versus lwin with concrete examples, and explicitly routes free-text label searches to elid_match_wine. Pagination instructions are also provided, leaving little ambiguity about use cases.

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.

  1. 5 tool updatesv0.1.0
    • First observedelid_get_wine
    • First observedelid_list_shops
    • First observedelid_match_wine
    • First observedelid_search_shop_prices
    • First observedelid_search_wines

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation4/5

The tools are mostly distinct: match vs search vs get vs list shops vs search prices. One minor overlap: elid_match_wine and elid_search_wines both accept text, but descriptions clearly separate free-text matching from substring/ELID lookup.

Naming Consistency4/5

All tools follow a consistent elid_<verb>_<noun> pattern (match_wine, search_wines, get_wine, list_shops, search_shop_prices). Minor inconsistency: 'search_wines' vs 'search_shop_prices' both use search, while 'list_shops' uses list, but the pattern is otherwise uniform.

Tool Count5/5

Five tools is well-scoped for a wine identity and price lookup server. Each tool covers a distinct need: matching, searching, retrieving details, listing shops, and searching prices.

Completeness4/5

The surface covers the core workflow: match free text, get wine details, search prices, and list shops. Minor gaps: no tool for retrieving a specific shop's details or for filtering prices by multiple vintages at once, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers