Skip to main content
Glama

anvisa-mcp

Servidor MCP que expõe duas consultas à base de dados abertos da Anvisa a um LLM: status de registro de medicamentos e busca de dispositivos médicos recentes, com uma tentativa de classificar quais deles usam IA. Roda local, contra um LLM que você mesmo hospeda.

⚠️ Não é fonte oficial

  • Não substitui a consulta ao portal da Anvisa. Os dados vêm dos arquivos abertos publicados pela agência e podem estar defasados em relação ao sistema oficial.

  • A classificação de uso de IA é heurística, feita por um LLM lendo texto livre. A Anvisa não publica campo estruturado sobre isso. Cada resposta traz confiança e justificativa justamente porque o veredito pode estar errado.

  • Não houve validação clínica ou regulatória deste software. Ele não foi avaliado por nenhum órgão e não é um dispositivo médico.

  • Para qualquer decisão regulatória, use o registro oficial no portal da Anvisa.

Requisitos

O quê

Versão

Para quê

Python

3.12+

runtime

uv

recente

dependências e venv

Um LLM local com API OpenAI-compatible

classificar dispositivos (llama.cpp, Ollama, LM Studio)

Espaço em disco

~500 MB

base DuckDB (~42 MB) + dependências

Não é preciso servidor de banco: o DuckDB é um arquivo.

Related MCP server: OpenFDA FastMCP Server

Instalação

git clone https://github.com/fabianofilho/anvisa-mcp.git
cd anvisa-mcp
uv sync
cp .env.example .env

Configuração

Edite o .env com o endereço do seu LLM:

Variável

Padrão

Observação

QWEN_ENDPOINT

http://127.0.0.1:8080/v1

llama.cpp. Ollama: :11434/v1. LM Studio: :1234/v1

QWEN_MODEL

local-model

llama.cpp e LM Studio aceitam qualquer nome; o Ollama exige o exato

DUCKDB_PATH

./data/anvisa.duckdb

onde a base local fica

SYNC_HORA_LOCAL

03:20

horário fixo do sync agendado

QWEN_TIMEOUT_SEGUNDOS

120

timeout por chamada ao LLM

Confirme que o LLM responde e baixe os dados:

uv run anvisa-cli llm     # deve imprimir a resposta do modelo
uv run anvisa-cli sync    # ~1 min: baixa os dois CSVs da Anvisa
uv run anvisa-cli schema  # contagens da base

O sync é idempotente: rode de novo quando quiser atualizar. A Anvisa republica os arquivos diariamente (D-1).

Ligando ao Claude Code

Troque /caminho/para/anvisa-mcp pelo caminho real do clone. Os caminhos precisam ser absolutos: o servidor é lançado de qualquer diretório, então ./data/anvisa.duckdb relativo não resolveria.

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

Uso

consultar_status_medicamento(nome_ou_principio_ativo: str)

Busca por nome comercial ou princípio ativo, ignorando acento e caixa. Devolve todos os registros que casam — grafias variam e a ambiguidade é de quem pergunta. Registros ativos vêm primeiro: dois terços da base são inativos.

{
  "termo_consultado": "dipirona",
  "fonte": "duckdb",
  "total": 20,
  "resultados": [
    {
      "numero_registro": "100430233",
      "nome_produto": "DIPBE",
      "principio_ativo": "dipirona",
      "empresa_detentora": "...",
      "situacao": "Ativo",
      "data_situacao": "2031-07-01",
      "categoria": "Similar"
    }
  ]
}

buscar_samd_recentes(dias=90, apenas_com_ia=True, apenas_software=True)

Dispositivos Classe III/IV registrados na janela, classificados quanto a uso de IA.

{
  "dias": 1825,
  "fonte": "duckdb",
  "total": 1,
  "indeterminados": 12,
  "resultados": [
    {
      "nome_produto": "CAD4TB",
      "classe_risco": "III",
      "classificacao": {
        "usa_ia": true,
        "confianca": 0.6,
        "justificativa": "O nome sugere CAD (Computer-Aided Diagnosis) e o fabricante é Delft AI.",
        "origem": "llm",
        "heuristica": true
      }
    }
  ]
}

A classificação fica cacheada no DuckDB: o mesmo registro não é reclassificado a cada chamada (13,4s na primeira vez, instantâneo depois).

Limitações conhecidas

