(Updated auto-generated PR description from @tadasant / Claude on Feb 22, 2026) ## Motivation and Context Fixes #637 Server lifecycle management (deprecation and yanking) is a standard requirement for package registries. Use cases like rebranding, security vulnerabilities, and end-of-life servers demand the ability to mark servers as deprecated or deleted, with optional messaging to guide consumers toward alternatives. ## Changes ### New API endpoints - **`PATCH /v0/servers/{serverName}/versions/{version}/status`** — Update the lifecycle status of a single server version - **`PATCH /v0/servers/{serverName}/status`** — Update the lifecycle status of all versions of a server in a single transaction Both endpoints accept: ```json { "status": "active|deprecated|deleted", "statusMessage": "Optional message (max 500 chars) explaining the change" } ``` ### New CLI command - **`mcp-publisher status <serverName> [version]`** — Update server lifecycle status from the command line - `--status` (required): `active`, `deprecated`, or `deleted` - `--message`: Optional status message - `--all-versions`: Apply to all versions of the server (replaces the `<version>` argument) ### API response changes `RegistryExtensions` now includes two new fields: - `statusChangedAt` — Timestamp of the last status change - `statusMessage` — Optional free-form message (e.g., deprecation reason, migration guidance) ### List endpoint changes - New `include_deleted` query parameter on `GET /v0/servers` — defaults to `false`, hiding deleted servers from listings - When `updated_since` is provided, `include_deleted` is automatically set to `true` for incremental sync ### Database - Migration `013_add_status_fields.sql`: Adds `status_changed_at` (NOT NULL, initialized from `published_at`) and `status_message` columns to the `servers` table ### Design decisions (from review discussion) - **Dedicated status endpoints** rather than overloading the existing edit endpoint - **Bidirectional status transitions** — all transitions between `active`, `deprecated`, and `deleted` are allowed - **`statusMessage` as free-form text** — no structured `nextName` or `alternativeUrl` fields (per maintainer feedback, to avoid complexity around chaining, trust transfer, etc.) - **Publish permission** grants status change access (not limited to admin/edit) - **Status message auto-cleared** when transitioning back to `active` Good, now I have the full picture. Here's the addendum: ### Consumer-facing API changes The new status fields live inside `_meta["io.modelcontextprotocol.registry/official"]` on every `ServerResponse`. This is the existing `RegistryExtensions` object — two new fields are added alongside the existing ones: **Before:** ```json { "server": { "name": "com.example/my-server", "...": "..." }, "_meta": { "io.modelcontextprotocol.registry/official": { "status": "active", "publishedAt": "2025-06-01T00:00:00Z", "updatedAt": "2025-06-15T00:00:00Z", "isLatest": true } } } ``` **After:** ```json { "server": { "name": "com.example/my-server", "...": "..." }, "_meta": { "io.modelcontextprotocol.registry/official": { "status": "deprecated", "statusChangedAt": "2026-02-01T12:00:00Z", "statusMessage": "Deprecated in favor of com.example/my-server-v2", "publishedAt": "2025-06-01T00:00:00Z", "updatedAt": "2026-02-01T12:00:00Z", "isLatest": true } } } ``` | New field | Type | Present when | |-----------|------|-------------| | `statusChangedAt` | `string` (RFC3339) | Always — initialized to `publishedAt` for existing records | | `statusMessage` | `string` (max 500 chars) | Only when set — `null`/omitted for active servers (auto-cleared on transition to active) | These fields appear on **every endpoint that returns a `ServerResponse`**: `GET /v0/servers`, `GET /v0/servers/{name}`, `GET /v0/servers/{name}/versions/{version}`, and the new PATCH status endpoints. ### List endpoint filtering `GET /v0/servers` gains an `include_deleted` query parameter: | Scenario | Behavior | |----------|----------| | No `include_deleted` param | Deleted servers hidden (default `false`) | | `include_deleted=true` | Deleted servers included in results | | `updated_since` provided | `include_deleted` forced to `true` for incremental sync | ## How Has This Been Tested? - Unit tests for status handler (`status_test.go`) covering status transitions, permission checks, validation errors, and the all-versions endpoint - Unit tests for the CLI command (`status_test.go`) - Integration with existing server/edit handler tests - Database layer tests for the new status update and query methods - Tested locally with `make dev-compose` ## Types of changes - [x] New feature (non-breaking change which adds functionality) ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Open items from review - [ ] `include_deleted` silent override: When `updated_since` is provided and `include_deleted=false` is explicitly passed, should return a 400 error rather than silently overriding ([thread](https://github.com/modelcontextprotocol/registry/pull/893#discussion_r2100879360)) — agreed upon but may not yet be implemented
5.1 KiB
Official MCP Registry API
This document describes the API for the official MCP Registry hosted at registry.modelcontextprotocol.io.
This API is based on the generic registry API with additional endpoints and authentication. For publishing servers using the API, see the publishing guide.
Base URLs
- Production:
https://registry.modelcontextprotocol.io - Staging:
https://staging.registry.modelcontextprotocol.io
Interactive Documentation
- Live API Docs - Stoplight elements with try-it-now functionality
- OpenAPI Spec - Complete machine-readable specification
Extensions
The official registry implements the Generic Registry API with the following specific configurations and extensions:
Authentication
Publishing requires namespace-based authentication:
- GitHub OAuth - For
io.github.*namespaces - GitHub OIDC - For publishing from GitHub Actions
- DNS verification - For domain-based namespaces (
com.example.*) - HTTP verification - For domain-based namespaces (
com.example.*)
See Publisher Commands for authentication setup.
Package Validation
The official registry enforces additional package validation requirements when publishing.
Server List Filtering
The official registry extends the GET /v0.1/servers endpoint with additional query parameters for improved discovery and synchronization:
updated_since- Filter servers updated after RFC3339 timestamp (e.g.,2025-08-07T13:15:04.280Z)search- Case-insensitive substring search on server names (e.g.,filesystem)- This is intentionally simple. For more advanced searching and filtering, use a subregistry.
version- Filter by version (currently supportslatestfor latest versions only)include_deleted- Include deleted servers in results (default:false, but automaticallytruewhenupdated_sinceis provided for incremental sync)
These extensions enable efficient incremental synchronization for downstream registries and improved server discovery. Parameters can be combined and work with standard cursor-based pagination.
Example: GET /v0.1/servers?search=filesystem&updated_since=2025-08-01T00:00:00Z&version=latest
Server Detail
The GET /v0.1/servers/{serverName}/versions/{version} endpoint returns detailed information about a specific server version.
Path parameters:
serverName- URL-encoded server name (e.g.,io.github.user%2Fmy-server)version- Server version orlatestfor the most recent version
Query parameters:
include_deleted- Include deleted servers in results (default:false)
Server Version History
The GET /v0.1/servers/{serverName}/versions endpoint returns all versions of a server.
Path parameters:
serverName- URL-encoded server name (e.g.,io.github.user%2Fmy-server)
Query parameters:
include_deleted- Include deleted servers in results (default:false)
Additional endpoints
Auth endpoints
- POST
/v0.1/auth/dns- Exchange signed DNS challenge for auth token - POST
/v0.1/auth/http- Exchange signed HTTP challenge for auth token - POST
/v0.1/auth/github-at- Exchange GitHub access token for auth token - POST
/v0.1/auth/github-oidc- Exchange GitHub OIDC token for auth token - POST
/v0.1/auth/oidc- Exchange Google OIDC token for auth token (for admins)
Status endpoints
Update Single Version Status
PATCH /v0.1/servers/{serverName}/versions/{version}/status - Update status of a specific server version.
Path parameters:
serverName- URL-encoded server name (e.g.,io.github.user%2Fmy-server)version- Server version to update
Request body:
status(required) - New status:active,deprecated, ordeletedstatusMessage(optional) - Message explaining the status change (max 500 characters, not allowed when status isactive)
Update All Versions Status
PATCH /v0.1/servers/{serverName}/status - Update status of all versions of a server in a single transaction.
Path parameters:
serverName- URL-encoded server name (e.g.,io.github.user%2Fmy-server)
Request body:
status(required) - New status:active,deprecated, ordeletedstatusMessage(optional) - Message explaining the status change (max 500 characters, not allowed when status isactive)
Status values:
active- Server is active and visible in default listingsdeprecated- Server is deprecated but still visible with a warning messagedeleted- Server is hidden from default listings (useinclude_deleted=trueto show)
Authentication: Requires publish or edit permission for the server namespace.
Admin endpoints
- GET
/metrics- Prometheus metrics endpoint - GET
/v0.1/health- Basic health check endpoint - PUT
/v0.1/servers/{serverName}/versions/{version}- Edit specific server version