> **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>
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:
- For step-by-step instructions on creating and using server.json files, see the publishing guide.
- For understanding the validation requirements when publishing to the official registry, see official registry requirements.
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.