Skip to content

Commit 4014e85

Browse files
committed
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.
1 parent 036c935 commit 4014e85

File tree

9 files changed

+91
-5
lines changed

9 files changed

+91
-5
lines changed

docs/guides/contributing/add-package-registry.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The MCP Registry project is a **metaregistry**, meaning that it hosts metadata f
44

55
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.
66

7-
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).
7+
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.
88

99
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.
1010

@@ -38,7 +38,7 @@ These steps may evolve as additional validations or details are discovered and m
3838
- Add your package registry base url to the `registryBaseUrl` example array.
3939
- Add the single-shot CLI command name to the `runtimeHint` example value array.
4040
- Update the [`openapi.yaml`](../../reference/api/openapi.yaml)
41-
- Add your package registry name to the `registryType` enum value array.
41+
- Add your package registry name to the `registryType` enum value array (not needed for `on_device`, which is already defined).
4242
- Add your package registry base url to the `registryBaseUrl` enum value array.
4343
- Add the single-shot CLI command name to the `runtimeHint` example value array.
4444
- Add a sample, minimal `server.json` to the [`server.json` examples](../../reference/server-json/generic-server-json.md).

docs/reference/api/openapi.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,14 @@ components:
275275
properties:
276276
registryType:
277277
type: string
278-
description: Registry type indicating how to download packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb')
278+
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.
279279
examples:
280280
- "npm"
281281
- "pypi"
282282
- "oci"
283283
- "nuget"
284284
- "mcpb"
285+
- "on_device"
285286
registryBaseUrl:
286287
type: string
287288
format: uri
@@ -336,6 +337,13 @@ components:
336337
description: A mapping of environment variables to be set when running the package.
337338
items:
338339
$ref: '#/components/schemas/KeyValueInput'
340+
manifest:
341+
type: object
342+
description: Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'.
343+
additionalProperties: true
344+
__dirname:
345+
type: string
346+
description: Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'.
339347

340348
Input:
341349
type: object

docs/reference/server-json/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
Changes to the server.json schema and format.
44

5+
## Unreleased
6+
7+
### Added
8+
- Support for `on_device` `registryType` for pre-installed/system-managed MCP servers.
9+
- New optional `manifest` field on package objects (used with `on_device`) to embed an MCPB-style manifest.
10+
- New optional `__dirname` field on package objects to specify the local directory containing on-device server assets.
11+
12+
513
## 2025-09-29
614

715
### ⚠️ BREAKING CHANGES

