Servidor MCP de OCR de passaportes para agentes de IA

Dê a um assistente a capacidade de ler um passaporte, um documento de identidade ou um documento de viagem – e de receber campos estruturados, não um bloco de texto. O servidor fala Model Context Protocol de duas formas: via stdio, instalado pelo npm e iniciado pelo seu cliente como um comando, ou via Streamable HTTP, hospedado em mcp.doc.cheap. Nos dois casos, ele é um cliente enxuto da API HTTP pública: não guarda nenhum dado próprio.

npx -y @doc-cheap/mcp

Publicado como @doc-cheap/mcp no npm e como cheap.doc/mcp no registro oficial de MCP; o código-fonte está no espelho público no GitLab.

Listado em o registro oficial de MCP, Smithery, cursor.directory, npm.

O que o seu agente recebe

Esta é a diferença que importa. Uma ferramenta de OCR que devolve uma página de texto entrega ao modelo algo para interpretar de novo, e um modelo a quem se pede para interpretar uma data de novo acaba inventando uma. Esta ferramenta devolve os campos já separados:

  • O titular – nomes, sobrenome, data de nascimento, sexo, nacionalidade.
  • O documento – tipo, país, Estado emissor, número, série, data de emissão, data de validade, se está vencido e quantos dias faltam.
  • Cada campo encontrado, cada um com a sua própria confiança, lido separadamente da zona de leitura mecânica (MRZ) e da zona visual impressa – para que o modelo possa ver que as duas leituras concordam, em vez de supor isso.
  • A zona de leitura mecânica com um veredito: aprovada, reprovada ou ausente, com o motivo, e as próprias linhas.
  • Um resumo de uma linha que o assistente pode mostrar a você enquanto trabalha.

As falhas voltam como uma linha legível em um bloco de erro, nunca como um resultado vazio e silencioso: o assistente pode agir a partir dela e mostrá-la a você. Uma recusa da API mantém o texto da própria API, o código de erro dela e o link para a página que o explica.

Instale no seu cliente

Claude Desktop

claude_desktop_config.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Claude Code

um comando, a partir do diretório do projeto

claude mcp add-json doc-cheap '{"command":"npx","args":["-y","@doc-cheap/mcp"],"env":{"DOC_CHEAP_API_KEY":"sk_live_your_key"}}'

Cursor

~/.cursor/mcp.json, ou .cursor/mcp.json em um projeto

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

VS Code

.vscode/mcp.json – atenção: fica aninhado em servers, não em mcpServers

{
  "servers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "type": "stdio",
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Gemini CLI

~/.gemini/settings.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Windsurf

~/.codeium/windsurf/mcp_config.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Kiro

.kiro/settings/mcp.json no workspace, ou ~/.kiro/settings/mcp.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "disabled": false,
      "autoApprove": [
        "check_balance",
        "search_docs"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Kiro, com um clique

O link de instalação do próprio cliente. Ele pede confirmação e mostra o comando e a lista de argumentos antes de gravar qualquer coisa.

Adicionar ao Kiro

  • Reinicie o cliente depois de adicionar o bloco. O servidor é iniciado pelo cliente, então ele só pega uma configuração ou um ambiente alterados ao iniciar do zero.
  • Sem DOC_CHEAP_API_KEY, o servidor recorre à chave pública do sandbox: as leituras rodam dentro da cota gratuita dela e não há saldo para informar. É o jeito mais rápido de ver funcionando.
  • Configurações opcionais: DOC_CHEAP_DOCS_BASE (para onde os resultados de busca apontam), DOC_CHEAP_DOCS_DIR (qual cópia da documentação é pesquisada) e DOC_CHEAP_IMAGE_ROOT (veja as proteções abaixo).

Ou conecte-se ao servidor hospedado

As mesmas três ferramentas estão hospedadas em https://mcp.doc.cheap/mcp via Streamable HTTP, então um cliente que se conecta a uma URL não precisa instalar nada. Sem login: envie a sua chave como X-Doc-Cheap-Api-Key ou como Authorization: Bearer – se as duas forem enviadas, vale o cabeçalho com nome próprio – ou não envie nenhuma e a chave pública do sandbox será usada. O servidor hospedado não consegue ler arquivos da sua máquina, então recebe a imagem em base64 ou como uma URL https.

https://mcp.doc.cheap/mcp

Claude Code

um comando

claude mcp add --transport http doc-cheap https://mcp.doc.cheap/mcp --header "Authorization: Bearer sk_live_your_key"

Cursor

~/.cursor/mcp.json

{
  "mcpServers": {
    "doc-cheap": {
      "url": "https://mcp.doc.cheap/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_your_key"
      }
    }
  }
}

VS Code

.vscode/mcp.json

{
  "servers": {
    "doc-cheap": {
      "type": "http",
      "url": "https://mcp.doc.cheap/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_your_key"
      }
    }
  }
}

