Commit graph registry/docs/reference/api/official-registry-api.md
Author SHA1 Message Date
Radoslav Dimitrov
a25f166b4b
docs: remove stale complete.md and fix remaining stale references (#1522)
Deletes `complete.md` and cleans up the last references to the
pre-restructuring docs layout.

## Why `complete.md` goes

It is 2,944 lines (31% of all documentation lines in the repo)
self-described as *"all documentation from the docs/ directory compiled
into a single markdown file"*. But:

- **No generator exists.** No make target, no workflow, no script. `grep
-rn "complete\.md"` finds **zero** references anywhere in the repo.
- **It mirrors a docs tree that no longer exists** — `docs/guides/`,
`docs/explanations/`, `docs/concepts/`.
- **All 72 of its relative links are broken**, and six of the basenames
it references exist nowhere in the repo.
- **~14 current docs are missing from it entirely** (`about.mdx`,
`authentication.mdx`, `package-types.mdx`, both CHANGELOGs, ...).
- **Its `server.json` examples pin the superseded `2025-07-09` schema**
(current is `2025-12-11`).

The strongest argument is its own last commit. [PR
#1278](https://github.com/modelcontextprotocol/registry/pull/1278)
closed [issue
#767](https://github.com/modelcontextprotocol/registry/issues/767) — a
real user-reported CLI flag bug — by editing **only `complete.md`**. A
genuine fix landed in a file nobody reads, while the docs a reader would
actually find stayed wrong.

A generated file with no generator degrades into a trap: authoritative
enough that people edit it, with nothing validating it. If the
LLM-consumption use case is worth keeping, the right shape is a `make
docs-bundle` target plus a `check-docs-bundle` CI job mirroring the
existing `check-schema` pattern — happy to do that instead if you would
rather keep it.

## Remaining stale references

| File | Was | Now |
|---|---|---|
| `contributing/add-package-registry.md` | Add
`docs/guides/publishing/publish-[yourregistry].md`, update
`docs/guides/publishing/README.md` | Add a section to
`package-types.mdx`. These were the **last live references** to the
obsolete `docs/guides/` layout outside `complete.md` |
| `administration/maintainer-onboarding.md` | Add them to "Current key
maintainers" in README | "Registry Working Group" — the section that
actually exists |
| `reference/README.md` | Omitted 6 reference docs | Adds
`api/extensions.md`, `api/openapi.yaml`, `api/CHANGELOG.md`,
`server-json/CHANGELOG.md`, `server-json/CONTRIBUTING.md`,
`server-json/draft/` |
| `docs/README.md` | Index omitted `community-projects.md` | Listed |
| `reference/api/generic-registry-api.md` | `PUT .../versions/{version}`
"not implemented by official registry" | It **is** implemented
([edit.go:36](https://github.com/modelcontextprotocol/registry/blob/main/internal/api/handlers/v0/edit.go#L36)),
and `official-registry-api.md` already lists it as an admin endpoint |
| `reference/api/official-registry-api.md` | Omitted 3 registered routes
| Adds `POST /v0.1/validate` (which `mcp-publisher validate` calls),
`GET /v0.1/ping`, `GET /v0.1/version`, and notes these plus `/health`
are absent from `openapi.yaml` |
| `server-json/official-registry-requirements.md` | Per-registry
verification → `quickstart.mdx` | → `package-types.mdx`, which has an
Ownership Verification section per registry |
| `design/design-principles.md` | Sections 1,2,3,4,**6**,7 | Renumbered
1–6 |
| `contributing/releasing.md` | Steps 1,2,3,**5**,6 | Renumbered 1–5 |

I left the sibling `DELETE` claim in `generic-registry-api.md` alone —
it is accurate, no DELETE route is registered (the `http.MethodDelete`
hit in `server.go` is CORS config, not a route).

## Staleness banners rather than rewrites

**`design/tech-architecture.md`** is substantially fictional. Rather
than a vague "may be outdated", the banner lists what I verified is
wrong:

- Describes Helm-chart deployment; the registry is a plain `Deployment`
([registry.go:65](https://github.com/modelcontextprotocol/registry/blob/main/deploy/pkg/k8s/registry.go#L65)).
Helm is used only for third-party components.
- Diagram shows a `StatefulSet` on port **27017** — MongoDB's port. The
DB is PostgreSQL on 5432 via the CloudNativePG operator.
- Documents a `verify-domain` challenge flow (`POST /verify-domain`,
`/verify-domain/check`, server-issued tokens) that **was never built**.
- Documents `/admin/*` routes that are not registered.
- Says the DB stores user auth state and DNS verification records; only
`servers` and `server_extensions` tables exist.

**`design/roadmap.md`** still says "Phase 1: MVP/Go-Live (Current
Focus)" ~11 months after launch. I added a dated note rather than
inventing a current phase — that is a working-group call.

## Verification

All **101** remaining relative links across every `.md`/`.mdx` in the
repo resolve. The only two non-resolving matches are the intentional
`[project-name](link)` template placeholder and the moderation link
fixed in #1518.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 16:32:37 +03:00
Preeti Dewani
bb84ea69e8
Publisher-managed "deleted" support (#893)
(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
2026-02-27 09:00:07 -08:00
Tadas Antanavicius
65b96b03ce
docs: update API endpoint documentation from /v0/ to /v0.1/ (#802)
Update all documentation to reference the stable `/v0.1/` API version
instead of the development `/v0/` version.

Didn't update internal references (e.g. in admin-only docs) as that
probably make sense to keep pointed at v0 as the "dev" option.

Authored by Claude Code, reviewed by me.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 13:02:45 -08:00
Jonathan Hefner
fadbba2364
Fix remaining broken links from docs reorganization (#789)
Follow-up to #728.

This fixes broken links due to file renames.

Fixes #788.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-19 16:18:18 +00:00
Radoslav Dimitrov
b21c6f564d
Changes on the server.json format and the API (#562) 2025-09-29 23:30:35 +03:00
Tadas Antanavicius
56e8b4879b
Introduce serverId, rename id to versionId (#465)
Wielded Claude Code to do this; across many iterations and have reviewed
all the code + largely rewritten the PR commentary here.

This PR implements the server ID consistency changes from
[#396](https://github.com/modelcontextprotocol/registry/issues/396). Our
goal is to:
- Rename `id` to `versionId` to make it clear that it is the ID for a
specific version, not a server
- Introduce `serverId` as a net new concept. This will be 1:1 with
`name`. While not strictly necessary (we could just use name as a PK),
the convention of having a UUID as an ID on our objects is just a
helpful subjective architecture decision. Plus also leaves open the door
to reconsidering the "should we allow renames" question.

## Key Changes

### 🗄️ Database Schema Changes
- **Renamed**: `id` column → `version_id` (unique identifier for each
server version)

### 📋 Metadata Structure Updates
- **JSON Schema**: Updated
`_meta.io.modelcontextprotocol.registry/official` to include:
  - `serverId`: Consistent ID across all versions of a server
  - `versionId`: Unique ID for this specific version (renamed from `id`)

### 🔧 API Endpoint Updates
- **New endpoint structure**: Changed from version-ID-based to
server-ID-based URLs:
  - `GET /v0/servers/{server_id}` - Get latest version of server
  - `GET /v0/servers/{server_id}?version=X.X.X` - Get specific version  
- `GET /v0/servers/{server_id}/versions` - List all versions of a server
  - `PUT /v0/servers/{server_id}?version=X.X.X` - Edit specific version
- **Consistent URL patterns**: All server endpoints now use `server_id`
as the primary identifier
 
### Database Migration Strategy
The migration (`005_add_server_id_rename_version_id.sql`):
1. Adds new `version_id` column  
2. Generates deterministic UUIDs for servers with the same name
3. Updates JSON metadata to add `serverId` and rename `id` to
`versionId`
4. Copies existing `id` values to `version_id` column
5. Drops old `id` column and makes `version_id` the new primary key

## Testing

Besides of course automated tests passing, I:
1. Set up my local db with the pre-005-migration state, imported all the
production data
2. Ran the migration
3. Spot checked some diffs of the data that resulted --

```json
// before
{
  "name": "io.github.ruvnet/ruv-swarm",
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "id": "0a9cda7f-2b73-4839-844b-6582f335de42",
      "is_latest": false,
      "updated_at": "2025-09-10T17:21:34.92137012Z",
      "published_at": "2025-09-10T17:15:32.69690433Z"
    }
  },
  "version": "1.0.18",
  "repository": {
    "url": "",
    "source": ""
  },
  "description": "Neural network swarm orchestration with WebAssembly acceleration and MCP integration"
}

// after
{
  "name": "io.github.ruvnet/ruv-swarm",
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "serverId": "e8538952-96af-4a33-9e31-7fbed012521e",
      "is_latest": false,
      "versionId": "0a9cda7f-2b73-4839-844b-6582f335de42",
      "updated_at": "2025-09-10T17:21:34.92137012Z",
      "published_at": "2025-09-10T17:15:32.69690433Z"
    }
  },
  "version": "1.0.18",
  "repository": {
    "url": "",
    "source": ""
  },
  "description": "Neural network swarm orchestration with WebAssembly acceleration and MCP integration"
}

```

Servers that have multiple versions stayed consistent in their
`serverId`:

```json
// First version
{
  "name": "app.getdialer/dialer",
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "serverId": "80f08bdb-f3e4-4f19-b072-1676ae49b663",
      "is_latest": false,
      "versionId": "04f25b17-331d-48d7-b08b-37baece208a7",
      "updated_at": "2025-09-09T00:16:49.162620072Z",
      "published_at": "2025-09-08T23:47:09.452137971Z"
    }
  },
  "status": "active",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
  "remotes": [
    {
      "url": "https://getdialer.app/mcp",
      "type": "streamable-http"
    },
    {
      "url": "https://getdialer.app/sse",
      "type": "sse"
    }
  ],
  "version": "1.0.0",
  "repository": {
    "url": "",
    "source": ""
  },
  "description": "An MCP server that provides your you make outbound phone calls using your own phone number"
}

// Second version
{
  "name": "app.getdialer/dialer",
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "serverId": "80f08bdb-f3e4-4f19-b072-1676ae49b663",
      "is_latest": true,
      "versionId": "faa26cb9-3aad-415e-aece-f715fff5fe5e",
      "updated_at": "2025-09-09T00:16:49.107842808Z",
      "published_at": "2025-09-09T00:16:49.107842808Z"
    }
  },
  "status": "active",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
  "remotes": [
    {
      "url": "https://getdialer.app/mcp",
      "type": "streamable-http"
    },
    {
      "url": "https://getdialer.app/sse",
      "type": "sse"
    }
  ],
  "version": "1.0.1",
  "repository": {
    "url": "",
    "source": ""
  },
  "description": "An MCP server that provides lets you make outbound phone calls using your own phone number"
}
```

And I also tried publishing a test server anew; looked good:

```bash
⏺ Bash(curl -s "http://localhost:8080/v0/servers/102dc4e4-6ca8-40e6-aa11-cd45763d3352" | jq '.')
  ⎿  {                                                                                             
       "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
       "name": "io.modelcontextprotocol.anonymous/test-claude-migration-server",
       "description": "A test server to verify the new migration and API endpoints work correctly",
       "status": "active",
       "repository": {
         "url": "https://github.com/example/test-claude-migration-server",
         "source": "github",
         "id": "example/test-claude-migration-server"
       },
       "version": "1.0.0",
       "_meta": {
         "io.modelcontextprotocol.registry/official": {
           "serverId": "102dc4e4-6ca8-40e6-aa11-cd45763d3352",
           "versionId": "48c9cd55-7bc4-4ac2-896e-59e81eb653e4",
           "published_at": "2025-09-12T18:33:23.264203-07:00",
           "updated_at": "2025-09-12T18:33:23.264203-07:00",
           "is_latest": true
         }
       }
     }

⏺ Bash(curl -s "http://localhost:8080/v0/servers/102dc4e4-6ca8-40e6-aa11-cd45763d3352/versions" | jq '.')
  ⎿  {                                                                                                 
       "servers": [
         {
           "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
           "name": "io.modelcontextprotocol.anonymous/test-claude-migration-server",
           "description": "A test server to verify the new migration and API endpoints work correctly",
           "status": "active",
           "repository": {
             "url": "https://github.com/example/test-claude-migration-server",
             "source": "github",
             "id": "example/test-claude-migration-server"
           },
           "version": "1.0.0",
           "_meta": {
             "io.modelcontextprotocol.registry/official": {
               "serverId": "102dc4e4-6ca8-40e6-aa11-cd45763d3352",
               "versionId": "48c9cd55-7bc4-4ac2-896e-59e81eb653e4",
               "published_at": "2025-09-12T18:33:23.264203-07:00",
               "updated_at": "2025-09-12T18:33:23.264203-07:00",
               "is_latest": true
             }
           }
         }
       ],
       "metadata": {
         "count": 1
       }
     }
```

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Preeti Dewani <preetidewani1990@gmail.com>
Co-authored-by: adam jones <adamj+git@anthropic.com>
Co-authored-by: Adam Jones <adamj@anthropic.com>
2025-09-21 15:00:09 +03:00
adam jones
a85456a9b9
Add filtering functionality to server list endpoint (#374)
## Summary
- Adds `updated_since`, `search`, and `version` query parameters to `GET
/v0/servers`
- Enables incremental synchronization via RFC3339 timestamp filtering
- Provides simple substring search on server names
- Supports latest version filtering with `version=latest`

This implementation provides the core filtering capabilities needed for
efficient registry synchronization and improved server discovery.

Fixes #291
Fixes #135
2025-09-08 13:55:33 -07:00
adam jones
2e7108d366
Big docs tidy up in preparation for launch (#364)
## Motivation and Context
Docs currently don't have very clear organisation, and don't explain
core flows.

This fixes #89 (although we still might want to push these to
`https://modelcontextprotocol.io/docs/`), based on the plan there.

One minor change from that plan is that I merged tutorials and guides,
because they ended up basically being duplicates which I thought would
be annoying for us to keep in sync. Additionally in the Diátaxis
framework, tutorials and guides are separated by whether they are
focused on acquisition of skills (e.g. in a learning environment) or
application of skills (e.g. in a work environment). I expect the
registry to be something that will be used occasionally in a work
environment, rather than a fundamental 'learnable' skill so I think it's
reasonable not to have tutorials and fold these into guides.

## How Has This Been Tested?
- Read through all these updated docs
- Unit and integration tests (that previously used examples.md and use
the schema) working
- Ran `npx markdown-link-check .` to check all the links work

## Breaking Changes
Links to old docs will break, but I don't think there are any. All
internal links have been checked and updated.

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update
2025-09-07 10:44:42 +01:00