Does a hotter year make antibiotic resistance worse across Europe? A causal panel built from four government data sources, a mandatory placebo test on every result, a live MCP server, and a CI pipeline built to catch its own next bug before a human has to.
Heat and antibiotic resistance are both rising, and it's tempting to link them: warmer years, more bacterial growth and horizontal gene transfer, more resistance. Raw correlations across countries and years will show you almost anything you want. What's missing is a test built to say no: a model that starts from the assumption there's nothing here, and makes the data work to overturn it.
This project builds that test for four major pathogen-antibiotic combinations across Europe, then does the harder thing: reports what it finds, including the parts of its own analysis that were wrong the first time.
Joined four government and research data sources (ECDC resistance surveillance, NASA weather reanalysis, EU antibiotic-consumption reporting, and a global health-index confounder) into a single country-year panel spanning 2000-2023, for four pathogen-antibiotic combinations.
Two-way fixed-effects regression, country and year, clustered standard errors. Every coefficient gets refit on 200 permuted datasets before it's allowed to be called significant. Not a footnote, a gate. A one-year-lag check runs alongside it, since resistance effects plausibly lag their trigger by a season.
The one finding that survived the placebo test was checked again against a completely different data source: gene-level resistance markers from sequenced bacterial isolates, pulled live via BigQuery, rather than the phenotypic lab measurements the main model uses.
Built on Anthropic's official MCP SDK, exposing live weather and live genomic-resistance data (not the frozen CSV) to any MCP-compatible client. Tested against a real external process, not just an in-process call.
Turned the placebo test from a step someone has to remember to run into a gate that refits every model, checks the permutation shuffle itself isn't broken, and flags drift from a stored baseline, wired to run on every push.
A causal claim is only as trustworthy as the QA process that tried to break it. Two bugs shipped in an earlier draft of this analysis before independent review caught them. Both are documented here rather than quietly fixed and forgotten.
An earlier version selected the antibiotic-consumption confounder column by position, not name. It picked a country label instead of the actual consumption figure: a bug with no error message, because the wrong column got silently absorbed into the model's own fixed effects instead of crashing. Every "consumption-adjusted" result in that draft was never adjusted for consumption. Full debug log →
An independent testing pass found that the consumption-adjusted model had skipped the mandatory 200-permutation check entirely, the exact safeguard the rest of the project treats as non-negotiable. Caught and closed before any result relying on it was reported.
ECDC's resistance-data export looks manual-UI-only but is scriptable once you notice its download-token parameter isn't validated server-side. Harvard Dataverse's API, separately, 403s the default Python HTTP client's user-agent string with no documentation saying so. Both found by testing directly against the live services, not by trusting their docs.
The one combination that shows a real effect has resistance rates sitting exactly at zero for roughly a fifth of its rows, a shape a linear model isn't built for. The finding's direction and significance are corroborated by two independent checks, but its exact magnitude is flagged as provisional rather than reported with false precision.
Across the full 2000-2023 panel, no pathogen-antibiotic combination shows a statistically significant weather effect. Every parametric p-value sits well above 0.05 before the placebo test is even run.
K. pneumoniae/carbapenem resistance, in a 2010-2022 subsample: a real, leave-one-country-out-stable effect, directionally confirmed by independent genomic data. It does not appear in the full panel, and the confounder meant to explain it isn't itself significant.
Read plainly: three of four combinations show nothing, anywhere, at any lag. The fourth shows something real but narrow: a pattern specific to one sample window, corroborated by an independent data source, not a confirmed climate-drives-resistance mechanism. That's the honest headline, and it's the one the write-up leads with.
This project pairs two things a deployed engineering role needs: production infrastructure (a live MCP server, a CI-gated model pipeline that catches its own regressions) and the discipline to report a mostly-null result instead of the more exciting one, including the two bugs that shipped before independent review caught them.
Building the pipeline is the easy half. Trusting it enough to publish what it says, bugs and all, is the harder one, and the one a customer-facing engineering role holds every delivered result to.