DATASUS SIH/SUS — Brazil Hospital Admissions (AIH) MCP

sih-br-mcp, microdatasus e PySUS: a mesma pergunta sobre internações do SIH/SUS por três caminhos

Internações por pneumonia de moradores do Espírito Santo em 2024, respondidas pelo microdado do DATASUS com microdatasus (R) e PySUS (Python) e pelo sih-br-mcp no assistente de IA: o mesmo total, quanto custa cada caminho e onde cada um serve. Medido em 02/11/2026.

Medido em 2 de novembro de 2026: sih-br-mcp 1.8.1 no endpoint público, microdatasus 3.0.0 com R 4.6.1 no Windows, PySUS 2.11.7 com Python 3.13 no Linux, numa conexão residencial no Brasil. Os scripts estão em scripts/comparativo/; nada aqui é ilustrativo.

Quem trabalha com internações hospitalares do SUS (SIH/SUS, as AIH publicadas pelo DATASUS) costuma chegar ao dado por dois pacotes: o microdatasus, em R, e o PySUS, em Python. Os dois baixam e decodificam o microdado do FTP do DATASUS. O sih-br-mcp fica uma camada acima: responde a pergunta agregada dentro do assistente de IA (Claude, ChatGPT ou qualquer cliente MCP), a partir de cubos pré-agregados, com a proveniência em toda resposta. Esta página faz a mesma pergunta pelos três caminhos.

A pergunta

"Quantas internações por pneumonia (CID-10 J12–J18) tiveram os moradores do Espírito Santo em 2024, e quantos óbitos?"

Ela parece pedir um arquivo. Pede 432. O DATASUS publica um arquivo por UF do hospital e por competência (o mês de faturamento), e a pergunta é por UF de residência e por data de internação. Quem mora no ES e foi internado em Minas está no arquivo de MG; quem internou em dezembro de 2024 pode ter sido faturado em março de 2025. Por isso: 27 UFs × 16 competências (2024-01 a 2025-04) = 432 arquivos, 1.358 MiB de .dbc, 18.863.265 registros. Lendo só o arquivo do ES (16 arquivos, 30 MiB) saem 13.097 internações: faltam 208, de moradores do ES internados em MG, no RJ e em outras UFs.

Os três caminhos, lado a lado

InternaçõesÓbitosO que baixouTempo
sih-br-mcp 1.8.113.3051.250resposta de 21 KB0,9 s
microdatasus 3.0.013.3051.250432 arquivos, 1.358 MiB40,6 min
PySUS 2.11.7, group="RD"9.135760345 de 432 arquivos59,4 min*

* No Linux do WSL, lendo e gravando no disco do Windows: não compare com o tempo do microdatasus.

O microdatasus e o sih-br-mcp chegam ao mesmo número, grupo a grupo (J12 461, J13 37, J14 1, J15 3.648, J16 265, J17 100, J18 8.793). Não é coincidência: os cubos do sih saem do espelho Parquet 1:1 dos mesmos .dbc, lendo a mesma janela de competências. A diferença é onde o trabalho acontece: no microdado, no seu computador, a cada pergunta; no sih, uma vez, na construção dos cubos.

microdatasus (R)

library(microdatasus)
library(dplyr)

ufs   <- c("AC", "AL", "AM", "AP", "BA", "CE", "DF", "ES", "GO", "MA", "MG", "MS", "MT", "PA",
         "PB", "PE", "PI", "PR", "RJ", "RN", "RO", "RR", "RS", "SC", "SE", "SP", "TO")
comps <- seq(as.Date("2024-01-01"), as.Date("2025-04-01"), by = "month")

pneu <- list()
for (d in as.list(comps)) for (uf in ufs) {
  y <- as.integer(format(d, "%Y")); m <- as.integer(format(d, "%m"))
  rd <- fetch_datasus(year_start = y, month_start = m, year_end = y, month_end = m,
                      uf = uf, information_system = "SIH-RD",
                      vars = c("MUNIC_RES", "DT_INTER", "DIAG_PRINC", "MORTE"))
  pneu[[length(pneu) + 1]] <- rd |>
    filter(substr(MUNIC_RES, 1, 2) == "32",                     # mora no ES
           substr(DT_INTER, 1, 4) == "2024",                    # internou em 2024
           substr(DIAG_PRINC, 1, 3) %in% sprintf("J%02d", 12:18))
}
bind_rows(pneu) |> summarise(internacoes = n(), obitos = sum(MORTE == "1"))
#>   internacoes obitos
#> 1       13305   1250

PySUS (Python)

import pandas as pd
import pysus

ufs = "AC AL AM AP BA CE DF ES GO MA MG MS MT PA PB PE PI PR RJ RN RO RR RS SC SE SP TO".split()
comps = [(2024, m) for m in range(1, 13)] + [(2025, m) for m in range(1, 5)]
pneumonia = {f"J{n}" for n in range(12, 19)}

