MCP Core Primitives: Tools, Resources, and Prompts — who is allowed to invoke what, and what a server must declare to offer it
MCP servers expose context and behavior to a host through three primitives — tools, resources, prompts — that differ in one deliberate axis: who decides to use them. Tools are model-controlled, resources are application-controlled, prompts are user-controlled. Sampling and notifications are secondary primitives that ride on top once a session is negotiated. Every one of these is switched on or off at the initialization handshake, which is the first concrete decision anyone writing a server (see Building an MCP Server: SDKs, Tool Schemas, Testing, and Deployment — the practical path from a 15-minute local prototype to a hosted remote server) has to get right.
Tools: model-controlled, executable, side-effecting
Tools let the model interact with external systems — querying databases, calling APIs, running computations — by invoking executable functions the server exposes (modelcontextprotocol.io/specification/2025-06-18/server/tools). Each tool has a unique name plus metadata: title, description, inputSchema, and an optional outputSchema — the spec describes both simply as "JSON Schema defining expected parameters" / "expected output structure," without pinning a specific JSON Schema draft version.
Discovery and invocation
tools/list (paginated) returns the available tools with full schemas; tools/call invokes one by name with arguments matching its inputSchema. A server that supports tools MUST declare the tools capability with a listChanged flag, and if it declared that flag it SHOULD emit notifications/tools/list_changed whenever the tool set changes.
Results and errors
a tool result carries text, image, audio, resource links, or embedded resources, plus an isError flag. MCP distinguishes two failure classes: protocol errors (standard JSON-RPC errors — unknown tool, invalid arguments, server error) and tool execution errors (surfaced inside the result with isError: true — API failures, bad input, business-logic failures). If a server declared an outputSchema, it MUST conform results to it and clients SHOULD validate against it. Content also carries optional annotations — audience, priority, lastModified — describing how a result should be displayed or prioritized.
Security
because the model decides when to call a tool, the spec's user-interaction model says there SHOULD always be a human in the loop able to deny an invocation, and applications SHOULD show which tools are exposed to the AI with visual indicators when one is invoked. This is the entry point for the failure modes in MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface and MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority.
Resources: application-controlled, read-only context
Resources expose read-only data — files, database schemas, application-specific information — that gives the model context (modelcontextprotocol.io/specification/2025-11-25/server/resources). Unlike tools, the model does not decide when a resource is used: it's the host application that determines how to incorporate it, based on the host's own needs. Each resource is identified by a URI (RFC 3986); common schemes are https://, file://, git://, plus custom schemes.
Discovery and reading
resources/list (paginated) returns uri, name, title, description, mimeType, and optional icons; resources/read returns the content as either text or base64-encoded binary. Servers can also expose resource templates — parameterized URIs following RFC 6570 — whose arguments may be auto-completed through the completion APIs.
Capability declaration and change tracking
a server supporting resources MUST declare the resources capability, with two independent optional flags — subscribe (clients may subscribe to a specific resource's changes) and listChanged (server will notify when the resource *list* changes). If subscriptions are supported, a subscribed client gets notifications/resources/updated; if listChanged is declared, the server SHOULD send notifications/resources/list_changed when the set of resources changes.
Annotations
audience (an array of "user" and/or "assistant"), priority (0.0–1.0), lastModified (ISO 8601).
Security
servers MUST validate all resource URIs, implement access controls for sensitive resources, properly encode binary data, and check permissions before operations — the same category of enforcement problem discussed in MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority.
Prompts: user-controlled, reusable templates
Prompts are server-exposed, parameterized templates that a host can inject into a conversation (modelcontextprotocol.io/specification/2025-06-18/server/prompts). They are explicitly user-controlled: the spec's design intent is that a user explicitly selects a prompt for use — the reference UI pattern given is a slash command.
Discovery and retrieval
prompts/list (paginated) returns name, title, description, and an optional arguments array; prompts/get takes a prompt name plus optional arguments and expands the template into one or more messages. A PromptMessage has a role ("user" or "assistant") and content of type text, image (base64), audio (base64), or an embedded resource. Embedded resources let a prompt pull in server-managed material — docs, code samples, reference material — as text or binary (blob) data, using the same annotation fields (audience, priority, lastModified) as tools and resources.
Capability and change tracking
a server supporting prompts MUST declare the prompts capability with an optional listChanged flag; if declared, it SHOULD send notifications/prompts/list_changed when the prompt list changes.
Security
servers SHOULD validate prompt arguments before processing, and implementations MUST carefully validate all prompt inputs and outputs to prevent injection attacks or unauthorized resource access. See MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface for why "validate the content, not just the schema" is structurally hard here.
Sampling and notifications: secondary primitives
Sampling inverts the usual direction: it lets a *server* ask the *client* for an LLM completion via sampling/createMessage (messages array, optional modelPreferences, optional systemPrompt, maxTokens), so the server can use AI capability without holding its own API key (modelcontextprotocol.io/specification/2025-11-25/client/sampling/). A client that supports it MUST declare the sampling capability, with optional sub-capabilities sampling.tools (tool use inside sampling) and sampling.context (legacy context inclusion).
Model selection is indirect: a server cannot request a specific model by name (the client may not have access to that exact model); instead it expresses preferences — costPriority, speedPriority, intelligencePriority, each 0–1 — plus optional model hints as flexible suggestions, and the client makes the final choice.
Tool use inside sampling requires the client to have declared sampling.tools; servers MUST NOT send tool-enabled sampling requests otherwise. It runs as a multi-turn agentic loop: the LLM can request tool calls, the server executes them, and the loop continues to a final response. Message shape rules are strict: tool results must be sent as user messages containing *only* ToolResultContent blocks — never mixed with text/image/audio in the same message — and every assistant message with ToolUseContent blocks MUST be followed by a user message whose ToolResultContent blocks match each tool use.
Cross-API compatibility is an explicit design goal: sampling is meant to work with Claude, OpenAI, Gemini, and other providers via abstraction of message roles, tool-choice modes (auto/required/none), and parallel tool use.
Security
as with tools, there SHOULD always be a human in the loop able to deny a sampling request, with UI to review the request and the generated response before it's delivered.
Notifications are the plumbing that keeps all three primitives' lists fresh without polling — JSON-RPC 2.0 notification messages a server (or client) sends without expecting a reply. The concrete set seen across the spec: notifications/tools/list_changed, notifications/resources/list_changed, notifications/resources/updated, notifications/prompts/list_changed, notifications/cancelled (either side may send it, for a request previously issued in that same direction, with an optional reason string), and notifications/initialized (client → server, sent once after the handshake completes to signal readiness for normal operation).
Capability negotiation: what a server must declare at handshake
None of the above is available by default — during the initialization handshake, a server declares which primitives it supports by listing capabilities in its init response, and a client declares its own (sampling, tool use in sampling, etc.) (modelcontextprotocol.io/specification/2025-11-25/architecture). Both parties MUST respect what was declared and MUST NOT invoke a feature that wasn't agreed to during that handshake. Concretely: tools capability carries an optional listChanged flag; resources carries optional subscribe and listChanged; prompts carries an optional listChanged. Each declared capability unlocks the matching protocol feature for that session — e.g. tools/call is only legal if tools was declared — and a server can declare several capabilities at once, exposing tools, resources, and prompts together in a single session.
Why this is the load-bearing detail for the wiki's goal
anyone building a server has to pick, upfront, which of these three primitives to declare and with which optional flags — that choice, not the transport, is what determines which protocol methods a client is even allowed to call against the server. See MCP Architecture: Host, Client, Server, and the JSON-RPC 2.0 Wire Format for where this sits in the client-host-server model and MCP Session Lifecycle: the Handshake a Client Must Get Right — and the One Being Removed in 2026-07-28 for the full handshake sequence and versioning story.
Related
- What Is the Model Context Protocol (MCP): the Open Standard Connecting AI Models to Tools and Data — the problem these three primitives solve (the M×N integration problem) before looking at their mechanics. - MCP Architecture: Host, Client, Server, and the JSON-RPC 2.0 Wire Format — the client-host-server model and JSON-RPC wire format that tools/resources/prompts messages travel over. - MCP Session Lifecycle: the Handshake a Client Must Get Right — and the One Being Removed in 2026-07-28 — the full initialization handshake these capability declarations are part of. - Building an MCP Server: SDKs, Tool Schemas, Testing, and Deployment — the practical path from a 15-minute local prototype to a hosted remote server — where declaring tools, resources, and prompts turns into actual server code and schemas. - MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface — why tool descriptions and resource/prompt content are an attack surface, not just a UX surface. - MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority — why the "human in the loop SHOULD deny" security note is a recommendation, not an enforced constraint.
Verified against
- modelcontextprotocol.io/specification/2025-06-18/server/tools
- modelcontextprotocol.io/specification/2025-11-25/server/resourc…
- modelcontextprotocol.io/specification/2025-06-18/server/prompts
- modelcontextprotocol.io/specification/2025-11-25/client/sampling
- modelcontextprotocol.io/specification/2025-11-25/architecture
- modelcontextprotocol.io/specification/2025-11-25/basic/utilitie…
- modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle
What links here
Source: Sinapsi — verified compositional memory, queryable by LLMs. Query this wiki live from your assistant over MCP, or build your own verified wiki (public, or private for your team). CC BY 4.0 — reuse with attribution to Sinapsi.