api

Public Endpoints

Public read endpoints for tools that want to read observatory state. Responses are JSON or <code>text/event-stream</code>, with <code>text/csv</code> from the batch endpoint via <code>format=csv</code>. No authentication required.

GET /api/events Server-sent events: live release + dependency activity.

response

{
  "kind": "release",
  "source": "npm",
  "server_id": "npm:fastmcp",
  "version": "1.2.3",
  "at": "2026-05-24T18:00:00Z"
}

cache

headerno-store
ttlno-store
GET /api/stats Aggregate counts: lifetime, 24h, active maintainers, last event.

response

{
  "totalTracked": 18432,
  "byKind": [
    {
      "kind": "npm",
      "count": 12044
    },
    {
      "kind": "pypi",
      "count": 4810
    },
    {
      "kind": "github-only",
      "count": 1578
    }
  ],
  "releasesToday": 47,
  "releasesPrior24h": 41,
  "activeMaintainers24h": 612,
  "topMaintainers": [
    {
      "maintainer": "alice",
      "count": 22
    },
    {
      "maintainer": "bob",
      "count": 18
    }
  ],
  "lastEventAt": 1748109501000,
  "hourlyReleases24h": [
    0,
    0,
    1,
    3,
    2,
    4,
    1,
    0,
    2,
    5,
    3,
    1,
    0,
    2,
    4,
    1,
    3,
    2,
    1,
    0,
    4,
    2,
    3,
    1
  ]
}

cache

headerpublic, max-age=30
ttl30s
GET /api/servers/{id} One server detail: identity, sources, dependencies, recent releases.

response

{
  "server": {
    "id": "npm:fastmcp",
    "name": "fastmcp",
    "kind": "npm",
    "description": "A fast MCP server",
    "repoUrl": "https://github.com/example/fastmcp",
    "homepage": null,
    "license": "MIT",
    "language": "TypeScript",
    "maintainer": "alice",
    "firstSeen": "2026-01-15T10:00:00Z",
    "lastSeen": "2026-05-24T17:58:21Z",
    "currentVersion": "1.2.3",
    "tags": [
      "mcp",
      "server"
    ]
  },
  "releases": [
    {
      "version": "1.2.3",
      "publishedAt": "2026-05-24T17:58:21Z",
      "source": "npm"
    }
  ],
  "deps": {
    "out": [
      {
        "fromServerId": "npm:fastmcp",
        "toServerId": "npm:zod",
        "type": "runtime"
      }
    ],
    "in": [
      {
        "fromServerId": "npm:other-mcp",
        "toServerId": "npm:fastmcp",
        "type": "runtime"
      }
    ]
  },
  "related": [
    {
      "id": "npm:slowmcp",
      "reason": "maintainer"
    }
  ]
}

cache

headerpublic, max-age=60
ttl60s
GET /api/servers?ids={a,b,…} Batch lookup (≤100 ids): risk grade, CVE count, 30d cadence per server. format=csv for CSV.

response

{
  "servers": [
    {
      "id": "npm:fastmcp",
      "name": "fastmcp",
      "kind": "npm",
      "maintainer": "alice",
      "description": "A fast MCP server",
      "license": "MIT",
      "currentVersion": "1.2.3",
      "lastSeen": "2026-05-24T17:58:21Z",
      "riskGrade": "B",
      "riskScore": 23,
      "cveCount": 0,
      "releases30d": 4
    }
  ],
  "unknownIds": [
    "npm:typo-mcp"
  ]
}

cache

headerpublic, max-age=60
ttl60s
GET /api/search?q={query} Typeahead search across servers + maintainers (≤8 hits).

response

{
  "hits": [
    {
      "id": "npm:fastmcp",
      "name": "fastmcp",
      "maintainer": "alice",
      "source": "npm",
      "type": "server"
    },
    {
      "id": "alice",
      "name": "alice",
      "maintainer": null,
      "source": "npm",
      "type": "maintainer",
      "count": 7
    }
  ]
}

cache

headerno-store
ttlno-store
GET /api/healthz Per-source poller health; 200 when all critical sources are fresh, 503 otherwise.

response

{
  "status": "ok",
  "failingCritical": [],
  "sources": [
    {
      "source": "npm",
      "status": "ok",
      "critical": true,
      "healthy": true,
      "lastFetchedAt": "2026-05-24T17:55:00Z",
      "nextDueAt": "2026-05-24T18:05:00Z",
      "overdueMs": 0,
      "lastError": null
    }
  ]
}

cache

headerno-store
ttlno-store

Live Cadence

The /api/events stream emits as the pollers ingest upstream activity; their poll intervals and last-fetched times are published on the feeds page, and the same events render human-readable on activity.

Querying Server Details

For the /api/servers/{id} endpoint, URL-encoding is not required! You can pass the full unencoded string (e.g. npm:@org/svr) because it uses a catch-all route. Bare names without a source prefix will automatically fall back through npm:, pypi:, then github: to find a match. To find an id to query, browse servers.

Every server also has a stable 8-character short id (shown on its detail page) that needs no URL-encoding — handy when several ids share one URL. Both /api/servers/{id} and the batch endpoint accept short ids interchangeably with canonical ids. Retired ids forward to their survivor, so old links keep resolving.

Batch Lookup

/api/servers?ids={a,b,…} takes a comma-separated ids list — canonical ids, short ids, or bare names, mixed freely — capped at 100 per call (extras are ignored). Ids are de-duplicated after resolution; any that resolve to nothing come back in unknownIds rather than failing the batch. An empty ids param returns 400. Add &format=csv for a text/csv body (one header row, then one row per server) suited to spreadsheet or SBOM-tool import; otherwise the response is JSON.