Investigate Internet outages with IODA events, alerts, and connectivity signals via MCP.
Investigate Internet outages with IODA events, alerts, and connectivity signals via MCP. STDIO or Streamable HTTP.
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 or stateless Streamable HTTP without an API key.
| Tool | Description |
|---|---|
ioda_search_entities | Resolve country, region, ASN, or geoasn names and codes |
ioda_get_status | Inspect recent detection evidence and coverage across three numeric sources |
ioda_find_outages | Retrieve overlapping outage events for an entity or globally |
ioda_summarize_outages | Rank the entities of one type by IODA's per-window outage score |
ioda_get_signals | Fetch BGP, active IPv4 /24 probing, or Merit telescope numeric series |
ioda_get_alerts | Retrieve detection and recovery transitions with source baselines |
ioda_search_entities toolentityType: country | region | asn | geoasn (a geoasn is one ASN within a region or country); choose query (up to 200 trimmed characters) or entityCode, 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).relatedToType and relatedToCode list entityType entities within one country, region, ASN, or geoasn, such as the regions or networks of a country; both or neither, entityType required, no entityCode, and a scope combines with query. A very large scope (thousands of networks in one country) can be incomplete; prefer region scopes there.limit is 1–1,000, default 20, served at most 100; page starts at 0. Returns original entities, pagination, and provenance; a metadata match does not establish measurement coverage.ioda_get_status toolentityType (country, region, asn, or geoasn) and entityCode; lookbackHours is 1–240, default 6, served at most 24 with a notice naming the uncovered earlier window. Collects events, alerts, and bgp, ping-slash24, and merit-nt summaries within the returned window.detection is observed, none_returned, or unknown; source coverage is independently recent, stale, no_data, or unknown. recent means 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 as pendingCount, not nullCount.signals entry carries IODA's unit for its source (Visible /24s, Up /24s, Unique Source IPs); latest, minimum, and maximum are in that unit.components disclose partial failures and standalone-tool recovery. Event/alert pages carry continuation metadata; raw samples come from ioda_get_signals. All-component failure fails the call; an unknown country, region, or geoasn code fails with entity_not_found.ioda_find_outages toolfrom and until; optional entityType (country, region, asn, or geoasn), entityCode, and source: bgp | ping-slash24 | merit-nt | gtr. Omit entity filters for global scope; a code requires its type. Optional relatedToType and relatedToCode limit results to entityType entities within one country, region, ASN, or geoasn (both or neither, entityType required, no entityCode). limit is 1–1,000, default 20, served at most 100.events, pagination, and provenance. Scores retain their source meaning; starts may precede the window and an end clipped at until does not establish recovery.includeAlerts defaults to false; extendWindowSeconds is 0–12,096,000, served at most 1,209,600. Omitted, it is 1,209,600 with entityType and 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 add entityType. Zero extension can miss long-running detections.ioda_summarize_outages toolentityType, from, and until; optional entityCode for one entity, or relatedToType and relatedToCode to rank entityType entities within one country, region, ASN, or geoasn (both or neither, no entityCode). limit is 1–1,000, default 20, served at most 100; extendWindowSeconds is 0–12,096,000, default 1,209,600, served at most 1,209,600. There is no source input.summaries in IODA's order, descending scores.overall, with pagination and provenance. Each row carries the entity, event_cnt (IODA's count of source events before merging), and unmodified scores: overall plus 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 into overall.entityCode or a related scope. An empty result is not an all-clear.ioda_get_signals toolentityType may be geoasn), from, until, and source: bgp | ping-slash24 | merit-nt (gtr and ucsd-nt are not numeric sources here). maxPoints is 1–20,000, default 200, served at most 2,000: an upstream aggregation target, not a hard returned-sample cap.series, source-specific semantics (measurement, IODA's unit, caveat), and provenance. An unknown country, region, or geoasn code fails with entity_not_found. from, until, step, nativeStep, and nulls preserve aligned bucket boundaries and missing observations; smaller targets lose temporal resolution.ioda_get_alerts toolfrom and until; optional entity, source, and related-scope filters match ioda_find_outages; a related scope is served at page 0 only, because IODA cannot continue scoped alerts. limit is 1–1,000, default 20, served at most 100; extendWindowSeconds is 0–12,096,000, default 0, served at most 1,209,600.alerts, pagination, and provenance, retaining source level, condition, value, and historyValue when reported. value and historyValue are in the source unit for bgp, ping-slash24, and merit-nt; for gtr they are IODA Traffic divided by 1,000,000 and truncated. A missing transition does not establish health or rule out an event that began earlier.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:
from < until <= now, at most 31 days. Split longer investigations into adjacent windows.nextPage with filters and limit unchanged. more: "possible" signals possible continuation, not a known total; restart at page 0 after changing the limit.limit 100, maxPoints 2,000, lookbackHours 24, extendWindowSeconds 1,209,600); a larger value is served at the cap and a notice names the requested value, the served value, and the route to the rest. Minimums and values above the accepted maximum fail argument validation.Agent-friendly output:
applied echoes effective inputs.content[] and structuredContent carry the same data, enrichment included. Upstream bodies cap at 2 MiB and the combined response at 96 KiB; past that, response_too_large names a smaller call instead of dropping records.Add the following to your MCP client configuration file. IODA requires no API key.
{
"mcpServers": {
"ioda-outages-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/ioda-outages-mcp-server@latest"]
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"ioda-outages-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/ioda-outages-mcp-server@latest"]
}
}
}
Or with Docker:
{
"mcpServers": {
"ioda-outages-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/ioda-outages-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
api.ioda.inetintel.cc.gatech.edu. No API key or account.git clone https://github.com/cyanheads/ioda-outages-mcp-server.git
cd ioda-outages-mcp-server
bun install
cp .env.example .env
# no server-specific variables; edit framework overrides as needed
The server has no settings of its own. The common framework variables:
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_HOST | HTTP bind address. | 127.0.0.1 |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_HTTP_ENDPOINT_PATH | MCP endpoint path. | /mcp |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of framework overrides.
Build and run the production version:
# One-time build
bun run rebuild
# Run the built server
bun run start:http
# or
bun run start:stdio
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more
bun run test # Runs the test suite
| Directory | Purpose |
|---|---|
src/index.ts | Server identity, tool registration, service lifecycle |
src/mcp-server/tools/definitions/ | Six read-only tools |
src/mcp-server/tools/ioda-common.ts | Shared input normalization, rendering, response budgeting |
src/services/ioda/ | Fixed-origin API client, schemas, pacing, status assessment |
tests/ | Contract, service, and formatting tests |
docs/design.md | Domain contracts, design decisions, API evidence |
docs/tree.md | Generated directory inventory |
See CLAUDE.md for development guidelines and architectural rules, and docs/design.md for the domain contracts. The short version:
try/catch in tool logicctx.log for logging, ctx.signal for cancellation, and ctx.enrich for applied inputs and noticescreateApp() arrays in src/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0; see LICENSE. IODA data retains its Georgia Tech Research Corporation copyright and remains subject to the source's terms.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @cyanheads/ioda-outages-mcp-serverMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cyanheads-ioda-outages-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/ioda-outages-mcp-server"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cyanheads/ioda-outages-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.