Module 3: Three Primitives — Resources, Tools, Prompts

Module 3: Three Primitives — Resources, Tools, Prompts

Module 3: Three Primitives — Resources, Tools, Prompts

Capsule description

You've come a long way. In Module 1 you understood why MCP exists — the M×N problem and how a standard protocol solves it. In Module 2 you learned how it works — the Host-Client-Server architecture and the data flow between layers. Now comes the natural question: what can an MCP server do?

The answer fits in three words: Resources, Tools, Prompts.

These are the three primitives — the fundamental building blocks — that every MCP server exposes. There isn't a fourth. Any capability an MCP server offers is implemented as one of these three. Understanding them is the difference between "I know what MCP is" and "I can design an MCP server."

This module is the bridge between theory and construction. By the end of it, you won't just understand the primitives conceptually — you'll have a minimal MCP server working with 1 resource, 1 tool, and 1 prompt.


Where are we?

Context within the guide

Phase 1: MCP Fundamentals (Modules 1-3)
  ✅ Module 1: What MCP is and why it matters
  ✅ Module 2: Host-Client-Server Architecture
  → Module 3: Three Primitives (YOU ARE HERE)

Phase 2: Build MCP Servers (Modules 4-6)
  ○ Module 4: MCP Server in TypeScript
  ○ Module 5: MCP Server in Python
  ○ Module 6: MCP Apps and Interactive UI

Phase 3: Production (Modules 7-8)
  ○ Module 7: Testing, Debugging, and Integration
  ○ Module 8: Project — Real MCP Server

What you already know

From the previous modules you bring:

  • The M×N vs M+N mental model — why a standard protocol is necessary
  • The Host-Client-Server architecture — how the pieces connect
  • The flow of a request — how data travels from the user to the server and back
  • Hands-on experience — you configured and used the Filesystem MCP Server in Claude Code

What's missing

You know that an MCP server exposes "capabilities" to the host. But what types of capabilities exist? How do you decide whether something should be a resource, a tool, or a prompt? How do you implement each one? That's exactly what this module covers.


Module objective

By the end of this module, you'll be able to:

  • ✅ Explain the difference between Resources, Tools, and Prompts with concrete examples
  • ✅ Decide when to use each primitive: "I need to expose data → Resource; I need to execute an action → Tool; I need to standardize a flow → Prompt"
  • ✅ Implement a Resource that exposes static and dynamic data
  • ✅ Implement a Tool that executes a function with side effects
  • ✅ Implement a Prompt that generates parameterized templates
  • ✅ Build a minimal MCP server with the 3 primitives working together
  • ✅ Connect your server to Claude Code and verify that it works

The 3 primitives: overview

Before going deep into each one (capsules 02-04), you need the complete map.

Analogy: a tool shop

Imagine that an MCP server is a tool shop:

MCP Server = Tool shop
│
├── Resources (the catalog)
│   "I can show you what we have in stock"
│   → Data you can read
│   → Doesn't modify anything — just queries
│
├── Tools (the services)
│   "I can cut, weld, paint for you"
│   → Functions that execute actions
│   → They can modify state
│
└── Prompts (the project recipes)
    "Here are step-by-step instructions"
    → Reusable templates
    → They standardize how to ask for things

Quick comparison table

AspectResourcesToolsPrompts
What it isContextual dataExecutable functionsReusable templates
DirectionPull: client asks, server respondsInvocation: model calls, server executesTemplate: client asks, server generates
Side effectsNo — read-onlyYes — can modify stateNo — just generates text
AnalogyReading a bookUsing a toolFollowing a recipe
ExampleRead a file, query a DBCreate a file, send an emailCode review template
Who initiatesThe client/user asks for dataThe model decides to invokeThe user selects a template
ControlControlled by the applicationControlled by the model (with approval)Controlled by the user

The natural flow

In a real server, the three primitives complement each other:

1. Resource → "What files are in the project?"
   Server responds with the list of files

2. Tool → "Refactor this file"
   Server executes the refactoring

3. Prompt → "Use the code review template"
   Server generates the prompt with the user's parameters

The resource exposes the data, the tool acts on it, and the prompt standardizes how things are asked for. Each has its role.

Decision tree: which primitive do I need?

When you design your MCP server, this tree helps you decide:

