Published on
- 12 min read
A Practical Guide to MCP Repository Metadata and Versioning
A Practical Guide to MCP Repository Metadata and Versioning
You can’t trust what you can’t describe, and you can’t upgrade what you can’t version. MCP repositories live or die on those two facts.
This guide walks through how to structure metadata and versioning in Model Context Protocol (MCP) repositories so tools, models, and humans can actually depend on them—safely and predictably.
1. Why MCP Repository Metadata Matters
An MCP repository is more than a code bucket. It’s a catalog of machine-usable capabilities: tools, resources, prompts, schemas, and configuration that a model or orchestration layer can load on demand.
Metadata is how you answer three core questions, programmatically and reliably:
- What is this?
- Can I trust it?
- Is it compatible with my environment and version?
If your metadata is weak or inconsistent, you’ll face:
- Tools that appear in one environment and vanish in another.
- Breaking changes shipped as “minor upgrades”.
- Confusing duplication (“Which
github-searchtool is the current one?”). - Hard-to-debug failures when model clients auto-load or auto-update MCP repositories.
Investing in consistent, explicit metadata and versioning makes the rest of your MCP journey survivable.
2. The Core Metadata Surface of an MCP Repository
While implementations will evolve, any serious MCP repository should standardize a top-level metadata file—often something like:
mcp.jsonmcp.config.jsonmcp.yaml- or a similar canonical configuration format.
At a minimum, this file should cover:
- Repository identity.
- Versioning and compatibility.
- Ownership and trust.
- Capabilities.
- Distribution and installation hints.
Let’s break this down.
2.1 Identity: Naming Things So They Don’t Hurt Later
Identity metadata should feel boring. That’s good. It should include:
id: a stable, machine-friendly identifier- Example:
"id": "com.acme.mcp.github" - Treat this as immutable once published.
- Example:
name: human-readable label- Example:
"name": "Acme GitHub MCP Tools"
- Example:
description: short, precise, non-marketing explanation- Example:
"description": "Tools for querying repositories, issues, and pull requests via GitHub's REST and GraphQL APIs."
- Example:
homepageordocs: where a human can go to learn more- Example:
"homepage": "https://acme.dev/mcp/github"
- Example:
Use globally unique, reverse-DNS-style IDs where possible (similar to Java packages or Android app IDs). This avoids collision when multiple vendors release similarly named repositories.
2.2 Ownership, Contact, and Trust Signals
If a model client auto-discovers MCP repositories, it needs hints about who stands behind this code:
publisher: organisation or individual"publisher": "Acme Corp"
contact: support or security contact"contact": "security@acme.dev"
license: SPDX identifier or clear license text reference"license": "Apache-2.0"
source: canonical source repository"source": "https://github.com/acme/mcp-github"
You can go further with:
signingKeys: public keys for repository signatures.verification: references to transparency logs or signing services.securityPolicy: link to a security policy or advisory page.
These fields let infrastructure enforce policies such as:
- “Only use MCP repositories signed by keys we trust.”
- “Only auto-install repositories from publishers on an allowlist.”
2.3 Platform, Runtime, and Model Compatibility
MCP repositories often depend on a runtime (Node, Python, Docker, serverless) and may assume features or size limits for model context.
Provide clear compatibility metadata:
{
"runtime": {
"type": "node",
"version": ">=18.0.0"
},
"mcp": {
"protocolVersion": ">=1.1.0 <2.0.0",
"features": ["tools", "resources", "events"]
},
"models": [
{
"pattern": "gpt-4.*",
"constraints": {
"maxContextTokens": 128000,
"supportsStreaming": true
}
}
]
}
Key ideas:
- Runtime compatibility
type: e.g.node,python,docker,binary,http.version: range or minimum version.
- MCP protocol compatibility
- Use ranges (e.g.
>=1.1.0 <2.0.0) rather than a single pinned version.
- Use ranges (e.g.
- Model hints
- Not hard requirements, but guidance to orchestrators:
- Minimum context size for safe use.
- Whether tools require streaming or JSON mode.
- Any known incompatibilities.
- Not hard requirements, but guidance to orchestrators:
This unlocks smarter scheduling:
- Tooling can decide not to load a heavy repository when using a small-context model.
- Gateways can warn: “This MCP repository may exceed your model’s context window.”
3. Structuring Capability Metadata
A repository is a bundle of capabilities. For MCP, these usually fall into:
- Tools
- Resources
- Config / settings
- Optional background services or event feeds
Metadata should make each capability discoverable, type-safe, and explainable to both models and operators.
3.1 Tools: Input/Output Contracts in the Open
Each tool in your repository should have a machine-readable description. In JSON Schema–style, something like:
{
"tools": [
{
"name": "search_issues",
"version": "1.2.0",
"description": "Search GitHub issues by repository, labels, and status.",
"inputSchema": { /* JSON Schema */ },
"outputSchema": { /* JSON Schema */ },
"examples": [
{
"summary": "Find open bugs labeled 'priority: high'",
"input": {
"repo": "acme/mcp-github",
"labels": ["bug", "priority: high"],
"state": "open"
}
}
],
"rateLimits": {
"perMinute": 30,
"burst": 10
},
"auth": {
"type": "oauth2",
"scopes": ["repo", "read:org"]
},
"deprecated": false,
"replacedBy": null
}
]
}
Important pieces:
name: stable tool identifier within the repository.version: per-tool semantic version (more on this later).inputSchema/outputSchema: strict, validated schema definition.examples: canonical usage hints; models and evaluation tools love these.rateLimits: so orchestrators can pace calls.auth: what secrets or scopes are needed.deprecated/replacedBy: soft migrations rather than surprise deletions.
3.2 Resources: Data, Files, and Streams
Resources cover things like:
- Knowledge bases.
- Configuration files.
- File system roots.
- Remote indexes.
Describe each resource with:
{
"resources": [
{
"id": "kb.product_docs",
"name": "Product Documentation",
"description": "Indexed product docs with sections and change history.",
"type": "search-index",
"format": "markdown",
"location": "s3://acme-docs-index/prod",
"version": "2025.10.3",
"access": {
"requiresAuth": true,
"allowedRoles": ["support", "engineering"]
}
}
]
}
Key points:
- Use logical IDs (
kb.product_docs) that remain constant even as backing storage evolves. - Distinguish between resource version and repository version.
- Capture access control assumptions: many MCP clients will need to respect them.
3.3 Configuration and Settings
Operators need to see what a repository expects from its environment. Think:
- API keys and secrets.
- Optional feature flags.
- Per-tenant configuration.
Represent these in structured metadata:
{
"config": {
"required": [
{
"key": "GITHUB_TOKEN",
"description": "GitHub personal access token with repo and read:org scopes.",
"type": "string",
"secret": true
}
],
"optional": [
{
"key": "DEFAULT_ORG",
"description": "Fallback organization for repository discovery.",
"type": "string",
"secret": false,
"default": "acme"
}
]
}
}
This allows:
- Automatic UI generation for config screens.
- Pre-flight checks before loading the repository.
- Safer secret handling (no more “stuff everything in a
.envand hope”).
4. Designing a Versioning Strategy That Holds Up
Now to the part that saves you from upgrade chaos: versioning.
Developers instinctively reach for semantic versioning (SemVer). That’s a good start, but MCP repositories have a few twists:
- There is a repository version and often per-tool versions.
- Clients may auto-upgrade without human intervention.
- Models rely on contracts inferred from examples and prior behavior.
4.1 The Three Version Layers
Think in three layers:
- Repository version
- Overall package version.
- Example:
"version": "1.4.0".
- Protocol compatibility range
"mcp.protocolVersion": ">=1.1.0 <2.0.0".
- Tool/resource versions
- Each tool or major resource can have its own
version.
- Each tool or major resource can have its own
The repository version should follow SemVer rules driven by client-visible change:
- MAJOR: breaking changes to:
- Tool names or removal of previously stable tools.
- Input/output schemas in a backward-incompatible way.
- Auth requirements (e.g. dropping a supported auth method).
- Critical behavioral contracts (e.g. “this tool no longer returns streaming output where it used to”).
- MINOR: backward-compatible additions:
- New tools.
- New optional fields in schemas.
- Performance improvements that don’t alter contract.
- PATCH: bug fixes that do not affect schema or semantics:
- Fixing a bug that previously crashed on valid input.
- Correcting documentation and examples.
- Tightening validation to match documented behavior.
4.2 When Tool-Level Versioning Helps
Per-tool versioning is valuable when:
- You support long-lived automation that pins to a specific tool version.
- You foresee multiple variants of a tool living side by side.
Patterns that work:
- Use
tool.versionas a semantic contract for just that tool’s API. - Keep the repository
versionfor the bundle as a whole. - Allow clients to request:
- “Load
search_issuesversion1.x” or - “Any compatible
search_issueswith version^1.2.0”.
- “Load
This gives you flexibility to:
- Experiment with
search_issues2.0.0while keeping1.xstable. - Encourage gradual migration rather than forced wholesale upgrades.
5. Stable Contracts: Schema and Behavior
Version numbers only mean something if they track real, stable contracts.
5.1 Forward- and Backward-Compatible Schema Changes
Follow some basic rules:
- Backward compatible (safe for MINOR):
- Adding a new field that is optional and has a default.
- Expanding an enum with a new value if callers can ignore it.
- Extending
oneOforanyOfin a non-breaking way.
- Backward incompatible (requires MAJOR):
- Renaming or removing fields used by callers.
- Tightening validation so previously valid payloads now fail.
- Changing field types (e.g. string to array).
Document these explicitly in your metadata:
{
"changelog": [
{
"version": "1.3.0",
"date": "2026-02-10",
"changes": [
{
"type": "schema",
"scope": "tool:search_issues",
"compatibility": "backward-compatible",
"description": "Added optional 'assignee' field to filter issues by assignee."
}
]
}
]
}
Even if not all clients read the changelog, it’s invaluable for human operators and automated QA.
5.2 Behavioral Contracts Beyond Schema
Schema isn’t enough. You also have behavioral guarantees:
- Ordering of results.
- Default limits and timeouts.
- Error handling and retry semantics.
- Idempotency.
Define these somewhere machine-readable or at least stably documented:
{
"behavior": {
"search_issues": {
"ordering": "sorted by updated_at descending by default",
"defaultLimit": 50,
"maxLimit": 200,
"idempotent": true,
"timeoutMs": 10000,
"retries": {
"max": 2,
"backoff": "exponential"
}
}
}
}
When you change these in a way that matters to clients (for example, you cut timeoutMs drastically or change the default order), treat it as a contract change and version accordingly.
6. Dependency Metadata and Composition
MCP repositories will increasingly depend on each other. For example:
- A “sales assistant” repository depends on:
- CRM tools.
- Product docs search.
- HR directory for account ownership.
You should expose dependency metadata to avoid a hidden web of brittle imports.
6.1 Describing Dependencies Explicitly
Use a structure similar to package managers:
{
"dependencies": {
"com.acme.mcp.crm": "^2.0.0",
"com.acme.mcp.product_docs": "~1.3.0"
},
"optionalDependencies": {
"com.acme.mcp.hr_directory": ">=1.0.0 <2.0.0"
},
"peerDependencies": {
"com.acme.mcp.auth": "^1.1.0"
}
}
Where:
dependencies: repository must be present for full functionality.optionalDependencies: repository can enhance behavior but isn’t required.peerDependencies: repository expected to be provided by the host environment (e.g. a shared auth layer).
Model-aware orchestrators can then:
- Check for missing dependencies early.
- Suggest installing required peers.
- Avoid loading incompatible combinations.
6.2 Transitive Metadata and Flattening
If you chain several repositories, their dependency graphs can grow quickly.
Good practice:
- Keep first-level dependencies short and clearly justified.
- Split monolith repositories into smaller, focused MCP packages when dependencies balloon.
- Consider providing a “meta” repository that aggregates lower-level ones:
- For example,
com.acme.mcp.sales_suitethat depends on several specific MCP repositories and surfaces a curated set of tools.
- For example,
7. Publishing, Discovery, and Indexing Metadata
Once your metadata is structured, you need to expose it in ways tooling can discover.
7.1 Standard Locations and Endpoints
Common patterns:
- Static manifest file at the repository root:
mcp.jsonormcp.yaml.
- Well-known URL for remote repositories:
https://example.com/.well-known/mcp.json.
- HTTP discovery endpoint:
GET /mcp/manifestreturning JSON metadata.
Ensure:
- The manifest is cacheable (with ETags,
Last-Modified, or versioned URLs). - The manifest includes content hashes or signatures for integrity if possible.
7.2 Central Indexes vs. Local Catalogs
Environments will likely maintain:
- A central index (like npm or PyPI for MCP).
- Enterprise catalogs with curated, approved repositories.
Make your metadata index-friendly:
- Provide short, clear descriptions.
- Include categories or tags:
"categories": ["developer-tools", "code-search", "issue-tracking"]
- Expose a minimal “card” view:
- ID, name, publisher, last updated, key capabilities.
Discovery tools can then show:
- “All MCP repositories that offer
code_searchtools.” - “Only MCP repositories that support protocol
>=1.2.0.”
8. Managing Upgrades in the Real World
Version numbers on paper are easy. Live environments full of automations and human users are not.
You need operational patterns that respect metadata and versioning.
8.1 Pinning, Ranges, and Auto-Updates
Clients and orchestrators should support:
- Pinned versions: exact version, e.g.
1.2.3. - Version ranges:
^1.2.0,~1.3.0,>=2.0.0 <3.0.0. - Channels:
stable,beta,canary.
Consider a configuration like:
{
"repositories": [
{
"id": "com.acme.mcp.github",
"version": "^1.3.0",
"channel": "stable",
"autoUpdate": true
}
]
}
Tradeoffs:
- Pinning gives maximum safety but no security or bugfix updates.
- Ranges allow automatic, controlled updates within a major version.
- Channels let you test new versions on limited workloads first.
8.2 Deprecation Windows and Sunset Policies
Breaking a contract overnight is a fast way to lose trust in your MCP ecosystem.
Build in:
- Deprecation flags in metadata:
{ "deprecated": true, "deprecationDate": "2026-05-01", "sunsetDate": "2026-08-01", "migrationGuide": "https://acme.dev/mcp/github/migration-1.x-to-2.x" } - Advance communication of:
- Which tools or endpoints will go away.
- Which replacements exist.
- How behavior will change.
Use metadata to allow tooling to warn:
- “This MCP repository will sunset in 45 days; update to
2.x.”
8.3 Rollbacks and Safe Releases
When a new version misbehaves, you need a simple way back.
Suggestions:
- Keep older metadata and artifacts accessible for a defined retention window.
- Tag releases clearly (
v1.4.0,v1.4.0-hotfix1). - Use metadata fields like:
{ "status": "stable", // other values: "beta", "deprecated", "withdrawn" "replacedByVersion": "1.4.1" }
If you must withdraw a release:
- Mark it as
"status": "withdrawn"in the index. - Update discovery endpoints quickly.
- Provide remediation notes (e.g. “Do not use
1.4.0for batch jobs; upgrade to1.4.1”).
9. Security, Integrity, and Auditability
MCP repositories sit at the intersection of automation and external systems. Security metadata isn’t optional.
9.1 Signing and Integrity Metadata
Provide fields that let clients validate what they download:
{
"integrity": {
"manifestHash": "sha256-...",
"signedBy": [
{
"keyId": "acme-mcp-signing-1",
"signature": "base64-..."
}
],
"signingCertificates": [
"https://acme.dev/keys/mcp-signing-1.pem"
]
}
}
This supports:
- Chain-of-trust validation.
- Policy like “only load repositories signed by these keys”.
9.2 Permission and Data Access Metadata
For environments dealing with sensitive data, describe:
- Data categories accessed:
"dataCategories": ["source-code", "customer-data", "billing"]
- Data residency assumptions:
"dataResidency": ["eu-west-1", "us-east-1"]
- Logging behavior:
"logs": { "storesPayloads": false, "retentionDays": 30 }
This lets security teams enforce:
- “No MCP repositories that handle customer-data may be loaded in this sandbox.”
- “Only EU-only data repositories for EU workloads.”
9.3 Audit Trails and Change History
Maintain an append-only audit log of:
- Changes in metadata.
- Published versions and their hashes.
- Security advisories.
Even a simple JSON-based history file (mcp.history.json) is a big win for:
- Forensics (“which version was loaded at the time of incident X?”).
- Compliance documentation.
- Regression debugging.
10. A Minimal, Coherent Metadata Template
Bringing this together, here’s a compact template that covers the essentials without being unwieldy:
{
"id": "com.acme.mcp.github",
"name": "Acme GitHub MCP Tools",
"description": "Tools for searching and managing GitHub repositories, issues, and pull requests.",
"version": "1.3.0",
"publisher": "Acme Corp",
"contact": "support@acme.dev",
"license": "Apache-2.0",
"homepage": "https://acme.dev/mcp/github",
"source": "https://github.com/acme/mcp-github",
"mcp": {
"protocolVersion": ">=1.1.0 <2.0.0",
"features": ["tools", "resources"]
},
"runtime": {
"type": "node",
"version": ">=18.0.0"
},
"tools": [
{
"name": "search_issues",
"version": "1.2.0",
"description": "Search GitHub issues with flexible filters.",
"inputSchema": { "$ref": "./schemas/search_issues_input.json" },
"outputSchema": { "$ref": "./schemas/search_issues_output.json" },
"deprecated": false
}
],
"resources": [
{
"id": "kb.repo_readme_cache",
"name": "Repository README Cache",
"type": "document-store",
"format": "markdown",
"location": "s3://acme-mcp/github-readmes/prod",
"version": "2026.02.01"
}
],
"config": {
"required": [
{
"key": "GITHUB_TOKEN",
"description": "GitHub token with repo and read:org scopes.",
"type": "string",
"secret": true
}
]
},
"dependencies": {
"com.acme.mcp.auth": "^1.1.0"
},
"categories": ["developer-tools", "code", "github"],
"tags": ["github", "issues", "repos"],
"integrity": {
"manifestHash": "sha256-...",
"signedBy": []
}
}
You can extend this template as your ecosystem matures, but even this baseline delivers:
- Clear identity.
- Honest compatibility.
- Discoverable capabilities.
- A clean starting point for version-aware automation.
11. Practical Recommendations to Adopt Today
To close, here are concrete steps to bring order to your MCP repository metadata and versioning:
- Choose a canonical manifest format
- Decide on
mcp.json(or similar) and stick to it.
- Decide on
- Define a repository ID scheme
- Reverse-DNS, unique per repository, immutable once published.
- Enforce semantic versioning rules
- Document what counts as MAJOR/MINOR/PATCH in your org.
- Require schema metadata for every tool
- Input/output schemas; validate in CI.
- Track tool-level versions only when necessary
- Don’t overcomplicate unless you need side-by-side variants.
- Expose dependency and compatibility ranges
- MCP protocol versions, runtimes, and repository dependencies.
- Implement deprecation fields and sunset windows
- Never yank tools without warning and migration guidance.
- Sign manifests or at least hash them
- Prepare for stricter security policies down the road.
- Integrate metadata checks into CI
- Lint manifests, validate schemas, enforce version bumps for contract changes.
- Publish a concise changelog per release
- Link it from metadata so humans and tooling can find it fast.
Do these consistently and your MCP repositories will be easier to discover, safer to upgrade, and more trusted by every model and platform that depends on them.
External Links
Registry FAQ - Model Context Protocol (MCP) awesome-mcp-servers/docs/version-control.md at main - GitHub How to MCP - The Complete Guide to Understanding Model Context … What is MCP Registry? Architecture, Benefits & Setup Guide A Developer’s Guide to the MCP - Zep