Skip to main content
Glama
telota

bbaw-dse-mcp

by telota
README.md
# bbaw-dse-mcp

An [MCP server](https://modelcontextprotocol.io/) for dialogical, exploratory access to digital scholarly editions.

> **DHd2026 Poster**: *Agenten im Dienst der Edition*

## Overview

Instead of complex search forms and navigation structures, this MCP server enables **natural-language conversation** with digital scholarly editions. An AI agent translates questions like *"Who was important for Schleiermacher in 1810?"* into structured database queries — and maintains conversational context across follow-up questions.

The current server composes edition backends and reusable external research
services into a single MCP endpoint using [FastMCP](https://gofastmcp.com/):

| Service | Prefix | Backend | Content |
|---|---|---|---|
| [schleiermacher digital](https://schleiermacher-digital.de) | `sd_` | eXist-db | Letters, diaries, lectures, chronology, glossary |
| [Praktiken der Monarchie](https://actaborussica.bbaw.de) | `mop_` | eXist-db | Documents on Prussian monarchy and governance |
| [Jean Paul Briefwechsel](https://www.jeanpaul-edition.de) | `jp_` | HTTPS connector | Letters, Umfeldbriefe, topics, correspondence networks |
| [correspSearch](https://correspsearch.net) | `cs_` | REST API | Cross-edition correspondence network search |
| Authority services | `authority_` | Lobid GND, GeoNames, Wikidata APIs | Reusable identifier and entity lookup |

## Available Tools

The composed server currently exposes 64 tools:

| Surface | Count | Description |
|---|---:|---|
| Shared | 10 | Cross-edition access, detailed search, capabilities, and identity comparison |
| Schleiermacher Digital (`sd_*`) | 13 | Bounded advanced search, glossary, passages, diaries, chronology, thesaurus, and Bible references; low-level eXist access is excluded from the public profile |
| Praktiken der Monarchie (`mop_*`) | 25 | Passages, research literature, biogrammes, adjutant journals, residential topography, court calendar, organigrams, thematic dossiers, eXist browsing |
| Jean Paul Briefwechsel (`jp_*`) | 6 | Native full-text and letter-metadata filters, controlled topics, and curated correspondence networks |
| correspSearch (`cs_*`) | 5 | Cross-edition correspondence metadata, normalized relations, typed networks, and edition discovery |
| Authority services (`authority_*`) | 5 | GND, GeoNames, and Wikidata lookup |

The full signatures and usage boundaries are documented in
[docs/TOOLS.md](docs/TOOLS.md); the source-code-derived edition-module
inventory is in [docs/EDITION_MODULES.md](docs/EDITION_MODULES.md).

Every successful `sd_*`, `mop_*`, `jp_*`, or `cs_*` response, including shared
calls that resolve edition data, carries a provenance block in MCP
`_meta.provenance`. It records every consulted source, the configured live
backend, dataset, and UTC retrieval time. Because the current connectors do
not expose one coherent machine-readable data release for their queried data,
`data_release` is truthfully `null` and `release_status` is
`not_provided_by_source`; a backend software version is never presented as an
edition release.

The capability tool, `get_capabilities(check_health=False)`, reports SD, MoP,
JP, correspSearch, Lobid GND, Wikidata, and GeoNames without exposing
credential values. It declares datasets, modules, filters, releases/interface
versions, and known license status. Its default is network-free;
`check_health=True` runs seven isolated read-only probes. A missing GeoNames
username is visible as `configured=false`, `available=false`, and
`status="missing_credentials"`.

`search_documents_detailed(...)` and `search_entities_detailed(...)` retain
results from successful editions when another backend fails and expose
per-source counts, failures, filter handling, completeness, and pagination.
Their `total_count` is exact only when `total_known=true`; otherwise it is an
explicit lower bound. `strict_filters=true` skips sources that cannot apply a
requested filter instead of silently broadening the search. The established
list-returning search tools remain backward compatible.

`get_resource_relations(ref=...)` exposes one common, evidence-backed relation
model for Schleiermacher, MoP, and Jean Paul resources, including the explicit
Jean-Paul module refs `jp:topic:<id>` and `jp:network:<id>`. Its resource kinds
and predicates are closed vocabularies, and every predicate validates the
allowed subject and object kinds. Relations retain provider-scoped references
and external identifiers; the server does not silently merge resources into a
cross-edition `sameAs` identity. The older `get_relations(...)` remains
available for its established edition-specific aggregate response shapes.

`compare_resource_identities(...)` performs that reconciliation explicitly.
It normalizes GND, GeoNames, Wikidata, VIAF, and source URLs, retaining
field-level evidence, conflicts, and partial failures. Only an exact authority
identifier or explicitly equal source URI confirms `same_as`; equal labels
produce an unconfirmed `candidate` and never merge records.

Schleiermacher correspondence relations are atomic sender-to-recipient edges
backed by individual letters. MoP relation extraction reads the complete
register-mention set and distinguishes explicit Hofkalendarium participants
from mere mentions. The query-oriented correspSearch equivalent,
`cs_search_correspondence_relations(...)`, retains every sent/received action
with all participants, places, and date assertions from each fetched record.
correspSearch metadata searches may start from any supported substantive
filter; the API defaults to ten records but accepts bounded page sizes up to
1,000. Normalized relation responses deliberately process one upstream page
and expose further pages through `upstream_continuations`.

Jean Paul's native `jp_search_documents_advanced` and `jp_filter_letters`
surfaces expose all three letter corpora with exact totals, stable offset
continuation, concrete source collections, and original citation routes. The
first adds full-text, lemma, sender/receiver, year, and counted-facet access;
the second combines correspondence metadata including co-senders,
co-recipients, topics, joint letters, and year bounds. Both fail explicitly on
unexpected source markup. Shared JP work lookup also covers the separate
`werke-jp` register and retains that collection in search and detail results.

MoP's shared full-text search now covers `Druck`, `Korrespondenz`,
`Adjutantenjournale`, `Hofkalendarium`, and `Instruktionen`. Use
`doc_types=["<collection>"]` to select one of them and
`mop_get_document_passages` to read beyond the 2,000-character preview without
silent passage truncation. The current source-gap and acceptance records are
in [docs/DATA_SOURCE_GAPS.md](docs/DATA_SOURCE_GAPS.md) and
[docs/MOP_ACCEPTANCE.md](docs/MOP_ACCEPTANCE.md).

## Installation

```bash
# Clone the repository
git clone https://github.com/telota/bbaw-dse-mcp.git
cd bbaw-dse-mcp

# Install with uv (recommended)
uv sync
```

Requires Python 3.11+.

For on-demand OCR of Schleiermacher letters that are available only as
facsimiles, install Tesseract and its German language data as well:

```bash
# Debian/Ubuntu
sudo apt install tesseract-ocr tesseract-ocr-deu

# Arch Linux
sudo pacman -S tesseract tesseract-data-deu
```

When `get_document(ref="sd:…", view="text")` encounters a letter without TEI
body text, it retrieves the BBAW IIIF facsimiles at 3000 px width, runs
Tesseract `deu` with positioned TSV output, and returns explicitly marked,
unreviewed OCR. Set `EDITIONS_SD_OCR_ENABLED=false` to disable this fallback.

## Configuration

Configuration uses environment variables (prefix `EDITIONS_`). Create a `.env` file:

```env
# Schleiermacher Digital eXist-db
EDITIONS_SD_URL=http://localhost:8080
EDITIONS_SD_USERNAME=admin
EDITIONS_SD_PASSWORD=

# Praktiken der Monarchie eXist-db
EDITIONS_AB_URL=https://actaborussica.bbaw.de
EDITIONS_AB_PUBLIC_URL=https://actaborussica.bbaw.de
EDITIONS_AB_USERNAME=
EDITIONS_AB_PASSWORD=

# correspSearch API (no auth required)
EDITIONS_CS_API_URL=https://correspsearch.net/api/v2.0
EDITIONS_CS_SPARQL_URL=https://lod.academy/correspsearch/data/main/sparql

# Required for the GeoNames lookup tools; capability discovery works without it
EDITIONS_GEONAMES_USERNAME=

```

## Usage

### Running the server

```bash
uv run bbaw-dse-mcp
```

### Prompt templates

Clients with MCP prompt support can start common, source-grounded workflows with:

- `research_correspondence` — investigate a person's correspondence network.
- `analyze_edition_document` — retrieve and analyze a known SD or MoP document.
- `deep_research` — plan and execute a multi-step cross-edition investigation.

These prompts orchestrate the existing MCP tools in the host model. The server does
not require a separate model-provider API key.

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "editions": {
      "command": "uv",
      "args": ["run", "bbaw-dse-mcp"],
      "cwd": "/path/to/bbaw-dse-mcp"
    }
  }
}
```

### Example Conversation

```
User: Search for letters mentioning Humboldt.

Agent: → sd_search_documents(query="Humboldt", doc_type="letters")
       Found 23 letters mentioning Humboldt, mostly from 1810 —
       the year of the Berlin university founding...

User: Who was important for Schleiermacher in 1810?

Agent: → sd_get_correspondent_stats(year=1810)
       Based on letter frequency, the most important correspondents in 1810:
       1. Charlotte Schleiermacher (15 letters) — his sister
       2. Wilhelm von Humboldt (8 letters) — central figure in university reform
       ...

User: Can we trace Humboldt's correspondence network beyond this edition?

Agent: → authority_search_gnd(name_query="Humboldt, Wilhelm von")
       → cs_search_correspondent_network(person_gnd="118554727")
       Cross-edition network across 12 editions: ...
```

## Tech Stack

- **[FastMCP](https://gofastmcp.com/) 3.x** — Python MCP server framework
- **[httpx](https://www.python-httpx.org/)** — Async HTTP client for eXist-db REST API
- **[lxml](https://lxml.de/)** — TEI-XML parsing
- **[Pydantic](https://docs.pydantic.dev/) v2** — Data models and settings

## Documentation

- [AGENT.md](./AGENT.md) — Project overview and design decisions
- [docs/TOOLS.md](./docs/TOOLS.md) — Detailed tool specifications
- [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) — Technical architecture
- [docs/CODING_GUIDELINES.md](./docs/CODING_GUIDELINES.md) — Extension and testing rules

## License

MIT

## Author

Tim Westphal, [BBAW TELOTA](https://www.bbaw.de/bbaw-digital/telota)

TDQS

A3.9/5.0

Scored across 44 tools

Disambiguation2/5

There are multiple pairs of essentially identical tools (sd_execute_xquery/mop_execute_xquery, sd_check_database_connection/mop_check_database_connection) and very similar search tools across editions (sd_search_documents/mop_search_documents). Additionally, cs_search_for_geonames_id and cs_get_place_geonames_id are confusingly similar, making tool selection difficult for an agent.

Naming Consistency4/5

The naming generally follows a consistent prefix_verb_noun pattern (e.g., sd_search_documents, mop_get_register_entry, cs_search_correspondences). Minor deviations exist: 'wohntopo' in mop_list_available_wohntopo_years contrasts with 'residential_topography' in other mop tools, and cs_get_place_geonames_id uses 'get' instead of 'search_for' seen in similar tools.

Tool Count3/5

44 tools is a heavy count for a single MCP server. While the server covers three distinct edition projects (Schleiermacher Digital, MoP, correspSearch), the count is inflated by redundant utilities (duplicate execute_xquery and check_database_connection) and many specific niche tools. The count is borderline but not extremely excessive given the multi-edition scope.

Completeness4/5

The tool set provides broad read-only coverage for the three digital editions, including browsing, full-text search, register lookups, document retrieval, and specialized features like diary/chronology access, biographical searches, residential topography, and cross-edition correspondence search. Minor gaps exist such as no direct get-by-ID for residential topography entries and no tool to retrieve a specific correspSearch letter, but overall the domain is well covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues