linda-mcp
# Linde MCP Server
Ein MCP (Model Context Protocol) Server, der KI-Modellen Zugriff auf **linda.lindeverlag.at** (Linde Datenbank) gibt. Suche, Dokument-Volltext, Ausgaben-Inhaltsverzeichnisse, Kommentare und See-Also-Verweise über stdio.
> **Wichtig:** Linda nutzt **IP-basierten Zugriff** (z.B. WU-Wien-Netz, VPN). Es ist **kein Login erforderlich** — der MCP-Server muss einfach vom WU-Netz aus erreichbar sein.
---
## Features
- **Suche**: Volltextsuche über `linda.lindeverlag.at/SearchResults/` mit Paginierung, Sortierung (Relevanz/Datum) und Filter (My/All, Archiv).
- **Autocomplete**: Vorschläge über `search/autocompletesuggestions`.
- **Dokument-Volltext**: Titel, Autor, Literaturquelle, Rechtsnorm-Verweise, Literaturverzeichnis und Volltext.
- **Ausgabe (Magazin)**: Inhaltsverzeichnis gruppiert nach Sektionen.
- **Kommentare**: Liste der verfügbaren Kommentare (My/All).
- **See-Also**: Verwandte Rechtsnormen, Literatur und Judikatur.
- **Auth-Status & Cookie-Set**: Optional — für hinter Paywall liegende Inhalte können manuell Cookies gesetzt werden.
---
## Konfiguration & Zugang
Linda ist über IP autorisiert (z.B. WU-Wien-Campus-Netz, eduroam, oder VPN zum WU-Netz). Keine Credentials nötig.
**Optionale Cookie-Authentifizierung** (für Premium-Inhalte):
- **Environment Variable**: `LINDA_COOKIE="DbSessionVWINASP02=...; bis_logonguid=..."`
- **Command Line Flag**: `--cookie "DbSessionVWINASP02=...; bis_logonguid=..."`
Cookie-Werte aus dem Browser: DevTools → Application → Cookies → `linda.lindeverlag.at` und `.lindeverlag.at`.
---
## Installation & Running
### Direkt via npx (empfohlen)
```bash
npx -y github:blueqwertz/linda-mcp
```
Mit Cookie:
```bash
LINDA_COOKIE="DbSessionVWINASP02=...; bis_logonguid=..." npx -y github:blueqwertz/linda-mcp
```
### Lokale Entwicklung
```bash
git clone https://github.com/blueqwertz/linda-mcp.git
cd linda-mcp
npm install
npm run build # TypeScript -> dist/
npm start # Startet den MCP-Server
```
Im Dev-Modus mit Hot-Reload:
```bash
npm run dev # tsx src/index.ts
```
Smoke-Test (6 Tests gegen die Live-Site, benötigt IP-Zugriff auf linda.lindeverlag.at):
```bash
npx tsx test.ts
```
---
## Integration mit AI-Agents
### Claude Desktop
`~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"linda-mcp": {
"command": "npx",
"args": ["-y", "github:blueqwertz/linda-mcp"]
}
}
}
```
Mit Cookie:
```json
{
"mcpServers": {
"linda-mcp": {
"command": "npx",
"args": ["-y", "github:blueqwertz/linda-mcp"],
"env": {
"LINDA_COOKIE": "DbSessionVWINASP02=...; bis_logonguid=..."
}
}
}
}
```
### Claude Code
```bash
claude mcp add linda-mcp -- npx -y github:blueqwertz/linda-mcp
```
### OpenCode
`opencode.json`/`opencode.jsonc`:
```json
{
"mcp": {
"linda-mcp": {
"type": "local",
"command": ["npx", "-y", "github:blueqwertz/linda-mcp"],
"enabled": true
}
}
}
```
### Codex
`~/.codex/config.toml`:
```toml
[mcp_servers.linda-mcp]
command = "npx"
args = ["-y", "github:blueqwertz/linda-mcp"]
```
---
## Exposed Tools
### `linda_search`
Durchsucht die Linde Datenbank.
- **Arguments**:
- `query` (string, required): Suchbegriff.
- `skip` (number, default 0): Offset für Paginierung (0, 20, 40, ...).
- `limit` (number, default 20, max 20): Max Treffer.
- `sort` (`"Rank"` | `"Date"`, default `"Rank"`).
- `place` (`"My"` | `"All"`, default `"My"`).
- `includingArchive` (bool, default false).
- **Returns**: `{query, skip, nextSkip, results: [{id, titel, beschreibung, vorschau, link, listPos}], totalCount?, hasMore}`
### `linda_autocomplete`
- **Arguments**: `query` (string, required).
- **Returns**: `{query, count, suggestions: [{text, isLastSearch}]}`
### `linda_get_document`
- **Arguments**:
- `id` (string, required): Dokument-ID (`"18729"`) oder URL.
- `includeVolltext` (bool, default true).
- `maxVolltextLength` (number, default 50000).
- **Returns**: `{id, titel, autor?, literaturQuelle?, rechtsnormVerweise: [{id,label,link}], literatur: string[], volltext?, meta, link}`
### `linda_get_issue`
- **Arguments**: `id` (string, required): Ausgabe-ID (`"WWK77SH6EQ"`) oder URL.
- **Returns**: `{id, titel, jahr?, ausgabeNr?, sectionCount, articleCount, sektionen: [{name, dokumente: [{id,titel,beschreibung?,link}]}]}`
### `linda_get_see_also`
- **Arguments**: `id` (string, required).
- **Returns**: `{id, summary, rechtsnormen: [...], literatur: [...], judikatur: [...], sonstiges: [...]}`
### `linda_list_kommentare`
- **Arguments**: `place` (`"My"` | `"All"`, default `"My"`).
- **Returns**: `{place, count, kommentare: [{bookId, titel, link}]}`
### `linda_auth_status`
- **Arguments**: keine.
- **Returns**: `{authenticated, statusCode, url, cookiesSet, note}`
### `linda_set_cookie`
- **Arguments**: `cookie` (string, required): `"name1=val1; name2=val2; ..."`.
- **Returns**: `{cookieSet, cookiesStored, note}`
---
## Architektur
```
src/
├── index.ts # CLI-Parsing, McpServer, stdio transport
├── client.ts # LindaClient: HTTP + CookieJar wrapper
├── auth.ts # CookieJar (in-memory name->value)
├── parser.ts # cheerio-basierte HTML-Extraktoren
└── tools/
├── index.ts # toolDefinitions + handleToolCall dispatch
├── search.ts # linda_search
├── autocomplete.ts
├── document.ts
├── issue.ts
├── see_also.ts
├── kommentare.ts
└── auth.ts # linda_auth_status + linda_set_cookie
```
Inspiriert von [blueqwertz/rdb-mcp](https://github.com/blueqwertz/rdb-mcp) (Manz RDB), aber angepasst an Lindes HTML-basierte API.
---
## License
MIT
TDQS
Scored across 8 tools
Each tool has a clear, distinct purpose: authentication check, autocomplete, document retrieval, issue table of contents, related content, commentary listing, search, and cookie setting. No two tools overlap in functionality.
All tools follow a consistent pattern: 'linda_' prefix + verb_noun (e.g., get_document, list_kommentare, set_cookie). Naming is uniform, descriptive, and uses snake_case throughout.
With 8 tools, the server is well-scoped for a legal database retrieval system. It covers essential operations without being too sparse or bloated.
The tool set covers key workflows: authentication, search, document retrieval, issue browsing, related content, and commentary lists. A minor gap is the absence of a dedicated tool to fetch a single commentary item, but the surface is largely complete for typical usage.