Model Context Protocol Documentation: Spec, Schema, Changelog
Model Context Protocol documentation is versioned by date, not by number. Each revision has its own specification pages, a schema published beside them, and a changelog recording what moved since the previous revision. Read the revision your client negotiated, use the schema when a field's shape matters, and read the changelog before you upgrade anything.
Short answer: Model Context Protocol documentation is versioned by date, not by number. Each revision has its own specification pages, a schema published beside them, and a changelog recording what moved since the previous revision. Read the revision your client negotiated, use the schema when a field's shape matters, and read the changelog before you upgrade anything.
Key takeaways
- Three documents, three questions. The specification says what is required, the schema says what a field's shape is, and the changelog says what changed and when.
- Revisions are dates. A page lives under
/specification/<YYYY-MM-DD>/, so a citation without the date is a citation of the site, not of a document. - Older revisions stay published. A client that negotiates 2025-11-25 is not broken by the existence of 2026-07-28; it is broken by a server that stopped honouring the older text.
- A schema beats prose for details. Enum values, optional fields and error codes are exact in the schema and approximate in a paragraph, so check the machine-readable half when a field matters.
- The changelog is the only honest upgrade note. It names the changes and the proposals behind them, which is the difference between reading a version number and knowing what it implies.
- Do this next: open your client's negotiated revision, find the matching changelog page, and write the revision date into your integration notes next to the client's version — that pair is what you will need the next time behaviour changes after an upgrade.
Documentation is the part of a protocol ecosystem that ages fastest, because the ecosystem moves while the text stays dated. The Model Context Protocol's documentation is unusually explicit about this: the site keeps every revision online, each one carries its own schema, and a changelog records the distance between them. What follows is how to read that set — which page answers which question, and which copy is authoritative when two of them disagree.
Where the protocol documentation actually lives
The documentation set is four surfaces rather than one. The specification is the normative text,
published per revision under modelcontextprotocol.io/specification/<revision>/, with chapters for
the lifecycle, the transports, authorization and each server and client feature. The schema is the
TypeScript source of the wire types, published beside each revision and rendered on the site as a
schema reference. The changelog is a per-revision page that lists what changed since the previous
revision, with the proposal identifiers behind each change. And the registry is a separate metadata
service for discovering servers, which answers a question the specification deliberately leaves out.
When an argument starts, the order to settle it is short: specification for requirements, schema for
shapes, changelog for history, registry only for discovery. If the actors themselves are still
unclear — which side is a client, what a capability negotiation is for — the protocol overview page
is the one page worth reading before any of the four, because every citation below assumes it.
A professional reading order for the specification
A professional first pass through the specification is five pages long, in this order: the overview for what the protocol is, the versioning page for how two peers agree on a revision, the lifecycle for what a connection does over time, the transports page for how messages travel, and the page for the primitive you actually use. What makes that order work is that documentation is assembled from sources rather than written page by page, and the loader is honest about it:
# lib/source.ts — source lines 18–27 (docsLoader)
function docsLoader(locale: Locale) {
const collection = (locale === "zh" ? docsZh : docsEn) as {
docs: Parameters<typeof toFumadocsSource>[0];
meta: Parameters<typeof toFumadocsSource>[1];
};
return loader({
baseUrl: "/docs",
source: toFumadocsSource(collection.docs, collection.meta),
});
}
Two collections and one locale decision. The content collection carries the documents, the meta collection carries the ordering and grouping, and the loader combines them into a single source under one base URL. That is why the specification reads consistently across revisions: the prose changes, the shell does not. Two consequences for a reader. First, a page's position — which sidebar section it appears in, and what precedes it — is editorial structure rather than protocol requirement, so cite the page rather than the sidebar label. Second, the locale switch happens at load time, which means a translation can lag the English text; when a requirement matters, read the revision's own words rather than the translation you were linked to.
Anyone arriving from a general AI course — an IBM RAG and agentic AI professional certificate, say — already has the retrieval half of the picture and none of the wire. The certificate teaches how documents get embedded and retrieved; this protocol teaches how a client asks a server for them. If your reading time is limited, spend it on the versioning and lifecycle pages, because those are the two places where an integration silently diverges from the specification it claims to implement.
Databricks AI gateway docs: reading a vendor page against the schema
Vendor documentation is the second layer of this set, and its relationship to the specification is easy to get wrong. An AI gateway product — Databricks's own gateway among them — documents its routing, its keys and its budget features; when it mentions protocol topics it is describing its implementation, not the requirement. Read a vendor page for what it configures and the specification for what a client must send. Versioned product schemas are where the two layers meet, and they are worth reading carefully because they encode the same discipline:
# config/plan-catalog.ts — source lines 60–74 (gatewaySeed)
function gatewaySeed(
rpm: number,
dailyCap: number | null,
): GatewayPolicyV1 {
return {
defaults: { compress_ratio: 0.5, budget_count_model: "deepseek-chat" },
playground: { rpm, daily_request_cap: dailyCap },
governance: {
allow_member_tool_overrides: false,
allow_integrator_hmac_budget: false,
},
analytics: { dashboard_include_playground: false },
aut_baseline: { ...PLATFORM_DEFAULTS.aut_baseline },
};
}
The type name carries the version — a policy object whose shape is pinned to a first revision — and the body separates three kinds of field. Defaults are values the deployment inherits when it says nothing. Playground settings are the ones an operator tunes per plan. Governance switches are booleans that are off unless someone deliberately turns them on, which tells you where a product's safe defaults actually live: in code that ships, not in a paragraph that recommends. When you read a vendor's page about protocol support, look for the same three things — the version token, the defaults, and the switches — and you will know how much of the page is a promise and how much is current behaviour.
Cloudflare AI gateway pricing: how a doc source version-stamps a page
Any documentation set that is served from a store rather than from static files needs two guarantees, and they are both visible in twenty lines of a source adapter. The first is that every page carries a version stamp, so a consumer can tell a current document from a leftover. The second is that the index only lists pages that still exist. Cloudflare's own AI gateway pricing page is the kind of vendor document that changes numbers without changing its URL, which is exactly why the stamp matters more than the address:
# lib/pseo/sources/cf-kv-source.ts — source lines 5–34 (CloudflareKVPseoSource)
class CloudflareKVPseoSource implements PseoSource {
async getPage(urlPath: string): Promise<PseoPageData | null> {
const data = await kvGet<PseoPageData & { version?: number }>(pseoPageKey(urlPath));
if (!data || (data.version !== undefined && data.version < 1)) return null;
return data;
}
async getIndex(indexKey: string): Promise<PseoIndex | null> {
return kvGet<PseoIndex>(indexKey);
}
async validateItems(items: PseoIndexItem[], kind?: string): Promise<PseoIndexItem[]> {
if (!items?.length) return [];
if (!kind) return items;
const results = await Promise.allSettled(
items.map(async (item) => {
const exists = await kvKeyExists(pseoContentKey(kind, item.slug));
return { item, exists };
}),
);
return results
.filter(
(r): r is PromiseFulfilledResult<{ item: PseoIndexItem; exists: boolean }> =>
r.status === "fulfilled" && r.value.exists,
)
.map((r) => r.value.item);
}
}
Read it as a set of promises about reading documentation. The page fetch returns nothing when the stored version is below the first revision, so an old record cannot be served as if it were current; a missing page is a miss rather than a best guess. The index fetch is a simple read, but the validation pass is the interesting one: it walks every item in the index, checks whether the content key behind it exists, and drops the ones that do not, in parallel, keeping the order of the items that survive. That is the difference between a curated index and a list of links that rots. Apply the same two rules to any doc set you maintain — stamp each page with the revision it was written against, and validate the index against the store before serving it — and dead links stop being a maintenance chore.
Databricks Unity AI gateway: what the documentation shell owns
Every published documentation set is two layers: a shell that owns navigation, width and footer, and a page that owns content. Knowing which layer you are looking at tells you whether a page can be cited. A shell is small — usually a navigation block, a wrapper and a footer — and its job is to make hundreds of pages look like one product:
# app/[locale]/(docs)/layout.tsx — source lines 10–21 (DocsLayout)
function DocsLayout({ children }: DocsLayoutProps) {
return (
<div className="flex flex-col">
<NavMobile />
<NavBar />
<MaxWidthWrapper className="min-h-screen" large>
{children}
</MaxWidthWrapper>
<SiteFooter className="border-t" />
</div>
);
}
Nothing in that shell knows anything about the protocol, and that is the point. The navigation is rendered for every page in the section, the wrapper sets the reading measure, and the footer closes the document. When you evaluate a vendor page — a Databricks Unity AI gateway chapter, for example — check whether the shell exposes two things: a revision or "last updated" marker, and a way to move to the previous revision of the same text. A shell that shows neither cannot tell you whether the words underneath are current, and a page that cannot be dated cannot be cited as a requirement. The practical rule is to cite the specification when a behaviour is mandatory, and a vendor page when you are describing that vendor's product.
Agent workflow memory: the index built on first use
Agent workflow memory is usually discussed as a property of the agent, and in the documentation context it is a property of the workload: something has to build the index that search runs against, and it should be built once, lazily, under its own name. The excerpt below is that pattern in code — a vector store created on first access, with a collection name derived from the resource it belongs to and a client shared with the parent store to avoid lock contention in embedded mode:
# backend/smartgate/modules/memory/algorithm.py — source lines 389–411 (Memory.entity_store)
@property
def entity_store(self):
"""Lazily initialize entity store on first use."""
if self._entity_store is None:
entity_config = _safe_deepcopy_config(self.config.vector_store.config)
entity_collection = f"{self.collection_name}_entities"
# Set collection name on the cloned config
if hasattr(entity_config, 'collection_name'):
entity_config.collection_name = entity_collection
elif isinstance(entity_config, dict):
entity_config['collection_name'] = entity_collection
# For Qdrant, share the existing client to avoid RocksDB lock contention
# when using embedded mode (path=...). QdrantConfig.client takes precedence
# over host/port/path.
if self.config.vector_store.provider == "qdrant" and hasattr(self.vector_store, "client"):
if hasattr(entity_config, "client"):
entity_config.client = self.vector_store.client
elif isinstance(entity_config, dict):
entity_config["client"] = self.vector_store.client
self._entity_store = VectorStoreFactory.create(
self.config.vector_store.provider, entity_config
)
return self._entity_store
Three decisions worth copying into a documentation pipeline. The store is created on first use rather than at import, so a process that never searches never pays for it. The collection name is derived — resource name plus a suffix — so two indexes cannot collide by accident. And the client is shared with the parent store where the provider needs it, because two clients pointing at one embedded database is a lock error waiting for load. The documentation lesson is that an index is a cache of the docs and nothing more: when the underlying pages change, the index is stale until it is rebuilt, which is why the version stamp from the previous section belongs on the page and the index key rather than only in a filename.
Schema reference and schema.ts: the machine-readable half
The schema is the part of the documentation set that a program can read, and it is published beside each revision as TypeScript source, with a rendered reference on the site. Use it whenever a question has a shape rather than a narrative answer: which fields are optional, which strings an enum accepts, which error code a failure returns. The newest revision is a good illustration of why this matters. It changed a resource-not-found error code to the JSON-RPC invalid-params code and added cache hints and a cache scope to list results — the kind of change that a paragraph mentions in passing and a schema states exactly. Reading the schema also tells you what the specification does not require: optional fields that a client may omit, and defaults a server may choose. A schema is a contract about shape, not a description of behaviour, so pair every field you take from it with the requirement that governs it.
The envelope those fields travel in is a separate document, and the JSON-RPC message format is where a request, a notification and a result are told apart — a distinction no field type in the schema carries.
Changelog discipline: 2026-07-28 against 2025-11-25
The changelog is the page most integrations never open, and it is the one that explains the afternoon. Read it top-down, because the entries are ordered by consequence rather than by topic. Major changes come first: the current revision removes protocol-level sessions and the session header from the HTTP transport, makes list endpoints independent of a connection, replaces server-initiated requests with a multi round-trip pattern, and adds an optional discovery call for clients that want capabilities up front. Smaller entries then carry the details that break code — list results gain cache hints, a not-found error code moves, authorization gains a check that requires an issuer parameter in the response to be validated by the client. Two habits make the page useful. Read it against the revision you negotiated rather than the newest one, since a client on the previous revision is unaffected by most of it. And treat the deprecation policy as part of the documentation: a feature moves from active to deprecated to removed, with a minimum gap between the last two, so a changelog entry is a schedule and not just a notice.
What an AI gateway, agent memory and RAG add to this
Three adjacent literatures get read alongside the protocol, and each answers a different question. An AI gateway is a proxy with policy — routing, keys, budgets, request logs — and its documentation is about operations rather than about the wire; read it when you are deciding who may call your server and what a call costs. Agent memory is what an assistant carries between turns, and its literature is about storage and retrieval rather than about messages; read it when the context a client sends is assembled from somewhere other than the conversation. RAG versus agentic AI is a debate about pipelines and loops, and it matters here only because it decides which of the three server primitives you reach for. None of the three is normative for the protocol, and all three are worth a page of reading — which is roughly how much this page gives them.
How SmartGate compares
Documentation discipline is not a competitor comparison, so read this table as a reading list for one question: where do I find the answer, and how much do I trust it?
| Where you read it | What it answers | How it changes | Trust it for |
|---|---|---|---|
| The dated specification | what is required of a client or server | once per revision, kept online | requirements and conformance |
| The schema, published per revision | field shapes, enums, error codes | with the revision it ships beside | exact types and defaults |
| The per-revision changelog | what moved and which proposal moved it | one page per revision | upgrade planning |
| A vendor's own documentation | that vendor's configuration and features | on the vendor's release cycle | describing that vendor |
| SmartGate's product docs | the seven tools, their limits and the audit surface | on the product's release cycle | running this endpoint |
What an MCP gateway does is the product-shaped answer to the operational questions a specification will not answer, and where the acronym's parts come from is the page to read first if the names in a client's configuration file are still opaque.
How to get started
- Find your client's negotiated revision. It is chosen during negotiation and carried on every later request as a protocol-version header; the client's log or its source will show it.
- Open that revision, not the newest one. Change the date segment in the URL; the site keeps every revision published, so the page you need usually exists.
- Read the changelog for that revision before the pages. The first section names the changes that break integrations; the rest is detail you can look up on demand.
- Pin the schema you are coding against. Keep the revision's schema beside your integration notes, because a field's shape is not part of a URL's promise.
- Stamp your own documentation. A doc set without a revision marker per page ages invisibly; the adapter earlier in this page shows the two rules that stop it, a version field and an index validated against the store.
- Then follow the cluster. The specification walkthrough walks the lifecycle and the error model, the transport history explains what each revision changed about connections, and the Anthropic client page covers the client half.
Start on the free tier — 2 million tokens a month and all seven tools — with start free; per-plan limits are on the pricing page, the endpoint shape and tool list are in the product docs, and contract traffic starts with the contact form. The tool surface itself is catalogued in the tools reference, and if you are deciding whether a server needs to exist at all, the protocol server page is the other half of this reading list.
Frequently Asked Questions
Limitations and what this does not do
- Three of eight sections carry no code. The gateways, memory and RAG sections matched no unique symbol in this codebase, so they are written from vendors' own documentation and the published specification. Where a section shows no fence, that is the reason rather than an omission.
- A schema describes shape, not behaviour. Fields and error codes are exact; what a server does with them is a requirement in the specification text. Pair every field with the clause that governs it.
- This page is not the specification. It is a reading guide for the specification, the schema and the changelog. Where the two disagree, the dated revision wins, and this page is deliberately not a substitute for it.
- Vendors move faster than the protocol. A gateway's pricing, plan names and defaults change on its own release cycle; read them at the vendor's page rather than from any summary, including this one.
- The code here is one documentation pipeline, not a standard. The loader, the shell, the source adapter and the lazily built index are this product's own; they show the shapes worth copying, not a format anything else must follow.
- Adjacent material is included at the depth it deserves. Gateways, agent memory and retrieval get one section between them, because none of the three is normative for this protocol.
Sources
- Model Context Protocol — specification for the current revision (2026-07-28) and the previous one (2025-11-25): https://modelcontextprotocol.io/specification/2026-07-28 · https://modelcontextprotocol.io/specification/2025-11-25
- Model Context Protocol — versioning and compatibility, and the per-revision changelog: https://modelcontextprotocol.io/specification/draft/basic/versioning · https://modelcontextprotocol.io/specification/2026-07-28/changelog
- Model Context Protocol — schema reference, published beside each revision: https://modelcontextprotocol.io/specification/2025-11-25/schema
- Model Context Protocol — the official registry, a metadata service for discovery: https://modelcontextprotocol.io/registry
- Databricks — AI gateway documentation: https://docs.databricks.com/aws/en/ai-gateway/
- Cloudflare — AI Gateway: https://developers.cloudflare.com/ai-gateway/
- SmartGate — product documentation, pricing and sales contact: https://smartgate.network/docs · https://smartgate.network/pricing · https://smartgate.network/contact
Method note
The code in this article is not transcribed. Every block was cut directly out of the slice body the SmartGate slice API returned and re-asserted byte-for-byte as a substring of that body before publication; the first line inside each fence records the file and the exact source lines. Symbols were pinned by whole-name containment (rule A level 2) and confirmed by the service's slot-proof endpoint — 5 of 8 planned sections pinned, 0 abstentions, 3 misses. Three sections (agent memory, the gateway definition and the RAG comparison) matched no unique symbol at all and are written from the published specification and the vendors' own documentation with no code, as the abstain rule requires. The code shown is this product's documentation pipeline — a content loader, a layout shell, a version-stamped source adapter, a versioned policy type and a lazily built vector index — rather than any part of the protocol implementation itself.
Demand figures come from this project's own keyword run, recorded in research_brief.md and
search_volume.json: the section phrases ibm rag and agentic ai professional certificate (320),
ai agent memory (210), ai gateway databricks (210), cloudflare ai gateway pricing (210),
databricks unity ai gateway (210), what is an ai gateway (210), agent workflow memory (170) and
rag vs agentic ai (170). The page's main term model context protocol documentation measured
1,600 a month in the same research pass with a difficulty of 62, and the section phrases were drawn
from a measured pool rather than from symbol names — the discipline the demand gate exists to enforce.
Slice provenance
| # | SERP keyword | Symbol | File | Source lines | How it was pinned | sha256(12) |
|---|---|---|---|---|---|---|
| 1 | ibm rag and agentic ai professional certificate | docsLoader |
lib/source.ts |
18–27 | rule A L2 → slot-proof | 6d4f2f2f1486 |
| 2 | ai gateway databricks | gatewaySeed |
config/plan-catalog.ts |
60–74 | rule A L2 → slot-proof | 8123510f9766 |
| 3 | cloudflare ai gateway pricing | CloudflareKVPseoSource |
lib/pseo/sources/cf-kv-source.ts |
5–34 | rule A L2 → slot-proof | 2f3b574688d7 |
| 4 | databricks unity ai gateway | DocsLayout |
app/[locale]/(docs)/layout.tsx |
10–21 | rule A L2 → slot-proof | 4d87a63c95dc |
| 5 | agent workflow memory | Memory.entity_store |
backend/smartgate/modules/memory/algorithm.py |
389–411 | rule A L2 → slot-proof | dc880596b229 |
Every fenced block above was cut from the slice body and re-asserted against it byte-for-byte before publication. 5 of 8 sections pinned, 0 abstentions, 3 misses.