SmartGateSmartGate

What Is the Model Context Protocol? A First-Principles Guide

The Model Context Protocol is a JSON-RPC interface that lets an AI assistant use capabilities it was never trained on — a file reader, a search index, a database — in one message format any host and any server can speak. The shape is small: an application opens one client per server, the server answers with tools, resources and prompts, and a tool call is one request and one response.

Short answer: The Model Context Protocol is a JSON-RPC interface that lets an AI assistant use capabilities it was never trained on — a file reader, a search index, a database — in one message format any host and any server can speak. The shape is small: an application opens one client per server, the server answers with tools, resources and prompts, and a tool call is one request and one response. What the protocol deliberately does not answer is who the caller is, what the call costs and where it is recorded.

Key takeaways

  • A message format, not a product. Nothing about MCP is a hosted service; it is a set of request and response shapes plus a small lifecycle, published as dated revisions.
  • Three nouns do the work. A host is the application a person uses, a client is the object the host opens for one server, and a server is the process that owns the capabilities.
  • Three capability types answer three different questions. Tools do things, resources are readable, prompts are reusable templates the user picks.
  • The transport decides where the server can live. Pipes to a local process for a laptop, a single HTTP endpoint for anything shared or remote.
  • The protocol is silent about the caller. Identity, rate, budget and the audit record are implementation concerns, which is why the same conversation reappears on every deployment.
  • Start by listing your own capabilities. Write down what an assistant should be able to reach, mark which entries are read-only, and only then decide which of them become a server.

The one-line definition, and the two problems behind it

The Model Context Protocol, abbreviated MCP, is a specification for how an AI application asks a program it does not control to do something and how that program answers. The protocol defines the message bodies, the lifecycle that opens a session, and the rules for exchanging capabilities between the two sides; it does not define what any capability does. The practical phrasing is that MCP is the plug shape, not the appliance.

Two problems made it worth standardising. First, every assistant framework grew its own way to describe a callable function — a private JSON schema here, a provider-specific tool object there — so a capability written for one product had to be rewritten for the next. Second, the same capability had to be re-integrated per host: a document reader wired into one editor had no path into a desktop chat application without a second integration. A single wire format collapses both problems into one adapter per side.

The demand for this exact question is small and deliberate: model context protocol definition measures about 30 searches a month in the United States, because most people ask it once. What they do afterwards is read the specification, and the specification is versioned — each revision is a dated document rather than a rolling page, so an integration should negotiate the revision it speaks instead of assuming today's (dated revisions and transports). Where the specification lives, and which parts of it are normative, is a separate question this page only points at.

The three actors, and why the client is not the host

Three nouns appear in every description of MCP, and they are not interchangeable. The host is the application a person actually uses — a desktop chat client, an editor, a command-line agent. The client is a small object the host creates for each server it wants to reach; it owns that one connection, that one set of negotiated capabilities and that one lifecycle. The server is the program on the other side, and it is the part you write if you are exposing a capability.

Keeping the client separate from the host buys two properties that matter in practice. A host can talk to several servers at once without those servers knowing about each other, because each connection has its own client and its own session. And a failure is contained: a server that does not answer, or answers in a way the host cannot parse, degrades one client rather than the application. The cost of that separation is that capability negotiation happens per connection, which is why a host's behaviour can differ between two servers on the same machine — one declares resources and the other only declares tools, and the host's interface follows the server.

For a reader arriving from the server side, the protocol view of these actors is the section-by- section version of this page: the actors and lifecycle walkthrough covers initialization, capability negotiation and shutdown in depth. If you would rather start from the thing you are going to build, standing up an MCP server is the other end of the same story, and it answers the questions this page leaves to the implementation.

A worked request: one tool call, from question to answer

Follow one call. A person asks their assistant whether a page they are looking at says anything about refunds. The model cannot see the page, so the host looks at the tool list the server declared during initialization and finds one that fetches a URL and returns text. The client sends a single request whose method is the tool call, carrying the tool's name and its arguments as a JSON object — here, one string. The server executes whatever that tool means, and returns a result whose content is a list of parts, typically text. The host hands those parts to the model, the model reads them, and the answer the person sees is composed from them.

Every hop in that sequence is a JSON-RPC message with a method and an identifier, and the JSON-RPC envelope is where the three shapes a client can receive — a result, an error and a notification — are told apart.

