Projeto IA.med Licença Apache-2.0 Conector ou local

anvisa-mcp

Servidor MCP para consulta regulatória da Anvisa: status de registro de medicamentos e dispositivos Classe III/IV recentes, com um veredito heurístico sobre uso de IA. Use pelo conector hospedado, sem instalar nada, ou rode na sua máquina contra um LLM que você hospeda.

O problema

Por que este projeto existe

Dado público, mas fragmentado

O registro sanitário no Brasil é público, porém espalhado em consultas separadas e pouco acessível de forma programática. Cruzar situação de registro, validade e empresa dá trabalho manual.

SaMD com IA não é um campo do registro

Software as a Medical Device que usa inteligência artificial não tem, no registro, um campo estruturado dizendo que usa IA. Saber quais dispositivos empregam IA hoje exige ler a documentação um a um.

Modelos de linguagem não têm essa ponte

Um modelo de linguagem não consegue, sozinho, consultar essas bases. Falta uma camada que exponha essas buscas como ferramentas que o modelo possa chamar, com a data da coleta em cada resposta.

Como funciona

Quatro camadas, do dado bruto ao agente

  1. 01

    Dados

    Os arquivos abertos de registro da Anvisa (medicamentos e dispositivos), baixados pelo sync. A Anvisa republica diariamente (D-1).

  2. 02

    Armazenamento

    Uma base DuckDB em arquivo (63 MB, lido em 12/10/2026). O sync é upsert: registro que sai da publicação fica marcado como não visto na última coleta.

  3. 03

    Classificação

    Um LLM local, compatível com a API da OpenAI, julga se um dispositivo usa IA. Quem grava os vereditos é a CLI; o servidor só lê.

  4. 04

    Ferramentas MCP

    Duas tools MCP, por stdio na sua máquina ou por HTTP no modo conector.

A classificação de SaMD com IA é heurística, gerada por um modelo de linguagem lendo nome técnico, nome comercial e fabricante (o registro não tem campo de descrição). Cada item traz confiança, justificativa e origem do veredito. Ajuda a triagem, mas não é fato regulatório e não substitui a consulta ao registro no portal da Anvisa.

As ferramentas

Duas tools MCP expostas ao modelo

