Skip to main content
Glama
eoset

Systembolaget API MCP Server

by eoset
README.md
# Systembolaget API MCP Server

MCP server that exposes the [Systembolaget](https://www.systembolaget.se/) (Swedish liquor store) product search API as a tool. Uses [FastMCP](https://gofastmcp.com/) and supports configurable launch date range and optional query parameters.

## Setup

1. **Clone or open this project.**

2. **Create a virtual environment and install dependencies:**

   ```bash
   python3 -m venv .venv
   source .venv/bin/activate   # On Windows: .venv\Scripts\activate
   pip install -r requirements.txt
   ```

3. **Set your API key.** The API requires the `Ocp-Apim-Subscription-Key` header. Provide it via environment variable:

   ```bash
   export SYSTEMBOLAGET_SUBSCRIPTION_KEY=your-subscription-key-here
   ```

   Copy `.env.example` to `.env` and fill in the key if you use a tool that loads `.env` (do not commit `.env`).

## Running the server

From the project root (with the venv activated):

```bash
python server.py
```

Or using the FastMCP CLI:

```bash
fastmcp run server.py:mcp
```

The server runs over **stdio** by default (for use with Claude Desktop, Cursor, etc.).

You can also run it with [uv](https://docs.astral.sh/uv/) (same pattern as other local MCP servers):

```bash
uv run --directory /path/to/bolki-mcp python server.py
```

## Cursor MCP configuration

Add this server to Cursor’s MCP settings (e.g. **Cursor Settings → MCP** or `~/.cursor/mcp.json`) using stdio and `uv`, in the same way as other local MCP servers:

```json
{
  "mcpServers": {
    "systembolaget": {
      "type": "stdio",
      "command": "/opt/homebrew/bin/uv",
      "args": [
        "run",
        "--directory",
        "/Users/erik/Development/_dev/bolki-mcp",
        "python",
        "server.py"
      ],
      "env": {
        "SYSTEMBOLAGET_SUBSCRIPTION_KEY": "your-subscription-key-here"
      }
    }
  }
}
```

- Use your actual project path for `--directory` (e.g. `/Users/erik/Development/_dev/bolki-mcp`).
- Use your system’s `uv` path if different (e.g. `uv` if it’s on your PATH).
- Set `SYSTEMBOLAGET_SUBSCRIPTION_KEY` to your API key. Do not commit the key; use a local config or secret.

## Tool: `search_products`

**Fetches all pages automatically** and returns the combined result.

- **Parameters:**
  - `launch_date_min` (required) – Start of launch date range, `YYYY-MM-DD`. Maps to `productLaunch.min`.
  - `launch_date_max` (required) – End of launch date range, `YYYY-MM-DD`. Maps to `productLaunch.max`.
  - `size` (optional, default `100`) – Page size used when fetching; all pages are requested automatically.
  - `sort_by` (optional, default `"Score"`) – Sort field.
  - `sort_direction` (optional, default `"Ascending"`) – Sort direction.
  - `assortment_text` (optional, default `"Tillfälligt sortiment"`) – Assortment filter.
  - `full_response` (optional, default `False`) – If `False`, returns a compact response for speed; if `True`, returns the full API-style JSON.

- **Returns:** By default a **compact response**: `metadata` (docCount, totalPages, nextPage, previousPage) and `products` with key fields only (productId, productNameBold, productNameThin, producerName, price, volume, volumeText, alcoholPercentage, country, categoryLevel1, customCategoryTitle, assortmentText, productLaunchDate, taste, usage, vintage). Set `full_response=True` to get the full response (all fields, filters, etc.) when needed.

### Tool: `list_products_formatted`

Returns a **ready-to-use list of lines** (filtering and formatting done in the MCP; no client-side parsing). **Fetches all pages automatically** so the list is complete.

- **Parameters:** Same `launch_date_min`, `launch_date_max` as above, plus:
  - `product_filter`: `"beer"` (default) – only products with CategoryLevel1 "Öl"; `"all"` – every product.
  - `size` – page size used when fetching (default 100); all pages are requested automatically.
  - `sort_by`, `sort_direction`, `assortment_text` – same as `search_products`.
- **Returns:** Sorted unique list of strings, e.g. `["Vreta klosters Våröl — 330 ml, 5.6%", ...]`. Use this instead of running Python scripts to parse search results.

## License

Use of the Systembolaget API is subject to Systembolaget’s terms. This project is for integration only.