MCP Server Change and Health Monitor
Pricing
from $4.25 / 1,000 server checks
MCP Server Change and Health Monitor
Watch MCP servers: one row per server saying whether it answered, how fast, what tools it exposes now, and what changed since the last run, with breaking changes marked. Takes HTTP endpoints, npm packages, or registry search terms.
Pricing
from $4.25 / 1,000 server checks
Rating
0.0
(0)
Developer
Mamba Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
an hour ago
Last modified
Categories
Security
Limited permissionsShare
Give this actor a list of MCP servers and get one row per server: did it answer, how fast, what tools it exposes now, and what changed since the last run. Changes are marked breaking, warning, or info. Run it on a schedule and it compares each run with the last one by itself. You pay per server checked; Mamba Labs pays the platform costs.
Features
- It speaks MCP. The actor connects as an MCP client (initialize, then the list calls), so it sees what an agent sees. You do not need to export a tool catalog.
- Three ways in. HTTP endpoints (streamable HTTP, then the older HTTP plus SSE), npm packages started over stdio, or search terms for the official MCP Registry, in any mix.
- Changes marked by what they break. Breaking: a tool or argument removed, an argument newly required, a type changed, an allowed value removed. Warning: a tool description, annotation, or output schema changed. Info: a tool or optional argument added.
- Description changes are reported. An agent reads a tool description as instructions, so a silent edit to one is reported with the before and after text.
- Health. Answer time, tool list time, server version, last time up, and down since. A server gets one retry before it is reported down.
- Scheduled runs compare themselves. The last result is saved under your Snapshot name in your Apify account. Or pass a SNAPSHOT record from any run.
- Cost guards. A max charge per run, and a cap on servers per registry search.
How the data is read
The actor connects straight to each server from Apify's network. A monitor should see a server the way a client does, so it does not go through a proxy. It uses no login of its own, no other developer's actor, and no key from Mamba Labs. Registry searches read the public API of the official MCP Registry.
Private servers. Put your headers in auth_headers, keyed by site. Each header goes only to its own site and is never sent across a redirect to another site. The field is encrypted by Apify, and the actor never logs it or saves it. Fixtures and the refused path are how this was tested: no real private server was used, so the first buyer's credentials are the live test.
npm packages. A package you list is downloaded and started inside your run, so its code runs there. The actor starts it under an unprivileged user with no environment variables and no install scripts, and refuses to start it if that user can read the run's Apify token. It can still reach the internet. List only packages you trust. Packages found through a registry search are listed in the row but never run.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
server_urls | array | HTTP endpoints of MCP servers. Streamable HTTP is tried first, then the older HTTP plus SSE transport. | |
npm_packages | array | npm package names, optionally with a version, such as @modelcontextprotocol/server-everything. Each is installed and started inside your run. The code in a package you list runs in your run, so list only packages you trust. No environment variables are passed to it. | |
registry_search | array | Search terms for the official MCP Registry. The HTTP endpoints of matching servers are checked. Packages found this way are listed but never run, because running code picked by a keyword is not safe. | |
max_servers | string | 25 | Most servers to check per registry search term, up to 200. Default 25. |
snapshot_key | string | default | Name of the memory that holds the last run's results, so a scheduled run finds changes on its own. Use a different name per list. Default default. |
previous_snapshot | string | Optional. The JSON of a SNAPSHOT record from an earlier run, or an https link to that record. It takes the place of the saved snapshot for this run. | |
timeout_seconds | string | 20 | How long one request to a server may take before it counts as no answer, 3 to 60. Default 20. A package gets 60 more seconds to install. |
include_resources_prompts | string | true | Also list the server's resources and prompts and report what changed in them. Default true. |
auth_headers | string | Optional, for servers you are allowed to check. JSON keyed by site, for example {"https://mcp.example.com%22:%7B%22Authorization%22:%22Bearer abc"}}. Each header goes only to its own site. Encrypted by Apify, never logged, never saved in a snapshot. | |
max_charge_usd | string | Optional. The run stops before a charge that would pass this amount. Free rows are always returned. |
Output
| Field | Type | What it holds |
|---|---|---|
row_type | string | One of: server_check, registry_query, run_summary. run_summary is the one free row written when the input is refused. |
server | string | The URL or npm package checked. On a registry_query row, the search term. |
source | string | url, npm, or registry: how this server got on the list. |
registry_name | string | The server's name in the official MCP Registry, when it came from a search. |
status | string | up (answered and listed its catalog), down (no valid answer after one retry), auth_required (answered 401), blocked (answered 403 or 429), invalid (bad entry), or not_run. |
change_status | string | baseline (first time seen, nothing to compare), unchanged, changed, or not_compared (the server gave no catalog). |
transport | string | http (streamable HTTP), sse (the older HTTP plus SSE), or stdio. |
latency_ms | integer | Time for the server to answer initialize. For a package this includes the install. |
list_latency_ms | integer | Time to read the full tool list. |
http_status | integer | The HTTP status behind a status other than up, when there was one. |
server_name | string | The name the server reports for itself. |
server_version | string | The version the server reports for itself. |
protocol_version | string | The MCP protocol version the server agreed to. |
tool_count | integer | How many tools the server exposes now. |
resource_count | integer | How many resources it exposes now. Empty when it has none or the option is off. |
prompt_count | integer | How many prompts it exposes now. Empty when it has none or the option is off. |
catalog_hash | string | A hash of the whole catalog. It changes when any compared part changes. |
tools | array | Every tool now: name, hash, and the first 300 characters of its description. |
changes | array | What changed since the last run. Each entry has severity (breaking, warning, or info), kind, item, and detail. |
change_count | integer | How many entries are in changes. |
breaking_count | integer | How many changes break a caller: a tool or argument removed, an argument newly required, a type changed, an allowed value removed. |
previous_checked_at | string | When the snapshot this run compared against was taken. |
last_up_at | string | The last time a run found this server up. |
down_since | string | When runs first found this server down, while it stays down. |
server_count | integer | On a registry_query row: HTTP endpoints from this search that will be checked. |
skipped_packages | array | On a registry_query row: matching servers that have only a package. They are listed, not run. |
checked_at | string | When this server was checked, UTC. |
row_status | string | ok, or why this row carries no data: no_results, no_change, partial, blocked, or error. |
error_reason | string | Why the row is not ok. A refused input reads input_invalid: followed by what to fix. |
billable_events_json | string | What this row was billed as, for example {"server-check":1}. {} means free. |
scraped_at | string | When the row was written, UTC. |
Pricing
Pay per event. You pay for a run start and for each server with a definite answer: up and compared, or down after a retry. A package costs more than a URL because each one is a full install. A down result is charged because it is the answer you asked for and the check took the full wait. A server that answers 401 (auth_required), 402, 403, or 429 (blocked), an invalid entry, a package name npm does not have, a package that was not run, a registry row, and a refused input are free.
| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
server-check, one MCP server checked | $0.005 | $0.00475 | $0.0045 | $0.00425 |
package-check, one npm package installed and checked | $0.02 | $0.019 | $0.018 | $0.017 |
apify-actor-start, once per run (one per GB of memory; the default 512 MB is one) | $0.002 | $0.002 | $0.002 | $0.002 |
Per 1,000 rows of server-check: $5.00 on the free plan, $4.25 on Gold.
Free plan cap: 1.50 USD of evaluation a month, about 300 rows. Any paid Apify plan removes the cap, and it resets on the 1st. The run stops before a charge that passes your maximum charge per run in Apify or your max_charge_usd input.
Mamba Labs pays the platform costs of your run, Apify proxy traffic included.
Usage examples
Apify Console or API. A scheduled check of two endpoints and one package:
{"server_urls": ["https://mcp.deepwiki.com/mcp", "https://knowledge-mcp.global.api.aws"],"npm_packages": ["@modelcontextprotocol/server-everything"],"snapshot_key": "my-agents"}
Registry search.
{ "registry_search": ["github"], "max_servers": "25" }
To act only on real changes, filter rows on change_status equal to changed, or breaking_count above 0.
Clay. Number and on or off inputs are text fields, which is what Clay sends. A list input takes a JSON list, so put the column inside a one item list.
MCP. The Mamba Labs MCP server @mambalabsdev/mcp-server-change-health-monitor exposes this actor to Claude and other MCP clients.
Error handling
| Case | What you get |
|---|---|
| Missing or unreadable input | One free row, row_type run_summary, error_reason starting input_invalid: with what to fix. The run ends successfully and charges nothing but the run start |
| A server gives no valid answer after one retry | One charged row, status down, error_reason says why |
| A server answers 401 | One free row, status auth_required. Add auth_headers to check it |
| A server answers 402, 403, or 429 | One free row, status blocked |
| A bad URL or package name in a good list | One free row for that entry, status invalid; the others run |
| A private or local address | Refused as invalid. The actor checks public servers |
| A package that needs an environment variable or argument to start | One charged row, status down, because none are passed. A package is not retried |
| The first run for a server | change_status baseline: nothing to compare yet |
| The run is close to its timeout | The actor stops starting new work 90 seconds before the timeout and delivers what it has |
Limitations
- The first run sets the baseline. Changes appear from the second run.
- It lists what a server exposes. It does not call tools, so it cannot tell whether a tool works.
- A server that shows a different catalog to each visitor, or changes its text per session, shows as changed. Read
changesto see what moved. - A package cannot receive environment variables or arguments in this version, so one that needs a key or a path to start reads as
down. - The older HTTP plus SSE transport was tested on fixtures only; no public server using it answered during the build.
- Up to 500 URLs, 25 packages, and 10 registry terms per run, with up to 200 servers per term. A list of more than 8 MB of snapshot keeps hashes only, so changes name the tool but not the old text.
- Answer time is measured from Apify's network in one place, so it is not a global uptime reading.
Mamba Labs actor suite
Built by Mamba Labs.