Transkribus MCP Server
Servidor MCP para a API REST do Transkribus — gerencie coleções, documentos, reconhecimento HTR/OCR, modelos e muito mais. 290 ferramentas em 22 domínios de recursos.
Documentação
transkribus-mcp-server
Servidor MCP para a API REST do Transkribus. Gerencie coleções, documentos, reconhecimento HTR/OCR, modelos e muito mais através do Model Context Protocol.
304 ferramentas em 23 domínios de recursos, com 9 pontos de entrada para que você possa escolher o servidor certo para o limite de ferramentas do seu cliente MCP.
Escopo da API: Este servidor cobre duas APIs do Transkribus:
- a API REST legada do TrpServer (
https://transkribus.eu/TrpServer/rest), baseada em sessão — 300 ferramentas;- a API de Processamento Metagrapho (
https://transkribus.eu/processing/v1), autenticação OIDC bearer viaaccount.readcoop.eu— as 4 ferramentastranskribus_processing_*.Atenção à versão. Alguns materiais do Transkribus ainda mostram
/processing/v2e um campoconfig.modelId. Esse caminho retorna 404; o serviço ativo é/processing/v1e aceitaconfig.textRecognition.htrId.
Instalação
npm install -g @lazyants/transkribus-mcp-server
Ou execute diretamente:
npx @lazyants/transkribus-mcp-server
Configuração
O Transkribus usa autenticação baseada em sessão. As credenciais são resolvidas nesta ordem, por valor:
- Chaveiro do sistema operacional (recomendado — nada é gravado em um arquivo de configuração em texto claro)
- Variável de ambiente (
TRANSKRIBUS_USER+TRANSKRIBUS_PASSWORD, ouTRANSKRIBUS_SESSION_ID)
Ou um nome de usuário e senha (o servidor faz login e gerencia a sessão) ou um ID de sessão que você já possui. Um ID de sessão tem precedência quando ambos estão disponíveis; ele expira, então um nome de usuário e senha é a melhor escolha para uma configuração de longo prazo — e é o que permite que o servidor reautentique após um 401.
O chaveiro nunca é obrigatório: se ele estiver indisponível — uma máquina Linux sem
serviço Secret Service, uma plataforma não suportada, uma instalação com --omit=optional —
ou se ele não responder dentro de 5 segundos, o servidor recorre ao
ambiente.
Armazenar as credenciais no chaveiro do sistema operacional
Três entradas sob um único nome de serviço, transkribus-mcp por padrão:
user, password e session-id (armazene apenas o que você usa).
[!IMPORTANT] Os comandos abaixo leem o valor de um prompt interativo em vez de recebê-lo como argumento, para que ele nunca apareça no histórico do shell, em uma linha de comando ou no ambiente de inicialização de outro processo. Evite colar uma senha diretamente na linha de comando.
macOS
Omitir o valor após -w faz o security solicitar:
security add-generic-password -s "transkribus-mcp" -a "user" -w
security add-generic-password -s "transkribus-mcp" -a "password" -w
[!NOTE] Um item do chaveiro de login pertence ao programa que o criou. Na primeira vez que o servidor ler um item criado por
security, o macOS mostra um diálogo "…quer usar suas informações confidenciais armazenadas em transkribus-mcp" — escolha Sempre Permitir e ele não perguntará novamente. Até que isso seja concedido, a leitura não pode ser concluída: o servidor espera 5 segundos e então recorre às variáveis de ambiente, então um servidor iniciado onde ninguém pode responder ao diálogo se comporta como se o chaveiro estivesse vazio, em vez de travar.Para evitar o diálogo completamente, escreva a entrada a partir do mesmo runtime Node.js que a lerá. O valor é enviado pela entrada padrão, então ele aparece nem em uma linha de comando nem em um ambiente de processo (
ps -Emostra esses). O prompt abaixo é POSIX simples, então ele se comporta da mesma forma emzshebash:npm install -g @lazyants/transkribus-mcp-server # o módulo do chaveiro acompanha cd "$(npm root -g)/@lazyants/transkribus-mcp-server" printf 'Senha do 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("armazenado"); }); ' unset TK_SECRETRepita com
"user"no lugar de"password". Uma instalação diferente do Node.js posteriormente (uma troca denvm, por exemplo) é um programa diferente para o chaveiro, então o diálogo pode aparecer mais uma vez para ela.
Windows (PowerShell)
cmdkey só pode receber o valor como argumento de linha de comando, o que o expõe na
lista de processos. Leia-o de um prompt oculto e escreva-o diretamente no
Gerenciador de Credenciais do Windows via CredWrite. O nome do alvo da credencial é
<account>.<service> — user.transkribus-mcp e password.transkribus-mcp
para o serviço padrão — que é exatamente o que o servidor lê de volta:
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'
Usando um
TRANSKRIBUS_KEYRING_SERVICEpersonalizado (por exemplo,acme)? DefinaTargetNameparauser.acme/password.acmepara corresponder — o servidor procura cada valor sob<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)
Uma vez armazenado, os arquivos de configuração MCP não precisam de credenciais.
Usar variáveis de ambiente em vez disso
export TRANSKRIBUS_USER=your-email@example.com
export TRANSKRIBUS_PASSWORD=your-password
Ou, com uma sessão que você já possui:
export TRANSKRIBUS_SESSION_ID=your-session-id
Variáveis de ambiente
| Variável | Padrão | Descrição |
|---|---|---|
TRANSKRIBUS_USER | — | E-mail da conta; usado quando o chaveiro não tem entrada user para o serviço configurado |
TRANSKRIBUS_PASSWORD | — | Senha da conta; usada quando o chaveiro não tem entrada password |
TRANSKRIBUS_SESSION_ID | — | Um ID de sessão existente; usado quando o chaveiro não tem entrada session-id |
TRANSKRIBUS_KEYRING_SERVICE | transkribus-mcp | Nome do serviço do chaveiro. Substitua para conectar-se a várias contas do Transkribus ao mesmo tempo — execute uma instância do servidor por conta, cada uma com seu próprio nome de serviço |
Credenciais da API de Processamento
As ferramentas transkribus_processing_* falam com um serviço diferente com um esquema de
autenticação diferente, mas não precisam de configuração extra: os mesmos
TRANSKRIBUS_USER + TRANSKRIBUS_PASSWORD são trocados por um token bearer OIDC
(concessão de senha SSO READCOOP, cliente processing-api-client) e atualizados
automaticamente. TRANSKRIBUS_SESSION_ID não se aplica a eles.
Duas substituições opcionais:
export TRANSKRIBUS_ACCESS_TOKEN=your-bearer-token # skip the token exchange entirely
export TRANSKRIBUS_PROCESSING_CLIENT_ID=custom-client # non-default OIDC client
Pontos de Entrada
| Comando | Domínios | Ferramentas |
|---|---|---|
transkribus-mcp-server | Todos os 23 domínios | 304 |
transkribus-mcp-collections | Auth, Coleções (core/docs/pages/users/crowd/editdecl/credits/stats/labels/activity/tags) | 131 |
transkribus-mcp-admin | Auth, Admin, Créditos, Uploads, Rótulos, Arquivos, Sistema, Raiz | 62 |
transkribus-mcp-transcription | Auth, Reconhecimento, Análise de Layout, PyLaia, P2PaLA, DU | 47 |
transkribus-mcp-users | Auth, Usuários, Crowdsourcing, eLearning | 29 |
transkribus-mcp-models | Auth, Modelos | 26 |
transkribus-mcp-jobs | Auth, Trabalhos, Ações | 19 |
transkribus-mcp-search | Auth, Busca, KWS | 16 |
transkribus-mcp-processing | Processamento (Metagrapho) — sem ferramentas de autenticação legadas | 4 |
Use servidores divididos para reduzir o tamanho do contexto — escolha apenas as divisões que você precisa.
Enviando um documento
Para ingerir um documento, use este fluxo de três etapas:
transkribus_upload_create_structure— forneçacollId, umtitlee um arraypagesde{ fileName, pageNr }(uma entrada por imagem de página que você está prestes a enviar). Retorna um upload com umuploadId.transkribus_upload_page— chame uma vez por página com ouploadIde oimagePath(um caminho para um arquivo de imagem local), opcionalmentepageXmlPathpara uma transcrição PAGE XML existente.transkribus_upload_get_status— consulte com ouploadIdaté que o documento apareça na coleção.
Essas ferramentas de upload vêm no transkribus-mcp-server completo e na divisão transkribus-mcp-admin
— não no transkribus-mcp-collections. A ingestão de PDF não é suportada; converta o PDF em
imagens de página primeiro e use o fluxo acima.
Claude Code
Adicione ao ~/.claude/settings.json. Com as credenciais no chaveiro do sistema operacional sob
o nome de serviço padrão (recomendado), nenhuma chave env é necessária:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"]
}
}
}
Ou use servidores divididos (escolha as divisões que você precisa):
{
"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"]
}
}
}
Duas contas do Transkribus ao mesmo tempo — uma instância por conta, cada uma apontada para seu próprio nome de serviço do chaveiro:
{
"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" }
}
}
}
Sem um chaveiro, passe as credenciais em env em vez disso:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": {
"TRANSKRIBUS_USER": "your-email@example.com",
"TRANSKRIBUS_PASSWORD": "your-password"
}
}
}
}
Claude Desktop
Adicione ao claude_desktop_config.json. Com as credenciais no chaveiro do sistema operacional
(recomendado — assume o nome de serviço padrão transkribus-mcp):
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"]
}
}
}
Sem um chaveiro:
{
"mcpServers": {
"transkribus": {
"command": "npx",
"args": ["-y", "@lazyants/transkribus-mcp-server"],
"env": {
"TRANSKRIBUS_USER": "your-email@example.com",
"TRANSKRIBUS_PASSWORD": "your-password"
}
}
}
}
Segurança
- Use o chaveiro do sistema operacional para manter sua senha fora de arquivos de configuração e do histórico do shell completamente (veja Configuração)
- Nunca envie suas credenciais para o controle de versão
- IDs de sessão expiram — prefira um nome de usuário e senha para configurações de longo prazo; um ID de sessão sozinho não pode ser renovado após um 401
Aviso Legal
Este é um servidor MCP não oficial para o Transkribus. Os autores não são afiliados à READ-COOP SCE. Use por sua conta e risco.
Lançamento
Os lançamentos são enviados via evento GitHub Release. Fluxo do mantenedor:
-
Aumente a versão em
package.json,package-lock.jsoneserver.json(npm version <x.y.z> --no-git-tag-versionatualiza os dois primeiros juntos).npm run check-versionsfalha de forma rígida a menos quepackage.json#/versioneserver.json#/packages[0].versionconcordem.server.json#/versioné verificado de forma flexível: deve estar presente e só falha quando regride abaixo depackages[0].version— um valor deixado no lançamento anterior passa com uma linhaWARN:e saída 0. O script não olha parapackage-lock.jsonouCHANGELOG.mdde forma alguma, então leia sua saída em vez de confiar no código de saída. -
Atualize
CHANGELOG.md. -
Faça o commit e mescle o aumento de versão em
mainantes de criar o lançamento. Então crie a tag você mesmo, em um SHA que você verificou, e só então crie o lançamento a partir dela: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"A falha que isso evita: sem uma tag existente,
gh release create vX.Y.Zcoloca uma na ponta do branch padrão. Execute-o enquanto o aumento ainda está em um branch de lançamento e ele marca o commit do lançamento anterior; o fluxo de trabalho então publica qualquer versão que encontrar nopackage.jsondesse commit, produzindo um GitHub ReleasevX.Y.Zque silenciosamente republica a versão antiga. O fluxo de trabalho de publicação agora se recusa a continuar quandoGITHUB_REF_NAMEnão év<package.json version>, então esse cenário exato falha antes denpm publishem vez de republicar silenciosamente. A sequência acima ainda é necessária e protege um caso que o fluxo de trabalho não pode: a proteção do fluxo de trabalho só é executada quando um lançamento já existe, e passa para qualquer commit que carregue a versão correta — então ela detecta um lançamento com tag incorreta, não o commit errado sendo marcado.Cada elemento é essencial:
-
gh pr view … .mergeCommit.oidnomeia o commit de squash do próprio PR de lançamento. Não substitua porgit rev-parse origin/main: isso é meramente o que estiver emmainno momento em que você olha, então um merge não relacionado que chegar nesse intervalo será marcado e publicado em seu lugar.ghsai com código 0 e não imprime nada para um PR não mesclado, daí otest -nexplícito.- A cadeia
&¶ na primeira falha em vez de cair na etapa irreversível. Ambas as chamadasgit showsão atribuídas a uma variável em vez de serem canalizadas diretamente, então seu status de saída é realmente verificado — um pipeline reporta apenas o status do último comando, a menos quepipefailesteja definido, o que não é assumido aqui. git merge-base --is-ancestorprova que o commit é alcançável a partir demain. A mera existência não é suficiente: um commit pode estar presente localmente porque outro branch foi buscado, e se seus arquivos de versão coincidirem, ele passaria em todas as verificações restantes.- O teste de versão lê
package.jsondo commit alvo, não da árvore de trabalho — que ainda mostraria a versão correta enquanto$SHAapontasse para outro lugar. - O
awkextrai a seção dessa versão doCHANGELOG.mddo commit para--notes-file. Sem ele, o corpo do lançamento é o que--notes-from-tagencontrar na anotação — aqui a string literalvX.Y.Z, uma nota de lançamento ruim para qualquer versão e enganosa para um lançamento com mudança que quebra compatibilidade. Ele para no próximo cabeçalho## [ou na primeira definição de referência de link, porque a entrada mais antiga não tem cabeçalho depois dela e, de outra forma, engoliria todo o bloco de referências de link.grep -qem vez detest -sprotege o resultado: uma seção vazia exceto por sua linha em branco ainda produz um arquivo de um byte, quetest -saceita. --verify-tagfazghabortar em vez de inventar uma tag se o push não ocorreu — a proteção contra o fallback de ponta do branch padrão descrito acima.
Se
gh release createfalhar depois que a tag já foi enviada, não execute novamente o bloco inteiro; ele parará emgit tag, o que está correto. Execute novamente apenas o comando final. - A cadeia
- O workflow
Publish to npm + MCP Registryroda automaticamente: elenpm publishcom proveniência, consulta o registro até o tarball estar disponível, então envia aserver.jsoncorrespondente para o MCP Registry viamcp-publisher.
O workflow pula npm publish limpo se a versão já estiver no npm (proteção de transição para lançamentos parcialmente publicados manualmente).
Autenticação npm
A publicação usa npm Trusted Publishing: o token OIDC do GitHub do workflow (id-token: write) é trocado por um token de publicação de uso único em tempo de execução. Nenhum segredo NPM_TOKEN precisa existir no repositório.
A vinculação é configurada na interface web do npm (pacote → Trusted Publishers): provedor GitHub Actions, organização lazyants, repositório transkribus-mcp-server, workflow publish-registry.yml.
Licença
FSL-1.1-MIT — veja LICENSE para os termos completos. Versões 1.x permanecem licenciadas sob MIT.