Model Context Protocol: Servers, Clients and Transports
The tools in the previous lesson were functions inside one program. That is fine until you want the same three tools in your own agent, in an editor and in a desktop chat application, at which point you are writing them three times. The Model Context Protocol exists to make a tool something you write once and connect to anything.
By the end of this lesson you will be able to name the three roles the protocol defines, choose between its two transports for a given deployment, say what a resource and a prompt are and why they are not tools, read a specification version and know what it commits you to, and work through a checklist before letting a third-party server anywhere near your machine.
Three roles, and why the names matter
Section titled “Three roles, and why the names matter”The specification’s overview is short about this, and precise. The protocol “uses JSON-RPC 2.0 messages to establish communication between” three things:
- Hosts: “LLM applications that initiate connections”
- Clients: “Connectors within the host application”
- Servers: “Services that provide context and capabilities”
Where each role sits when your agent talks to a tool server
- HostThe application the person is using: your agent script, an editor, a desktop chat app. It holds the model connection, the conversation, and the decision about what runs.you are here in the labs
- ClientOne connector per server, inside the host. Speaks JSON-RPC over a transport, lists what the server offers, and calls it. A host with four servers has four clients.
- Transportstdio for a subprocess on the same machine, Streamable HTTP for a service you deploy. The protocol semantics are identical on both.
- ServerA separate program exposing tools, resources and prompts. It knows nothing about the model, the conversation, or which host is calling.
- The actual capabilityA filesystem, a database, an API, a search index. The part with consequences.
The separation is the whole value. A server written once is reachable from every host that speaks the protocol, and the host keeps the parts that need judgement: which servers to trust, what to show the user, and what to run without asking.
Two transports
Section titled “Two transports”The transports overview names exactly two standard bindings and is explicit that they change nothing about meaning: “Protocol semantics are identical on every transport. A transport is a binding.”
stdio is the one you will use in the lab. The client launches the server as a subprocess and
they exchange newline-delimited JSON-RPC over its standard streams. The rules are short enough
to quote in full, and two of them cause every stdio bug there is: “The server MUST NOT write
anything to its stdout that is not a valid MCP message”, while “The server MAY write UTF-8
strings to stderr for any logging purposes”. A stray print() in a server breaks the
connection; the same message on stderr is fine. Shutdown is by closing the server’s standard
input, and servers “SHOULD exit promptly when their standard input is closed”.
Streamable HTTP is for a server that runs as its own process and serves several clients. The server exposes “a single HTTP endpoint (the MCP endpoint) that accepts POST”, each JSON-RPC message is its own POST, and the server answers “with either a single JSON object or a Server-Sent Events (SSE) stream scoped to that request”.
Its security section is three normative sentences that should be read as a deployment checklist:
- “Servers MUST validate the
Originheader on all incoming connections to prevent DNS rebinding attacks.” - “When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0).”
- “Servers SHOULD implement proper authentication for all connections.”
The specification states the reason plainly: “Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.” A page you visit in a browser can be made to talk to a service listening on your own machine. Part 10’s lesson on serving beyond localhost made the same argument about model endpoints; it applies with more force here, because a tool server is by definition a thing that does something.
Tools, resources and prompts
Section titled “Tools, resources and prompts”Servers offer three kinds of thing, and the specification separates them by who decides to use them. Servers offer “Resources: Context and data, for the user or the AI model to use”, “Prompts: Templated messages and workflows for users” and “Tools: Functions for the AI model to execute”.
| Primitive | Who chooses | Typical example |
|---|---|---|
| Tool | The model, during a loop | Search the index, run the tests, read a file |
| Resource | The application, on the user’s behalf | A file’s contents, a database row, a document by URI |
| Prompt | A person, by name | A slash command or menu item that fills in a template |
The distinction is not decoration. Tools are “model-controlled”, and the specification puts a normative warning next to that: “For trust & safety and security, there SHOULD always be a human in the loop with the ability to deny tool invocations.” Applications “SHOULD provide UI that makes clear which tools are being exposed to the AI model”, insert visual indicators when tools are invoked, and present confirmation prompts. Resources and prompts do not carry that warning, because nothing in them is chosen by a token predictor.
Two details of the tool definition matter when you write one in the second lab. The
inputSchema “MUST be a valid JSON Schema object (not null)”, and for a tool with no
parameters the recommended form is { "type": "object", "additionalProperties": false }. And
errors come in two flavours: protocol errors, for an unknown tool or a malformed request, and
tool execution errors returned inside a normal result with isError: true. The specification’s
guidance on which to use is about what the model can do with them, since clients “SHOULD
provide tool execution errors to language models to enable self-correction”. An invalid date
should come back as a result saying so, not as a JSON-RPC error.
The specification has a date, and the date is the version
Section titled “The specification has a date, and the date is the version”MCP versions are dates. The versioning page defines the format as YYYY-MM-DD, “to indicate the
last date backwards incompatible changes were made”, and notes that the version is not
incremented for backwards-compatible updates. Revisions are marked Draft, Current or
Final, and as read on 2026-09-09 the current version is 2026-07-28.
That revision was not a small one, which is a useful thing to know before you read older
material. Its changelog lists, among its major changes, removing “protocol-level sessions and the
Mcp-Session-Id header from the Streamable HTTP transport”, making the protocol stateless by
removing “the initialize/notifications/initialized handshake” so that every request carries
its protocol version in a _meta field, adding a mandatory server/discover RPC, replacing the
HTTP GET stream with a subscriptions/listen request, and moving tasks into an official
extension. It also deprecates the Roots, Sampling and Logging features, with the migration advice
to “log to stderr (stdio) or use OpenTelemetry instead of Logging”.
Governance is worth two minutes because it tells you how fast this can change under you. The project “has been established as Model Context Protocol a Series of LF Projects, LLC”, with code and specification contributions under Apache 2.0 and documentation under Creative Commons Attribution 4.0. Technical governance is a four-level ladder of Contributors, Maintainers, Core Maintainers and Lead Maintainers, the last described as “the final decision makers”, and together they form the MCP Steering Group. Changes to the specification must be submitted as Specification Enhancement Proposals, the Core Maintainer group “meets every two weeks to discuss and vote on proposals”, and the 2026-07-28 revision added a feature lifecycle policy with “a minimum twelve-month deprecation window” and a registry of deprecated features.
So: a foundation-hosted specification, an open proposal process, a published deprecation window, and dated revisions that have recently made large breaking changes. Pin the revision your code speaks and read the changelog when it moves.
What connecting a server exposes you to
Section titled “What connecting a server exposes you to”Everything above is the useful half. This is the half that decides whether you should connect a particular server at all.
A tool description is text the model reads. So is a tool result. Neither is under your control when the server is not yours, and a model has no mechanism for treating one span of its context as less authoritative than another. OWASP’s definition covers the general case: a prompt injection vulnerability “occurs when user prompts alter the LLM’s behavior or output in unintended ways”, with the indirect form arriving when a model “accepts input from external sources like websites or files”.
MCP adds two specific shapes to that.
Tool poisoning. Invariant Labs’ write-up of 1 April 2025 describes instructions embedded in tool descriptions that are “invisible to users but visible to AI models”. The asymmetry is the attack: “AI models see the complete tool descriptions, including hidden instructions, while users typically only see simplified versions in their UI.” You approve a tool called “add two numbers” after reading one line; the model reads four hundred words, the last of which tell it to read a key file and pass the contents as an argument.
Rug pulls and shadowing. The same write-up describes a server that can “change the tool description after the client has already approved it”, so approval is not a durable statement about what a tool does. And tool shadowing, where a description from one server “modifies the agent’s behavior with respect to a trusted service or tool”, lets a malicious server “override rules and instructions from other servers” without ever appearing in the user-facing log. This is why the specification says clients “MUST consider tool annotations to be untrusted unless they come from trusted servers”, and why “trusted” has to mean something you checked rather than something you downloaded.
Injection through results. Even a perfectly honest server returns content it did not write. A file, a web page, a database field, an issue comment: any of them can contain text addressed to the model. The second lab builds exactly this and tests whether your agent follows it.
A checklist before you trust a server
Section titled “A checklist before you trust a server”Work through this before adding anything you did not write. It takes ten minutes and it is the only defence that acts before the model sees anything.
- Source. Who publishes it, and does the name match a real project? Read the repository, not the directory listing that links to it. Prefer something you can pin to a commit.
- Read the tool descriptions in full. Not the summary the host shows you. Open the source or
dump
tools/listyourself, and read every character of everydescriptionand every parameter description. This is where poisoning lives, and it is visible if you look. - What does it read, and what does it write? List the files, directories, network hosts and credentials it touches. A server that needs your home directory to summarise a document is asking for more than the job needs.
- Transport and reach. stdio, or HTTP? If HTTP, does it bind to localhost, validate
Originand require authentication, as the specification says it should? - Permissions it will run with. Your user, or a dedicated one? A container, or your machine? The MCP specification cannot enforce anything here and says so; the sandbox is yours to build.
- Does it complete the trifecta? With this server added, does the agent have private data, untrusted content and a way to send data out, all at once? If so, remove one of the three.
- Pin it, and re-check on update. Because descriptions can change after approval, an unpinned server is a standing invitation. Record the version you reviewed.
LM Studio’s own MCP page puts the short version bluntly: “Never install MCPs from untrusted sources”, because “some MCP servers can run arbitrary code, access your local files, and use your network connection”. That is the correct level of alarm, and it applies to every host.
Separate protocol discovery from permission to execute
Section titled “Separate protocol discovery from permission to execute”Discovering a tool tells the host its name, description and input schema. It does not establish that the tool is trustworthy, that every user may invoke it or that its result should become an instruction. Treat tool descriptions and returned content as data from the connected server, with provenance retained.
Trace a minimal connection through initialisation, capability negotiation, tool listing and one call. Keep the protocol revision and transport explicit. For a local standard-input/output server, protocol messages must remain distinct from diagnostic output; for HTTP, endpoint authentication and session handling belong to that transport’s contract.
Before connecting the model, call the tool directly with valid and invalid arguments and verify the expected denial or error. Then test the model-mediated path. A host may aggregate tools from several servers, so use stable qualified identities to avoid ambiguity. The protocol standardises communication; the application still decides which server to trust, which resources a caller may access and whether a proposed action needs approval.
MCP defines hosts, which are the applications holding the model and the consent; clients, which
are one connector per server inside a host; and servers, which expose capabilities and know
nothing about the conversation. Two transports carry identical semantics: stdio, where the client
launches the server as a subprocess and the only rules that matter are that stdout carries
nothing but protocol messages and stderr carries the logs, and Streamable HTTP, whose
specification requires Origin validation, recommends binding to localhost and recommends
authentication. Servers offer tools chosen by the model, resources chosen by the application and
prompts chosen by a person, and only the first of those carries a normative human-in-the-loop
warning. The specification is versioned by date, currently 2026-07-28, governed through a Linux
Foundation project with a public proposal process and a twelve-month deprecation window, and that
revision removed the initialisation handshake and protocol-level sessions, so older material
describes a different protocol. And connecting someone else’s server means importing text the
model will read as instructions, in tool descriptions that can change after you approved them and
in results that can contain anything, which is why the checklist and the lethal-trifecta test
come before the install command.
Check your understanding
Sources for this lesson
12 verified · checked 2026-09-09
- 01Model Context Protocol — Specification§ Overview; features; Security and Trust & Safetymodelcontextprotocol.io/specification2026-09-09
- 02Model Context Protocol — Versioning§ Revision states; the current version; negotiationmodelcontextprotocol.io/specification/versioning2026-09-09
- 03Model Context Protocol — Transports overview§ Standard bindings; messages; custom transportsmodelcontextprotocol.io/specification/2026-07-28/basic/transports2026-09-09
- 04Model Context Protocol — stdio transport§ Framing; stdout and stderr rules; shutdownmodelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio2026-09-09
- 05Model Context Protocol — Streamable HTTP transport§ Security and endpoint; sending and receiving messagesmodelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http2026-09-09
- 06Model Context Protocol — Tools§ User interaction model; tool definitions; error handling; security considerationsmodelcontextprotocol.io/specification/2026-07-28/server/tools2026-09-09
- 07Model Context Protocol — Key changes in 2026-07-28§ Major changes; deprecated featuresmodelcontextprotocol.io/specification/2026-07-28/changelog2026-09-09
- 08Model Context Protocol — Governance and stewardship§ Project policies; technical governance; SEPsmodelcontextprotocol.io/community/governance2026-09-09
- 09Invariant Labs — MCP security notification, tool poisoning attacks§ Tool poisoning; rug pulls; tool shadowinginvariantlabs.ai/blog/mcp-security-notification-tool-poisoning-attacks2026-09-09
- 10Simon Willison — The lethal trifecta for AI agents§ The three capabilitiessimonwillison.net/2025/Jun/16/the-lethal-trifecta2026-09-09
- 11OWASP LLM01:2025 Prompt Injection§ Direct and indirect injection; preventiongenai.owasp.org/llmrisk/llm01-prompt-injection2026-09-09
- 12LM Studio — MCP§ Configuration; cautionslmstudio.ai/docs/app/mcp2026-09-09
Every technical claim on this page was checked against the official documentation of the tool, vendor or model publisher on the date shown, at the version pinned for the course. Where the course disagrees with folklore, the source is how you can tell which one to trust.