Quick Answer: MCP tools, resources, and prompts are the three building blocks every MCP server can expose. Tools are actions the model calls autonomously. Resources are read-only data the application injects. Prompts are reusable templates the user triggers on demand.
The Model Context Protocol defines a standard way for AI agents to connect to external systems. But understanding MCP tools, resources, and prompts as distinct primitives — each with a different controller, lifecycle, and intent — is what separates developers who use MCP effectively from those who only scratch the surface.
Most teams start with tools and stop there. That leaves significant capability on the table. This guide covers all three server-side primitives, when to use each, and how they compose into complete workflows. If you're building or consuming MCP servers, cowork.ink integrates with the MCP ecosystem to give your team shared access to these agents — no per-developer setup.
The Control Hierarchy: Who Owns Each Primitive?
The clearest mental model for MCP primitives is who controls them — not what they do technically, but who decides when they're used.
| Primitive | Controlled By | Initiated How |
|---|---|---|
| Tools | Model | Autonomously, based on context |
| Resources | Application | Programmatically, before model sees context |
| Prompts | User | Explicitly, via slash command or UI trigger |
This hierarchy matters when you're designing a server. If something should happen automatically, make it a tool. If it's data the model should always have available, make it a resource. If it's a workflow pattern users want to invoke on demand, make it a prompt.
Tools: What the Model Can Do
Tools are executable functions the LLM discovers and calls autonomously. They are the most familiar primitive — analogous to function calling in standard LLM APIs but standardized across providers.
Each tool is defined with a name, a description the model uses to decide when to invoke it, and a JSON Schema inputSchema that specifies what arguments it accepts. Tools can have side effects: calling APIs, writing files, triggering webhooks, or querying databases.
A minimal tool definition looks like this:
{
"name": "create_issue",
"description": "Creates a new issue in the project tracker",
"inputSchema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] }
},
"required": ["title"]
}
}
The protocol exposes two methods: tools/list for discovery and tools/call for execution. Because tools can mutate state, the MCP spec explicitly recommends user approval before execution — a human-in-the-loop gate that responsible agentic systems should enforce.
Unlike resources, tools can change things. Always implement confirmation flows for destructive or irreversible tool calls. The MCP spec makes human approval a SHOULD requirement.
Resources: What the Model Can Know
Resources are read-only data sources the server exposes as named, URI-identified content. They represent the facts the model needs without giving it the power to modify anything.
Each resource has a URI (like file:///project/schema.sql or git://repo/HEAD/README.md) and a MIME type so clients handle the content correctly. The application — not the model — decides when to attach resources to context.
There are two kinds:
- Static resources — fixed URIs with stable content
- Resource templates — RFC 6570 URI templates with variables (e.g.,
logs://{date}/{service}) that clients fill in at read time
A resource subscription model allows servers to push change notifications (notifications/resources/updated) when content changes. The client re-fetches the resource after the notification — the data delivery is always a separate pull.
The critical distinction: resources inform, tools act. Use a resource to give the model a database schema it should reference. Use a tool if it needs to query that database at runtime.
Prompts: What the User Can Trigger
Prompts are pre-defined, parameterized instruction templates that users explicitly invoke. Think of them as slash commands your server publishes.
Where tools fire when the model judges it appropriate, prompts only run when a user deliberately triggers them. They accept named arguments with optional descriptions and autocomplete hints, and the server substitutes values when the client calls prompts/get.
A prompt can reference available resources and tools, effectively packaging a complete workflow into a single named operation. For example, a code_review prompt might pull in the diff resource, set a tone parameter, and scaffold a review structure — all in one invocation.
Because prompts live on the server, you can update them without touching client code. This makes them the right primitive for encoding team best practices: standardized review formats, consistent report templates, shared debugging workflows.
Side-by-Side Comparison
| Tools | Resources | Prompts | |
|---|---|---|---|
| Purpose | Execute actions | Provide context | Package workflows |
| Controlled by | Model (autonomous) | Application (programmatic) | User (explicit) |
| Side effects | Yes | No (read-only) | No (template only) |
| Protocol methods | tools/list, tools/call | resources/list, resources/read | prompts/list, prompts/get |
| Typical use case | API calls, file writes, DB mutations | Schemas, docs, logs, config | Slash commands, review templates |
| Dynamic | Arguments at call time | Resource templates, subscriptions | Arguments at invocation |
The Fourth Primitive: Sampling
Beyond the three server-side primitives, MCP defines a client-side primitive worth knowing: sampling.
Sampling lets a server request an LLM completion from the host client — the data flow runs in reverse. The server calls sampling/createMessage and the client calls the model on its behalf. This means server-side tools can include sub-agent reasoning without the server needing its own API keys.
The practical implication: you can write a tool that summarizes a long document before returning it, or runs a validation sub-agent on tool output — all mediated through the same human-approval gates the client already enforces.
How They Compose
The real power of MCP primitives emerges when you use them together. Consider a code review workflow:
- A resource exposes the git diff for the current PR
- A prompt (
/review-pr) gives the user a one-click way to kick off the review - The model calls a tool to post the review comment back to the pull request
- Sampling lets the tool run a secondary LLM pass to check for security issues
Each primitive does exactly what it should. The resource is read-only. The prompt is user-controlled. The tool has the side effect. No primitive is being stretched beyond its purpose.
For a hands-on walkthrough of building this kind of server, see our guide to building an MCP server. For a broader look at how MCP compares to other agent protocols, MCP vs. A2A covers the landscape. And if security is on your mind, our MCP security best practices guide covers the risks by primitive type.
Get Started
If you're building AI agents that expose MCP servers, understanding the primitive boundaries — what the model controls, what the app controls, what the user controls — will save you significant debugging time and architectural regret.
Solo developer? GoGogot is an open-source self-hosted agent with built-in MCP support — one Docker command, your keys stay on your machine.
Building for a team? cowork.ink gives your engineering team shared access to MCP-connected agents — shared workspace, zero per-developer prompt setup, AI code review out of the box.