| layout | default |
|---|---|
| title | Chapter 3: server.json Schema and Package Verification |
| nav_order | 3 |
| parent | MCP Registry Tutorial |
Welcome to Chapter 3: server.json Schema and Package Verification. In this part of MCP Registry Tutorial: Publishing, Discovery, and Governance for MCP Servers, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
The server.json spec is the core contract between publishers, registries, and consumers.
- model required fields and extension metadata safely
- understand supported package types and registry constraints
- satisfy ownership verification rules for each package ecosystem
- avoid common validation failures before publish
| Package Type | Ownership Signal |
|---|---|
| npm | mcpName in package.json |
| PyPI / NuGet | mcp-name: <server-name> marker in README |
| OCI | io.modelcontextprotocol.server.name image annotation |
| MCPB | artifact URL pattern + file SHA-256 metadata |
Run mcp-publisher validate locally before each publish attempt and treat warnings as pre-release review items.
- server.json Format Specification
- Official Registry Requirements
- Supported Package Types
- Publisher Validate Command
You can now design metadata that is far less likely to fail publication checks.
Next: Chapter 4: Authentication Models and Namespace Ownership
The validateRepository function in internal/validators/validators.go handles a key part of this chapter's functionality:
// Validate repository
repoResult := validateRepository(ctx.Field("repository"), serverJSON.Repository)
result.Merge(repoResult)
// Validate website URL if provided
websiteResult := validateWebsiteURL(ctx.Field("websiteUrl"), serverJSON.WebsiteURL)
result.Merge(websiteResult)
// Validate title if provided
titleResult := validateTitle(ctx.Field("title"), serverJSON.Title)
result.Merge(titleResult)
// Validate icons if provided
iconsResult := validateIcons(ctx.Field("icons"), serverJSON.Icons)
result.Merge(iconsResult)
// Validate all packages (basic field validation)
// Detailed package validation (including registry checks) is done during publish
for i, pkg := range serverJSON.Packages {
pkgResult := validatePackageField(ctx.Field("packages").Index(i), &pkg)
result.Merge(pkgResult)
}
// Validate all remotes
for i, remote := range serverJSON.Remotes {
remoteResult := validateRemoteTransport(ctx.Field("remotes").Index(i), &remote)
result.Merge(remoteResult)
}
return result
}This function is important because it defines how MCP Registry Tutorial: Publishing, Discovery, and Governance for MCP Servers implements the patterns covered in this chapter.
The validateWebsiteURL function in internal/validators/validators.go handles a key part of this chapter's functionality:
// Validate website URL if provided
websiteResult := validateWebsiteURL(ctx.Field("websiteUrl"), serverJSON.WebsiteURL)
result.Merge(websiteResult)
// Validate title if provided
titleResult := validateTitle(ctx.Field("title"), serverJSON.Title)
result.Merge(titleResult)
// Validate icons if provided
iconsResult := validateIcons(ctx.Field("icons"), serverJSON.Icons)
result.Merge(iconsResult)
// Validate all packages (basic field validation)
// Detailed package validation (including registry checks) is done during publish
for i, pkg := range serverJSON.Packages {
pkgResult := validatePackageField(ctx.Field("packages").Index(i), &pkg)
result.Merge(pkgResult)
}
// Validate all remotes
for i, remote := range serverJSON.Remotes {
remoteResult := validateRemoteTransport(ctx.Field("remotes").Index(i), &remote)
result.Merge(remoteResult)
}
return result
}
func validateRepository(ctx *ValidationContext, obj *model.Repository) *ValidationResult {
result := &ValidationResult{Valid: true, Issues: []ValidationIssue{}}This function is important because it defines how MCP Registry Tutorial: Publishing, Discovery, and Governance for MCP Servers implements the patterns covered in this chapter.
The validateTitle function in internal/validators/validators.go handles a key part of this chapter's functionality:
// Validate title if provided
titleResult := validateTitle(ctx.Field("title"), serverJSON.Title)
result.Merge(titleResult)
// Validate icons if provided
iconsResult := validateIcons(ctx.Field("icons"), serverJSON.Icons)
result.Merge(iconsResult)
// Validate all packages (basic field validation)
// Detailed package validation (including registry checks) is done during publish
for i, pkg := range serverJSON.Packages {
pkgResult := validatePackageField(ctx.Field("packages").Index(i), &pkg)
result.Merge(pkgResult)
}
// Validate all remotes
for i, remote := range serverJSON.Remotes {
remoteResult := validateRemoteTransport(ctx.Field("remotes").Index(i), &remote)
result.Merge(remoteResult)
}
return result
}
func validateRepository(ctx *ValidationContext, obj *model.Repository) *ValidationResult {
result := &ValidationResult{Valid: true, Issues: []ValidationIssue{}}
// Skip validation if repository is nil or empty (optional field)
if obj == nil || (obj.URL == "" && obj.Source == "") {
return result
}This function is important because it defines how MCP Registry Tutorial: Publishing, Discovery, and Governance for MCP Servers implements the patterns covered in this chapter.
The validateIcons function in internal/validators/validators.go handles a key part of this chapter's functionality:
// Validate icons if provided
iconsResult := validateIcons(ctx.Field("icons"), serverJSON.Icons)
result.Merge(iconsResult)
// Validate all packages (basic field validation)
// Detailed package validation (including registry checks) is done during publish
for i, pkg := range serverJSON.Packages {
pkgResult := validatePackageField(ctx.Field("packages").Index(i), &pkg)
result.Merge(pkgResult)
}
// Validate all remotes
for i, remote := range serverJSON.Remotes {
remoteResult := validateRemoteTransport(ctx.Field("remotes").Index(i), &remote)
result.Merge(remoteResult)
}
return result
}
func validateRepository(ctx *ValidationContext, obj *model.Repository) *ValidationResult {
result := &ValidationResult{Valid: true, Issues: []ValidationIssue{}}
// Skip validation if repository is nil or empty (optional field)
if obj == nil || (obj.URL == "" && obj.Source == "") {
return result
}
// validate the repository source
repoSource := RepositorySource(obj.Source)
if !IsValidRepositoryURL(repoSource, obj.URL) {This function is important because it defines how MCP Registry Tutorial: Publishing, Discovery, and Governance for MCP Servers implements the patterns covered in this chapter.
flowchart TD
A[validateRepository]
B[validateWebsiteURL]
C[validateTitle]
D[validateIcons]
E[validateIcon]
A --> B
B --> C
C --> D
D --> E