ioda-outages-mcp-server
Provides access to country-level Google Transparency Report traffic numeric series through IODA outage signal tools, enabling comparison of a country's traffic against its own history.
Public Hosted Server: https://ioda-outages.caseyjhand.com/mcp
Overview
Internet outage evidence from IODA, using its public v2 API. Resolve countries, regions, and autonomous systems; inspect recent detections and measurement coverage; then investigate events, alert transitions, per-entity outage rankings, and numeric signals. Runs over stdio, stateless Streamable HTTP, or the public hosted endpoint above, without an API key.
Tools
Tool | Description |
| Resolve country, region, ASN, or geoasn names and codes |
| Inspect recent detection evidence and coverage across three numeric sources |
| Retrieve overlapping outage events for an entity or globally |
| Rank the entities of one type by IODA's per-window outage score |
| Fetch BGP, active IPv4 /24 probing, Merit telescope, or country-level Google Transparency Report traffic numeric series |
| Retrieve detection and recovery transitions with source baselines |
Skills
Skill | Description |
| Investigate Internet outages with the |
Related MCP server: PeerGlass
Capability reference
ioda_search_entities tool
Required
entityType: country | region | asn | geoasn(a geoasn is one ASN within a region or country); choosequery(up to 200 UTF-16 code units after trimming, matched literally as a case-insensitive name substring) orentityCode, or omit both to list the type. Country codes use two letters, regions use IODA numeric codes, ASNs use decimal digits, and geoasns join an ASN and a region or country code (40934-576,59962-IR).Optional
relatedToTypeandrelatedToCodelistentityTypeentities within one country, region, ASN, or geoasn; both or neither,entityTyperequired, noentityCode, and a scope combines withquery. Page this resolver to select codes for individual outage investigations.limitis at least 1, default 20, served at most 1,000;pagestarts at 0. Returns originalentities,pagination, andprovenance; a metadata match does not establish measurement coverage. Region pages can include IODA geolocation catch-alls named[Invalid Region (N)]orUnknown Region in <country>; a notice names their codes, and the rows stay as IODA returns them. AnasnentityCodeIODA holds no record of returns a placeholder row withattrs.ip_count"0"; a notice names it.
ioda_get_status tool
Required
entityType(country,region,asn, orgeoasn) andentityCode;lookbackHoursis at least 1, default 6, served at most 24 with a notice naming the uncovered earlier window. Collects events, alerts, andbgp,ping-slash24, andmerit-ntsummaries within the returnedwindow.detectionisobserved,none_returned, orunknown; sourcecoverageis independentlyrecent,stale,no_data, orunknown.recentmeans the latest completed observation ended within a 1,800-second publication allowance of the call, the same for all three sources, a server policy rather than an upstream SLA. Trailing nulls inside the allowance count aspendingCount, notnullCount.Each
signalsentry carries IODA'sunitfor its source (Visible /24s,Up /24s,Unique Source IPs);latest,minimum, andmaximumare in that unit.componentsdisclose partial failures and standalone-tool recovery. Event/alert pages carry continuation metadata; raw samples come fromioda_get_signals. All-component failure fails the call; an unknown country, region, or geoasn code fails withentity_not_found. IODA answers an unknownasncode with a placeholder instead; when no event, alert, or series came back for anasn, a notice says a returnedioda_search_entitiesrow does not confirm IODA holds data for it.
ioda_find_outages tool
Required
fromanduntil; optionalentityType(country,region,asn, orgeoasn),entityCode, andsource: bgp | ping-slash24 | merit-nt | gtr. Omit entity filters for global scope; a code requires its type. OptionalrelatedToTypeandrelatedToCodelimit results toentityTypeentities within one country, region, ASN, or geoasn (both or neither,entityTyperequired, noentityCode).limitis at least 1, default 20, served at most 1,000.Returns source
events,pagination, andprovenance. Scores retain their source meaning; starts may precede the window and an end clipped atuntildoes not establish recovery.includeAlertsdefaults to false;extendWindowSecondsis at least 0, served at most 1,209,600. Omitted, it is 1,209,600 withentityTypeand 86,400 without it, because large global extensions can time out; the applied value is echoed, and a notice discloses the global default. Global searches over multi-day windows can still time out: narrow the window or addentityType. Zero extension can miss long-running detections.
ioda_summarize_outages tool
Required
entityType,from, anduntil; optionalentityCodefor one entity, orrelatedToTypeandrelatedToCodeto rankentityTypeentities within one country, region, ASN, or geoasn (both or neither, noentityCode).limitis at least 1, default 20, served at most 1,000;extendWindowSecondsis at least 0, default 1,209,600, served at most 1,209,600. There is nosourceinput.Returns
summariesin IODA's order, descendingscores.overall, withpaginationandprovenance. Each row carries theentity,event_cnt(IODA's count of source events before merging), and unmodifiedscores:overallplus one sum of event scores per<source>.<method>key. IODA merges overlapping events from different sources, scores each merged event as the product of its sources' scores, and sums the merged events intooverall.Scores are window totals for ranking the rows of one request, not current status, and are not comparable across requests with different windows. Large type-only rankings (every region, for example) can time out; add
entityCodeor a related scope. Region rankings, like region events and alerts, can include the catch-all rows described above; a notice names their codes. An empty result is not an all-clear.
ioda_get_signals tool
Required entity pair (
entityTypemay begeoasn),from,until, andsource: bgp | ping-slash24 | merit-nt | gtr(gtrcovers countries only;ucsd-ntis not supported).maxPointsis at least 1, default 200, served at most 10,000: an upstream aggregation target, not a hard returned-sample cap.Returns every numeric subtype in
series, source-specificsemantics(measurement, IODA'sunit, caveat;gtrreadsTraffic, to compare a country with its own history), andprovenance. An unknown country, region, or geoasn code fails withentity_not_found. Returneduntilis an exclusive bucket bound; alignment can extend beyond requested bounds. Coarse series carry a notice: values need not equal an unweighted mean of finer returned buckets, and non-null aggregates cannot establish complete finer-resolution coverage. Values, nulls, and units remain unchanged; status coverage staysunknownfor coarse series.Trailing nulls are not zero connectivity. A notice counts each series' trailing nulls as not yet ended, pending (ended within the publication allowance before the call: 1,800 seconds for
bgpandping-slash24, 10,800 formerit-ntandgtr), or missing; the first two are usually unpublished, so end the window at least the allowance plus one bucket step before the call, since the last returned bucket can end afteruntil. A coarse last non-null bucket inside the allowance can aggregate only the samples published so far. Interior nulls stay missing observations.An empty
seriesgets a notice by case:gtrfor a region, ASN, or geoasn (it covers countries only); a window ending by the source's archive start, which says IODA holds nothing earlier instead of suggesting another code or window; a window starting inside the publication allowance, which IODA may not have published yet; anasn, where a returned search row does not confirm data andattrs.ip_count"0" marks IODA's placeholder.
ioda_get_alerts tool
Required
fromanduntil; optional entity, source, and related-scope filters matchioda_find_outages; a related scope is served at page 0 only, because IODA cannot continue scoped alerts.limitis at least 1, default 20, served at most 1,000;extendWindowSecondsis at least 0, default 0, served at most 1,209,600.Returns
alerts,pagination, andprovenance, retaining sourcelevel,condition,value, andhistoryValuewhen reported.valueandhistoryValueare in the source unit forbgp,ping-slash24, andmerit-nt; forgtrthey are IODA Traffic divided by 1,000,000 and truncated. A recovery'shistoryValuecan be a baseline IODA re-based during a long event; compare itsvaluewith the detection'shistoryValueandcondition. A missing transition does not establish health or rule out an event that began earlier.
ioda-outages-guide skill
Helps an agent investigate a shutdown or outage, check whether a place or network is degraded now, rank the worst-hit entities, and chart connectivity: where each IODA code comes from,
asnversusgeoasn, getting the clock from the server, publication lag, native signal resolution, and which conclusions the evidence supportsServed over MCP as the resource
skill://ioda-outages-guide/SKILL.mdunder the templateskill://{+path}; also ships inskills/for plugin installs and the.mcpbbundle
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
IODA-specific:
Keyless reads from a fixed HTTPS API origin; no local database or native helper.
Historical windows use integer Unix seconds UTC:
from < until <= now, at most 31 days. Alerts include transitions at both bounds (widened by extension); events and summaries include starts atuntil. Adjacent windows can duplicate boundary detections. Signal bounds describe aligned buckets; status echoes the requested window across components with different selection rules. IODA's API holds no outage detections before 2022-01-26 UTC and nomerit-nt,bgp, orping-slash24observations before 2022-01-09, 2022-01-18, and 2022-02-02 (gtrhas no start); an empty result for a window ending by then says so instead of suggesting another code or a wider window.ignoreMethods: string[]on events, alerts, and rankings excludes detections upstream before event construction and scoring:source.method,source.*, or*.method, with sourcesbgp,ping-slash24,merit-nt, andgtr. Case/whitespace normalize and duplicates collapse; an empty array excludes nothing. Malformed terms and*.*failinvalid_arguments; an explicitsourceplus its ownsource.*failsinvalid_ignore_methods. Keep exclusions fixed across pages and ranking drill-downs; provider scores and order are preserved.Every related-scope outage response warns that membership coverage is unverified, even on short or empty pages. Page
ioda_search_entitieswith the same entity type, scope, and limit, then query selected codes individually with the original window, source/exclusions, extension, and paging limit; each response supplies the concrete calls.pagination.moredescribes row pages, not scope completeness.Pagination is zero-based; follow
nextPagewith filters andlimitunchanged.more: "possible"signals possible continuation, not a known total; restart at page 0 after changing the limit.Numeric inputs have no advertised maximum: a larger
limit(cap 1,000),maxPoints(10,000),lookbackHours(24), orextendWindowSeconds(1,209,600) is served at the cap, and a notice names the requested value, the served value, and the route to the rest. Minimums and non-integers fail argument validation. WithIODA_CLAMP_LIMITS=false, each cap is the schema maximum and a larger value failsinvalid_arguments.Shared request pacing allows one in-flight request and at least two seconds between starts, with a 45-second invocation deadline. Avoid concurrent investigations.
IODA describes macroscopic connectivity. Missing detections are not an all-clear; source scores are not universal severity, and observations cannot establish a shutdown cause or one office's connectivity.
Agent-friendly output:
Provenance — endpoint links, fetch times, and the original Georgia Tech Research Corporation attribution accompany returned evidence;
appliedechoes effective inputs.Explicit uncertainty — null samples, missing fields, source coverage, and partial component failures stay distinct.
Complete responses —
content[]andstructuredContentcarry the same data, enrichment included, and a page is never shortened to fit a size budget. An upstream body over 4 MiB failsupstream_schema.
Getting started
Connect to the hosted instance, no install:
claude mcp add --transport http ioda-outages-mcp-server https://ioda-outages.caseyjhand.com/mcpOr run it locally:
claude mcp add ioda-outages-mcp-server -- npx -y @cyanheads/ioda-outages-mcp-serverFor other clients, add this to the MCP config file:
{
"mcpServers": {
"ioda-outages-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/ioda-outages-mcp-server"]
}
}
}IODA needs no API key or account, only outbound HTTPS to api.ioda.inetintel.cc.gatech.edu. For Docker or a source build, see Running the server.
Configuration
One server-specific variable, then the common framework variables:
Variable | Description | Default |
| Serve an over-cap |
|
| Transport: |
|
| HTTP bind address. |
|
| HTTP server port. |
|
| MCP endpoint path. |
|
| HTTP session mode: |
|
| Authentication: |
|
| Log level ( |
|
| Directory for log files (Node.js only). |
|
| Enable OpenTelemetry. |
|
See .env.example for the full list of framework overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
Clone and install:
git clone https://github.com/cyanheads/ioda-outages-mcp-server.git cd ioda-outages-mcp-server && bun install cp .env.example .env # optional: `IODA_CLAMP_LIMITS` and framework overridesBuild and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker run --rm -p 3010:3010 ghcr.io/cyanheads/ioda-outages-mcp-server:latestThe image defaults to HTTP transport, stateless session mode, and logs to /var/log/ioda-outages-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/ioda-outages-mcp-server:latest"]. To build locally, docker build -t ioda-outages-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
| Server identity, tool registration, published skill, service lifecycle |
|
|
| Six read-only tools |
| Server-specific environment configuration ( |
| Shared input normalization, served caps and notices, rendering |
| Fixed-origin API client, schemas, pacing, status assessment |
| Contract, service, and formatting tests |
| Domain contracts, design decisions, API evidence |
| Generated directory inventory |
Development guide
See CLAUDE.md for development guidelines and architectural rules, and docs/design.md for the domain contracts. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor logging,ctx.signalfor cancellation, andctx.enrichfor applied inputs and noticesRegister new tools in the
createApp()arrays insrc/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields, and keep both response surfaces complete
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0; see LICENSE. IODA data retains its Georgia Tech Research Corporation copyright and remains subject to the source's terms.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Read-only outage intelligence: live service status, report history, geography and spikes
IP geolocation, ASN and network data, plus VPN, proxy and Tor detection. ASN tools need no key.
Live internet status, security incidents, and dependency and GitHub repo checks. No key.
Signed internet telemetry, read-only: DNS, TLS, WHOIS, reachability. Every record Ed25519-signed.
Related MCP Servers
- AlicenseAqualityAmaintenanceThis server provides access to IBGE's public APIs, enabling AI assistants to query geographic, demographic, and statistical data from Brazil.23376 npm14MIT
- AlicenseAqualityDmaintenanceProvides global internet resource intelligence by querying RIRs for IP and ASN data, routing visibility, and network health. It enables users to perform RPKI validation, BGP inspection, and historical allocation analysis through natural language or a REST API.421MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying global disaster alerts from GDACS including earthquakes, tropical cyclones, floods, volcanoes, droughts, and wildfires. Supports listing events, getting details, and retrieving GeoJSON or RSS feeds.132 npmMIT
- AlicenseAqualityBmaintenanceThis server enables checking real-time service status and outage information from Downdetector for various services and regions.159 npm3MIT