Transkribus MCP Server
Servidor MCP para la API REST de Transkribus: gestiona colecciones, documentos, reconocimiento HTR/OCR, modelos y más. 290 herramientas en 22 dominios de recursos.
Documentación
transkribus-mcp-server
Servidor MCP para la API REST de Transkribus. Gestiona colecciones, documentos, reconocimiento HTR/OCR, modelos y más a través del Protocolo de Contexto de Modelos.
304 herramientas en 23 dominios de recursos, con 9 puntos de entrada para que puedas elegir el servidor adecuado según el límite de herramientas de tu cliente MCP.
Alcance de la API: Este servidor cubre dos APIs de Transkribus:
- la API REST heredada de TrpServer (
https://transkribus.eu/TrpServer/rest), basada en sesiones — 300 herramientas;- la API de Procesamiento Metagrapho (
https://transkribus.eu/processing/v1), autenticación OIDC bearer medianteaccount.readcoop.eu— las 4 herramientastranskribus_processing_*.Ten en cuenta la versión. Parte del material de Transkribus aún muestra
/processing/v2y un campoconfig.modelId. Esa ruta devuelve 404; el servicio activo es/processing/v1y aceptaconfig.textRecognition.htrId.
Instalación
npm install -g @lazyants/transkribus-mcp-server
O ejecuta directamente:
npx @lazyants/transkribus-mcp-server
Configuración
Transkribus utiliza autenticación basada en sesiones. Las credenciales se resuelven en este orden, por valor:
- Llavero del sistema operativo (recomendado — no se escribe nada en un archivo de configuración en texto claro)
- Variable de entorno (
TRANSKRIBUS_USER+TRANSKRIBUS_PASSWORD, oTRANSKRIBUS_SESSION_ID)
Ya sea un nombre de usuario y contraseña (el servidor inicia sesión y gestiona la sesión) o un ID de sesión que ya poseas. Un ID de sesión tiene prioridad cuando ambos están disponibles; caduca, por lo que un nombre de usuario y contraseña es la mejor opción para una configuración de larga duración — y es lo que permite al servidor reautenticarse después de un 401.
El llavero nunca es obligatorio: si no está disponible — una máquina Linux sin
servicio Secret Service, una plataforma no compatible, una instalación con --omit=optional —
o si no responde en 5 segundos, el servidor recurre al
entorno.
Almacenar las credenciales en el llavero del sistema operativo
Tres entradas bajo un único nombre de servicio, transkribus-mcp por defecto:
user, password y session-id (almacena solo lo que uses).
[!IMPORTANTE] Los comandos siguientes leen el valor desde un prompt interactivo en lugar de tomarlo como argumento, para que nunca termine en el historial de tu shell, en una línea de comandos, o en el entorno de lanzamiento de otro proceso. Evita pegar una contraseña directamente en la línea de comandos.
macOS
Omitir el valor después de -w hace que security lo solicite:
security add-generic-password -s "transkribus-mcp" -a "user" -w
security add-generic-password -s "transkribus-mcp" -a "password" -w
[!NOTA] Un elemento del llavero de inicio de sesión pertenece al programa que lo creó. La primera vez que el servidor lee un elemento creado por
security, macOS muestra un diálogo "…quiere usar tu información confidencial almacenada en transkribus-mcp" — elige Permitir siempre y no volverá a preguntar. Hasta que se conceda, la lectura no puede completarse: el servidor espera 5 segundos y luego recurre a las variables de entorno, por lo que un servidor iniciado donde nadie puede responder al diálogo se comporta como si el llavero estuviera vacío en lugar de bloquearse.Para evitar el diálogo por completo, escribe la entrada desde el mismo runtime de Node.js que la leerá. El valor se introduce por la entrada estándar, por lo que aparece ni en una línea de comandos ni en un entorno de proceso (
ps -Elos muestra). El prompt siguiente es POSIX estándar, por lo que se comporta igual enzshybash:npm install -g @lazyants/transkribus-mcp-server # el módulo del llavero se incluye cd "$(npm root -g)/@lazyants/transkribus-mcp-server" printf 'Contraseña de Transkribus: ' >&2; stty -echo; IFS= read -r TK_SECRET; stty echo; printf '\n' >&2 printf '%s' "$TK_SECRET" | node -e ' const { Entry } = require("@napi-rs/keyring"); let value = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", (chunk) => { value += chunk; }); process.stdin.on("end", () => { new Entry("transkribus-mcp", "password").setPassword(value); console.log("almacenado"); }); ' unset TK_SECRETRepite con
"user"en lugar de"password". Una instalación diferente de Node.js más adelante (un cambio denvm, por ejemplo) es un programa diferente para el llavero, por lo que el diálogo puede aparecer una vez más para ella.
Windows (PowerShell)
cmdkey solo puede tomar el valor como argumento de línea de comandos, lo que lo expone en
la lista de procesos. Léelo desde un prompt oculto en su lugar y escríbelo directamente en
el Administrador de Credenciales de Windows mediante CredWrite. El nombre de destino de la credencial es
<account>.<service> — user.transkribus-mcp y password.transkribus-mcp
para el servicio predeterminado — que es exactamente lo que el servidor lee:
Add-Type -Namespace TranskribusKeyring -Name Native -MemberDefinition @'
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CREDENTIAL {
public uint Flags;
public uint Type;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetName;
[MarshalAs(UnmanagedType.LPWStr)] public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public uint CredentialBlobSize;
public IntPtr CredentialBlob;
public uint Persist;
public uint AttributeCount;
public IntPtr Attributes;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias;
[MarshalAs(UnmanagedType.LPWStr)] public string UserName;
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredWriteW(ref CREDENTIAL credential, uint flags);
'@
function Set-TranskribusCredential {
param([Parameter(Mandatory)][string]$Account, [Parameter(Mandatory)][string]$Prompt)
$secure = Read-Host -AsSecureString $Prompt
$blob = [Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($secure)
try {
$cred = New-Object TranskribusKeyring.Native+CREDENTIAL
$cred.Type = 1 # CRED_TYPE_GENERIC
$cred.Persist = 2 # CRED_PERSIST_LOCAL_MACHINE
$cred.TargetName = "$Account.transkribus-mcp" # "<account>.<service>"
$cred.UserName = $Account
$cred.CredentialBlob = $blob
$cred.CredentialBlobSize = $secure.Length * 2 # UTF-16 bytes, no terminator
if (-not [TranskribusKeyring.Native]::CredWriteW([ref]$cred, 0)) {
throw "CredWrite failed (Win32 error $([Runtime.InteropServices.Marshal]::GetLastWin32Error()))"
}
Write-Host "Stored '$Account' in Windows Credential Manager."
} finally {
[Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($blob)
$secure.Dispose()
Remove-Variable secure, blob
}
}
Set-TranskribusCredential -Account 'user' -Prompt 'Transkribus user (e-mail)'
Set-TranskribusCredential -Account 'password' -Prompt 'Transkribus password'
¿Usas un
TRANSKRIBUS_KEYRING_SERVICEpersonalizado (p. ej.acme)? EstableceTargetNameauser.acme/password.acmepara que coincida — el servidor busca cada valor bajo<account>.<service>.
Linux
secret-tool store --label="Transkribus user" service transkribus-mcp username user
secret-tool store --label="Transkribus password" service transkribus-mcp username password
# (each prompts for the value)
Una vez almacenadas, los archivos de configuración de MCP no necesitan credenciales en absoluto.
Usar variables de entorno en su lugar
export TRANSKRIBUS_USER=your-email@example.com
export TRANSKRIBUS_PASSWORD=your-password
O, con una sesión que ya poseas:
export TRANSKRIBUS_SESSION_ID=your-session-id
Variables de entorno
| Variable | Predeterminado | Descripción |
|---|---|---|
TRANSKRIBUS_USER | — | Correo de la cuenta; se usa cuando el llavero no tiene una entrada user para el servicio configurado |
TRANSKRIBUS_PASSWORD | — | Contraseña de la cuenta; se usa cuando el llavero no tiene una entrada password |
TRANSKRIBUS_SESSION_ID | — | Un ID de sesión existente; se usa cuando el llavero no tiene una entrada session-id |
TRANSKRIBUS_KEYRING_SERVICE | transkribus-mcp | Nombre del servicio del llavero. Sobrescríbelo para conectarte a varias cuentas de Transkribus a la vez — ejecuta una instancia del servidor por cuenta, cada una con su propio nombre de servicio |
Credenciales de la API de Procesamiento
Las herramientas transkribus_processing_* hablan con un servicio diferente con un
esquema de autenticación diferente, pero no necesitan configuración adicional: el mismo
TRANSKRIBUS_USER + TRANSKRIBUS_PASSWORD se intercambian por un token bearer OIDC
(concesión de contraseña SSO de READCOOP, cliente processing-api-client) y se renuevan
automáticamente. TRANSKRIBUS_SESSION_ID no se aplica a ellas.
Dos sobrescrituras opcionales:
export TRANSKRIBUS_ACCESS_TOKEN=your-bearer-token # skip the token exchange entirely
export TRANSKRIBUS_PROCESSING_CLIENT_ID=custom-client # non-default OIDC client
Puntos de entrada
| Comando | Dominios | Herramientas |
|---|---|---|
transkribus-mcp-server | Los 23 dominios | 304 |
transkribus-mcp-collections | Auth, Colecciones (core/docs/pages/users/crowd/editdecl/credits/stats/labels/activity/tags) | 131 |
transkribus-mcp-admin | Auth, Admin, Créditos, Subidas, Etiquetas, Archivos, Sistema, Raíz | 62 |
transkribus-mcp-transcription | Auth, Reconocimiento, Análisis de diseño, PyLaia, P2PaLA, DU | 47 |
transkribus-mcp-users | Auth, Usuarios, Crowdsourcing, eLearning | 29 |
transkribus-mcp-models | Auth, Modelos | 26 |
transkribus-mcp-jobs | Auth, Trabajos, Acciones | 19 |
transkribus-mcp-search | Auth, Búsqueda, KWS | 16 |
transkribus-mcp-processing | Procesamiento (Metagrapho) — sin herramientas de autenticación heredadas | 4 |
Usa servidores divididos para reducir el tamaño del contexto — elige solo las divisiones que necesites.
Subir un documento
Para ingerir un documento, usa este flujo de tres pasos:
transkribus_upload_create_structure— proporciónalecollId, untitley un arraypagesde{ fileName, pageNr }(una entrada por imagen de página que estés a punto de enviar). Devuelve una subida con unuploadId.transkribus_upload_page— llama una vez por página con eluploadIdy elimagePath(una ruta a un archivo de imagen local), opcionalmentepageXmlPathpara una transcripción PAGE XML existente.transkribus_upload_get_status— consulta con eluploadIdhasta que el documento aparezca en la colección.
Estas herramientas de subida se incluyen en el transkribus-mcp-server completo y en la división transkribus-mcp-admin
— no en transkribus-mcp-collections. La ingesta de PDF no es compatible; convierte el PDF a
imágenes de página primero y usa el flujo anterior.
Claude Code
Añade a ~/.claude/settings.json. Con las credenciales en el llavero del sistema operativo bajo
el nombre de servicio predeterminado (recomendado), no se necesita ninguna clave env:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"]
}
}
}
O usa servidores divididos (elige las divisiones que necesites):
{
"mcpServers": {
"transkribus-collections": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/transkribus-mcp-server", "transkribus-mcp-collections"]
},
"transkribus-transcription": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/transkribus-mcp-server", "transkribus-mcp-transcription"]
}
}
}
Dos cuentas de Transkribus a la vez — una instancia por cuenta, cada una apuntando a su propio nombre de servicio del llavero:
{
"mcpServers": {
"transkribus-team-a": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": { "TRANSKRIBUS_KEYRING_SERVICE": "transkribus-team-a" }
},
"transkribus-team-b": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": { "TRANSKRIBUS_KEYRING_SERVICE": "transkribus-team-b" }
}
}
}
Sin llavero, pasa las credenciales en env en su lugar:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": {
"TRANSKRIBUS_USER": "your-email@example.com",
"TRANSKRIBUS_PASSWORD": "your-password"
}
}
}
}
Claude Desktop
Añade a claude_desktop_config.json. Con las credenciales en el llavero del sistema operativo
(recomendado — asume el nombre de servicio predeterminado transkribus-mcp):
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"]
}
}
}
Sin llavero:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": {
"TRANSKRIBUS_USER": "your-email@example.com",
"TRANSKRIBUS_PASSWORD": "your-password"
}
}
}
}
Seguridad
- Usa el llavero del sistema operativo para mantener tu contraseña fuera de los archivos de configuración y del historial del shell por completo (consulta Configuración)
- Nunca confirmes tus credenciales en el control de versiones
- Los ID de sesión caducan — prefiere un nombre de usuario y contraseña para configuraciones de larga duración; un ID de sesión solo no puede renovarse después de un 401
Aviso legal
Este es un servidor MCP no oficial para Transkribus. Los autores no están afiliados a READ-COOP SCE. Úsalo bajo tu propio riesgo.
Publicación
Las versiones se publican mediante el evento de Release de GitHub. Flujo del mantenedor:
-
Incrementa la versión en
package.json,package-lock.jsonyserver.json(npm version <x.y.z> --no-git-tag-versionactualiza los dos primeros juntos).npm run check-versionsfalla de forma estricta a menos quepackage.json#/versionyserver.json#/packages[0].versioncoincidan.server.json#/versionse comprueba de forma flexible: debe estar presente, y solo falla cuando retrocede por debajo depackages[0].version— un valor dejado en la versión anterior pasa con una líneaWARN:y código de salida 0. El script no mirapackage-lock.jsonniCHANGELOG.mden absoluto, así que lee su salida en lugar de confiar en su código de salida. -
Actualiza
CHANGELOG.md. -
Confirma y fusiona el incremento de versión a
mainantes de crear la release. Luego crea la etiqueta tú mismo, en un SHA que hayas verificado, y solo entonces crea la release a partir de ella:V=X.Y.Z && PR=<release-pr-number> && SHA="$(gh pr view "$PR" --json mergeCommit -q .mergeCommit.oid)" && test -n "$SHA" && git fetch origin main && git merge-base --is-ancestor "$SHA" origin/main && PKG="$(git show "$SHA:package.json")" && test "$(printf '%s' "$PKG" | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).version')" = "$V" && CL="$(git show "$SHA:CHANGELOG.md")" && printf '%s\n' "$CL" | awk -v v="$V" 'index($0,"## ["v"]")==1{f=1;next} /^## \[/{f=0} /^\[[0-9]+\.[0-9]+\.[0-9]+\]:/{f=0} f' > "/tmp/notes-v$V.md" && grep -q '[^[:space:]]' "/tmp/notes-v$V.md" && git tag -a "v$V" "$SHA" -m "v$V" && git push origin "v$V" && gh release create "v$V" --verify-tag --notes-file "/tmp/notes-v$V.md"El fallo que esto previene: sin una etiqueta existente,
gh release create vX.Y.Zcoloca una en la punta de la rama predeterminada. Ejecútalo mientras el incremento aún está en una rama de release y etiquetará el commit de la versión anterior; el flujo de trabajo entonces publica cualquier versión que encuentre en elpackage.jsonde ese commit, produciendo una Release de GitHubvX.Y.Zque republica silenciosamente la versión anterior. El flujo de trabajo de publicación ahora se niega a continuar cuandoGITHUB_REF_NAMEno esv<package.json version>, por lo que ese escenario exacto falla antes denpm publishen lugar de republicar silenciosamente. La secuencia anterior sigue siendo necesaria y protege un caso que el flujo de trabajo no puede: la protección del flujo de trabajo solo se ejecuta una vez que ya existe una release, y pasa para cualquier commit que lleve la versión correcta — por lo que detecta una release mal etiquetada, no el commit incorrecto siendo etiquetado.Cada elemento es esencial:
-
gh pr view … .mergeCommit.oidnombra el commit de squash propio del PR de lanzamiento. No sustituyasgit rev-parse origin/main: eso es meramente lo que esté enmainen el momento en que mires, por lo que una fusión no relacionada que llegue en el intervalo se etiquetaría y publicaría en su lugar.ghsale con 0 y no imprime nada para un PR sin fusionar, de ahí eltest -nexplícito.- La cadena
&&se detiene en el primer fallo en lugar de pasar al paso irreversible. Ambas llamadas agit showse asignan a una variable en lugar de canalizarse directamente, por lo que su estado de salida se comprueba de hecho — una canalización informa solo del estado de su último comando a menos quepipefailesté configurado, lo cual no se asume aquí. git merge-base --is-ancestordemuestra que el commit es alcanzable desdemain. La mera existencia no es suficiente: un commit puede estar presente localmente porque se obtuvo otra rama, y si sus archivos de versión coinciden, de otro modo pasaría todas las comprobaciones restantes.- La prueba de versión lee
package.jsondel commit objetivo, no del árbol de trabajo — que aún mostraría la versión correcta mientras$SHAapuntara a otro lugar. - El
awkextrae la sección de esa versión delCHANGELOG.mddel commit para--notes-file. Sin él, el cuerpo del lanzamiento es lo que--notes-from-tagencuentre en la anotación — aquí la cadena literalvX.Y.Z, una nota de lanzamiento pobre para cualquier versión y engañosa para un lanzamiento que lleva un cambio disruptivo. Se detiene en el siguiente encabezado## [o en la primera definición de referencia de enlace, porque la entrada más antigua no tiene encabezado después y de otro modo se tragaría todo el bloque de referencias de enlace.grep -qen lugar detest -sprotege el resultado: una sección vacía aparte de su línea en blanco aún produce un archivo de un byte, quetest -sacepta. --verify-taghace queghse interrumpa en lugar de inventar una etiqueta si el push no se realizó — la protección contra la alternativa de la punta de la rama predeterminada descrita anteriormente.
Si
gh release createfalla después de que la etiqueta ya se haya enviado, no vuelvas a ejecutar todo el bloque; se detendrá engit tag, lo cual es correcto. Vuelve a ejecutar solo el comando final. - La cadena
- El flujo de trabajo
Publish to npm + MCP Registryse ejecuta automáticamente:npm publishcon procedencia, consulta el registro hasta que el tarball esté disponible, luego envía elserver.jsoncorrespondiente al Registro MCP mediantemcp-publisher.
El flujo de trabajo omite npm publish limpiamente si la versión ya está en npm (protección de transición para lanzamientos que se publicaron parcialmente de forma manual).
Autenticación de npm
La publicación utiliza npm Trusted Publishing: el token OIDC de GitHub del flujo de trabajo (id-token: write) se intercambia por un token de publicación de un solo uso en tiempo de ejecución. No es necesario que exista ningún secreto NPM_TOKEN en el repositorio.
El enlace se configura en la interfaz web de npm (paquete → Trusted Publishers): proveedor GitHub Actions, organización lazyants, repositorio transkribus-mcp-server, flujo de trabajo publish-registry.yml.
Licencia
FSL-1.1-MIT — consulta LICENSE para los términos completos. Las versiones 1.x permanecen con licencia MIT.