O modelo chama estas funções durante a conversa. As assinaturas são as da v0.1.0, e os retornos são saídas reais de 24/09/2026 (o de SaMD, cortado num item). São anteriores à correção de 12/10/2026 (PR #4), que passou a devolver coletado_em com fuso. Toda resposta traz coletado_em e ganha aviso quando a última coleta passou de 48 horas.

consultar_status_medicamento

Busca por trecho do nome comercial ou do princípio ativo (sem precisar de acento) ou pelo número de registro, com ou sem pontos. Devolve situação (Ativo ou Inativo, como a Anvisa publica), vencimento do registro, empresa e categoria. Um princípio ativo comum casa com centenas de registros ("dipirona" dá 557): use total, não o tamanho da lista. Termo sem correspondência devolve lista vazia.

consultar_status_medicamento(
    termo: str,
    limite: int = 20,  # 1 a 200
) -> RespostaMedicamentos
{
  "termo_consultado": "1.1819.0006",
  "fonte": "duckdb",
  "coletado_em": "2026-09-24T03:22:04.857697",
  "total": 1,
  "retornados": 1,
  "truncado": false,
  "resultados": [
    {
      "numero_registro": "118190006",
      "nome_produto": "DELTALAB",
      "principio_ativo": "deltametrina",
      "empresa_detentora": "92265552000905 - MULTILAB INDUSTRIA E COMERCIO DE PRODUTOS FARMACEUTICOS LTDA",
      "situacao": "Ativo",
      "data_situacao": "2029-02-01",
      "categoria": "Similar",
      "visto_na_ultima_coleta": true
    }
  ],
  "aviso": null
}
Saída real, busca por número de registro

buscar_samd_recentes

Lista dispositivos Classe III/IV registrados na janela, cada um com um veredito heurístico sobre uso de IA: confiança, justificativa e origem (llm, cache, nao_classificado ou indisponivel). nao_classificado quer dizer "não se sabe", não "sem IA", e indeterminados conta esses casos. apenas_software filtra por palavra-chave e troca recall por custo.

buscar_samd_recentes(
    dias: int = 90,              # 1 a 3650
    apenas_com_ia: bool = True,
    apenas_software: bool = True,
    limite: int = 50,            # 1 a 200
) -> RespostaSaMD
{
  "dias": 3650,
  "apenas_com_ia": true,
  "fonte": "duckdb",
  "coletado_em": "2026-09-24T03:22:40.940760",
  "total": 310,
  "analisados": 200,
  "retornados": 1,
  "truncado": true,
  "indeterminados": 158,
  "resultados": [
    {
      "numero_registro": "80102513702",
      "nome_produto": "CAD4TB",
      "empresa_detentora": "VR MEDICAL IMPORTADORA E DISTRIBUIDORA DE PRODUTOS MÉDICOS LTDA",
      "classe_risco": "III",
      "situacao": "29/06/2036",
      "validade_registro": "2036-06-29",
      "data_registro": "2026-06-29",
      "visto_na_ultima_coleta": true,
      "classificacao": {
        "usa_ia": true,
        "confianca": 0.6,
        "justificativa": "O nome 'CAD4TB' sugere uso de CAD (Computer-Aided Diagnosis) para tuberculose, e o fabricante 'DELFT AI B.V.' indica forte probabilidade de uso de IA, mas a documentação fornecida é insuficiente para confirmar o funcionamento técnico.",
        "evidencia_confere": null,
        "origem": "cache",
        "heuristica": true
      }
    }
  ],
  "aviso": "A Anvisa não publica campo estruturado de uso de IA. A classificação abaixo é heurística (...)"
}
Trecho de saída real no conector (dias=3650, limite=200)

A base e os limites

O que há na base, e o que ele não diz

Números lidos da base real em 12/10/2026 (arquivo DuckDB de 63 MB), com 113 testes automatizados na suíte. Os dados são cópia de dado público, com a data da coleta em toda resposta. O LLM entra só na heurística de SaMD.

dispositivos_medicos

101.082

Registros de dispositivo publicados pela agência

medicamentos

32.798

Registros de medicamento

classificacoes_samd

370

Vereditos de SaMD que a coleta já gravou

Conferir a citação não pega erro de interpretação

A heurística de SaMD pode devolver uma citação real e contígua do registro e ainda assim classificar errado em cima dela.

A coluna de situação tem data vazando

Em dispositivos_medicos, o campo situacao traz "VIGENTE" em 83.971 linhas e datas como "29/06/2036" em outras (o exemplo de SaMD acima mostra um caso). Achado em 12/10/2026 e ainda não investigado: não se sabe se é a fonte ou o parser.

Um terço dos registros citados pelo TUSS não está aqui

Dos 560 registros de dispositivo que o TUSS cita, 368 constam desta base (lido em 12/10/2026). O motivo não está nos dados, então não conclua que foram cancelados.

Dois jeitos de usar

Pelo conector hospedado, ou na sua máquina

O mesmo servidor fala stdio (local) e streamable-http (conector). Em nenhum dos dois ele grava na base: quem escreve é a CLI.

Conector hospedado

Há uma instância pública, mantida pelo autor, para usar sem instalar nada. No Claude (web ou desktop): Configurações, Conectores, adicionar conector personalizado, e colar a URL abaixo.

https://debian-f.tailf42a96.ts.net/anvisa/mcp
URL do conector
claude mcp add --transport http anvisa https://debian-f.tailf42a96.ts.net/anvisa/mcp
No Claude Code

Antes de usar o conector

  • Dados públicos da Anvisa, sem garantia A base é montada a partir dos arquivos abertos da agência, uma vez por dia de madrugada. Cada resposta traz coletado_em. Não é fonte oficial e não substitui o portal da Anvisa.
  • Sem garantia de disponibilidade Roda numa máquina pessoal atrás do Tailscale Funnel. Pode sair do ar, reiniciar ou mudar de endereço sem aviso. Se você depende dele, rode o seu.
  • Sem autenticação, com limites 600 requisições por minuto por origem e 1.200 no total; acima disso, HTTP 429 por um minuto. limite vai de 1 a 200 nas duas tools e dias de 1 a 3650; fora da faixa, a chamada é recusada.
  • Somente leitura, sem LLM na hora O conector não classifica sob demanda: serve os vereditos que a coleta diária gravou, que cobrem os dispositivos dos últimos 10 anos que passam no filtro de software. O resto vem como nao_classificado.
  • O que você consulta passa por lá Os termos e parâmetros de cada chamada chegam ao servidor do autor. O código não registra os termos nem mantém log de acesso; só a origem de quem passa do limite de taxa.

stdio (local)

O cliente sobe o processo na sua máquina, contra a sua cópia da base (passo a passo abaixo). Nada fica exposto na rede, e os termos consultados não saem do seu computador. Com o LLM no ar, o que não está no cache é classificado na hora, sem ser gravado.

streamable-http (o seu conector)

Para hospedar a sua instância. O servidor escuta no loopback; expor é papel de um proxy reverso com TLS ou de um túnel. Ele não chama o LLM nem coleta: serve o cache que o sync publica. O tráfego do Claude chega dos IPs da Anthropic, então há um teto global e um por origem.

# expor a sua própria instância como conector HTTP (escuta só no loopback)
TRANSPORTE=streamable-http HTTP_HOST=127.0.0.1 HTTP_PORTA=8000 uv run anvisa-mcp

# atrás de túnel ou proxy com TLS, declare o nome público (senão responde 421)
HTTP_HOSTS_PUBLICOS=mcp.exemplo.ts.net

# a coleta roda fora do servidor e é o único momento em que o LLM entra
uv run anvisa-cli sync --publicar --classificar --dias-classificacao 3650

Como rodar

Instalação local

Se preferir não depender do conector hospedado, clone o repositório, aponte para o seu LLM (llama.cpp, Ollama ou LM Studio, com API compatível com a da OpenAI) e monte a sua base. O repositório não traz a base pronta.

# 1. clonar e instalar (Python 3.12+ e uv)
git clone https://github.com/fabianofilho/anvisa-mcp.git
cd anvisa-mcp
uv sync
cp .env.example .env   # QWEN_ENDPOINT e QWEN_MODEL do seu LLM local

# 2. conferir o LLM e baixar os dados da Anvisa
uv run anvisa-cli llm      # deve imprimir a resposta do modelo
uv run anvisa-cli sync     # ~1 min: baixa os dois CSVs
uv run anvisa-cli schema   # contagens da base

# 3. classificar os dispositivos e gravar os vereditos
uv run anvisa-cli classificar --dias 365
O sync é idempotente. Para rodar todo dia, use o timer systemd de deploy/ ou o agendador que preferir.
claude mcp add anvisa --scope user \
  -e DUCKDB_PATH=/caminho/para/anvisa-mcp/data/anvisa.duckdb \
  -e QWEN_ENDPOINT=http://127.0.0.1:8080/v1 \
  -e QWEN_MODEL=local-model \
  -- uv --directory /caminho/para/anvisa-mcp run anvisa-mcp
Ligando ao Claude Code. Os caminhos precisam ser absolutos.

classificar e sync --classificar saem com código 1 quando os vereditos não puderam ser gravados, em vez de dar a classificação por feita. Com um conector lendo a mesma base, use sempre --publicar: a CLI monta a base ao lado e troca por rename. --reclassificar refaz uma vez os vereditos gravados antes da checagem de evidência, inclusive os que estão fora da janela e do filtro de software.

No modo local, só saem da máquina as requisições a dados.anvisa.gov.br para baixar os CSVs públicos. Os termos consultados ficam na base local, e o texto dos registros vai só para o LLM que você configurou. Sem telemetria. Pelo conector hospedado, os termos de cada consulta chegam ao servidor do autor.