Four details in that sequence are worth remembering, because they explain most surprises later. The tool list is usually fetched once per session rather than per call, so a tool that appears mid-session may simply not have been advertised yet. Arguments are validated against the schema the server itself published, so a mismatch is a client-side error rather than a server bug. A tool that fails should return that failure inside its result rather than throwing, which is why a host can distinguish "the tool ran and reported a problem" from "the call never arrived". And nothing in the exchange carries the user's identity unless the deployment put it there: the protocol moves messages, and the tool schema reference documents the field names a shape has to have.

The primitives beside tools are a different kind of thing. Resources, prompts and sampling are readable data, user-selected templates and a way for a server to ask the client's model to generate something, and each of them changes who initiates the exchange. A call is one request and one response; handing a whole task to a different agent is the subject of a separate protocol, and MCP next to A2A is where that comparison belongs.

RAG architecture explained in one paragraph, and how MCP differs

Retrieval-augmented generation is a technique for answering with a model that was not trained on your data: split the corpus into chunks, turn each chunk into a vector with an embedding model, store the vectors in an index, and at question time embed the question, fetch the nearest chunks and paste them into the prompt. The model then answers from material it can see. Every production retrieval stack is a variation on that loop, with ranking, filtering and re-ranking layered on top, and how a retrieval stack is assembled is the place to read the variants.

MCP does not replace that loop and does not perform any step of it. Retrieval answers what should be in the context window the model reads. MCP answers how the assistant reaches a capability while it is running — including a retrieval index, which is a perfectly ordinary thing to expose as a tool or a resource. The two meet at exactly one point: a retrieval step can be implemented as a server, at which point the host does not care whether the chunks came from a vector store or a keyword index, and the retrieval team does not care which assistant asked. Confusing the two is the most common category error in this space: MCP is a transport for capabilities, and retrieval is one of the capabilities it can carry.

Agent memory survey: the three places state can actually live

A short survey of state, because "does it remember?" is the second question everyone asks after "what is it?". There are exactly three places state can live in an MCP deployment, and they behave differently.

Nowhere. The server is a function: arguments in, result out, nothing retained. This is the default, it is the easiest to reason about, and it is correct for most tools — a fetch, a lookup, a calculation.

In the client's own store. The host keeps the conversation, the project files and the configuration that lists servers. This state is real and useful, but it belongs to the host, not to the protocol: a second host pointed at the same server starts empty.

On the server. A memory tool turns the server into a system of record, which is a different class of commitment. Two hosts sharing that server share the memory; retention becomes a policy question with a legal edge; and deleting a memory is now an operation someone has to design. Where agent memory lives covers the storage side, and the decision to put state on the server should be made deliberately rather than as a side effect of adding a tool.

Client-side memory: what a Claude agent keeps between sessions

The protocol itself has no memory primitive, so everything a "remembering" assistant appears to keep is either in the host's own storage or in a server someone built. Looking at one client makes the split concrete. A Claude-family host keeps a configuration file that lists the servers it may reach, per-project instruction files that travel with a repository, and the conversation history for the session. None of those three is protocol state. The configuration is read and used to open clients; the instruction files are text the host injects into its own context; the history is kept by the application so the next turn has something to continue from.

That split produces the failure people report as "the assistant forgot". A tool called from one host session and then from a different session sees no shared memory unless the server keeps it, and a server that keeps it under a per-user key behaves differently again when the same person switches machines. Anthropic's client-side view describes which clients speak the protocol and what each of them reads at startup; the design question a server author should answer first is what a tool is allowed to remember, and with which identifier.

Databricks AI gateway pricing: when a hosted server starts metering

The protocol has no opinion about money or limits, and that absence becomes visible the moment a server is hosted rather than spawned. A local process inherits whatever discipline its caller has; a remote endpoint serves callers it has never met, and someone has to decide what a call costs, how often it may happen and what happens when a team exceeds the allowance. Vendors document this layer explicitly: the phrase databricks ai gateway pricing measures about 70 searches a month, and Databricks describes a usage-tracking table that captures request and response details, token use and latency for a model service, and bills for the usage it logs (Databricks).

The excerpt below is the human-readable end of that layer — not a meter, but the sentence a meter produces for the person who has to act on it:

# dashboard-calibration/dashboard_calibration/report.py — source lines 48–55 (pricing_notes_for_verdict)
def pricing_notes_for_verdict(verdict: str) -> list[str]:
    notes = {
        "cap_too_high": ["Quota likely too high — users may feel unused capacity."],
        "cap_too_low": ["Quota likely too tight — consider tier upgrade or overage."],
        "upgrade_tier": ["Usage exceeds current plan cap — upgrade or enterprise contract."],
        "ok": ["Utilization in healthy 60–80% band (approx)."],
    }
    return notes.get(verdict, [])

