Primitives
The most important part of MCP is its primitives: the kinds of context a server can offer a client. Officially there are three, split by who decides to use them.
If you know HTTP: a resource is like GET (load data; do not change the world). A tool is like POST (do work; may have side effects). A prompt is closer to a saved query the user runs by name.
Tools: actions the model calls
Each tool has a name, a description, and a JSON Schema for arguments. The model decides when to call; the host should still approve writes and other risky work.
A conceptual list request (the current spec also sends _meta on every call; only the method matters here):
A list result might include an adder:
A call:
With the official Python SDK you do not write this JSON by hand: type hints become the schema and the docstring becomes the description. See Python Server.
Design notes: one job per tool; stable names (weather_current beats a vague get); mention side effects in the description so the host can ask the user first.
Resources: data the app loads
A resource has a URI and a MIME type. The host chooses what to read and how much to pass to the model.
Two shapes:
The body is the resource content (text or encoded bytes). It is not a guarantee the model “already read it”—the host may attach only a summary.
Do not expose secrets, full production connection strings, or raw personal data as resources. Resources are often pasted wholesale into context and leak more easily than a tool return value.
Prompts: templates the user invokes
A prompt is triggered from a slash command, palette, or button—not silently by the model. prompts/get fills arguments; the server returns one or more messages; the host sends them to the model.
Good uses: a domain workflow (“review this PR against our checklist”) or a demo of how to combine this server’s tools and resources. Poor use: stuffing an employee handbook into a template—that belongs in a resource.
Discovery sequence (mental model)
server/discover is optional but returns capabilities and cache hints (ttlMs, cacheScope) in one shot. List methods may paginate with cursor. The SDK and Inspector walk this path for you.
Deprecated: Sampling (awareness only)
Older revisions let a server call sampling/createMessage and ask the host to run the model. As of 2026-07-28, Sampling (and Roots / Logging as core features) is deprecated, with at least a twelve-month window. Do not implement Sampling in new tutorials or new projects. If you need a model, call a provider API from your app or host. The rest of this course does not teach Sampling.
Clients may still support elicitation (ask the user to confirm or fill a gap). The current spec expresses that with Multi Round-Trip Requests, not a permanently open bidirectional stream.