docs/reference/server-json/generic-server-json.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,49 @@ For MCP servers that follow a custom installation path or are embedded in applic
678678
}
679679
```
680680

681+
### On-Device (Pre-Installed) Server Example
682+
683+
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.
684+
685+
```json
686+
{
687+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
688+
"name": "com.example/troubleshooting",
689+
"description": "On-device troubleshooting server provided by the OS",
690+
"version": "1.0.0",
691+
"packages": [
692+
{
693+
"registryType": "on_device",
694+
"identifier": "com.example.troubleshooting",
695+
"version": "1.0.0",
696+
"runtimeHint": "odr.exe",
697+
"transport": { "type": "stdio" },
698+
"manifest": {
699+
"manifest_version": "0.2",
700+
"name": "troubleshooting-mcp-server",
701+
"version": "1.0.0",
702+
"description": "MCP server for OS troubleshooting utilities",
703+
"author": { "name": "ExampleOS" },
704+
"server": {
705+
"type": "binary",
706+
"entry_point": "C:\\Windows\\System32\\odr.exe",
707+
"mcp_config": {
708+
"command": "odr.exe",
709+
"args": ["mcp", "--proxy", "troubleshooting-mcp-server"]
710+
}
711+
}
712+
},
713+
"__dirname": "C:\\Windows\\System32\\mcp\\troubleshooting"
714+
}
715+
]
716+
}
717+
```
718+
719+
Notes:
720+
721+
- `registryBaseUrl` is omitted because the package is not fetched remotely.
722+
- `manifest` embeds the MCPB-style metadata so clients have consistent information without a download.
723+
- `__dirname` gives clients a stable local path if they need to resolve relative resources (optional).
724+
- Validation for `on_device` packages does not perform remote ownership checks; responsibility shifts to the platform distribution.
725+
726+

docs/reference/server-json/server.schema.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@
192192
},
193193
"Package": {
194194
"properties": {
195+
"__dirname": {
196+
"description": "Optional local directory path containing the on-device server implementation (analogous to Node.js __dirname). Only used when registryType is 'on_device'.",
197+
"type": "string"
198+
},
195199
"environmentVariables": {
196200
"description": "A mapping of environment variables to be set when running the package.",
197201
"items": {
@@ -213,6 +217,11 @@
213217
],
214218
"type": "string"
215219
},
220+
"manifest": {
221+
"additionalProperties": true,
222+
"description": "Optional embedded MCPB manifest describing an on-device server. Only used when registryType is 'on_device'.",
223+
"type": "object"
224+
},
216225
"packageArguments": {
217226
"description": "A list of arguments to be passed to the package's binary.",
218227
"items": {
@@ -234,13 +243,14 @@
234243
"type": "string"
235244
},
236245
"registryType": {
237-
"description": "Registry type indicating how to download packages (e.g., 'npm', 'pypi', 'oci', 'nuget', 'mcpb')",
246+
"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.",
238247
"examples": [
239248
"npm",
240249
"pypi",
241250
"oci",
242251
"nuget",
243-
"mcpb"
252+
"mcpb",
253+
"on_device"
244254
],
245255
"type": "string"
246256
},

internal/validators/package.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ func ValidatePackage(ctx context.Context, pkg model.Package, serverName string)
2323
return registries.ValidateOCI(ctx, pkg, serverName)
2424
case model.RegistryTypeMCPB:
2525
return registries.ValidateMCPB(ctx, pkg, serverName)
26+
case model.RegistryTypeOnDevice:
27+
// On-device packages are assumed to be pre-installed and do not require
28+
// remote registry validation. Basic structural validation (e.g., presence
29+
// of identifier/version) is handled elsewhere. We simply accept them here.
30+
return nil
2631
default:
2732
return fmt.Errorf("unsupported registry type: %s", pkg.RegistryType)
2833
}

internal/validators/validators_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,7 @@ func TestValidate_RegistryTypesAndUrls(t *testing.T) {
16231623
{"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},
16241624
{"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
16251625
{"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
1626+
{"valid_on_device", "io.github.domdomegg/airtable-mcp-server", model.RegistryTypeOnDevice, "", "airtable-mcp-server", "1.7.2", "", false},
16261627

16271628
// Test MCPB without file hash (should fail)
16281629
{"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},

pkg/model/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ const (
77
RegistryTypeOCI = "oci"
88
RegistryTypeNuGet = "nuget"
99
RegistryTypeMCPB = "mcpb"
10+
// RegistryTypeOnDevice represents a package that is already available on the local device
11+
// and should be launched using the provided runtimeHint / manifest configuration rather than
12+
// being downloaded from a remote registry.
13+
RegistryTypeOnDevice = "on_device"
1014
)
1115

1216
// Registry Base URLs - supported package registry base URLs

pkg/model/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ type Package struct {
3131
RuntimeArguments []Argument `json:"runtimeArguments,omitempty"`
3232
PackageArguments []Argument `json:"packageArguments,omitempty"`
3333
EnvironmentVariables []KeyValueInput `json:"environmentVariables,omitempty"`
34+
// Manifest is an optional embedded MCPB manifest describing an on-device server. Only used when registryType == on_device.
35+
Manifest map[string]any `json:"manifest,omitempty"`
36+
// 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.
37+
Dirname string `json:"__dirname,omitempty"`
3438
}
3539

3640
// Repository represents a source code repository as defined in the spec

0 commit comments

Comments
 (0)