MCP Primitives: Tools, Resources, and Prompts
Scenario
You want your AI assistant to automatically search your product database whenever a user asks about stock levels. You confidently expose the `search_inventory` function as an MCP Resource. A user asks 'Do we have any red shoes?', and the LLM just hallucinates an answer. It never runs your search.
A developer wants the LLM to search a database autonomously during a conversation and defines the search function as a Resource. Why does the LLM ignore it?
Mental model
Resources are files you drag-and-drop. Prompts are templates you click to start. Tools are buttons the LLM can press itself.
MCP exposes exactly three primitives. The technical distinction between them is entirely about *control*. Resources are application-controlled (you attach them before chatting). Prompts are user-controlled (you select 'Code Review Template' from a menu). Tools are model-controlled (the LLM decides to fire them mid-conversation). If you want the AI to do something autonomously, it must be a Tool.
Deep dive
A Server's capabilities are divided into three strict categories: Resources, Prompts, and Tools. When a Host connects, it explicitly asks the Server to list them via separate JSON-RPC calls (`resources/list`, `prompts/list`, `tools/list`). How the Host handles the response depends entirely on the primitive type.
A Server exposes capabilities as Resources, Prompts, or Tools.
Resources are static or dynamic data—like a local file, a database schema, or an API response. Crucially, Resources are *application-controlled*. The user or the Host application fetches the Resource and injects it into the context window *before* the LLM is invoked. The LLM cannot autonomously trigger a Resource fetch mid-thought.
Resources are data fetched by the application and loaded before the LLM acts.
Tools are functions the LLM can execute. Unlike Resources, Tools are *model-controlled*. The Host passes the tool schemas to the LLM, and the LLM autonomously decides if, when, and with what arguments to call the tool during its generation loop. If you need the AI to search a database based on a user's question, it must be a Tool.
Tools are functions the LLM autonomously chooses to execute during generation.
Because the word 'prompt' usually means 'system instructions', developers often assume MCP Prompts are used to set behavioral guardrails. They aren't. MCP Prompts are *user-controlled* workflow templates. The user explicitly selects a Prompt (e.g., 'Summarize Jira Ticket') from a UI menu to bootstrap a new conversation.
Prompts are user-selected templates to start workflows, not hidden system instructions.
The control boundary is why the distinction matters. If you expose a capability as the wrong primitive, the intended actor literally cannot see or use it. The LLM only sees Tools. The User sees Prompts and Resources.
Execution control determines the primitive: App controls Resources, User controls Prompts, Model controls Tools.
Code examples
The JSON-RPC lists: How the Host parses primitives
// 1. Host asks: "What Resources do you have?"
// Response: Data the user can attach (like files)
{
"method": "resources/list",
"result": {
"resources": [
{ "uri": "file:///logs/app.log", "name": "Application Logs" }
]
}
}
// 2. Host asks: "What Tools do you have?"
// Response: Functions the LLM can call autonomously
{
"method": "tools/list",
"result": {
"tools": [
{ "name": "search_logs", "inputSchema": { ... } }
]
}
}
The Host treats these payloads completely differently. It puts Resources into a UI menu for the user to attach. It passes Tools directly into the LLM's system payload so the AI can use them.
The Prompt Primitive: User-selected templates
// Host asks: "What Prompts do you have?"
{
"method": "prompts/list",
"result": {
"prompts": [
{
"name": "review_code",
"description": "Template for reviewing PRs",
"arguments": [ { "name": "pr_number", "required": true } ]
}
]
}
}
This is not a system instruction. The Host renders this as a clickable button in the UI. When the user clicks it, they are asked for the `pr_number`, and the server returns the actual text to start the chat.
Common mistakes
- Assuming Resources are just data-fetching tools: Developers often think Resources and Tools are interchangeable ways to get data into the context window. Reality: The distinction is about control. The LLM cannot execute a Resource. If you want the LLM to autonomously search a database, it must be a Tool. If you want the user to click a button to load a database schema before chatting, it's a Resource.
- Using Prompts for system instructions: Because 'prompt' is heavily associated with 'system prompt', developers try to use MCP Prompts to enforce an agent's tone or rules. Reality: MCP Prompts are user-selected templates. If the user never explicitly clicks the Prompt template in the UI, the LLM's behavior will not change.
Glossary
- Tool
- A capability exposed by the server that the LLM autonomously chooses to execute during generation based on context.
- Resource
- Data exposed by the server that the Host application (or user) loads directly into the context window *before* the LLM acts.
- Prompt
- A reusable, user-selected template or workflow provided by the server to bootstrap an LLM session, not a system instruction.
Recall questions
- What dictates whether data should be exposed as a Resource or a Tool?
- How do Prompts function within the protocol's lifecycle?
- A developer attempts to enforce an agent's tone by writing an MCP Prompt, but the LLM behavior does not change. Why?
- A developer wants the LLM to search a database autonomously during a conversation and defines the search function as a Resource. Why does the LLM ignore it?
Questions & answers
What's the actual difference between tools, resources, and prompts?
The difference is execution control. Resources are data loaded by the Host/User before inference. Tools are functions autonomously executed by the Model during inference. Prompts are reusable conversation templates selected by the User to bootstrap a session.
Approach: Define each by *who* controls it: App/User controls Resources, Model controls Tools, User controls Prompts.
What kinds of resources can an MCP server expose?
An MCP server can expose both static resources (like a specific local file or a hardcoded database schema) and dynamic resources (using URI templates like `user://{id}` to generate content on the fly based on the Host's request).
Approach: Mention that resources can be both static files and dynamically generated data, as long as they are fetched by the Host prior to model execution.
Continue learning
Previous: MCP Architecture: Hosts, Clients, and Servers