Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/guides/contributing/add-package-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The MCP Registry project is a **metaregistry**, meaning that it hosts metadata f

For local MCP servers, the MCP Registry has pointers in the `packages` node of the [`server.json`](../../reference/server-json/generic-server-json.md) schema that refer to packages in supported package managers.

The list of supported package managers for hosting MCP servers is defined by the `properties.packages[N].properties.registryType` string enum in the [`server.json` schema](../../reference/server-json/server.schema.json). For example, this could be "npm" (for npmjs.com packages) or "pypi" (for PyPI packages).
The list of supported package managers for hosting MCP servers is defined by the `properties.packages[N].properties.registryType` string enum in the [`server.json` schema](../../reference/server-json/server.schema.json). For example, this could be "npm" (for npmjs.com packages) or "pypi" (for PyPI packages). A special `on_device` value is also supported for pre-installed, system-managed servers that do not originate from a remote package registry.

For remote MCP servers, the package registry is not relevant. The MCP client consumes the server via a URL instead of by downloading and running a package. In other words, this document only applies to local MCP servers.

Expand Down Expand Up @@ -38,7 +38,7 @@ These steps may evolve as additional validations or details are discovered and m
- Add your package registry base url to the `registryBaseUrl` example array.
- Add the single-shot CLI command name to the `runtimeHint` example value array.
- Update the [`openapi.yaml`](../../reference/api/openapi.yaml)
- Add your package registry name to the `registryType` enum value array.
- Add your package registry name to the `registryType` enum value array.
- Add your package registry base url to the `registryBaseUrl` enum value array.
- Add the single-shot CLI command name to the `runtimeHint` example value array.
- Add a sample, minimal `server.json` to the [`server.json` examples](../../reference/server-json/generic-server-json.md).
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,14 @@ components:
properties:
registryType:
type: string
description: Registry type indicating how to download packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb')
description: Registry type indicating how to download or locate packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb', 'on_device'). The 'on_device' type represents a pre-installed server that should be launched locally and not downloaded.
examples:
- "npm"
- "pypi"
- "oci"
- "nuget"
- "mcpb"
- "on_device"
registryBaseUrl:
type: string
format: uri
Expand Down
5 changes: 5 additions & 0 deletions docs/reference/server-json/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Changes to the server.json schema and format.

## Unreleased

### Added
- Support for `on_device` `registryType` for pre-installed/system-managed MCP servers. For servers marked as such, registries provide MCPB manifests and `__dirname` in `server._meta`.

## 2025-09-29