Read the four cases and one absence. Each verdict — a cap set too high, a cap set too tight, usage past the plan, or a healthy band — resolves to a note that names the next action rather than the number, because the person reading a quota report already knows the number. An unrecognised verdict returns an empty list instead of a guess, which is the honest default for a function that turns machine state into advice: a wrong recommendation about spend is worse than silence. The generalisation to any hosted MCP server is that metering is a policy object with its own vocabulary, and it sits in front of the server rather than inside it — what a gateway adds is the layer-by-layer version of that argument.

How SmartGate compares

The choice is not between protocols. It is about where a capability lives, who may call it, and what is recorded when they do.

What it is Who calls it Limits and records
A local server over stdio A process the host spawns on your machine One host, one person None: the process trusts whoever launched it
A self-hosted remote server Your endpoint on your own host Whoever has the URL and a credential Whatever you build, in your code
A hosted MCP endpoint (SmartGate) Streamable HTTP at one POST endpoint, with seven tools Any host, with a key per caller Per-key rate, a daily cap clamped to the plan, and a record per call
A generic model proxy Forwarding and TLS in front of a model API Any client with the proxy's credential Request counts; tool calls usually stay outside its view

The reason the third row exists is the gap the first three sections describe. Nothing in the protocol meters a call, so a shared server either grows that layer itself or sits behind something that already has it. SmartGate is one implementation of the layer in front: hosts point at one endpoint and receive seven tools, and the free tier covers 2 million tokens a month with all of them. Pro starts at $18 a month and Teams at $55; the per-plan request ceilings, log retention and token pools are on the pricing page.

How to get started

  1. Read one real tool list. Point the inspector at a server you already have and read the response. Seeing the field names once is worth more than a diagram.
  2. Write your own capability list. Five to ten entries in a text file, each marked read-only or not. The read-only ones are the tools you can safely connect first.
  3. Expose one of them. A small server with a single tool is enough; the Python walkthrough uses the official SDK and keeps the server half short.
  4. Point a host at it and call the tool by hand. A successful call and a visible result is the proof that the wiring is right, before any agent loop exists.
  5. Decide about callers before you share it. If more than one person or machine will reach the server, decide now whether it gets its own keys, limits and log, or whether it sits behind a hosted endpoint that already provides them.
  6. Then read the protocol. The product documentation and the specification answer the questions this page only names.

Start on the free tier — 2 million tokens a month and all seven tools, no card required — with start free; contract and enterprise traffic starts at the contact form.

Frequently Asked Questions

Limitations and what this does not do

  • Four of the five planned sections quote no code. Only the metering section pinned a unique symbol; the definition, actors, request, retrieval and memory sections matched no single symbol in the codebase, so they are written from the published specification and the vendors' documentation with no quoted implementation. Where a section shows no fence, that is the reason.
  • This page is an introduction, not the specification. Field names, error codes and the exact lifecycle are normative documents, and a dated revision is a snapshot — negotiate it rather than pinning the one you happened to read.
  • The working example is described, not executed. The four observations in the request section are properties of the protocol, not a transcript of one deployment's traffic.
  • The comparison table is not a price list. The rows describe where a capability lives and what is recorded; only the paragraph under it carries current plan numbers.
  • Nothing here meters anything. If you need limits and records, they are yours to build or someone else's to host, and this page does not claim the protocol provides them.

Sources

Method note

No code on this page was transcribed. The single fence above was cut out of the slice body returned by the SmartGate slice API and re-asserted byte-for-byte as a substring of that body before publication; the first line inside the fence records the file and the exact source lines. The symbol was pinned by whole-name containment (rule A level 2) and confirmed by the service's slot-proof endpoint before any prose was written.

One of the five planned sections pinned a slice. The other four matched no unique symbol and were written from the published specification and the vendors' own documentation, with no quoted implementation — that is a recorded verdict, not an omission, and it is why most of this page is prose rather than code. Demand figures come from this project's own keyword run, recorded in research_brief.md and search_volume.json: databricks ai gateway pricing measured about 70 US searches a month, agent memory survey and claude agent memory about 70 each, rag architecture explained about 50, and model context protocol definition about 30.

Slice provenance

# SERP keyword Symbol File Source lines How it was pinned sha256(12)
1 databricks ai gateway pricing pricing_notes_for_verdict dashboard-calibration/dashboard_calibration/report.py 48–55 rule A L2 → slot-proof 2503fe62ebba

Every fenced block above was cut from the slice body and re-asserted against it byte-for-byte before publication. 1 of 5 sections pinned, 0 abstentions, 4 misses.