# MCP Registry Tracker (official registry, deltas + trending) (`sellavir/mcp-registry-tracker`) Actor

Tracks the official Model Context Protocol registry. Delta mode emits only servers that are new/updated/deprecated/deleted since your last run, with canonical dedup, optional GitHub stars enrichment, and trending ranks.

- **URL**: https://apify.com/sellavir/mcp-registry-tracker.md
- **Developed by:** [Vic](https://apify.com/sellavir) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## MCP Registry Tracker

Tracks the **official Model Context Protocol (MCP) registry**
([registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io)) and tells you
**what changed since your last run**: new MCP servers, updated versions, deprecations, and
deletions — with canonical dedup, optional GitHub health signals (stars, forks, last push,
archived), and trending ranks based on your own run history.

### Quickstart

1. Run the Actor with default input (`mode: "delta"`). The first run quietly seeds change-tracking state (~2 min, run-start fee only, no rows) — set `firstRunFullSnapshot: true` if you want the full registry delivered immediately instead.
2. Schedule it (e.g. daily). Every later run emits **only** servers that are new / updated / deprecated / deleted since your previous run.
3. Read results from the default dataset (JSON/CSV/Excel via the Apify API or console).

### Honest framing: what you are paying for

The raw registry API is **free and public** — anyone can call it. This Actor sells the layer
the free API cannot give you:

- **Persistent change tracking** — run-over-run `deltaType` (`new` / `updated` / `deprecated` / `deleted`) kept in a named key-value store under your account (`mcp-registry-state`).
- **Deletion detection** — servers that vanish from the registry between complete snapshots are emitted as `deltaType: "deleted"` rows.
- **Canonical dedup** — registry entries pointing at the same repository (including renames) are collapsed; monorepo subfolders are kept distinct; prior names land in `aliases`.
- **GitHub enrichment** — stars, forks, last push, archived flag for servers with GitHub repos.
- **Trending** — `starsDelta` and `trendingRank` computed against *your* previous run's state.

If you just want a one-off dump of the registry, the free API (or `mode: "snapshot"` here) will
do it; the recurring value is the delta feed.

### Modes and input recipes

#### Daily delta feed (recommended)

```json
{ "mode": "delta", "enrichGithub": true, "githubToken": "ghp_yourtoken" }
```

First run: seeds state silently (run-start fee only, ~2 min, no rows emitted). Set
`firstRunFullSnapshot: true` if you want the first run to deliver the full registry
(~25,000 rows, billed at the snapshot rate — use the default 3600s timeout).
Every later run: only changed servers, typically tens of rows per day.

#### Weekly full snapshot (also reconciles deletions)

```json
{ "mode": "snapshot" }
```

A complete, deduped export of the current registry (~25,000+ rows — see pricing below).
When you have a previous complete snapshot in state, vanished servers are appended as
`deltaType: "deleted"` rows.

#### Search-filtered watch

```json
{ "mode": "delta", "search": "postgres" }
```

Uses the registry's `search` parameter. Each distinct search term keeps its own delta timeline,
so a "postgres" watch does not pollute your global feed's state.

### Input

| field | type | default | notes |
|---|---|---|---|
| `mode` | `delta` | `snapshot` | `delta` | delta = changes since your last run; snapshot = full export |
| `search` | string | `""` | registry search term; separate state timeline per term |
| `enrichGithub` | boolean | `true` | stars/forks/pushedAt/archived for GitHub-hosted servers |
| `githubToken` | secret string | — | your token → 5,000 req/hr. Without it enrichment is limited to delta rows, max 25 repos/run (GitHub's unauthenticated limit is 60 req/hr) |
| `computeTrending` | boolean | `true` | starsDelta + trendingRank vs your previous run |
| `firstRunFullSnapshot` | boolean | `false` | delta mode only; `false` = first run silently seeds state (run-start fee only), `true` = first run delivers the full registry at the snapshot rate |
| `maxServers` | integer | `30000` | hard cap on processed (and billed) rows per run |

### Output example (real row from a delta run)

```json
{
  "serverName": "io.github.amyodov/yet-another-agentic-chat",
  "canonicalId": "repo:github.com/amyodov/yet-another-agentic-chat",
  "description": "Messaging between concurrent AI coding sessions, across clients, over MCP. Zero infrastructure.",
  "version": "0.5.0",
  "status": "active",
  "repositoryUrl": "https://github.com/amyodov/yet-another-agentic-chat",
  "repositorySource": "github",
  "packages": [{ "registry": "pypi", "name": "yet-another-agentic-chat", "version": "0.5.0" }],
  "remotes": [],
  "publishedAt": "2026-08-29T14:13:55.92155Z",
  "updatedAt": "2026-08-29T14:13:55.92155Z",
  "deltaType": "new",
  "ghStars": 3,
  "ghForks": 0,
  "ghPushedAt": "2026-08-29T14:22:29Z",
  "ghArchived": false,
  "starsDelta": null,
  "trendingRank": null,
  "firstSeenAt": "2026-08-29T14:35:44.971Z",
  "scrapedAt": "2026-08-29T14:35:44.971Z",
  "aliases": []
}
```

#### Field dictionary

| field | type | notes |
|---|---|---|
| `serverName` | string | canonical registry name (e.g. `io.github.owner/repo`) |
| `canonicalId` | string | dedup key: normalized repo URL (+ monorepo subfolder) else name |
| `description` | string | null | from registry |
| `version` | string | latest version |
| `status` | string | `active` / `deprecated` / `deleted` |
| `repositoryUrl` | string | null | |
| `repositorySource` | string | null | `github` / `gitlab` / `other` |
| `packages` | array | `[{registry (npm/pypi/oci/...), name, version}]` |
| `remotes` | array | `[{transportType (sse/streamable-http), url}]` |
| `publishedAt` / `updatedAt` | string | ISO 8601, from registry |
| `deltaType` | string | null | `new` / `updated` / `deprecated` / `deleted`; null on snapshot rows |
| `ghStars` / `ghForks` | integer | null | GitHub enrichment |
| `ghPushedAt` | string | null | GitHub enrichment |
| `ghArchived` | boolean | null | GitHub enrichment |
| `starsDelta` | integer | null | stars gained vs your previous run (needs ≥ 2 enriched runs) |
| `trendingRank` | integer | null | 1 = biggest star gain among this run's rows |
| `firstSeenAt` | string | when *your* state first saw this server |
| `scrapedAt` | string | ISO 8601 |
| `aliases` | array | previous/duplicate registry names collapsed into this row |
| `raw` | object | original registry entry — **snapshot mode only** (schema-drift safety net) |

### Pricing (pay per event)

| event | price | charged for |
|---|---|---|
| Run start | $0.001 | each run |
| Server snapshot row | $0.002 | each row in snapshot mode (and the optional first-run snapshot) |
| Server delta row | $0.003 | each new/updated/deprecated/deleted row in delta mode |

Worked examples:

- **Daily delta feed**: typically tens to a few hundred changed servers/day → roughly **$0.05–$0.60 per day**.
- **Full snapshot**: the registry currently holds ~25,000+ latest-version servers, so a complete snapshot bills **around $51**. Use it sparingly (e.g. weekly reconciliation) or cap it with `maxServers` — the delta mode is the economical default.
- First delta run (default `firstRunFullSnapshot: false`): **$0.001** total (seeds state, emits nothing).

You are never charged for rows that are not delivered to the dataset.

### How long does a run take / recommended timeout

Measured on the Apify platform (4 GB, default build):

| run type | duration (measured 2026-09-03) | recommended timeout |
|---|---|---|
| First delta run (default, silent seed) | ~47 s | default 3600s (300s also works) |
| Daily delta run | ~5 s – 1 min | default 3600s |
| **Full snapshot** (~25,000 rows) | **~2–3 min** (registry crawl ~45 s + batched delivery at 400–1,200 rows/s) | **keep the default 3600s** |
| Capped snapshot (`maxServers: 500`) | ~30 s | 300s is fine |

`maxServers` bounds both cost and time — a `maxServers: 500` snapshot bills at most
500 rows (~$1) and finishes in about a minute. GitHub enrichment with a token adds
time proportional to the number of unique repos being enriched.

### Timeouts, partial runs, and resurrection (no double billing)

The Actor watches its own run timeout and **stops gracefully ~20–30s before the
platform would kill it**: it flushes a delivery checkpoint into the run's key-value
store, finishes as SUCCEEDED, and sets a status message like
`Partial: 5,970 of ~25,000 rows delivered…`.

- **Resurrect the same run** (Runs > ⋯ > Resurrect, pick a longer timeout) and it
  **continues where it left off**. Already-delivered rows are never re-pushed and
  never re-charged — the checkpoint lives in the run's own storage and the flat
  run-start fee is charged at most once per run.
- In delta mode, even a **fresh** follow-up run continues cleanly: delivered rows are
  recorded in your delta state, so they are not billed again unless they change.
- Rows are charged strictly **after** they are written to the dataset, in batches:
  a row that never reached your dataset is never billed.

### Data sources & respect

- **registry.modelcontextprotocol.io** — the official, public, OpenAPI-documented registry of
  the Model Context Protocol open-source project. Full credit to the MCP project for the data.
  The Actor uses plain HTTP JSON pagination with a descriptive User-Agent, a small delay
  between pages (the registry's cursor pagination is inherently sequential), and
  exponential backoff honoring Retry-After on errors. No PII is collected (server metadata only).
- **api.github.com** — optional enrichment. Bring your own token for full coverage; without
  one the Actor stays well inside GitHub's unauthenticated limit and stops gracefully if the
  limit is hit (`partial` enrichment noted in the run status).
- PulseMCP and Glama are **not** included: PulseMCP's API is being sunset, and Glama's requires
  an API key with attribution requirements.

### Limitations (honest)

- Registry metadata quality varies by publisher — many servers have no repository URL or packages.
- Trending needs at least 2 runs with GitHub enrichment before `starsDelta`/`trendingRank` are non-null.
- No download counts — no open source for MCP server download numbers currently exists.
- Deletion detection via disappearance requires a previous *complete* snapshot in state; the
  registry's own `status: deleted`/`deprecated` markers are picked up in every delta run.
- Delta state is per Apify account (named key-value store `mcp-registry-state`) and per search term.

### Support

Report problems in the Actor's **Issues** tab — responses within 24 hours. If the registry API
shape drifts, the built-in contract test fails the run loudly instead of emitting malformed data.

# Actor input Schema

## `mode` (type: `string`):

delta = only servers new/updated/deprecated/deleted since your last run (uses updated\_since + persistent state). snapshot = full current registry export.

## `search` (type: `string`):

Optional registry search term (passed to the API's search parameter). Each distinct search term keeps its own delta-state timeline.

## `enrichGithub` (type: `boolean`):

Looks up stars, forks, pushedAt, archived for servers with GitHub repo URLs.

## `githubToken` (type: `string`):

Personal token raises GitHub API limit to 5,000 req/hr. Without it, enrichment is capped (60 req/hr) and applied only to delta rows.

## `computeTrending` (type: `boolean`):

Day-over-day star deltas and trending rank vs your previous run state.

## `firstRunFullSnapshot` (type: `boolean`):

Delta mode only. When no previous state exists, the first run by default just seeds change-tracking state quietly (run-start fee only, ~2 min) and later runs emit deltas. Set true to emit the full current registry on the first run instead (~25,000 rows, billed at the snapshot rate, needs the default 3600s timeout).

## `maxServers` (type: `integer`):

Hard cap on servers processed (and therefore on billed rows) in one run.

## Actor input object example

```json
{
  "mode": "delta",
  "search": "",
  "enrichGithub": true,
  "computeTrending": true,
  "firstRunFullSnapshot": false,
  "maxServers": 30000
}
```

# Actor output Schema

## `results` (type: `string`):

One row per MCP registry server (deltas or full snapshot) with version, status, packages, remotes, GitHub enrichment and trending rank.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("sellavir/mcp-registry-tracker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("sellavir/mcp-registry-tracker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call sellavir/mcp-registry-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sellavir/mcp-registry-tracker"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/LBHQ26WdqMPa02F5L/builds/0y7yQVV5NSCKMZtAE/openapi.json