partes = []
for y, m in comps:
    for uf in ufs:
        rd = pysus.ftp.sih(state=uf, year=y, month=m, group="RD", as_dataframe=True)
        if rd.empty:
            continue
        partes.append(rd[rd["MUNIC_RES"].str[:2].eq("32")
                         & rd["DT_INTER"].str[:4].eq("2024")
                         & rd["DIAG_PRINC"].str[:3].isin(pneumonia)])
pneu = pd.concat(partes)
len(pneu)
#> 9135      # ver a seção sobre o PySUS 2.11.7

sih-br-mcp (no assistente)

A pergunta vai em linguagem comum; o assistente escolhe a ferramenta e lê a resposta, que traz a safra e a citação:

get_hospitalizations {
  "uf": ["ES"], "year": [2024], "cid_chapter": [10], "group_by": ["cid_group"]
}
# J12 461 · J13 37 · J14 1 · J15 3.648 · J16 265 · J17 100 · J18 8.793
# soma J12–J18: 13.305 internações, 1.250 óbitos
# provenance: competências 2024-01 a 2025-04, 27 UFs de arquivo, safra do espelho, citação

Uma nota sobre o PySUS 2.11.7

Com group="RD", a chamada acima devolveu 9.135 internações, não 13.305. A causa está no catálogo que o PySUS 2.11.7 consulta antes de baixar: dos 10.946 arquivos RD do SIH, 4.526 estão sem grupo, e a consulta por grupo não os enxerga — sem erro e sem aviso. Na janela desta pergunta são 87 dos 432 arquivos (entre eles 7 dos 16 meses do próprio ES), com 4.170 das pneumonias. Chamando sem group, esses arquivos aparecem (junto com os de outros grupos, ER, RJ e SP, que é preciso descartar). No Windows há um segundo defeito: o filtro de caminho não reconhece a barra invertida, e as chamadas do SIH devolveram uma tabela vazia. É o tipo de coisa que se conserta numa tarde depois de relatada; até lá, confira a contagem de arquivos que voltaram.

Volume, em números

Tamanho
Microdado bruto SIH-RD, 1992–2026, no espelho23,86 GiB, 11.211 arquivos, 432.173.746 registros
Tudo o que o canal de cubos publica (cubos, pré-agregados, população, tabelas)1,63 GiB
A pergunta desta página432 arquivos e 1.358 MiB pelo microdado; 21 KB pelo sih
Internações, dias, gasto e óbitos por ano, 1992–2025420.107.114 internações numa chamada de menos de 1 s

O que o sih-br-mcp não faz

Para tudo isso, o caminho é o microdatasus ou o PySUS.

Qual usar

sih-br-mcp, microdatasus and PySUS: one SIH/SUS hospital admissions question, three ways

Measured on 2 November 2026: sih-br-mcp 1.8.1 on the public endpoint, microdatasus 3.0.0 with R 4.6.1 on Windows, PySUS 2.11.7 with Python 3.13 on Linux, over a residential connection in Brazil. The scripts are in scripts/comparativo/ of the repository.

Brazilian hospital admission data (SIH/SUS, the AIH records published by DATASUS) is usually reached through microdatasus (R) or PySUS (Python), which download and decode the raw microdata. sih-br-mcp sits one layer up: it answers the aggregate question inside an AI assistant, from pre-built cubes, with provenance in every answer.

The question — pneumonia admissions (ICD-10 J12–J18) of Espírito Santo residents, by admission date in 2024 — needs 432 DATASUS files: one per hospital state and billing month, 27 states × 16 months, 1,358 MiB of .dbc, 18,863,265 records. Reading only Espírito Santo's own files gives 13,097, missing the 208 residents admitted in other states.

AdmissionsDeathsDownloadedTime
sih-br-mcp 1.8.113,3051,25021 KB response0.9 s
microdatasus 3.0.013,3051,250432 files, 1,358 MiB40.6 min
PySUS 2.11.7, group="RD"9,135760345 of 432 files59.4 min*

* On Linux under WSL, reading and writing the Windows disk: not comparable with microdatasus's time.

microdatasus and sih-br-mcp agree to the unit, group by group: the cubes are built from a 1:1 Parquet mirror of the same .dbc files, over the same billing-month window. PySUS 2.11.7 returned fewer admissions because 4,526 of the 10,946 SIH RD files in its catalog carry no group, and a group="RD" query silently skips them (87 of the 432 files here); calling without group reaches them. On Windows, a path-separator check made the SIH calls return an empty table.

Which one. Aggregate question, auditable answer, inside the assistant: sih-br-mcp. Record-level data, variables the cubes do not carry (procedure, facility, secondary diagnosis) or other DATASUS systems (SIM, SINASC, SIA, SINAN): microdatasus or PySUS. To check sih-br-mcp, redo the count from the microdata, as this page did; a difference is a bug.