Back to Browse

Databnf MCP Server

Developer ToolsLow Risk10.0LocalNew
Free

Search the BnF open catalogue: authors, works, editions and links to what is digitised.

About

Search the BnF open catalogue: authors, works, editions and links to what is digitised.

Security Report

10.0
Low Risk10.0Low Risk

Valid MCP server (1 strong, 1 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry. Trust signals: trusted author (10/10 approved).

4 files analyzed · 1 issue found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

file_system

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

Identify your own client. The project's own identifier is appended, so the BnF can always reach a person.Optional

Environment variable: BNF_USER_AGENT

Minimum milliseconds between requests. Default 3000, which is also the floor.Optional

Environment variable: BNF_MIN_INTERVAL_MS

Deadline for one SPARQL query, in milliseconds. Default 60000.Optional

Environment variable: BNF_TIMEOUT_MS

Attempts after a busy answer. Default 3.Optional

Environment variable: BNF_MAX_RETRIES

How long an answer is kept in memory, in milliseconds. Default 900000. Zero turns the cache off.Optional

Environment variable: BNF_CACHE_TTL_MS

silent, error, info or debug. Default error. Logs go to stderr.Optional

Environment variable: BNF_LOG_LEVEL

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-smeet666-mcp-databnf": {
      "env": {
        "BNF_LOG_LEVEL": "your-bnf-log-level-here",
        "BNF_TIMEOUT_MS": "your-bnf-timeout-ms-here",
        "BNF_USER_AGENT": "your-bnf-user-agent-here",
        "BNF_MAX_RETRIES": "your-bnf-max-retries-here",
        "BNF_CACHE_TTL_MS": "your-bnf-cache-ttl-ms-here",
        "BNF_MIN_INTERVAL_MS": "your-bnf-min-interval-ms-here"
      },
      "args": [
        "-y",
        "mcp-databnf"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

mcp-databnf

An MCP server for data.bnf.fr, the open catalogue of the Bibliothèque nationale de France. Look up an author, find a work, list the editions the BnF holds of it, and gather the links to what has been digitised.

No API key. No account. Read-only.

npm CI licence: MIT


What it is for

The BnF publishes its authority file and its bibliographic records as linked data, and answers questions about them over SPARQL. That dataset knows things a web search does not: which of two people bearing one name wrote a given book, what the BnF recorded as somebody's date and place of death, which editions of a work exist and who printed them, and which of those have been digitised.

This server asks those questions for you, in six tools, and reports what the catalogue answers without adding to it.

Install

npx mcp-databnf

Claude Desktop, Claude Code, and other stdio clients

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

The six tools

ToolAnswers
search_authorsWho does the BnF record under this name, and which record is which
get_authorDates, places, occupation, language, country, Dewey class, and the same person in VIAF, IdRef, DBpedia, Wikidata and ISNI
search_worksWhich works have these words in their title
get_workTitle, creators, date, language, form, subject, and whether the record is established or provisional
list_editionsPublisher, place, year, edition statement, extent, ISBN, catalogue link, and the Gallica link when there is one
find_digitisedEvery digitised document the catalogue attaches to a person or a work, as links

A typical exchange asks search_authors for a name, reads the rows, and passes one identifier to get_author or search_works.

What it does not do, and why

It never reads Gallica. The BnF puts its metadata and its digitised contents under two different regimes. The metadata this server reads may be reused freely provided the source and the date of retrieval are stated. The contents on gallica.bnf.fr are governed separately: their terms make use inside an artificial-intelligence project subject to a paid licence outside academic research, and the site refuses ClaudeBot and GPTBot at the server, then bans the calling address after about fifteen requests whatever the pace.

So a Gallica address is treated here as what the catalogue says it is: a piece of metadata, rendered as a link for a person to open. The server will tell you that a 1873 Brussels printing of Une saison en enfer has been digitised and give you its address. It will not tell you what is on page four, whether the scan is complete, or whether the document opens at all. A bnf-onto:OCR link names a machine-read text of a document; the server reports that the text exists and leaves it where it is. A test fails if any address on that host is ever built to be called.

It does not rank. The BnF's full-text index answers whether a title or a name carries the words asked for. It returns no measure of how well, so the rows come back in the order the index holds them. Searching for saison enfer returns a dozen studies of Rimbaud before Rimbaud, and every one of them is a correct match. This server says so rather than inventing an order the catalogue does not support, and it reports no total, because a total on a search that does not rank reads as a measure of relevance.

It does not write biographies. The field the BnF calls biographical information is an occupation on most records: Rimbaud's says Poète, and that is the whole of it. get_author returns that word and says what it is.

It exposes no raw SPARQL tool. An arbitrary query is an unbounded load on a service a public institution pays for, and nothing here would control what the caller wrote. Every query this server sends is one of nine written in advance.

The licence, and what it asks of you

The BnF states one condition on these metadata:

L'utilisation de ces métadonnées est libre et gratuite sous réserve du maintien de la mention de leur source et de l'indication de leur date de récupération.

Use is free of charge, provided the source is named and the date of retrieval is stated. That second half is a design constraint: every answer this server produces carries retrieved_at in its payload and ends its text block with the source and that date. A cached answer reports the moment it was originally read, since that is the date it was retrieved. Repeat both wherever you show what you got.

How it treats the service

data.bnf.fr is a query service a public institution runs at its own cost, and a SPARQL query is a more expensive request than fetching a page.

  • One request at a time, never in parallel.
  • At least three seconds between two of them. Configuration can widen that and cannot narrow it, including through the published client entry point.
  • The User-Agent always carries the project identifier and an address where a person can be reached, whatever a caller sets.
  • Answers are cached in memory for fifteen minutes, so a conversation that walks back over one author does not ask twice.

The BnF publishes no rate for this endpoint. It publishes Crawl-delay: 5 on its other host and enforces it there, which is the only figure it has stated about how fast it wants to be read, and the floor here was set with that in mind.

Settings

Every one is optional.

VariableDefaultMeaning
BNF_USER_AGENTnoneIdentify your own client. The project identifier is appended, so the BnF can always reach a person.
BNF_MIN_INTERVAL_MS3000Milliseconds between requests. The floor is 3000 and cannot be lowered.
BNF_TIMEOUT_MS60000Deadline for one query.
BNF_MAX_RETRIES3Attempts after a busy answer.
BNF_CACHE_TTL_MS900000How long an answer is kept. 0 turns the cache off.
BNF_CACHE_MAX_ENTRIES200How many answers are kept.
BNF_LOG_LEVELerrorsilent, error, info or debug. Logs go to stderr.

A value that cannot be read is refused, named on stderr, and the default stands. The setting is not clamped: clamping would let you believe a value took effect when it did not.

Errors

CodeMeans
not_foundThe endpoint answered, and the BnF describes no such record
invalid_inputThe request was refused rather than answered
rate_limitedThe endpoint asked this client to slow down
parse_failureThe answer arrived in a shape this client cannot read
network_errorThe request did not complete
timeoutThe query exceeded its deadline, or the endpoint gave it up

rate_limited never means the record is missing. Neither does timeout: the endpoint answers 200 with an empty body when it abandons a query part way through, and this server calls that a failure to read rather than an absence, because the two look identical and mean opposite things.

Using the access layer on its own

The lower layer imports nothing from the MCP protocol and is published under the ./client subpath, with its pacing, its cache and its error taxonomy attached.

import { BnfClient } from "mcp-databnf/client";

const client = new BnfClient();
const { data, retrievedAt } = await client.searchAuthors("Rimbaud", 10, 0);
for (const author of data.rows) console.log(author.id, author.name, author.birthYear);
console.log("retrieved", retrievedAt);

Development

npm install
npm test          # unit tests, against generated fixtures, no network
npm run typecheck
npm run build
BNF_LIVE=1 npm run test:live   # one real query per route

The unit tests reach no network. Fixtures are generated by scripts/build-fixtures.mjs from invented records, so no BnF content lives in this repository and every test is reproducible. The live suite runs nightly as a canary, and it is the only thing that would notice the day the catalogue changes shape.

Contributing

CONTRIBUTING.md. Reports of a wrong answer are the most useful kind: say what you asked, what came back, and what the record actually holds.

Licence

MIT for this code. See LICENSE.

The metadata belong to the Bibliothèque nationale de France and are published under the condition quoted above: name the source, and state the date of retrieval.


mcp-databnf (français)

Un serveur MCP pour data.bnf.fr, le catalogue ouvert de la Bibliothèque nationale de France. Chercher un auteur, trouver une œuvre, lister les éditions que la BnF en conserve, et rassembler les liens vers ce qui a été numérisé.

Sans clé d'API. Sans compte. En lecture seule.

À quoi il sert

La BnF publie son fichier d'autorité et ses notices bibliographiques en données liées, et répond aux questions qu'on lui pose en SPARQL. Ce jeu de données sait des choses qu'une recherche sur le web ignore : lequel de deux homonymes a écrit tel livre, ce que la BnF a enregistré comme date et lieu de mort de quelqu'un, quelles éditions d'une œuvre existent et qui les a imprimées, et lesquelles ont été numérisées.

Ce serveur pose ces questions pour vous, en six outils, et rapporte ce que le catalogue répond sans y ajouter.

Installation

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

Les six outils

OutilRépond à
search_authorsQui la BnF enregistre sous ce nom, et quelle notice est laquelle
get_authorDates, lieux, profession, langue, pays, indice Dewey, et la même personne dans VIAF, IdRef, DBpedia, Wikidata et ISNI
search_worksQuelles œuvres portent ces mots dans leur titre
get_workTitre, auteurs, date, langue, forme, sujet, et si la notice est établie ou provisoire
list_editionsÉditeur, lieu, année, mention d'édition, pagination, ISBN, lien catalogue, et le lien Gallica quand il existe
find_digitisedTous les documents numérisés que le catalogue rattache à une personne ou à une œuvre, sous forme de liens

Ce qu'il ne fait pas, et pourquoi

Il ne lit jamais Gallica. La BnF place ses métadonnées et ses contenus numérisés sous deux régimes différents. Les métadonnées lues ici sont réutilisables librement à condition d'en citer la source et la date de récupération. Les contenus de gallica.bnf.fr relèvent d'un autre régime : leurs conditions soumettent l'usage dans un projet d'intelligence artificielle à une licence payante hors recherche académique, et le site refuse ClaudeBot et GPTBot au niveau du serveur, puis bannit l'adresse appelante après une quinzaine de requêtes, quel que soit le rythme.

Une adresse Gallica est donc traitée ici pour ce que le catalogue en dit : une métadonnée, rendue comme un lien qu'une personne ouvrira. Le serveur vous dira qu'un tirage bruxellois de 1873 d'Une saison en enfer a été numérisé et vous en donnera l'adresse. Il ne vous dira pas ce qu'il y a page quatre, si la numérisation est complète, ni si le document s'ouvre. Un lien bnf-onto:OCR désigne un texte océrisé : le serveur signale qu'il existe et le laisse où il est. Un test échoue si une adresse sur cet hôte est un jour construite pour être appelée.

Il ne classe pas. L'index plein texte de la BnF répond si un titre ou un nom porte les mots demandés. Il ne rend aucune mesure de pertinence, donc les lignes arrivent dans l'ordre de l'index. Chercher saison enfer rend une douzaine d'études sur Rimbaud avant Rimbaud, et chacune est une correspondance correcte. Ce serveur le dit, plutôt que d'inventer un ordre que le catalogue ne porte pas, et il ne rapporte aucun total : sur une recherche qui ne classe pas, un total se lit comme une mesure de pertinence.

Il n'écrit pas de biographies. Le champ que la BnF appelle information biographique contient une profession sur la plupart des notices : celle de Rimbaud dit Poète, et c'est tout. get_author rend ce mot et dit ce que c'est.

Il n'expose aucun outil SPARQL brut. Une requête arbitraire est une charge non bornée sur un service qu'une institution publique paie, et rien ici ne contrôlerait ce que l'appelant a écrit. Chacune des requêtes envoyées est l'une des neuf écrites à l'avance.

La licence, et ce qu'elle vous demande

La BnF pose une condition :

L'utilisation de ces métadonnées est libre et gratuite sous réserve du maintien de la mention de leur source et de l'indication de leur date de récupération.

La date de récupération est une contrainte de conception : chaque réponse porte retrieved_at dans sa charge structurée et termine son bloc de texte par la source et cette date. Une réponse servie depuis le cache rapporte le moment où elle a été lue la première fois, puisque c'est là qu'elle a été récupérée. Reprenez les deux partout où vous montrez ce que vous avez obtenu.

Le rythme

Une requête à la fois, jamais en parallèle. Au moins trois secondes entre deux requêtes : la configuration peut élargir cet intervalle et ne peut pas le réduire, y compris par le point d'entrée client publié. Le User-Agent porte toujours l'identifiant du projet et une adresse où joindre une personne. Les réponses sont gardées quinze minutes en mémoire.

La BnF ne publie aucune limite pour ce point d'accès. Elle publie Crawl-delay: 5 sur son autre hôte et l'y fait respecter, ce qui est le seul chiffre qu'elle ait énoncé sur la vitesse à laquelle elle veut être lue.

Réglages

Tous facultatifs : BNF_USER_AGENT, BNF_MIN_INTERVAL_MS (3000, plancher infranchissable), BNF_TIMEOUT_MS (60000), BNF_MAX_RETRIES (3), BNF_CACHE_TTL_MS (900000), BNF_CACHE_MAX_ENTRIES (200), BNF_LOG_LEVEL (error). Une valeur illisible est refusée, signalée sur stderr, et la valeur par défaut s'applique.

Erreurs

not_found, invalid_input, rate_limited, parse_failure, network_error, timeout. rate_limited ne veut jamais dire que la notice est absente. timeout non plus : le point d'accès répond 200 avec un corps vide quand il abandonne une requête en cours de route, et ce serveur appelle cela un échec de lecture plutôt qu'une absence, parce que les deux se ressemblent et veulent dire le contraire.

Licence

MIT pour ce code. Les métadonnées appartiennent à la Bibliothèque nationale de France et sont publiées sous la condition citée plus haut : citer la source, et indiquer la date de récupération.

Reviews

No reviews yet

Be the first to review this server!