Home · Guides

server.json, field by field, with the limits that fail a publish

Three fields are required: name, description and version. Everything else is optional, and most publish failures come from a limit on one of the three rather than from a missing field.

The one that catches people: description has a maximum length of 100 characters. Not 100 words, and not a soft guideline. It is maxLength: 100 in the schema, so a sentence that reads well in a README is refused.

Top level

FieldType and limitsNotes
namestring, 3 to 200, pattern ^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$Reverse DNS namespace, exactly one forward slash. Capitals are legal and they change your search rank.
descriptionstring, 1 to 100"Should focus on capabilities, not implementation details."
versionstring, up to 255Must be unique per publication. Immutable once published.
titlestring, 1 to 100, optionalDisplay name. Clients may or may not use it.
websiteUrlURI, optionalHomepage or documentation.
repositoryobject, optionalurl and source both required if present.
packagesarray, optionalInstallable forms.
remotesarray, optionalHosted endpoints.
iconsarray, optionalSee below.
_metaobject, optionalReverse-DNS namespaced extension data.
$schemaURI, optionalPoints at the schema version you wrote against.

A server may declare packages, remotes, both, or neither. Neither is legal and useless: a survey filed as registry#1579 on 2026-08-27 counted 387 active servers that declare no package and no remote and therefore cannot be reached by anything.

version, and the four ways it goes wrong

Any string up to 255 characters is accepted, but the registry parses it as a semantic version for sorting and to decide which row is marked latest. From the registry's versioning documentation, read 2026-09-09:

packages

registryType, identifier and transport are required on every entry. registryType is a string such as npm, pypi, oci, nuget or mcpb. version must be a specific version; ranges are rejected here too.

fileSha256 is a 64-character lowercase hex string, required for mcpb packages and optional for the rest. A downloadable bundle with no hash is not publishable, which is the right way round: the identifier for an mcpb package is a URL, and a URL alone proves nothing about what arrives.

The remaining fields are runtimeHint, runtimeArguments, packageArguments, environmentVariables and registryBaseUrl. The schema carries a warning on the argument types worth reading before you accept user input into one: arguments build command lines, and a client that runs them through a shell inherits an injection risk, so the schema tells clients to prefer non-shell execution.

remotes

type is streamable-http or sse, and url must match ^https?://[^\s]+$. Both fields are required. SSE is deprecated and exists for older clients; a server may publish both at different URLs.

URLs support {curly_brace} template variables with a variables map carrying description, isRequired, default, choices and isSecret, which is how a multi-tenant or multi-region service publishes one entry. headers declares headers the client should send, each with its own isRequired and isSecret.

One rule is not in the schema and will fail your publish anyway: a remote URL already claimed by a different server name is refused. That is its own trap.

repository and icons

repository needs url and source, and takes an optional id and subfolder, the latter being the relative path to the server inside a monorepo.

icons entries need src, an HTTPS URI of at most 255 characters. The optional mimeType is an enum of png, jpeg, jpg, svg+xml and webp, and sizes entries must match WxH or the literal any. The schema warns consumers to treat SVGs carefully, since they can carry script.

_meta

Custom data survives publishing under _meta.io.modelcontextprotocol.registry/publisher-provided. There is a hard 4096-byte limit on the JSON, and exceeding it fails the publish. The registry writes its own block at _meta.io.modelcontextprotocol.registry/official carrying status, publishedAt, updatedAt and isLatest, which is where you read whether a row is active or deprecated.

Sources: https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json, fetched and parsed 2026-09-09, for every type, limit and pattern quoted; the registry documentation pages on versioning, remote servers and the FAQ, read the same day, for the version rules and the 4KB limit. This project publishes its whole catalogue to the registry and has hit the description limit, the version-range rule and the remote URL rule.

Questions

What happens if my description is longer than 100 characters?

The publish is rejected by schema validation. Write the 100-character version first and treat it as a headline: what the server does, in the words someone would use to look for it. The long explanation belongs in the README and on your website.

Do I have to include $schema?

No, it is optional. Including it pins the version you wrote against, which is worth doing because the schema is generated from the registry's OpenAPI definition and does change.

Can I publish without a repository?

Yes, repository is optional. It is recommended for transparency, and directories that build from source have nothing to build without it, so a server with only a remote endpoint and no repository limits where it can be listed.

Which registryType do I use for a downloadable bundle?

mcpb, with the identifier set to the download URL and fileSha256 set to the file's hash. That is the only package type where the hash is required.

Can I fix a typo in a published version?

No. Metadata is immutable per version, so the fix is a new version string. Nothing can be unpublished either, so the version with the typo stays visible in the version list even after a newer one is marked latest.

Related

All MCP servers and prices · All guides · Buy the bundle $39