If you have never built anything with MCP, this is the page that has to land. Everything else in the course is built on it, so we are going to go slowly, and we are going to look at the actual bytes before the end.
Part 1 · The problem, before any jargon
An AI model is a brain in a jar. It is very smart, and it is completely stuck.
It can think about your files. It cannot open them. It can talk about rolling dice. It cannot actually roll one — ask it for a random number and it will say 7 far more often than chance allows, because it is pattern-matching against text, not rolling anything.
Your code is the opposite problem. It has hands and no idea what you want.
Why this is harder than "just call a function"
The obvious thought is: fine, let the model call my function. But a language model does not execute anything. It produces text. That is the only thing it can do.
So "the model called my function" always means, underneath:
- The model produced some text that describes a function call.
- Your program read that text, recognised it as a request, and ran the function itself.
- Your program put the result back into the conversation as more text.
- The model read that text on its next turn.
There is no step where the model reaches out and touches anything. Every integration is a loop of text going back and forth, with your code in the middle doing the actual work.
Part 2 · The fix is a list taped to a box
Picture a toy box. The AI cannot see inside it. So you tape a list to the outside:
Inside this box:
🎲 1 dice — for when you need real randomness
🍪 1 cookie jar — for counting cookies
🔐 1 decoder ring — for secret messagesThe AI reads the list, points at one, and says "use that one, please, with these settings." You reach in, use it, and hand back the result.
MCP is the agreed-upon shape of those messages — the shape of the list, and the shape of "use that one, please." That is the entire idea. Everything below is detail.
What "protocol" actually means here
It is worth being concrete, because "protocol" sounds grander than it is.
A protocol is just an agreement about the shape of messages so two programs written by strangers can talk. HTTP is an agreement that a request starts with a method and a path. MCP is an agreement that:
- asking what's available is a message whose
methodis"tools/list" - using one is a message whose
methodis"tools/call" - a tool is described by a
name, adescription, and aninputSchema
Nothing more mystical than that. There is no MCP daemon, no special port, no binary format. It is JSON, usually over an ordinary HTTP POST.
Part 3 · Why a standard was worth having
Before MCP, connecting 10 AI apps to 10 services meant writing 100 bespoke integrations — every app against every service, each one hand-rolled, each one breaking on its own schedule.
With MCP it is 10 + 10 = 20. Each app learns MCP once. Each service speaks MCP once. Everything plugs into everything.
It is USB-C for AI. One shape of plug. The value is not that the plug is clever — it is that everybody agreed on it.
Part 4 · Three words, defined plainly
These three get used interchangeably everywhere, and they are not interchangeable. Getting them straight now will save you the entire course.
| Word | What it is | Analogy | Built in |
|---|---|---|---|
| Server | Offers tools. Waits. Never starts anything. | a vending machine | project #1 |
| Client | The piece that speaks to exactly one server. | the coin slot and keypad | project #2 |
| Host | Owns the conversation with the model, wrangles several servers, runs the loop, holds the API key. | the person with the wallet, standing in front of a row of machines | project #2 |
Where you have already met these
You have almost certainly used a host without calling it that.
Claude Desktop is a host. When you add an MCP server to its config file and restart it, Claude Desktop connects a client to your server, fetches your tool list, and includes it in every message it sends to the model. When the model asks for a tool, Claude Desktop runs it and pastes the result back.
Claude Code, Cursor, and every "AI app with plugins" are the same shape.
Part 5 · A complete conversation, in six messages
Here is the whole thing, end to end. Six ordinary HTTP POSTs carrying JSON.
| # | What happens | The actual message |
|---|---|---|
| 1 | The AI knocks. Which version do you speak? | initialize |
| 2 | The AI reads the list. Every tool's name, description and inputs. | tools/list |
| 3 | You ask for something. "Roll me three d20s." | (plain English, no MCP yet) |
| 4 | The AI points at a toy. It matched your sentence to a description. | tools/call |
| 5 | Your code runs. On your server, with your data. | (just JavaScript) |
| 6 | The answer comes home. | (the response) |
Now let us actually look at the bytes, because this is the part most introductions skip and it is the part that makes MCP stop being mysterious.
Message 2 — asking what's available
You send this:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }Four fields, and three of them are boilerplate:
| Field | What it is for |
|---|---|
jsonrpc | Always "2.0". It says which envelope format this is. |
id | Any number you choose. The reply comes back carrying the same id, so you can match replies to requests when several are in flight. |
method | The only interesting field. What you are asking for. |
params | Arguments for the method. Omitted here, because "what have you got?" needs none. |
That envelope — jsonrpc, id, method, params — is JSON-RPC 2.0, and
it is the entire wire format. It predates MCP by fifteen years and MCP just
uses it.
And the server answers
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "roll_dice",
"description": "Roll one or more dice and return the individual results and their total. Use this whenever real randomness is needed — the model cannot generate random numbers itself.",
"inputSchema": {
"type": "object",
"properties": {
"sides": { "type": "integer", "minimum": 2, "maximum": 1000, "default": 6 },
"times": { "type": "integer", "minimum": 1, "maximum": 20, "default": 1 }
}
}
}
]
}
}Same id, so you know which question this answers. And a result containing
one tool.
Read what a "tool" actually is, because it is less than you might expect:
- a name — an identifier
- a description — a paragraph of English
- an inputSchema — JSON Schema describing the arguments
That is all. There is no code in a tool definition. The implementation lives on the server and is never shown to anybody. The model only ever sees these three things.
Message 4 — using one
The host takes that tool list, hands it to the model along with your sentence
"roll me three twenty-sided dice", and the model replies with a request to
use roll_dice with sides: 20, times: 3.
The host turns that into:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "roll_dice",
"arguments": { "sides": 20, "times": 3 }
}
}Your server runs your JavaScript and answers:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "Rolled 3d20 -> [17, 9, 18] Total: 44" }
]
}
}The same thing, as a picture
Part 6 · Try it right now
Project #1's server is deployed and open. You do not need to install anything, sign up for anything, or hold an API key — a server costs nothing to run and nothing to call.
curl -X POST https://learn-mcp-5-year-old.vercel.app/api/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Checkpoint
You get back a JSON blob listing four tools with their descriptions and input
schemas. That is a real MCP conversation, and you just had one with
curl.
If you got a 406, see the callout below — it is the single most common
first-contact error.
And to actually run one:
curl -X POST https://learn-mcp-5-year-old.vercel.app/api/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"roll_dice","arguments":{"sides":20,"times":3}}}'Part 7 · What a server can offer
Almost everybody only ever builds tools. There are five capabilities in total, and the other four matter because they answer a question tools cannot: who gets to decide?
| Capability | What it is | Who pulls the trigger |
|---|---|---|
| 🔧 tools | A verb. Something to do. | the model decides |
| 📄 resources | A noun. Something to read, addressed by URI. | the host decides |
| 💬 prompts | A saved fill-in-the-blank instruction. | the human decides |
| 🧠 sampling | The server asks your host to run a model call. | the server asks |
| 🙋 elicitation | The server asks your user a question. | the server asks |
The next page takes each of these apart. For now, one number is worth carrying:
What you now know
Before moving on, you should be able to say all of these without looking:
- A model produces text and touches nothing; your program performs the actions.
- MCP is an agreement about the shape of JSON messages, carried over ordinary HTTP POSTs.
- The envelope is JSON-RPC 2.0:
jsonrpc,id,method,params. - Three messages do almost everything:
initialize,tools/list,tools/call. - A tool is a name, a description and an inputSchema — no code.
- The description is what the model reads when choosing.
- A server offers and waits; a client talks to one server; a host owns the model conversation, the loop and the money.
Next: the five capabilities, sorted by who pulls the trigger.