ddb-mcp
The ddb-mcp server provides tools to search, browse, and retrieve OCR text from the Deutsches Zeitungsportal, a collection of ~33.8 million digitised German newspaper pages.
search_ddb: Perform full Solr syntax searches (exact phrases, boolean operators, wildcards, fuzzy matching, proximity) across the OCR text. Filter results by publication year range, newspaper title, place of distribution, and language. Returns relevance-ranked pages with metadata, viewer URLs, and highlighted snippets showing where the query matched.
get_ddb_snippets: Locate where a query appears within a specific newspaper page or across all pages of an issue, returning snippets with highlighted terms.
download_ddb_text: Download the full OCR text of a single page or all pages of an issue, with local caching and an option to refresh cached copies. Returns the local file path.
No authentication is required, though optional DDB API key support is included.
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., "@ddb-mcpsearch for 'Luftschiffhafen Friedrichshafen'"
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.
DDB MCP Server
MCP server and CLI for the Deutsches Zeitungsportal, the newspaper collection of the Deutsche Digitale Bibliothek (DDB). Search the full text of ~33.8 million digitised German newspaper pages, of which roughly 27.9 million fall between 1850 and 1949.
search: full Solr syntax over page OCR — exact phrases, boolean operators, wildcards, fuzzy matching and proximity — with filters for date, title, place, language and holding institution. Every hit is an individual page, and comes with highlighted snippets showing where the query matched.
facets: list the values a filter can take, with page counts — the places, holding institutions, languages and newspaper titles the index actually holds, either across the whole corpus or within one query's results.
snippets: locate a query inside one page or across every page of an issue you already have in hand.
get: download the OCR text of a page or a whole issue, cached locally.
There are two ways to use it: an MCP server for clients that speak MCP, and a ddb CLI for agents driven through a shell. Both share one client, one cache and one set of behaviours. The CLI is what the bundled ddb-search skill uses.
Installation
Install the code
uv syncInstall the CLI
uv tool install . # puts `ddb` on your PATHInstall to MCP CLIs
Installs to Claude Code, Codex CLI, and Gemini CLI:
uv run ddb-mcp-installVerify the installation:
claude mcp list # For Claude Code
codex mcp list # For Codex CLI
gemini mcp list # For Gemini CLIRelated MCP server: gallica-mcp
Usage
ddb search '"Luftschiffhafen Friedrichshafen"' # 29 pages, 1909-1935
ddb search '"Luftschiffhafen Friedrichshafen"' --pages all # sweep a bounded query
ddb search 'Zeppelin' --from-year 1900 --to-year 1910 --rows 50
ddb search 'Straßenbahn AND Unfall' --place Berlin
ddb facets place # places the index holds, by page count
ddb facets place 'Zeppelin' --limit 5 # where a term appears
ddb facets title 'Zeppelin' --from-year 1900 --to-year 1910 # which papers carried it
ddb snippets BGQICR4U4JYQ35MJ35MNBWQSJ6LA7KDR 'Zeppelin' # where it appears in an issue
ddb get BGQICR4U4JYQ35MJ35MNBWQSJ6LA7KDR-ALTO10268886_DDB_FULLTEXT # cached OCR text pathAdd --json for machine-readable output.
--place and --provider match a whole string, which is what facets is for. They are Solr string fields, so a near-miss is not a near-miss: --place Halle reports 0 pages matched with no error at all, while --place 'Halle (Saale)' matches 1.1 million pages. Institution names are worse, being long and official — Bayerische Staatsbibliothek matches 8.3 million pages and Bayerische matches none. ddb facets place and ddb facets provider print the values verbatim, so they can be copied across. --title is the forgiving one: it is analysed text with German stemming, so a fragment of a title is enough.
Given a query, facets describes that result set rather than the corpus, which makes it a characterisation tool as much as a lookup: the geography of a term, or the newspapers that carried it. Counts are computed by the index over the whole result set, not over the results already fetched. facets title lists ZDB identifiers with one recorded title form each — the title field is stemmed text and facets into word stems (zeitung, nachricht) rather than titles, so titles are counted through zdb_id and labelled afterwards. The label is a signpost, not a date-accurate title: the recorded string describes a paper's whole run, so a date-bounded listing can show a subtitle the paper only acquired later. The identifier beside it is the exact thing, and goes straight into --zdb-id.
The filters the portal itself offers are year, title, place, provider and language, and all five are here. There is no facet for publication frequency, region or state, subject, format, contributor or material type: those fields are absent from this index, not merely unexposed.
Search already includes snippets, which is the important workflow difference from the sibling clients. DDB returns highlighted excerpts in the search response itself, so judging a hit costs nothing beyond the search that found it. Reach for get only when a page or issue is worth reading at length. Use --no-snippets when you want a compact listing.
There is no date ordering, deliberately. publication_date is a Solr DateRangeField and the server refuses to sort on it, so results always come back by relevance. Rather than offer a flag that quietly reordered only the handful of results already fetched — a chronology in name while the selection stayed relevance-ranked — the client omits it. Chronological work means bounding the query with --from-year/--to-year and sweeping the range with --pages all; the ordering then falls out of the sweep.
The result total is a true count. Solr reports numFoundExact, and it survives checking: "Luftschiffhafen Friedrichshafen" reports 29 results and returns exactly 29 documents, spanning 1909 to 1935. This is unlike Gallica, whose totals are a ranking depth — here a total can be quoted, and a swept query really has been swept.
Downloads are cached in $XDG_CACHE_HOME/ddb-mcp (override with --cache-dir or DDB_CACHE_DIR). The cache location does not depend on the working directory, so the CLI can be run from anywhere.
Requests are paced one per second by default, overridable with DDB_MIN_REQUEST_INTERVAL. DDB publishes no rate limit for this endpoint, sends no rate-limit headers, and serves no robots.txt on the API host; none was observed across roughly eighty requests including a deliberate burst. One second is therefore a conservative choice, not a measured ceiling — there is no evidence about where the real limit sits, only that ordinary use does not come near it.
API key
None is needed: the newspaper search index answers unauthenticated. That may be an unenforced gate rather than deliberate policy, so if you hold a DDB API key, set DDB_API_KEY and the client will send it — the CLI keeps working if enforcement is ever switched on.
Where to get one: https://www.deutsche-digitale-bibliothek.de/user/apikey — the key page inside your DDB account. It needs a free DDB account first, registered at https://www.deutsche-digitale-bibliothek.de/user/register; once logged in, the key is generated on that page and shown immediately.
It is free and needs no institutional affiliation. Per DDB's own documentation, "Alle registrierten Nutzer*innen der Deutschen Digitalen Bibliothek können sich einen Authentifikationsschlüssel für die Verwendung der APIs erzeugen lassen" — any registered DDB user can have a key generated, from the Meine DDB area of their own account. There is no paid tier and no approval step.
Then:
export DDB_API_KEY=your_key_hereBoth links live on the www host, which serves an anti-bot challenge to scripted clients but passes a real browser transparently — so open them in a browser, and expect curl to get a challenge page instead. The apikey URL is DDB's own, taken from the documentation page linked above; the registration path has not been walked through here.
MCP server
Run the server directly:
uv run ddb-mcpTest with MCP Inspector:
uv run fastmcp dev src/ddb_mcp/server.pyMaintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceComprehensive MCP server for academic research workflows, enabling paper searching across multiple sources, manuscript processing with citation placeholders, search caching, and citation export.Last updated11MIT
- AlicenseAqualityBmaintenanceEnables searching and accessing OCR text from millions of digitized documents in Gallica, the digital library of the Bibliothèque nationale de France, through MCP tools for text search, snippet retrieval, and full-text download.Last updated31Apache 2.0
- Alicense-qualityDmaintenanceEnables natural-language querying of multiple digital scholarly editions, aggregating Schleiermacher digital, Praktiken der Monarchie, and correspSearch into a single MCP endpoint.Last updatedMIT
- Alicense-qualityBmaintenanceA local MCP server for searching scientific papers, retrieving metadata and abstracts, and legally downloading Open Access PDFs via OpenAlex, CrossRef, and Unpaywall APIs.Last updated1MIT
Related MCP Connectors
MCP server for Altmetric APIs - track research attention across news, policy, social media, and more
Keyless open data for 84 German cities: 12 lean read-only MCP tools covering 67 data types.
IEEE Xplore MCP — BYOK wrapper over the IEEE Xplore Metadata Search API
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/nestordemeure/ddb-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server