No Claude Desktop e no claude.ai, adicione em Settings, Connectors, como conector personalizado com a URL https://mcp.doc.cheap/mcp; sem chave, ele roda com a chave do sandbox.

As três ferramentas

As três ferramentas que o servidor MCP publica
FerramentaO que fazO que devolveComportamento que declara
scan_document Recognise a passport or ID documentReconhece a imagem de um documentoO resultado estruturado completo, mais o resumo de uma linhaNão é somente leitura – pode consumir um crédito. Não é destrutiva. É idempotente quando você envia uma chave de idempotência, e só nesse caso. Mundo aberto: a resposta vem de um serviço remoto.
check_balance Check remaining creditsLê o uso da contaO saldo e os contadores do período atualSomente leitura e mundo aberto: os números são a situação da conta em tempo real.
search_docs Search the doc.cheap API documentationPesquisa a documentaçãoAs seções correspondentes, com títulos, links e trechos – offlineSomente leitura e mundo fechado: o acervo é a cópia da documentação distribuída junto com o servidor, então a mesma consulta dá a mesma resposta sem rede nenhuma.
  • scan_document recebe a imagem como image_base64, image_path ou image_url, e as mesmas opções de uma chamada direta, entre elas expect_country, return_portrait, reference e idempotency_key.
  • search_docs lê uma cópia da documentação distribuída junto com o servidor, então responde sem rede nenhuma – o que significa que o agente pode consultar o vocabulário de campos ou um código de erro sem gastar uma chamada.
  • check_balance precisa de uma chave com uma conta por trás. Com a chave pública do sandbox, ela diz com clareza que não há saldo, em vez de responder com zeros que parecem uma leitura.
  • Cada ferramenta declara um esquema de saída e devolve conteúdo estruturado que o segue, então um agente pode usar os campos sem interpretar texto.
  • Cada página da documentação também é um recurso que o agente pode ler, e quatro prompts – ler um documento para JSON, conferir uma data de validade, ler um lote, explicar um código de erro – iniciam as tarefas comuns em um passo.

Quanto custa

$0.01 por documento reconhecido. Preço fixo, para toda conta, em qualquer volume – um único número, e nada para negociar. Um documento só é cobrado quando foi reconhecido: uma leitura que não encontra nada, não consegue ler a imagem ou não consegue identificar o tipo responde com o seu veredito e não custa nada. Cada resultado diz qual foi o caso, então o agente – e você – sempre sabem se aquela chamada gastou alguma coisa.

Antes de ter uma conta: a chave pública do sandbox executa 10 documentos reconhecidos grátis por endereço IP no total, com no máximo 10 requisições por hora, seja qual for a resposta, e o cadastro acrescenta 20 créditos. Um crédito é um centavo de dólar, que é um documento.

O reconhecimento leva cerca de 275 ms na mediana em produção, e cada resultado traz os seus próprios tempos, então um loop de agente pode planejar com base em um número real.

O que o servidor reporta

Por padrão, o servidor não envia relatório nenhum para lugar nenhum: o envio de falhas fica desligado a menos que você mesmo configure um destino, e sem ele a biblioteca de rastreamento nem chega a ser carregada.

Duas proteções que vale conhecer

O servidor roda na sua máquina com os seus privilégios, e os argumentos dele são escolhidos por um modelo. Por isso, dois deles têm cerca:

Arquivos locais ficam desligados até você abrir um diretório

image_path se recusa a fazer qualquer coisa até que DOC_CHEAP_IMAGE_ROOT indique um diretório, e diz ao assistente para enviar image_base64 no lugar. Com a variável definida, tanto o diretório quanto o arquivo pedido são resolvidos seguindo links simbólicos antes da verificação de contenção; um segmento .. e um link que aponta para fora são recusados, e um caminho relativo é tomado a partir desse diretório, e não de onde quer que o cliente tenha iniciado o processo. Um caminho fora da raiz e um caminho que não existe dão a mesma mensagem – uma mensagem diferente para cada caso responderia “este arquivo existe?” para qualquer caminho da sua máquina.

Imagens remotas precisam ser https públicas

image_url é baixada pelo servidor, então o esquema precisa ser https: e o host precisa resolver apenas para endereços públicos da internet: faixas de loopback, privadas, link-local, NAT de operadora (CGNAT), multicast e reservadas são recusadas, incluindo as formas mapeadas em IPv6. Uma única resposta não pública recusa a URL inteira. Redirecionamentos são seguidos manualmente, no máximo três saltos, e cada salto é verificado de novo. O corpo tem limite de 25 MB, contado à medida que chega, e não confiado a partir de um cabeçalho.

image_base64 não tem nenhuma dessas restrições, porque quem chama já tem os bytes – e é por isso que cada recusa acima aponta para ela.

Leia o guia