registry/scripts/mirror_data/README.md
Radoslav Dimitrov 3e463e52bb
docs: correct contributor prerequisites and stale dev-env references (#1520)
The README prerequisites were both stale, and the docs restated the Go
version in three places.

## Prerequisites: name the source, do not restate the version

| README said | Reality |
|---|---|
| `Go 1.24.x` | `go 1.26` in
[go.mod](https://github.com/modelcontextprotocol/registry/blob/main/go.mod)
|
| `golangci-lint v2.4.0` | `v2.11.4` pinned in
[ci.yml:30](https://github.com/modelcontextprotocol/registry/blob/main/.github/workflows/ci.yml#L30)
|

Rather than swap in fresher numbers — which only resets the clock on the
same drift — this **removes the numbers** and names the authoritative
file:

```
- **Go** - version per the `go` directive in go.mod; the Go toolchain fetches it for you
- **golangci-lint** - version per the `golangci-lint-action` pin in ci.yml, so local lint matches CI
```

The Go version was stated in **three** places, which is exactly why all
three drifted together. All three now point at a single source, so the
prerequisites list cannot go stale.

Two notes on why the numbers earn so little in prose:

- **Go corrects itself.** `go.mod` has no `toolchain` directive, so
under the default `GOTOOLCHAIN=auto` the toolchain downloads the
required version automatically. A contributor on an older Go gets an
upgrade, not a failure — it only hard-errors under `GOTOOLCHAIN=local`.
(An earlier version of this description said such a contributor "cannot
build"; that was too strong.)
- **golangci-lint does not.** Version skew here genuinely changes what
you see: running CI's config under a newer golangci-lint (2.12.2)
surfaces 23 `goconst` findings in
`cmd/publisher/commands/validate_test.go` that CI's pinned 2.11.4 does
not report. That is why the README now points at the pin rather than a
number someone has to keep in sync.

## `make check` does more than documented

Documented in three files as "lint, unit tests and integration tests".
Actually [`check: dev-down lint validate
test-all`](https://github.com/modelcontextprotocol/registry/blob/main/Makefile#L85)
— it also runs schema validation and **stops your running `dev-compose`
environment**. Worth knowing before running it mid-session. The
Makefile's own `##` help string already said this correctly; only the
prose was stale.

## Other verified corrections

- **README project structure** omitted `cmd/registry/` — the server
entry point and ko/goreleaser build target — and `internal/importer/`.
- **`tests/integration/README.md`** said the suite launches **MongoDB**.
It launches PostgreSQL (`postgres-integration-test`), as the same file
admits nine lines later. It also cited `/v0/servers/{server_id}`, a path
removed a while ago; the test actually calls `GET /v0/servers` and `GET
/v0/servers/{serverName}/versions/latest`
([main.go:210,255](https://github.com/modelcontextprotocol/registry/blob/main/tests/integration/main.go#L210)).
- **`scripts/mirror_data/README.md`** pointed at
`internal/database/migrations/008_separate_official_metadata.sql`, which
does not exist — that migration is `009_`, while `008_` is
`clean_invalid_data.sql`. (Migration 008's own header still calls itself
"007a", which is how the numbering slipped.) Also swapped two "edit line
NN" pointers for identifier names, since both had already drifted
(`maxMigration` is at :30 not :24; the connection string at :23 not
:17), and corrected the fetch URL from `/v0.1/servers` to the
`/v0/servers` the script actually requests.
- **`.env.example`** was missing
`MCP_REGISTRY_ENABLE_REGISTRY_VALIDATION`, even though the config reads
it
([config.go:18](https://github.com/modelcontextprotocol/registry/blob/main/internal/config/config.go#L18))
and README:50 tells contributors to set it while pointing at
`.env.example` as *the* reference.
- **`docker-compose.yml`** set `MCP_REGISTRY_ENVIRONMENT`, which nothing
reads — no `ENVIRONMENT` env tag in `internal/config`, and no other
occurrence in the repo. Removed. (The Pulumi-side
`mcp-registry:environment` key is a separate, real thing and is
untouched.)
- **Deleted `CHANGES.md`** — 0 bytes, untouched since the squashed
history base, zero references anywhere.

## Verification

`docker compose config` validates. `grep` for `Go 1.x` / `golangci-lint
vX` across all `.md`/`.mdx` now returns nothing outside `complete.md`
(which #1522 deletes). Both `../../README.md#pre-requisites` links
resolve and the anchor matches the real `#### Pre-requisites` heading.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 16:32:25 +03:00

6.5 KiB

Mirror Production Data

Note: These tools were created by Claude Code as a simple way to kick the tires on data migrations. They are not intended for production use.

Tools to fetch and load production registry data for local testing and migration debugging.

Overview

These scripts help you:

  1. Fetch all server data from the production registry API
  2. Load it into a local PostgreSQL database
  3. Test migrations against real production data

Prerequisites

  • Go — see the prerequisites in the root README for the required version
  • PostgreSQL (via Docker or local installation)
  • Required Go packages:
    go get github.com/google/uuid github.com/lib/pq
    

Usage

1. Fetch Production Data

# From the project root directory
go run scripts/mirror_data/fetch_production_data.go

This will:

Output: production_servers.json containing all server records

2. Set Up Test Database

Start a PostgreSQL container for testing:

docker run -d --name test-postgres \
  -p 5433:5432 \
  -e POSTGRES_PASSWORD=testpass \
  -e POSTGRES_DB=registry_test \
  postgres:16

Or reset an existing database:

docker exec test-postgres psql -U postgres postgres -c "DROP DATABASE IF EXISTS registry_test;"
docker exec test-postgres psql -U postgres postgres -c "CREATE DATABASE registry_test;"

3. Load Production Data

# From the project root directory
go run scripts/mirror_data/load_production_data.go

This will:

  1. Connect to PostgreSQL at localhost:5433
  2. Apply migrations up to a configurable point (default: migration 007)
  3. Load all production server data
  4. Analyze the data and report statistics
  5. Show sample servers with NULL status values

To test a different migration, edit maxMigration in load_production_data.go

4. Test Migrations

After loading the data, you can test migrations against real production data.

Testing a Single Migration

# Test the separate_official_metadata migration
cat internal/database/migrations/009_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test

Debugging Failed Migrations

  1. Check the error output:
# Run migration and capture all output
cat internal/database/migrations/009_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test 2>&1 | \
  grep -E "(ERROR|NOTICE|WARNING)"
  1. Inspect data before migration:
# Check for NULL values that might cause issues
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT COUNT(*) FROM servers WHERE value->>'status' IS NULL;"

# Find sample problematic records
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT value->>'name', value->>'version' FROM servers \
   WHERE value->>'status' IS NULL LIMIT 5;"
  1. Test partial migrations:
# Extract and run only part of a migration to isolate issues
# For example, run only up to the NOT NULL constraint:
docker exec test-postgres psql -U postgres -d registry_test <<EOF
BEGIN;
-- Paste migration SQL up to the problematic line
-- Check intermediate state
SELECT COUNT(*) FROM servers WHERE status IS NULL;
ROLLBACK;  -- or COMMIT if testing further
EOF

Testing Migration Rollback

# Start a transaction to test and rollback
docker exec test-postgres psql -U postgres -d registry_test <<EOF
BEGIN;
\i /dev/stdin < internal/database/migrations/009_separate_official_metadata.sql
-- Inspect the results
\d servers
SELECT COUNT(*) FROM servers;
ROLLBACK;  -- Undo all changes
EOF

Iterative Testing Workflow

  1. Reset database to clean state:
docker exec test-postgres psql -U postgres postgres -c "DROP DATABASE IF EXISTS registry_test;"
docker exec test-postgres psql -U postgres postgres -c "CREATE DATABASE registry_test;"
go run scripts/mirror_data/load_production_data.go
  1. Test your migration changes:
cat internal/database/migrations/009_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test
  1. Verify the results:
# Check final table structure
docker exec test-postgres psql -U postgres -d registry_test -c "\d servers"

# Verify data integrity
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT COUNT(*), COUNT(DISTINCT server_name) FROM servers;"

Common Migration Issues to Check

  • NULL values: Check columns before adding NOT NULL constraints
  • Unique constraints: Verify no duplicates exist before adding
  • Check constraints: Validate all existing data matches the constraint
  • Data type changes: Ensure all values can be cast to new type
  • Foreign keys: Verify referential integrity before adding

5. Clean Up

docker stop test-postgres
docker rm test-postgres

Configuration

The load_production_data.go script connects to:

  • Host: localhost
  • Port: 5433
  • Database: registry_test
  • User: postgres
  • Password: testpass

Modify the sql.Open connection string in load_production_data.go if you need different connection parameters.

Example Output

When running load_production_data.go:

Running migrations 001-007...
  Applying migration 1: 001_initial_schema.sql
  Applying migration 2: 002_add_server_extensions.sql
  ...

Loading production data...
Loading 779 servers...
Data loaded successfully!

Total servers in database: 779

Analyzing status field in JSON data...
  Total servers: 779
  NULL status: 126
  Empty status: 0
  'null' string status: 0
  'active' status: 652
  'deprecated' status: 0
  'deleted' status: 0
  Other/Invalid: 1

Sample servers with NULL status:
  - com.biodnd/agent-ip@0.1.2
  - io.github.jkakar/cookwith-mcp@1.0.0
  ...

Database is ready for testing migration 008!

Troubleshooting

Port already in use

If port 5433 is already in use, either:

  • Stop the existing service using that port
  • Use a different port in both the Docker command and the Go script

Connection refused

Ensure the PostgreSQL container is running and healthy:

docker ps | grep test-postgres
docker logs test-postgres

Migration failures

The script stops at migration 007 intentionally. To test later migrations (008 onwards), run them manually after the data is loaded, in order.