From 4014e8555182c5215a1e881892b5358158b7a46c Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 9 Oct 2025 10:19:18 -0700 Subject: [PATCH 1/3] Add support for on-device packages in MCP Registry - Introduced `on_device` registry type for pre-installed servers. - Added optional `manifest` and `__dirname` fields in package objects. - Updated validation logic to accept on-device packages without remote checks. - Enhanced documentation and examples for on-device server usage. --- .../contributing/add-package-registry.md | 4 +- docs/reference/api/openapi.yaml | 10 +++- docs/reference/server-json/CHANGELOG.md | 8 ++++ .../server-json/generic-server-json.md | 46 +++++++++++++++++++ docs/reference/server-json/server.schema.json | 14 +++++- internal/validators/package.go | 5 ++ internal/validators/validators_test.go | 1 + pkg/model/constants.go | 4 ++ pkg/model/types.go | 4 ++ 9 files changed, 91 insertions(+), 5 deletions(-) diff --git a/docs/guides/contributing/add-package-registry.md b/docs/guides/contributing/add-package-registry.md index a00f0931..d61c932e 100644 --- a/docs/guides/contributing/add-package-registry.md +++ b/docs/guides/contributing/add-package-registry.md @@ -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. @@ -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 (not needed for `on_device`, which is already defined). - 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). diff --git a/docs/reference/api/openapi.yaml b/docs/reference/api/openapi.yaml index 95c42429..6c023471 100644 --- a/docs/reference/api/openapi.yaml +++ b/docs/reference/api/openapi.yaml @@ -275,13 +275,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 @@ -336,6 +337,13 @@ components: description: A mapping of environment variables to be set when running the package. items: $ref: '#/components/schemas/KeyValueInput' + manifest: + type: object + description: Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'. + additionalProperties: true + __dirname: + type: string + description: Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'. Input: type: object diff --git a/docs/reference/server-json/CHANGELOG.md b/docs/reference/server-json/CHANGELOG.md index f828ee8e..dc744903 100644 --- a/docs/reference/server-json/CHANGELOG.md +++ b/docs/reference/server-json/CHANGELOG.md @@ -2,6 +2,14 @@ Changes to the server.json schema and format. +## Unreleased + +### Added +- Support for `on_device` `registryType` for pre-installed/system-managed MCP servers. +- New optional `manifest` field on package objects (used with `on_device`) to embed an MCPB-style manifest. +- New optional `__dirname` field on package objects to specify the local directory containing on-device server assets. + + ## 2025-09-29 ### ⚠️ BREAKING CHANGES diff --git a/docs/reference/server-json/generic-server-json.md b/docs/reference/server-json/generic-server-json.md index c6a0b4b3..7847edb1 100644 --- a/docs/reference/server-json/generic-server-json.md +++ b/docs/reference/server-json/generic-server-json.md @@ -678,3 +678,49 @@ 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" }, + "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": "C:\\Windows\\System32\\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-style metadata 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. + + diff --git a/docs/reference/server-json/server.schema.json b/docs/reference/server-json/server.schema.json index a033f2fa..84867dd3 100644 --- a/docs/reference/server-json/server.schema.json +++ b/docs/reference/server-json/server.schema.json @@ -192,6 +192,10 @@ }, "Package": { "properties": { + "__dirname": { + "description": "Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'.", + "type": "string" + }, "environmentVariables": { "description": "A mapping of environment variables to be set when running the package.", "items": { @@ -213,6 +217,11 @@ ], "type": "string" }, + "manifest": { + "additionalProperties": true, + "description": "Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'.", + "type": "object" + }, "packageArguments": { "description": "A list of arguments to be passed to the package's binary.", "items": { @@ -234,13 +243,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" }, diff --git a/internal/validators/package.go b/internal/validators/package.go index 7104f730..62317ec3 100644 --- a/internal/validators/package.go +++ b/internal/validators/package.go @@ -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) } diff --git a/internal/validators/validators_test.go b/internal/validators/validators_test.go index 6a8c6d42..ed1c6de4 100644 --- a/internal/validators/validators_test.go +++ b/internal/validators/validators_test.go @@ -1623,6 +1623,7 @@ func TestValidate_RegistryTypesAndUrls(t *testing.T) { {"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_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, model.RegistryURLGitHub, "https://github.com/domdomegg/airtable-mcp-server/releases/download/v1.7.2/airtable-mcp-server.mcpb", "1.7.2", "", true}, diff --git a/pkg/model/constants.go b/pkg/model/constants.go index dce27500..47874654 100644 --- a/pkg/model/constants.go +++ b/pkg/model/constants.go @@ -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 diff --git a/pkg/model/types.go b/pkg/model/types.go index ef2dbbb0..ea29c77e 100644 --- a/pkg/model/types.go +++ b/pkg/model/types.go @@ -31,6 +31,10 @@ type Package struct { RuntimeArguments []Argument `json:"runtimeArguments,omitempty"` PackageArguments []Argument `json:"packageArguments,omitempty"` EnvironmentVariables []KeyValueInput `json:"environmentVariables,omitempty"` + // Manifest is an optional embedded MCPB manifest describing an on-device server. Only used when registryType == on_device. + Manifest map[string]any `json:"manifest,omitempty"` + // Dirname is the directory on the local filesystem containing the on-device server (mirrors Node.js __dirname semantics for discovery). Only used when registryType == on_device. + Dirname string `json:"__dirname,omitempty"` } // Repository represents a source code repository as defined in the spec From e0bd45c418fdd6a41ad0118dca8dc8a518937c30 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Thu, 9 Oct 2025 10:25:50 -0700 Subject: [PATCH 2/3] Update expected server JSON count in validation --- tools/validate-examples/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/validate-examples/main.go b/tools/validate-examples/main.go index 4df9a88a..ac3cc0eb 100644 --- a/tools/validate-examples/main.go +++ b/tools/validate-examples/main.go @@ -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"), From 5b6929f381ef981a77de90b6303833c0783a44b8 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Fri, 10 Oct 2025 16:09:02 -0700 Subject: [PATCH 3/3] Refactor package registry documentation and schema: remove on-device specific fields and update changelog; those fields now go into _meta under com.microsoft.windows (or other vendor-specific namespace) --- docs/guides/contributing/add-package-registry.md | 2 +- docs/reference/api/openapi.yaml | 7 ------- docs/reference/server-json/CHANGELOG.md | 5 +---- docs/reference/server-json/generic-server-json.md | 12 ++++++++---- docs/reference/server-json/server.schema.json | 9 --------- pkg/model/types.go | 4 ---- 6 files changed, 10 insertions(+), 29 deletions(-) diff --git a/docs/guides/contributing/add-package-registry.md b/docs/guides/contributing/add-package-registry.md index d61c932e..87f1be95 100644 --- a/docs/guides/contributing/add-package-registry.md +++ b/docs/guides/contributing/add-package-registry.md @@ -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 (not needed for `on_device`, which is already defined). + - 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). diff --git a/docs/reference/api/openapi.yaml b/docs/reference/api/openapi.yaml index 6c023471..44cb9ce4 100644 --- a/docs/reference/api/openapi.yaml +++ b/docs/reference/api/openapi.yaml @@ -337,13 +337,6 @@ components: description: A mapping of environment variables to be set when running the package. items: $ref: '#/components/schemas/KeyValueInput' - manifest: - type: object - description: Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'. - additionalProperties: true - __dirname: - type: string - description: Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'. Input: type: object diff --git a/docs/reference/server-json/CHANGELOG.md b/docs/reference/server-json/CHANGELOG.md index dc744903..922c7bae 100644 --- a/docs/reference/server-json/CHANGELOG.md +++ b/docs/reference/server-json/CHANGELOG.md @@ -5,10 +5,7 @@ Changes to the server.json schema and format. ## Unreleased ### Added -- Support for `on_device` `registryType` for pre-installed/system-managed MCP servers. -- New optional `manifest` field on package objects (used with `on_device`) to embed an MCPB-style manifest. -- New optional `__dirname` field on package objects to specify the local directory containing on-device server assets. - +- 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 diff --git a/docs/reference/server-json/generic-server-json.md b/docs/reference/server-json/generic-server-json.md index 7847edb1..d49757ee 100644 --- a/docs/reference/server-json/generic-server-json.md +++ b/docs/reference/server-json/generic-server-json.md @@ -694,7 +694,11 @@ Some platforms (e.g., an operating system distribution) may provide a catalog of "identifier": "com.example.troubleshooting", "version": "1.0.0", "runtimeHint": "odr.exe", - "transport": { "type": "stdio" }, + "transport": { "type": "stdio" } + } + ], + "_meta": { + "com.microsoft.windows": { "manifest": { "manifest_version": "0.2", "name": "troubleshooting-mcp-server", @@ -703,7 +707,7 @@ Some platforms (e.g., an operating system distribution) may provide a catalog of "author": { "name": "ExampleOS" }, "server": { "type": "binary", - "entry_point": "C:\\Windows\\System32\\odr.exe", + "entry_point": "odr.exe", "mcp_config": { "command": "odr.exe", "args": ["mcp", "--proxy", "troubleshooting-mcp-server"] @@ -712,14 +716,14 @@ Some platforms (e.g., an operating system distribution) may provide a catalog of }, "__dirname": "C:\\Windows\\System32\\mcp\\troubleshooting" } - ] + } } ``` Notes: - `registryBaseUrl` is omitted because the package is not fetched remotely. -- `manifest` embeds the MCPB-style metadata so clients have consistent information without a download. +- `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. diff --git a/docs/reference/server-json/server.schema.json b/docs/reference/server-json/server.schema.json index 84867dd3..e71c639d 100644 --- a/docs/reference/server-json/server.schema.json +++ b/docs/reference/server-json/server.schema.json @@ -192,10 +192,6 @@ }, "Package": { "properties": { - "__dirname": { - "description": "Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'.", - "type": "string" - }, "environmentVariables": { "description": "A mapping of environment variables to be set when running the package.", "items": { @@ -217,11 +213,6 @@ ], "type": "string" }, - "manifest": { - "additionalProperties": true, - "description": "Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'.", - "type": "object" - }, "packageArguments": { "description": "A list of arguments to be passed to the package's binary.", "items": { diff --git a/pkg/model/types.go b/pkg/model/types.go index ea29c77e..ef2dbbb0 100644 --- a/pkg/model/types.go +++ b/pkg/model/types.go @@ -31,10 +31,6 @@ type Package struct { RuntimeArguments []Argument `json:"runtimeArguments,omitempty"` PackageArguments []Argument `json:"packageArguments,omitempty"` EnvironmentVariables []KeyValueInput `json:"environmentVariables,omitempty"` - // Manifest is an optional embedded MCPB manifest describing an on-device server. Only used when registryType == on_device. - Manifest map[string]any `json:"manifest,omitempty"` - // Dirname is the directory on the local filesystem containing the on-device server (mirrors Node.js __dirname semantics for discovery). Only used when registryType == on_device. - Dirname string `json:"__dirname,omitempty"` } // Repository represents a source code repository as defined in the spec