O registro de dispositivos não tem campo de descrição. O texto que alimenta a classificação é nome técnico + nome comercial + fabricante. É pouco. Um produto cujo nome não diga o que ele faz será classificado com confiança baixa — e confiança baixa significa "não dá para saber", não "não usa IA". Por isso a resposta traz indeterminados.

apenas_software=True troca recall por custo. No último ano há 1.832 registros Classe III/IV e só 13 mencionam software. Sem esse pré-filtro por palavra-chave, uma varredura dos 60 registros mais recentes encontra zero software — são cânulas, parafusos e testes rápidos. Com ele, um produto que use IA sem dizer "software", "algoritmo" ou "CAD" fica de fora. Use apenas_software=False para varrer tudo, ao custo de uma chamada de LLM por registro.

A calibração de confiança do LLM é parcial. Modelos pequenos tendem a responder com confiança alta mesmo quando o texto não sustenta. O prompt fixa faixas de confiança por situação, o que melhorou bastante (reagentes saem com 0,9, nomes ambíguos com 0,2), mas não resolve por completo.

A base guarda o último estado visto, e não remove nada. O sync é upsert: um registro que a Anvisa tira da publicação continua na base com a situação da última vez que apareceu. Registro que sai da publicação costuma ter sido cancelado, então cada resultado traz visto_na_ultima_coleta, e a resposta ganha um aviso quando algum vier false. Aconteceu de verdade: entre 20 e 21/09/2026, 13 dispositivos sumiram do arquivo publicado.

anvisa-cli schema mostra a contagem, e o sync loga um aviso quando há registros assim.

Medicamentos sem número de registro não entram. O arquivo inclui produtos notificados (baixo risco), que não têm registro — e a pergunta "qual o status do registro" não se aplica a eles.

As URLs dos datasets podem mudar. Elas estão em data/sources.py, confirmadas em 20/09/2026 baixando os arquivos. Se uma sair do ar, o sync falha com mensagem explicando como reconfirmar, em vez de baixar o arquivo errado em silêncio.

O DuckDB aceita um escritor por vez. Durante o sync, as tools não conseguem ler e caem para dados de exemplo — mas o aviso diz que a base está ocupada, não vazia.

Privacidade

  • Sai da máquina: requisições HTTP para dados.anvisa.gov.br, para baixar os CSVs públicos. Nada mais.

  • Não sai: os termos que você consulta. A busca roda contra a base local.

  • O LLM é o seu: o texto dos registros vai para o endpoint que você configurou.

  • Sem telemetria, sem analytics, sem coleta de uso.

Contribuindo

Veja CONTRIBUTING.md. Em resumo: rode pytest, ruff e mypy antes do PR, e não rode sincronizações em loop contra os dados abertos da Anvisa.

Licença e atribuição

Apache License 2.0 — escolhida por tocar em regulação de dispositivo médico, onde a cláusula explícita de patente é mais protetiva.

Construído no contexto do IA.med.

Available Tools

2 tools
buscar_samd_recentesA

Lista dispositivos médicos Classe III/IV registrados recentemente na Anvisa.

Para cada registro, classifica se o produto usa IA ou aprendizado de máquina. A Anvisa não publica esse campo: a classificação é heurística, feita por um LLM local lendo o texto do registro, e cada item traz confiança e justificativa. Não apresente o veredito como fato regulatório.

Args: dias: tamanho da janela, em dias, a contar de hoje. apenas_com_ia: quando True, devolve só os classificados como usando IA. apenas_software: quando True, analisa só registros cujo texto sugere software. SaMD é raro no registro (13 de 1.832 registros Classe III/IV do último ano mencionam software), então sem esse filtro a busca gasta as chamadas de LLM em cânulas e parafusos. Desligue para varrer tudo, ao custo de ser lento.