Does the model need to READ data?
├── Yes → Do the parameters fit in a URI?
│   ├── Yes → Resource (with a URI template if it's dynamic)
│   └── No → Read-only Tool (with a schema for complex parameters)
└── No
    ↓
Does the model need to EXECUTE an action with side effects?
├── Yes → Tool
│   └── Is it a destructive action?
│       ├── Yes → Tool with a dryRun pattern
│       └── No → Standard Tool
└── No
    ↓
Do you want to STANDARDIZE how the user asks for something?
├── Yes → Prompt
│   └── Does it need context from files/data?
│       ├── Yes → Prompt with an embedded resource
│       └── No → Prompt with just text
└── No → You probably don't need MCP for this

Examples of real MCP servers and their primitives

To anchor this in reality, let's see how existing servers use the primitives:

Filesystem Server (Anthropic official):

Resources: (doesn't expose resources, uses tools for everything)
Tools:
├── read_file         → Reads a file
├── write_file        → Writes a file
├── list_directory    → Lists a directory
├── search_files      → Searches files
├── create_directory  → Creates a directory
├── move_file         → Moves/renames
└── ...
Prompts: (doesn't define prompts)

This server is 100% tools because all the operations are actions with variable inputs. Note that read_file is a tool and not a resource — because the file's path comes as a complex parameter, not as a predefined URI.

A hypothetical GitHub Server:

Resources:
├── github://repos/{owner}/{repo}/readme      → The repo's README
├── github://repos/{owner}/{repo}/issues/open  → Open issues
└── github://repos/{owner}/{repo}/stats        → Statistics
Tools:
├── create_issue     → Creates an issue
├── close_issue      → Closes an issue
├── create_pr        → Creates a pull request
├── merge_pr         → Merges a PR
└── add_comment      → Adds a comment
Prompts:
├── bug-report       → Standardized bug report template
├── pr-description   → Generates a PR description
└── code-review      → Code review template with criteria

This server uses the 3 primitives: resources for query data, tools for actions, prompts to standardize common interactions.


The mental model: think in layers

A useful way to think about the primitives is as the layers of a restaurant:

┌─────────────────────────────────────┐
│           MENU (Prompts)            │
│  What the customer sees and chooses │
│  "Combo #3: burger + fries"         │
├─────────────────────────────────────┤
│          KITCHEN (Tools)            │
│  Where the actions are executed     │
│  "Cook burger, fry fries"           │
├─────────────────────────────────────┤
│        INVENTORY (Resources)        │
│  The available ingredients          │
│  "Bread, meat, potatoes, oil"       │
└─────────────────────────────────────┘
  • The menu (Prompts) standardizes how the customer asks — they don't need to know the internal details.
  • The kitchen (Tools) executes the real actions — it transforms ingredients into dishes.
  • The inventory (Resources) provides the base data — what's available, quantities, status.

The customer doesn't go to the inventory directly. They don't enter the kitchen. They use the menu. But behind it, everything works as an integrated system.


Module roadmap

CapsuleTopicWhat you'll learn
02Resources: contextual dataExpose data the model can read — files, DB records, API responses
03Tools: executable functionsCreate functions the model can invoke — with real side effects
04Prompts: reusable templatesDesign parameterized templates for common interactions
05Combining primitivesHow the 3 work together in a real server
06Mini-projectImplement an MCP server with 1 resource, 1 tool, 1 prompt

Learning flow

The progression is deliberate:

  1. Resource (capsule 02) — we start with the simplest primitive: read-only data. No side effects, no complexity.
  2. Tool (capsule 03) — we raise the complexity: functions that execute actions and can modify state. It requires schemas, validation, permissions.
  3. Prompt (capsule 04) — the least intuitive for developers: reusable templates. It's not code that executes — it's text that guides.
  4. Combination (capsule 05) — the 3 together: how a real server orchestrates resources, tools, and prompts as a cohesive system.
  5. Mini-project (capsule 06) — you build your first functional MCP server with the 3 primitives.

Each capsule has examples in TypeScript (primary) and Python (secondary). Both official SDKs are supported.


Connection to the project

This module's mini-project

You're going to build a minimal MCP server with:

  • 1 Resource: list a directory's files
  • 1 Tool: create a new file
  • 1 Prompt: refactoring template

It's deliberately simple. The goal is for you to understand the 3 primitives in action, not to build something complex. The complexity comes in modules 4-6.

Connection to the capstone project (Module 8)

This module's minimal server is the seed of the final project. In Module 4 you'll scale it up with complete TypeScript (multiple tools, Zod schemas, transports). In Module 8 you'll turn it into a production-ready server connected to a real API/database. The patterns you learn here — how to define resources, tools, and prompts — are exactly the ones you'll use at scale.


Prerequisites

For this module you need:

  • ✅ Claude Code installed and working
  • ✅ Node.js v18+ and npm installed
  • ✅ To have completed modules 1 and 2 (concepts and architecture)
  • ✅ To have used the Filesystem MCP Server (module 1, capsule 05)

Recommended but not required:

  • Basic familiarity with TypeScript (you can learn as you go)
  • Basic familiarity with Python (only needed if you choose the Python implementation)
  • To have explored the Filesystem Server beyond the module 1 examples

Boundaries: what is NOT covered in this module

  • ❌ Complete implementation in TypeScript — That comes in module 4
  • ❌ Complete implementation in Python — That comes in module 5
  • ❌ Advanced Zod schemas — Covered in module 4
  • ❌ Transports (stdio, HTTP/SSE) — Covered in module 4
  • ❌ Testing and debugging — Covered in module 7
  • ❌ MCP Apps and UI — Covered in module 6

This module is conceptual + first hands-on contact. You're building the "what it can do" before the "how to do it at scale."


Signs of success

By the end of this module, you'll know you succeeded if:

  • ✅ You can explain Resources, Tools, and Prompts to a colleague using concrete examples
  • ✅ Given a use case, you can decide which primitive(s) you need
  • ✅ You have a minimal MCP server running with 1 of each primitive
  • ✅ You've connected your server to Claude Code and tested it
  • ✅ You understand how the 3 primitives combine in a real server
  • ✅ You feel prepared to scale this up in TypeScript (module 4)

Design decision: why only 3 primitives?

It may seem limiting — only three types of capability? But that simplicity is intentional. Think of HTML: the entire web is built with ~100 tags, but most pages use only 20-30. The simplicity of the set doesn't limit what you can build — it enables it.

Resources cover any data the model needs to read

It doesn't matter where the data comes from:

  • Filesystem files → file:///src/main.ts
  • Records from a database → db://users/123
  • Responses from external APIs → api://weather/madrid
  • System configurations → config://app/settings
  • Logs and metrics → metrics://server/cpu
  • Service status → status://docker/containers

Any data you can put in a URI, you can expose as a Resource.

Tools cover any action the model needs to execute

If it has a verb, it's probably a Tool:

  • Create: files, records, issues, PRs
  • Read with complex parameters: searches, queries with filters
  • Update: modify data, configurations, state
  • Delete: remove records, files, resources
  • Execute: deploy, test, lint, build
  • Send: emails, notifications, messages

Everything that modifies state or requires validated parameters is a Tool.

Prompts cover any interaction you want to standardize

If you repeat an interaction pattern, encapsulate it in a Prompt:

  • Code review templates with specific criteria
  • Step-by-step code generation wizards
  • Debugging flows with a structured format
  • Standardized reports (standup, sprint review)
  • Documentation with a consistent format

You don't need a fourth primitive because these three cover the complete spectrum: read data (Resource), execute actions (Tool), and standardize interactions (Prompt).


Frequently asked questions before starting

"Do I need all 3 primitives in my server?"

No. Many servers only use Tools (like the Filesystem Server). Others only expose Resources (a metrics server). Some only have Prompts (a template server). Use the ones you need.

"Do the primitives call each other?"

Not directly at the protocol level. But in your code, a Tool can read data internally (as a Resource would), and a Prompt can generate instructions that lead the model to use a Tool. The integration happens at the design level, not the protocol level.

"Which is the most important?"

Tools. It's the most used primitive in practice. If your server could only have one type of primitive, it would be Tools. But the 3 together make a server much more powerful and usable.

"Can I create my own types of primitives?"

Not in the standard protocol. MCP defines exactly 3 primitives. If something doesn't fit in Resources, Tools, or Prompts, you probably need to rethink your design — almost everything fits if you model it correctly.


Mental preparation

Before entering the technical capsules, keep this in mind:

  • You don't need to memorize the APIs. What matters is the mental model — knowing when to use each primitive. You look up the syntax in the documentation.
  • TypeScript first, Python second. If you don't know TypeScript, don't worry — the examples are self-explanatory and the patterns are universal.
  • The mini-project is the goal. Everything you learn in capsules 02-05 converges in capsule 06, where you build a functional server.

Summary

  • This module covers the what an MCP server can do — the 3 primitives
  • Resources = read-only data the model queries
  • Tools = executable functions with side effects
  • Prompts = reusable templates with parameters
  • Progression: Resource → Tool → Prompt → Combination → Mini-project
  • By the end you'll have a minimal MCP server with the 3 primitives working
  • This minimal server is the seed you'll scale up in modules 4-8

Additional resources

  1. MCP Specification — Primitives - Official specification of Resources, Tools, and Prompts
  2. MCP TypeScript SDK - SDK you'll use to implement the primitives
  3. MCP Python SDK - Python alternative
  4. Building MCP Servers (Anthropic Docs) - Official construction guide
  5. MCP Inspector - Tool to inspect resources, tools, and prompts
  6. Awesome MCP Servers - Real examples of servers with different combinations of primitives

Note about the code examples

Throughout this module you'll find examples in TypeScript (primary language) and Python (secondary language). Both official MCP SDKs are supported and the choice depends on your preference:

  • TypeScript SDK (@modelcontextprotocol/sdk) — More mature, more reference servers available, uses Zod for schema validation
  • Python SDK (pip install mcp) — More concise thanks to decorators, ideal if your stack is Python-centric, uses type hints and Pydantic

In module 4 you'll go deeper into TypeScript and in module 5 into Python. Here you'll see both so you can compare and choose.


Next capsule: Resources — contextual data the model can read. The simplest primitive and the perfect entry point to understand how an MCP server exposes capabilities.