registry/docs/reference/server-json/generic-server-json.md
Wolfe-James 685e354b2f
feat: add cargo (crates.io) as a package registry type (#1207)
> **Update — 2026-06-01 (commit 1f3be53)**
>
> - **All @P4ST4S review feedback addressed** — positive-path hermetic
mock + live anchor against `rust-faf-mcp v0.3.1`; 5xx routed as
transient; doc comment qualified. See the [close-out
comment](https://github.com/modelcontextprotocol/registry/pull/1207#issuecomment-4589711057)
for the per-item breakdown.
> - **Runtime-model question RESOLVED** — `package-types.mdx` documents
cargo and MCPB as both first-class Rust MCP distribution paths (cargo
for source-distributed, MCPB for prebuilt-binary). The "Open question"
section below was the original draft framing; the doc now ships the
resolution.
> - **Cargo-specific gotcha discovered and documented** — crates.io
strips HTML comments during README rendering, unlike PyPI/NuGet.
`package-types.mdx` now spells this out so cargo authors don't ship
invisible mcp-name tokens (which is exactly what happened to
`rust-faf-mcp v0.3.0`; fixed in v0.3.1).
> - **Stale reference removed in this update** — the "Out of scope" line
mentioning `docs/guides/publishing/publish-cargo.md` pointed at a path
that doesn't exist. The canonical per-type doc is
`docs/modelcontextprotocol-io/package-types.mdx`; the Cargo section has
been added there directly.
> - **Two real-world Rust MCP servers queued for day-one register**:
`rust-faf-mcp v0.3.1` (live, end-to-end validated by the new live test)
and `perfetto-mcp-rs` ([@0xZOne](https://github.com/0xZOne) in #1055).
> - **Tests:** 19/19 cargo tests pass (16 existing + 2 hermetic + 1 live
anchor). `make validate` clean. `golangci-lint` 0 issues.

---

Adds support for `registryType: cargo` so Rust MCP servers published to
crates.io can be registered through the
documented validation flow rather than the MCPB binary-packaging
workaround. Closes #1055.

  ## Motivation and Context

#1055 noted that crates.io has ~1,800 MCP-related packages with no
direct path into the registry — only the MCPB
binary-packaging workaround. This PR adds first-class support for cargo
as a package registry type: schema +
API surface, validator, integration tests, and a documented example. The
publishing guide
(`docs/guides/publishing/publish-cargo.md`) follows on this branch once
the runtime-model direction in
  **Additional context** is settled.

  ## How Has This Been Tested?

- **`make validate`** — clean. Schema-vs-openapi sync verified; 17/17
examples in `generic-server-json.md`
validate against the schema; `expectedServerJSONCount` bumped 16 → 17 to
match the new Cargo example.
- **`go test ./internal/validators/...`** — passes. 16 cargo validator
sub-cases across 4 test functions, run
  against real crates.io (~2.5s wall):
    - Input validation rejection paths
- Registry-baseURL rejection (4 variants: different host, trailing
slash, http-not-https, subdomain typo)
- Ownership validation against real crates (`serde`, `tokio`, `rand`) —
all correctly rejected for missing
  `mcp-name` token
- Server-name format variations (canonical `io.github.OWNER/REPO`,
multi-hyphen, underscore, numeric suffix)
- **Positive-path test** — gated on `rust-faf-mcp` v0.2.3+ being
published with `mcp-name:
io.github.Wolfe-Jam/rust-faf-mcp` in its README. Reserved as a TODO in
`cargo_test.go`; uncomments to become the
   live anchor once that publish lands.
- **Local `make test-unit`** — not run due to a Go toolchain version
quirk on my workstation (project
auto-downloads 1.26.0; my local `go` is 1.25.6, causing compile
mismatch). CI will exercise the full
  PostgreSQL-backed suite.

  ## Breaking Changes

None. This is an additive change — `cargo` joins the supported
`registryType` enum alongside
`npm`/`pypi`/`nuget`/`oci`/`mcpb`. Existing publishes continue to work
unchanged.

  ## Types of changes

  - [x] New feature (non-breaking change which adds functionality)
- [x] Documentation update (new Cargo example in
`generic-server-json.md`)

  ## 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

  ## Additional context

  ### Validator design — two-call retrieval on the documented API

`internal/validators/registries/cargo.go` mirrors the PyPI validator's
README-token approach (substring-match
`mcp-name: <serverName>`), with a two-call retrieval pattern to stay on
the documented public crates.io API:

1. `GET /api/v1/crates/{name}/{version}/readme` returns 200 OK with a
JSON pointer (`{"url":
"https://static.crates.io/readmes/.../...html"}`) — crates.io hands us
the URL rather than emitting a 302.
2. Follow the pointer to the rendered HTML; substring-match for the
token.

The two-call pattern stays on the documented public surface. The CDN URL
layout is observed-stable, but treating
it as the entry point would mean depending on an undocumented path. With
two calls, crates.io controls where
the README lives — if they move it, the metadata endpoint hands us the
new URL.

Missing crates and missing versions surface as **403** from the CDN
(S3's default for missing keys), not 404.
The validator treats any non-200 as "not found" and surfaces the actual
status code in the error message.

  ### Open question — runtime model

Cargo's runtime model is genuinely different from npm/PyPI/NuGet. `cargo
install` is one-time (binary lands on
PATH at `~/.cargo/bin`), not per-invocation like `npx`, `uvx`, or `dnx`
(the new one in .NET 10 SDK Preview 6+).
The new Cargo example in `generic-server-json.md` annotates this
honestly and omits `runtimeHint`.

If a different framing is preferred — e.g. recommending **MCPB**
(prebuilt binary distribution via GitHub
Releases) as the primary path for Rust MCP servers instead of cargo —
happy to adjust the documentation
accordingly. The schema + validator code in this PR is **additive** and
doesn't force a recommendation either
way; a Rust author who chooses cargo can use it, and one who prefers
MCPB still can.

  ### Out of scope (deferred)

- **`docs/guides/publishing/publish-cargo.md`** — follows on this branch
once the runtime-model direction above
  is settled.
- **Publisher CLI `Cargo.toml` autodetect** in
`cmd/publisher/commands/init.go` — separate concern, separate PR.
- **Positive-path validator test** — gated on `rust-faf-mcp` v0.2.3+
publishing as noted in *How Has This Been
  Tested?*.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-06-03 10:56:43 -04:00

24 KiB

server.json Format Specification

A server.json file is a standardized way to describe MCP servers for registry publishing, client discovery, and package management.

Also see:

Browse the Complete Schema

📋 View the full specification interactively: Open server.schema.json in a schema viewer like json-schema.app.

The schema contains all field definitions, validation rules, examples, and detailed descriptions.

The official registry has some more restrictions on top of this. See the official registry requirements for details.

Extension Metadata with _meta

The optional _meta field allows publishers to include custom metadata alongside their server definitions using reverse DNS namespacing.

{
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      // Your custom metadata here
    }
  }
}

When publishing to the official registry, custom metadata must be placed under the key io.modelcontextprotocol.registry/publisher-provided. See the official registry requirements for detailed restrictions and examples.

Examples

Basic Server with NPM Package

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/brave-search",
  "description": "MCP server for Brave Search API integration",
  "title": "Brave Search",
  "websiteUrl": "https://anonymous.modelcontextprotocol.io/examples",
  "repository": {
    "url": "https://github.com/modelcontextprotocol/servers",
    "source": "github"
  },
  "version": "1.0.2",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "@modelcontextprotocol/server-brave-search",
      "version": "1.0.2",
      "transport": {
        "type": "stdio"
      },
      "environmentVariables": [
        {
          "name": "BRAVE_API_KEY",
          "description": "Brave Search API Key",
          "isRequired": true,
          "isSecret": true
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "npm-publisher",
      "version": "1.0.1",
      "build_info": {
        "timestamp": "2023-12-01T10:30:00Z"
      }
    }
  }
}

Server in a Monorepo with Subfolder

For MCP servers located within a subdirectory of a larger repository (monorepo structure), use the subfolder field to specify the relative path:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol/everything",
  "description": "MCP server that exercises all the features of the MCP protocol",
  "title": "Everything",
  "repository": {
    "url": "https://github.com/modelcontextprotocol/servers",
    "source": "github",
    "subfolder": "src/everything"
  },
  "version": "0.6.2",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "@modelcontextprotocol/everything",
      "version": "0.6.2",
      "transport": {
        "type": "stdio"
      }
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "npm-publisher",
      "version": "1.0.1",
      "build_info": {
        "timestamp": "2023-12-01T10:30:00Z"
      }
    }
  }
}

Constant (fixed) arguments needed to start the MCP server

Suppose your MCP server application requires a mcp start CLI arguments to start in MCP server mode. Express these as positional arguments like this:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.joelverhagen/knapcode-samplemcpserver",
  "description": "Sample NuGet MCP server for a random number and random weather",
  "version": "0.4.0-beta",
  "packages": [
    {
      "registryType": "nuget",
      "registryBaseUrl": "https://api.nuget.org/v3/index.json",
      "identifier": "Knapcode.SampleMcpServer",
      "version": "0.4.0-beta",
      "transport": {
        "type": "stdio"
      },
      "packageArguments": [
        {
          "type": "positional",
          "value": "mcp"
        },
        {
          "type": "positional",
          "value": "start"
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "nuget-publisher",
      "version": "2.1.0",
      "build_info": {
        "timestamp": "2023-11-15T14:22:00Z",
        "pipeline_id": "nuget-build-456"
      }
    }
  }
}

This will essentially instruct the MCP client to execute dnx Knapcode.SampleMcpServer@0.4.0-beta -- mcp start instead of the default dnx Knapcode.SampleMcpServer@0.4.0-beta (when no packageArguments are provided).

Filesystem Server with Multiple Packages

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.modelcontextprotocol/filesystem",
  "description": "Node.js server implementing Model Context Protocol (MCP) for filesystem operations.",
  "title": "Filesystem",
  "repository": {
    "url": "https://github.com/modelcontextprotocol/servers",
    "source": "github",
    "id": "b94b5f7e-c7c6-d760-2c78-a5e9b8a5b8c9"
  },
  "version": "1.0.2",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "@modelcontextprotocol/server-filesystem",
      "version": "1.0.2",
      "transport": {
        "type": "stdio"
      },
      "packageArguments": [
        {
          "type": "positional",
          "valueHint": "target_dir",
          "description": "Path to access",
          "default": "/Users/username/Desktop",
          "isRequired": true,
          "isRepeated": true
        }
      ],
      "environmentVariables": [
        {
          "name": "LOG_LEVEL",
          "description": "Logging level (debug, info, warn, error)",
          "default": "info"
        }
      ]
    },
    {
      "registryType": "oci",
      "identifier": "docker.io/mcp/filesystem:1.0.2",
      "transport": {
        "type": "stdio"
      },
      "runtimeArguments": [
        {
          "type": "named",
          "description": "Mount a volume into the container",
          "name": "--mount",
          "value": "type=bind,src={source_path},dst={target_path}",
          "isRequired": true,
          "isRepeated": true,
          "variables": {
            "source_path": {
              "description": "Source path on host",
              "format": "filepath",
              "isRequired": true
            },
            "target_path": {
              "description": "Path to mount in the container. It should be rooted in `/project` directory.",
              "isRequired": true,
              "default": "/project"
            }
          }
        }
      ],
      "packageArguments": [
        {
          "type": "positional",
          "valueHint": "target_dir",
          "value": "/project"
        }
      ],
      "environmentVariables": [
        {
          "name": "LOG_LEVEL",
          "description": "Logging level (debug, info, warn, error)",
          "default": "info"
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "ci-publisher",
      "version": "3.2.1",
      "build_info": {
        "commit": "a1b2c3d4e5f6789",
        "timestamp": "2023-12-01T10:30:00Z",
        "pipeline_id": "filesystem-build-789",
        "environment": "production"
      }
    }
  }
}

The same registryType / identifier pattern works for other supported OCI hosts. For example, an image on Quay.io:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.example/quay-sample-mcp",
  "description": "Example MCP server distributed as an OCI image on Quay.io",
  "version": "1.0.0",
  "packages": [
    {
      "registryType": "oci",
      "identifier": "quay.io/myorg/my-mcp-server:1.0.0",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

Remote Server Example

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/mcp-fs",
  "description": "Cloud-hosted MCP filesystem server",
  "repository": {
    "url": "https://github.com/example/remote-fs",
    "source": "github",
    "id": "xyz789ab-cdef-0123-4567-890ghijklmno"
  },
  "version": "2.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://mcp-fs.anonymous.modelcontextprotocol.io/http"
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "cloud-deployer",
      "version": "2.4.0",
      "build_info": {
        "commit": "f7e8d9c2b1a0",
        "timestamp": "2023-12-05T08:45:00Z",
        "deployment_id": "remote-fs-deploy-456",
        "region": "us-west-2"
      }
    }
  }
}

Python Package Example

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.example/weather-mcp",
  "description": "Python MCP server for weather data access",
  "title": "Weather",
  "repository": {
    "url": "https://github.com/example/weather-mcp",
    "source": "github",
    "id": "def456gh-ijkl-7890-mnop-qrstuvwxyz12"
  },
  "version": "0.5.0",
  "packages": [
    {
      "registryType": "pypi",
      "registryBaseUrl": "https://pypi.org",
      "identifier": "weather-mcp-server",
      "version": "0.5.0",
      "runtimeHint": "uvx",
      "transport": {
        "type": "stdio"
      },
      "environmentVariables": [
        {
          "name": "WEATHER_API_KEY",
          "description": "API key for weather service",
          "isRequired": true,
          "isSecret": true
        },
        {
          "name": "WEATHER_UNITS",
          "description": "Temperature units (celsius, fahrenheit)",
          "default": "celsius"
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "poetry-publisher",
      "version": "1.8.3",
      "build_info": {
        "python_version": "3.11.5",
        "timestamp": "2023-11-28T16:20:00Z",
        "build_id": "pypi-weather-123",
        "dependencies_hash": "sha256:a9b8c7d6e5f4"
      }
    }
  }
}

Cargo (Rust) Package Example

cargo install <crate> places the binary on PATH (via ~/.cargo/bin); MCP clients invoke it directly by name. There is no single-shot equivalent of npx (npm), uvx (PyPI), or dnx (NuGet, .NET 10 SDK) for cargo — install once, run by name.

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.example/widget-mcp",
  "description": "Rust-native MCP server",
  "title": "Widget",
  "repository": {
    "url": "https://github.com/example/widget-mcp",
    "source": "github"
  },
  "version": "0.3.0",
  "packages": [
    {
      "registryType": "cargo",
      "registryBaseUrl": "https://crates.io",
      "identifier": "widget-mcp",
      "version": "0.3.0",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

NuGet (.NET) Package Example

The dnx tool ships with the .NET 10 SDK, starting with Preview 6.

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.joelverhagen/knapcode-samplemcpserver",
  "description": "Sample NuGet MCP server for a random number and random weather",
  "repository": {
    "url": "https://github.com/joelverhagen/Knapcode.SampleMcpServer",
    "source": "github",
    "id": "example-nuget-id-0000-1111-222222222222"
  },
  "version": "0.5.0",
  "packages": [
    {
      "registryType": "nuget",
      "registryBaseUrl": "https://api.nuget.org/v3/index.json",
      "identifier": "Knapcode.SampleMcpServer",
      "version": "0.5.0",
      "runtimeHint": "dnx",
      "transport": {
        "type": "stdio"
      },
      "environmentVariables": [
        {
          "name": "WEATHER_CHOICES",
          "description": "Comma separated list of weather descriptions to randomly select.",
          "isRequired": true,
          "isSecret": false
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "dotnet-publisher",
      "version": "8.0.100",
      "build_info": {
        "dotnet_version": "8.0.0",
        "timestamp": "2023-12-10T12:15:00Z",
        "configuration": "Release",
        "target_framework": "net8.0",
        "build_number": "20231210.1"
      }
    }
  }
}

Complex Docker Server with Multiple Arguments

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.example/database-manager",
  "description": "MCP server for database operations with support for multiple database types",
  "repository": {
    "url": "https://github.com/example/database-manager-mcp",
    "source": "github",
    "id": "ghi789jk-lmno-1234-pqrs-tuvwxyz56789"
  },
  "version": "3.1.0",
  "packages": [
    {
      "registryType": "oci",
      "identifier": "docker.io/example/database-manager-mcp:3.1.0",
      "transport": {
        "type": "stdio"
      },
      "runtimeArguments": [
        {
          "type": "named",
          "name": "--network",
          "value": "host",
          "description": "Use host network mode"
        },
        {
          "type": "named",
          "name": "-e",
          "value": "DB_TYPE={db_type}",
          "description": "Database type to connect to",
          "isRepeated": true,
          "variables": {
            "db_type": {
              "description": "Type of database",
              "choices": [
                "postgres",
                "mysql",
                "mongodb",
                "redis"
              ],
              "isRequired": true
            }
          }
        }
      ],
      "packageArguments": [
        {
          "type": "named",
          "name": "--host",
          "description": "Database host",
          "default": "localhost",
          "isRequired": true
        },
        {
          "type": "named",
          "name": "--port",
          "description": "Database port",
          "format": "number"
        },
        {
          "type": "positional",
          "valueHint": "database_name",
          "description": "Name of the database to connect to",
          "isRequired": true
        }
      ],
      "environmentVariables": [
        {
          "name": "DB_USERNAME",
          "description": "Database username",
          "isRequired": true
        },
        {
          "name": "DB_PASSWORD",
          "description": "Database password",
          "isRequired": true,
          "isSecret": true
        },
        {
          "name": "SSL_MODE",
          "description": "SSL connection mode",
          "default": "prefer",
          "choices": [
            "disable",
            "prefer",
            "require"
          ]
        }
      ]
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "docker-buildx",
      "version": "0.12.1",
      "build_info": {
        "docker_version": "24.0.7",
        "timestamp": "2023-12-08T14:30:00Z",
        "platform": "linux/amd64,linux/arm64",
        "registry": "docker.io",
        "image_digest": "sha256:1a2b3c4d5e6f7890"
      }
    }
  }
}

Server with Remote and Package Options

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/hybrid-mcp",
  "description": "MCP server available as both local package and remote service",
  "title": "Hybrid",
  "repository": {
    "url": "https://github.com/example/hybrid-mcp",
    "source": "github",
    "id": "klm012no-pqrs-3456-tuvw-xyz789abcdef"
  },
  "version": "1.5.0",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "@example/hybrid-mcp-server",
      "version": "1.5.0",
      "runtimeHint": "npx",
      "transport": {
        "type": "stdio"
      },
      "packageArguments": [
        {
          "type": "named",
          "name": "--mode",
          "description": "Operation mode",
          "default": "local",
          "choices": [
            "local",
            "cached",
            "proxy"
          ]
        }
      ]
    }
  ],
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://mcp.anonymous.modelcontextprotocol.io/http",
      "headers": [
        {
          "name": "X-API-Key",
          "description": "API key for authentication",
          "isRequired": true,
          "isSecret": true
        },
        {
          "name": "X-Region",
          "description": "Service region",
          "default": "us-east-1",
          "choices": [
            "us-east-1",
            "eu-west-1",
            "ap-southeast-1"
          ]
        }
      ]
    },
    {
      "type": "sse",
      "url": "https://mcp.anonymous.modelcontextprotocol.io/sse"
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "hybrid-deployer",
      "version": "1.7.2",
      "build_info": {
        "timestamp": "2023-12-03T11:00:00Z",
        "deployment_strategy": "blue-green",
        "npm_version": "10.2.4",
        "node_version": "20.10.0",
        "service_endpoints": {
          "sse": "deployed",
          "streamable": "deployed"
        }
      }
    }
  }
}

MCP Bundle (MCPB) Package Example

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol/text-editor",
  "description": "MCP Bundle server for advanced text editing capabilities",
  "title": "Text Editor",
  "repository": {
    "url": "https://github.com/modelcontextprotocol/text-editor-mcpb",
    "source": "github"
  },
  "version": "1.0.2",
  "packages": [
    {
      "registryType": "mcpb",
      "identifier": "https://github.com/modelcontextprotocol/text-editor-mcpb/releases/download/v1.0.2/text-editor.mcpb",
      "fileSha256": "fe333e598595000ae021bd27117db32ec69af6987f507ba7a63c90638ff633ce",
      "transport": {
        "type": "stdio"
      }
    }
  ],
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": {
      "tool": "mcpb-publisher",
      "version": "1.0.0",
      "build_info": {
        "timestamp": "2023-12-02T09:15:00Z",
        "bundle_format": "mcpb-v1"
      }
    }
  }
}

This example shows an MCPB (MCP Bundle) package that:

  • Is hosted on GitHub Releases (an allowlisted provider)
  • Includes a SHA-256 hash for integrity verification
  • Can be downloaded and executed directly by MCP clients that support MCPB

Embedded MCP inside a CLI tool

Some CLI tools bundle an MCP server, without a standalone MCP package or a public repository. In these cases, reuse the existing packages shape by pointing at the host CLI package and supplying the packageArguments and runtimeHint if needed to start the MCP server.

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.snyk/cli-mcp",
  "description": "MCP server provided by the Snyk CLI",
  "title": "Snyk",
  "version": "1.1298.0",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "snyk",
      "version": "1.1298.0",
      "transport": {
        "type": "stdio"
      },
      "packageArguments": [
        { "type": "positional", "value": "mcp" },
        {
          "type": "named",
          "name": "-t",
          "description": "Transport type for MCP server",
          "default": "stdio",
          "choices": ["stdio", "sse"]
        }
      ]
    }
  ]
}

Server with Custom Installation Path

For MCP servers that follow a custom installation path or are embedded in applications without standalone packages, use the websiteUrl field to direct users to setup documentation:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/embedded-mcp",
  "description": "MCP server embedded in a Desktop app",
  "websiteUrl": "https://anonymous.modelcontextprotocol.io/embedded-mcp-guide",
  "version": "0.1.0"
}

Remote Server with URL Templating

This example demonstrates URL templating for remote servers, useful for multi-tenant deployments where each instance has its own endpoint. Unlike Package transports (which reference parent arguments/environment variables), Remote transports define their own variables:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/multi-tenant-server",
  "description": "MCP server with configurable remote endpoint",
  "title": "Multi-Tenant Server",
  "version": "1.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://anonymous.modelcontextprotocol.io/mcp/{tenant_id}",
      "variables": {
        "tenant_id": {
          "description": "Tenant identifier (e.g., 'us-cell1', 'emea-cell1')",
          "isRequired": true
        }
      }
    }
  ]
}

Clients configure the tenant identifier, and the {tenant_id} variable in the URL gets replaced with the provided variable value to connect to the appropriate tenant endpoint (e.g., https://anonymous.modelcontextprotocol.io/mcp/us-cell1 or https://anonymous.modelcontextprotocol.io/mcp/emea-cell1).

The same URL templating works with SSE transport:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.modelcontextprotocol.anonymous/events-server",
  "description": "MCP server using SSE with tenant-specific endpoints",
  "version": "1.0.0",
  "remotes": [
    {
      "type": "sse",
      "url": "https://events.anonymous.modelcontextprotocol.io/sse/{tenant_id}",
      "variables": {
        "tenant_id": {
          "description": "Tenant identifier",
          "isRequired": true
        }
      }
    }
  ]
}

Local Server with URL Templating

This example demonstrates URL templating for local/package servers, where variables reference parent Package arguments or environment variables:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.example/configurable-server",
  "description": "Local MCP server with configurable port",
  "title": "Configurable Server",
  "version": "1.0.0",
  "packages": [
    {
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "identifier": "@example/mcp-server",
      "version": "1.0.0",
      "transport": {
        "type": "streamable-http",
        "url": "http://localhost:{--port}/mcp"
      },
      "packageArguments": [
        {
          "type": "named",
          "name": "--port",
          "description": "Port for the server to listen on",
          "default": "3000"
        }
      ]
    }
  ]
}

The {--port} variable in the URL references the --port argument name from packageArguments. For positional arguments, an argument with the valueHint of port could similarly be referenced as {port}. When the package runs with --port 8080, the URL becomes http://localhost:8080/mcp.