### ⚠️ BREAKING CHANGES
Expand Down
50 changes: 50 additions & 0 deletions docs/reference/server-json/generic-server-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,3 +672,53 @@ For MCP servers that follow a custom installation path or are embedded in applic
}
```

### On-Device (Pre-Installed) Server Example

Some platforms (e.g., an operating system distribution) may provide a catalog of pre-installed or system-managed MCP servers. These can be referenced using the `on_device` `registryType`. In this case, the server is not downloaded from a registry. Instead, the platform launches it using a known runtime or entry point. An embedded `manifest` can be provided (reusing the MCPB manifest format) along with an optional `__dirname` pointing to the local directory where related assets or binaries reside.

```json
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
"name": "com.example/troubleshooting",
"description": "On-device troubleshooting server provided by the OS",
"version": "1.0.0",
"packages": [
{
"registryType": "on_device",
"identifier": "com.example.troubleshooting",
"version": "1.0.0",
"runtimeHint": "odr.exe",
"transport": { "type": "stdio" }
}
],
"_meta": {
"com.microsoft.windows": {
"manifest": {
"manifest_version": "0.2",
"name": "troubleshooting-mcp-server",
"version": "1.0.0",
"description": "MCP server for OS troubleshooting utilities",
"author": { "name": "ExampleOS" },
"server": {
"type": "binary",
"entry_point": "odr.exe",
"mcp_config": {
"command": "odr.exe",
"args": ["mcp", "--proxy", "troubleshooting-mcp-server"]
}
}
},
"__dirname": "C:\\Windows\\System32\\mcp\\troubleshooting"
}
}
}
```

Notes:

- `registryBaseUrl` is omitted because the package is not fetched remotely.
- `manifest` embeds the MCPB manifest so clients have consistent information without a download.
- `__dirname` gives clients a stable local path if they need to resolve relative resources (optional).
- Validation for `on_device` packages does not perform remote ownership checks; responsibility shifts to the platform distribution.


5 changes: 3 additions & 2 deletions docs/reference/server-json/server.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,14 @@
"type": "string"
},
"registryType": {
"description": "Registry type indicating how to download packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb')",
"description": "Registry type indicating how to download or locate packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb', 'on_device'). The 'on_device' type represents a pre-installed server that should be launched locally and not downloaded.",
"examples": [
"npm",
"pypi",
"oci",
"nuget",
"mcpb"
"mcpb",
"on_device"
],
"type": "string"
},
Expand Down
5 changes: 5 additions & 0 deletions internal/validators/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ func ValidatePackage(ctx context.Context, pkg model.Package, serverName string)
return registries.ValidateOCI(ctx, pkg, serverName)
case model.RegistryTypeMCPB:
return registries.ValidateMCPB(ctx, pkg, serverName)
case model.RegistryTypeOnDevice:
// On-device packages are assumed to be pre-installed and do not require
// remote registry validation. Basic structural validation (e.g., presence
// of identifier/version) is handled elsewhere. We simply accept them here.
return nil
default:
return fmt.Errorf("unsupported registry type: %s", pkg.RegistryType)
}
Expand Down
5 changes: 5 additions & 0 deletions internal/validators/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1619,8 +1619,13 @@ func TestValidate_RegistryTypesAndUrls(t *testing.T) {
{"valid_oci", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeOCI, "", "domdomegg/airtable-mcp-server:1.7.2", "", "", false},
{"valid_nuget", "io.github.domdomegg/time-mcp-server", model.RegistryTypeNuGet, model.RegistryURLNuGet, "TimeMcpServer", "1.0.2", "", false},
{"valid_nuget", "io.github.domdomegg/time-mcp-server", model.RegistryTypeNuGet, "", "TimeMcpServer", "1.0.2", "", false},
{"valid_mcpb_github", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeMCPB, model.RegistryURLGitHub, "https://github.com/domdomegg/airtable-mcp-server/releases/download/v1.7.2/airtable-mcp-server.mcpb", "1.7.2", "fe333e598595000ae021bd27117db32ec69af6987f507ba7a63c90638ff633ce", false},
{"valid_mcpb_github", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeMCPB, "", "https://github.com/domdomegg/airtable-mcp-server/releases/download/v1.7.2/airtable-mcp-server.mcpb", "1.7.2", "fe333e598595000ae021bd27117db32ec69af6987f507ba7a63c90638ff633ce", false},
{"valid_mcpb_gitlab", "io.gitlab.fforster/gitlab-mcp", model.RegistryTypeMCPB, model.RegistryURLGitLab, "https://gitlab.com/fforster/gitlab-mcp/-/releases/v1.31.0/downloads/gitlab-mcp_1.31.0_Linux_x86_64.tar.gz", "1.31.0", "abc123ef4567890abcdef1234567890abcdef1234567890abcdef1234567890", false}, // this is not actually a valid mcpb, but it's the closest I can get for testing for now
{"valid_mcpb_gitlab", "io.gitlab.fforster/gitlab-mcp", model.RegistryTypeMCPB, "", "https://gitlab.com/fforster/gitlab-mcp/-/releases/v1.31.0/downloads/gitlab-mcp_1.31.0_Linux_x86_64.tar.gz", "1.31.0", "abc123ef4567890abcdef1234567890abcdef1234567890abcdef1234567890", false}, // this is not actually a valid mcpb, but it's the closest I can get for testing for now
{"valid_mcpb_github", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeMCPB, "", "https://github.com/domdomegg/airtable-mcp-server/releases/download/v1.7.2/airtable-mcp-server.mcpb", "", "fe333e598595000ae021bd27117db32ec69af6987f507ba7a63c90638ff633ce", false},
{"valid_mcpb_gitlab", "io.gitlab.fforster/gitlab-mcp", model.RegistryTypeMCPB, "", "https://gitlab.com/fforster/gitlab-mcp/-/releases/v1.31.0/downloads/gitlab-mcp_1.31.0_Linux_x86_64.tar.gz", "", "abc123ef4567890abcdef1234567890abcdef1234567890abcdef1234567890", false}, // this is not actually a valid mcpb, but it's the closest I can get for testing for now
{"valid_on_device", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeOnDevice, "", "airtable-mcp-server", "1.7.2", "", false},

// Test MCPB without file hash (should fail)
{"invalid_mcpb_no_hash", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeMCPB, "", "https://github.com/domdomegg/airtable-mcp-server/releases/download/v1.7.2/airtable-mcp-server.mcpb", "", "", true},
Expand Down
4 changes: 4 additions & 0 deletions pkg/model/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const (
RegistryTypeOCI = "oci"
RegistryTypeNuGet = "nuget"
RegistryTypeMCPB = "mcpb"
// RegistryTypeOnDevice represents a package that is already available on the local device
// and should be launched using the provided runtimeHint / manifest configuration rather than
// being downloaded from a remote registry.
RegistryTypeOnDevice = "on_device"
)

// Registry Base URLs - supported package registry base URLs
Expand Down
2 changes: 1 addition & 1 deletion tools/validate-examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func main() {

func runValidation() error {
// Define what we validate and how
expectedServerJSONCount := 12
expectedServerJSONCount := 13
targets := []validationTarget{
{
path: filepath.Join("docs", "reference", "server-json", "generic-server-json.md"),
Expand Down
Loading