Skip to content

API reference

Base URL: http://<registry-host>:5001. All bodies are JSON. Errors use {"detail": "<message>"} with a conventional status code.

Authorization: Bearer <jwt> — HS256 against the platform JWT_SECRET. Identity comes from sub (or user_id); tokens without exp are accepted, expired ones are treated as anonymous. With no JWT_SECRET configured (dev mode) any non-empty bearer authenticates as demo_user.

Read endpoints are public. Mutations require auth; tokens carrying a scope/scopes claim additionally need mcp-registry:write (or mcp-registry:admin) — see publishing.

/v0.1 — official spec surface (2025-12-11)

Section titled “/v0.1 — official spec surface (2025-12-11)”
Method Path Notes
GET /v0.1/servers limit (≤100), cursor (opaque), search, updated_since (RFC 3339; implies update-time ordering + tombstones), include_deleted
GET /v0.1/servers/{name}/versions All versions, each a full server document
GET /v0.1/servers/{name}/versions/{version} latest resolves to the current version
PUT /v0.1/servers/{name}/versions/{version} Publish; 409 if the version exists (immutability)
PATCH /v0.1/servers/{name}/status {"status", "statusMessage"?} — deprecate/delete/reactivate
PATCH /v0.1/servers/{name}/versions/{version}/status Per-version lifecycle
GET /v0.1/health · /v0.1/ping · /v0.1/version version reports "specVersion": "2025-12-11"

{name} is the URL-encoded full name (io.github.acme%2Fwidget).

Listing shape:

{
"servers": [ { "$schema": "...", "name": "...", "version": "...", "_meta": { } } ],
"metadata": { "nextCursor": "b2Zmc2V0OjUw", "count": 50 }
}

Every served document carries:

  • io.modelcontextprotocol.registry/officialstatus, publishedAt, updatedAt, isLatest, and when set, statusMessage + statusChangedAt.
  • ai.brutor.registry (extension) — downloadCount, stars, verified, namespaceVerified, securityScan, sourceConnection (provenance), and governanceStatus: governed | ungoverned | unknown.

GET /v0.1/x/ai.brutor/governance/{name} — just the governance block for one server, for tooling that only wants posture:

{
"extension": "ai.brutor.registry/governance",
"server": "io.github.acme/widget",
"governance": { "governanceStatus": "governed", "verified": true }
}

Unprefixed extension routes: POST /namespace/verify, POST /namespace/verify/check, GET /auth/github/callback — see namespace verification.

Server listings and details on this surface carry a source_registry: {"id", "name"} field on aggregator-imported records — the connection the server was federated from; locally published servers omit it.

Kept for the Console and older tooling: GET /v0/servers (offset cursors, namespace/keyword/verified_only filters), GET /v0/servers/{id} (also accepts row UUIDs; increments the download counter), POST /v0/publish, POST /v0/validate (no-auth dry run), icon endpoints (GET/PUT/DELETE /v0/servers/{id}/icon — PNG/JPEG/SVG/WebP, ≤ 512 KiB, GET is public), version listing/status routes, and the connections API under /v0/connections.

Path Auth Notes
/health public 200 healthy / 503 with a JSON body when the DB is unreachable
/status public Uptime, totals, aggregator state
/config public Effective non-secret configuration
/logs required Last ≤ 500 in-process log entries, ?level= filter
/metrics required Request/publish/download/search counters, response-time stats