Skip to content

MCP tool and skill change monitor ​

Follow a public MCP server, agent skill or npm package and see when its declarations change: publisher, digest, declared tools and their schemas, and requested permissions. Link a release comparison into a security review, or pin an approved release in CI and fail the build when it changes.

Console: https://sectigoaxiom.com/tools/change-monitor (no account needed to create a monitor or compare releases; sign in to watch one).

What this does not prove

A hosted interface exposes its declarations; its implementation may differ. The monitor compares what the source declares, not what it does. A stable digest does not prove the server behaves the same. Every monitor response carries this note.

What is monitored ​

kindSourceNormalised declarations
mcp_serverAn MCP Streamable HTTP endpointinitialize and tools/list (JSON or single-message SSE responses, paged): each tool's name, title, description, input and output schemas and annotations; tool hints as permissions.
skillA SKILL.md URLYAML frontmatter (name, description, version, allowed-tools, permissions, metadata) plus a digest of the instructions body.
npmA package (and version) in the npm registryPublisher, dist.integrity, bin entries (as tools), install scripts (preinstall, install, postinstall, prepare, as install_script:* permissions) and dependencies.

The release digest is the SHA-256 of the RFC 8785 (JCS) canonical manifest (sha-256: plus base64url). Key order and whitespace never create a spurious release; any change to a description or schema does, so a "rug pull" that rewrites a tool description shows up as a new release. A source that reverts to an earlier declaration reuses that release rather than creating a duplicate.

Create or refresh a monitor ​

sh
curl -sS https://api.sectigoaxiom.com/v1/public/monitors \
  -H 'content-type: application/json' \
  -d '{"source_url":"https://mcp.example.com/mcp","kind":"mcp_server"}'

Returns { monitor, release, changed } with 201 for a new monitor and 200 for an existing one. A source URL maps to one monitor (registering it again with a different kind is 409 conflict). A monitor is re-fetched on demand at most every 10 minutes; watched monitors are re-checked by the maintenance sweep every 6 hours, and watchers are emailed when a new digest appears.

Read history and compare ​

sh
curl -sS https://api.sectigoaxiom.com/v1/public/monitors/mon_01…
curl -sS "https://api.sectigoaxiom.com/v1/public/monitors/mon_01…/compare?from=rel_01…&to=rel_02…"

GET /v1/public/monitors/:id returns the monitor, up to 100 releases ({ id, digest, version, publisher, observed_at }, newest first) and the latest manifest. When you are signed in it also says whether you are watching.

compare takes release IDs or digests. Without parameters it compares the latest release with the one before it. The response:

FieldMeaning
from, toThe two releases compared.
digest_changed, publisher_changed, version_changedWhether the manifest digest, publisher or version differs.
tools.added[], tools.removed[]Tool names that appeared or disappeared.
tools.changed[]{ name, fields[] }: which of title, description, input_schema, output_schema, annotations changed.
permissions.added[], permissions.removed[]Requested permissions that changed.
noteThe declarations-only limitation above.

Watch a monitor ​

Signed in (session cookie, plus x-axiom-csrf): POST /v1/public/monitors/:id/watch; stop with DELETE on the same path.

Pin a release in CI ​

GET /v1/public/monitors/:id/badge.json?pin=… returns shields.io endpoint-badge fields (schemaVersion, label, message, color) plus latest_digest, status and changed_since:

Requeststatus
no pinunchanged; changed_since is when the latest release was observed.
pin matches latestunchanged (message: "matches pin").
pin differschanged; changed_since is when it first changed after the pin.
no releases yetunknown.

pin is a digest or release ID approved in your security review. A GitHub Actions step that fails when the pinned tool server changes:

yaml
- name: Check pinned MCP server declarations
  env:
    MONITOR: mon_01…
    PIN: sha-256:… # digest approved in the last security review
  run: |
    curl -sSf -X POST https://api.sectigoaxiom.com/v1/public/monitors \
      -H 'content-type: application/json' \
      -d '{"source_url":"https://mcp.example.com/mcp","kind":"mcp_server"}' > /dev/null || true
    status=$(curl -sSf "https://api.sectigoaxiom.com/v1/public/monitors/$MONITOR/badge.json?pin=$PIN" | jq -r .status)
    echo "declarations: $status"
    test "$status" = "unchanged"

The first call asks for a fresh fetch (honoured at most every 10 minutes); the second fails the job when the declarations no longer match the pin. Embed the badge in a README with https://img.shields.io/endpoint?url= followed by the URL-encoded badge.json URL.

Limits ​

Up to 10 new monitors and 120 reads per minute per client address; at most 1 MB per fetch, 10 pages and 500 tools per MCP server. Unreachable sources are recorded, not retried forever. Private catalogs and admission policies are not part of the free service.

Developer preview. Contract version 2026-11-14.