ParametersJSON Schema
NameRequiredDescriptionDefault
diasNo
apenas_com_iaNo
apenas_softwareNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
diasYes
avisoNo
fonteYes'mock' = dado de exemplo, ainda não é registro real da Anvisa
totalYes
resultadosYes
apenas_com_iaYes
indeterminadosNoQuantos registros ficaram de fora por terem sido classificados como sem IA com confiança baixa — ou seja, o texto não permitiu decidir, o que não é o mesmo que não usar IA

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full responsibility and delivers thoroughly. It discloses the classification is heuristic, performed by a local LLM, and includes confidence and justification per item. It explicitly warns against presenting the verdict as regulatory fact, and notes the cost and speed implications of disabling the filter. This goes well beyond a simple read-only hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with a clear purpose statement, a behavioral note, and an Args section. It is slightly longer than minimal but every sentence adds value—no fluff. The key caveat about heuristic classification is front-loaded, and the filter explanation is concise yet informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, heuristic nature, cost trade-offs, and parameter semantics. It mentions output includes confidence and justification, and an output schema exists to define the full return format. Minor gaps like pagination or error handling are not addressed, but given the output schema and the richness of the description, it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must explain each parameter, and it does. The Args section clarifies 'dias' as a window from today, 'apenas_com_ia' as a filter, and 'apenas_software' with additional rationale about rarity and cost. Defaults are not restated, but the schema provides them; the description adds meaningful semantics beyond names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists Class III/IV medical devices recently registered with Anvisa and classifies each for AI/ML usage. The verb 'Lista' and resource 'dispositivos médicos Classe III/IV' are specific, and the added classification step is explicit. It clearly distinguishes itself from the sibling tool about medication status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides strong contextual guidance on when to use the 'apenas_software' filter, explaining the rarity of SaMD and the cost of LLM calls when not filtering. It implies the tool is for AI-related medical device discovery, though it doesn't explicitly contrast with the sibling tool (which is unrelated). The trade-off guidance for filters is a clear usage instruction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

consultar_status_medicamentoA

Consulta o status do registro de um medicamento na Anvisa.

Busca por nome comercial ou princípio ativo e devolve todos os registros que casam, com situação (válido, caducado, em análise), número de registro, data e empresa detentora. Quando a base local ainda não foi sincronizada, devolve dados de exemplo com fonte='mock' — nesse caso, não trate como informação regulatória.

Args: nome_ou_principio_ativo: nome comercial ou princípio ativo, ex.: "dipirona".

ParametersJSON Schema
NameRequiredDescriptionDefault
nome_ou_principio_ativoYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
avisoNo
fonteYes'mock' = dado de exemplo, ainda não é registro real da Anvisa
totalYes
resultadosYes
termo_consultadoYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses a critical behavioral trait: when the local base is not synchronized, it returns mock data with fonte='mock' and warns not to treat it as regulatory information. This is valuable context beyond the schema. It does not mention rate limits or auth, but for a read-only query tool, the mock-data disclosure is the most important behavior to surface.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the first sentence states the purpose, the second details the search behavior and output fields, and the third warns about mock data. Every sentence earns its place, and the parameter explanation is integrated naturally.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values are already structured. The description covers the key context: what it searches, what it returns, and the mock-data caveat. It could mention pagination or result limits, but for a single-parameter query tool, the description is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, so the description must compensate. It does: it explains the parameter 'nome_ou_principio_ativo' with an example ('dipirona') and clarifies that it accepts either a commercial name or active ingredient. This adds meaning beyond the bare schema definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('consulta'), a specific resource ('status do registro de um medicamento na Anvisa'), and the exact search dimensions (nome comercial ou princípio ativo). It clearly distinguishes the tool's function from the sibling 'buscar_samd_recentes', which is about recent SAMD records, not medication registration status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does and what it returns, and it implicitly differentiates from the sibling by focusing on medication registration status. It does not explicitly state when NOT to use it or name the sibling as an alternative, but the context is clear enough for an agent to select it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedbuscar_samd_recentes
    • First observedconsultar_status_medicamento

TDQS

A4.3/5.0

Scored across 2 tools

Disambiguation5/5

The two tools operate in completely separate domains: one retrieves recent Class III/IV medical devices with AI classification, the other queries drug registration status. There is no overlap or ambiguity between them.

Naming Consistency5/5

Both tool names follow the same verb_noun pattern in Portuguese: buscar_samd_recentes and consultar_status_medicamento. The naming is clean, descriptive, and consistent.

Tool Count3/5

With only two tools, the server feels thin for the broad regulatory scope of Anvisa. The count is borderline acceptable because each tool covers a distinct product category, but it leaves many common regulatory queries unaddressed.

Completeness2/5

The device tool only covers recent SaMD registrations with a heuristic AI filter, and the drug tool only checks registration status. There are significant gaps such as searching devices by name/number, retrieving full regulatory details, or covering other Anvisa-regulated product types.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers