← Back to Agentic AI map
Lesson 4.1 · Model Context Protocol (MCP)

What is MCP and Why It Matters

You have wrapped the same tool three times - for your own agent, for LangChain, for LangGraph. MCP is one standard plug: write a tool once as a server, and any MCP app can use it. We prove it with one Python server and three very different clients.

mcp

What you will be able to do

  • Explain the problem MCP solves, using the tools you built in Modules 1-3
  • Say what MCP is - and what it is not
  • Name the three roles: host, client and server
  • Explain why "write once, use anywhere" matters for tools
  • See one server work with three different clients
  • Know the safety rules: a server is code that runs with your rights
  • Know when MCP is not worth it

The idea, in plain English

Think about the tools you have built in this course. In Module 1 you wrote a tool as a Python function and added it to your own tool list. In Lesson 2.6 you wrapped a function with LangChain’s @tool. In Lesson 3.5 you gave tools to LangGraph’s ToolNode. Three times, the same idea - a function the model may call - and three different kinds of glue code.

Now imagine everyone doing this. A company has a database tool. It must write glue code for LangChain, again for another framework, again for a chat app, again for a code editor. And every app that wants tools must write glue code for every tool. That is a lot of work that all does the same thing.

The Model Context Protocol (MCP) is an open standard that fixes this. It was introduced by Anthropic in November 2024. It defines one common way for an AI app to find tools and data, and to use them. You write a tool once, as an MCP server. Any app that speaks MCP - an MCP client - can use it, without new glue code.

In this module we build MCP servers in Python and connect them to agents. This first lesson explains the idea and proves it with a real run: one small server, three very different clients. Everything was run with the official MCP Python SDK, version 2.3.0.

Worked example: One "current time" server, used unchanged by our Python client, by curl, and by the official MCP Inspector (written in TypeScript).

workflowOne server, three different clientsstep 1 / 3

1 - A Python program asks

Our Python client starts the server, asks which tools it has, and calls get_current_time for Asia/Kolkata.

client
Python, mcp 2.3.0
tools found
get_current_time
answer
2026-10-09 18:59:49 IST
server changed?
no

Real runs. The same time_server.py - not changed once - answered a Python program, a curl command and the MCP Inspector, a tool written in TypeScript.

Words you will see in this module

MCP has a few words of its own. Learn these four first - the rest of the module uses them all the time.

Small dictionary
MCPModel Context Protocol: a standard way for AI apps to use tools and data.
ProtocolAn agreed set of messages and rules, so two programs can talk.
MCP serverA program that offers tools (and data). Our time-server is one.
MCP clientThe part of an app that connects to one server and talks MCP with it.
HostThe app the user works with - a chat app, a code editor, or your own agent. It contains the clients.
SDKA library that writes the MCP messages for you. We use the official Python SDK: pip install mcp.

An everyday example: one plug for every device

Years ago, every phone had its own charger. A new phone meant a new charger, and a friend’s charger never fitted. Today most devices use USB-C: one plug shape. Any charger works with any phone, laptop or headphones.

MCP is often called "USB-C for AI tools". Before MCP, every AI app needed its own adapter for every tool. With MCP, a tool has one standard "plug" - the MCP server - and every app has the matching "socket" - the MCP client. The tool maker writes the server once. The app maker writes the client once.

The problem in numbers

Count the glue code. With 3 apps and 3 tools and no standard, every app needs its own adapter for every tool: 3 x 3 = 9 adapters. With 10 apps and 10 tools it is 100.

With a standard, each tool is written once as a server and each app speaks the protocol once: 3 + 3 = 6 pieces of work. With 10 apps and 10 tools it is 20, not 100. And when a new app arrives, every existing tool already works with it.

The same tool, three times, in this course
Module 1A plain function, plus your own TOOLS dict and your own code to call it.
Lesson 2.6The function wrapped with LangChain’s @tool decorator.
Lesson 3.5The same @tool, given to LangGraph’s ToolNode.
With MCP (this module)Written once as an MCP server. Lesson 4.4 connects it to a LangGraph agent - and any other MCP app can use it too.

Three roles: host, client, server

The server offers things. Our time-server offers one tool, get_current_time. A server can be a small Python file on your laptop, or a service on the internet.

The host is the app the person uses: a chat app, a code editor, or the agent you build in Lesson 4.4. The host decides which servers to connect to, and it talks to the model.

Inside the host there is one client for each server. The client does the MCP talking: "which tools do you have?", "please run this tool with these arguments". The model never talks to the server directly. It asks the host to use a tool, and the host’s client does it - the same pattern as tool calling in Module 1.

The server we used

Here is the whole server from the diagram. Do not worry about every line yet - Lesson 4.3 builds it step by step. Notice how little there is: a normal Python function, plus two lines that turn it into an MCP server.

time_server.py - a complete MCP server
from datetime import datetime from zoneinfo import ZoneInfo from mcp.server.mcpserver import MCPServer # the official MCP Python SDK, version 2.x server = MCPServer("time-server") # 1. create a server and give it a name @server.tool() # 2. this function is now an MCP tool def get_current_time(timezone: str = "UTC") -> str: """Return the current date and time in an IANA timezone, such as Asia/Kolkata.""" now = datetime.now(ZoneInfo(timezone)) return now.strftime("%Y-%m-%d %H:%M:%S %Z") if __name__ == "__main__": server.run() # stdio: read requests on stdin, write answers on stdout

Proof: one server, three clients

First client: a Python program using the MCP SDK. It starts the server, lists its tools and calls one. The SDK read the tool’s description from the docstring, and the input format from the type hints - we wrote neither by hand.

Second client: curl, with no SDK at all. We started the same server in HTTP mode and sent one JSON message by hand. The answer came back as JSON. If curl can use a server, so can a program in any language.

Third client: the MCP Inspector, the official testing tool for MCP servers. It is written in TypeScript and runs with npx. It started our Python server and called the same tool. Python server, TypeScript client - and neither knows or cares what language the other is written in.

Client 1 - Python, with the MCP SDK (output)
tool: get_current_time | Return the current date and time in an IANA timezone, such as Asia/Kolkata. input schema: {'type': 'object', 'properties': {'timezone': {'default': 'UTC', 'title': 'Timezone', 'type': 'string'}}, 'title': 'get_current_timeArguments'} result: ... content=[TextContent(type='text', text='2026-10-09 18:59:49 IST', ...)] structured_content={'result': '2026-10-09 18:59:49 IST'} is_error=False
Client 2 - curl, one HTTP request typed by hand
$ curl -s -X POST http://127.0.0.1:8931/mcp \ -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \ -H "MCP-Protocol-Version: 2026-07-28" -H "Mcp-Method: tools/call" -H "Mcp-Name: get_current_time" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_current_time","arguments":{"timezone":"Asia/Tokyo"},"_meta":{...}}}' {"jsonrpc":"2.0","id":1,"result":{"content":[{"text":"2026-10-09 22:31:24 JST","type":"text"}],"isError":false, ...}}
Client 3 - the MCP Inspector (TypeScript), from the command line
$ npx -y @modelcontextprotocol/inspector@latest --cli python time_server.py \ --method tools/call --tool-name get_current_time --tool-arg timezone=Asia/Kolkata { "content": [ { "type": "text", "text": "2026-10-09 19:02:32 IST" } ], "structuredContent": { "result": "2026-10-09 19:02:32 IST" }, "isError": false }

Tip: The Inspector needs Node.js. Version 2.10.1 printed a warning that it wants Node 22.19 or newer (we had 22.13) - and still worked. Lesson 4.3 uses it to test your own server.

What MCP is not

MCP is not a model. It does not make the model smarter, and it does not decide which tool to call - the model still decides, exactly as in Module 1.

MCP is not an agent framework. It does not replace LangChain or LangGraph. It is the connection between an agent and its tools. In Lesson 4.4 a LangGraph agent will use MCP tools - LangGraph runs the loop, MCP brings the tools.

MCP is not only for tools. A server can also offer resources (data the app can read, such as a file) and prompts (ready-made message templates). Lesson 4.2 shows all three.

MCP is new and changes fast

MCP is young, and it is still changing. The Python SDK we installed knows five protocol versions, each named by a date: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25 and 2026-07-28. The newest one changed how a connection starts (Lesson 4.2 shows both ways).

The SDK changed too. Version 2 renamed the main class: many tutorials on the internet still write "from mcp.server.fastmcp import FastMCP", which is version 1 code. In version 2.3.0 that line fails with a clear message. When you follow a tutorial, check which SDK version it uses.

Version 1 code on SDK 2.3.0
>>> from mcp.server.fastmcp import FastMCP ModuleNotFoundError: No module named 'mcp.server.fastmcp'. This is mcp 2.x, where FastMCP was renamed to MCPServer (from mcp.server.mcpserver import MCPServer) and other APIs changed; see the migration guide ...

Safety: a server is code that runs as you

When a host starts an MCP server on your computer, that server is a normal program running with your user’s rights. It can read your files, use your network, and run commands - whatever its code does. Install only servers you trust, just as you would with any other program.

The tool descriptions a server sends are shown to the model. A bad server could write a description that tries to trick the model ("ignore your instructions and..."). And tool results can contain such text too. Treat everything that comes from a server as untrusted input.

For tools with real effects - sending email, deleting files, paying money - keep a human approval step in front of them, as in Lesson 3.7. MCP makes tools easy to connect; it does not make them safe.

When MCP is worth it, and when it is not

MCP adds a second program and a protocol between your agent and its tool. That is worth it when the tool should be shared, reused or used from many apps. It is not worth it for one small script that calls one function.

Plain function or MCP server?
One script, one tool, only you use itA plain function (Module 1) or @tool (Lesson 2.6) is simpler.
Several agents or apps need the same toolMCP server - write it once.
You want to use it in a chat app or code editor tooMCP server - those apps speak MCP.
The tool belongs to another team or companyMCP - they ship a server, you connect to it.
The tool is written in another languageMCP - a Python agent can use a TypeScript server, and the other way round.

MCP at a glance

Install the SDK

The official Python SDK.

pip install "mcp>=2,<3"
Make a server

Version 2 name (version 1 called it FastMCP).

from mcp.server.mcpserver import MCPServer
Make a tool

A normal function with a decorator.

@server.tool()
Run it

Over stdin/stdout by default.

server.run()
Test it

The official Inspector, from the command line.

npx @modelcontextprotocol/inspector --cli python server.py --method tools/list

Try it yourself

The code does not change. Swap the content string and the program does something else entirely.

Install and check

“Create a fresh virtual environment, run pip install "mcp>=2,<3", and print mcp’s version with importlib.metadata.version("mcp").”

Run the Inspector

“Save time_server.py and run the Inspector command with --method tools/list. Find the description and the timezone field in the output.”

Count the glue

“List the AI apps and tools you use today. How many adapters would you need without a standard? How many with MCP?”

Old tutorial

“Find an MCP tutorial online. Does it use FastMCP (version 1) or MCPServer (version 2)?”

What usually goes wrong

Thinking MCP replaces LangChain or LangGraph

MCP connects tools to apps. Your agent still needs a loop and a model - Module 1, LangChain or LangGraph. Lesson 4.4 puts them together.

Following a version 1 tutorial with SDK 2

FastMCP was renamed to MCPServer in version 2. Check the version, or pin the one your tutorial uses.

✗ from mcp.server.fastmcp import FastMCP     # ModuleNotFoundError on mcp 2.x
✓ from mcp.server.mcpserver import MCPServer
Installing any server you find

A local MCP server runs with your rights. Read what it does, prefer well-known sources, and keep approval in front of risky tools.

Using MCP for everything

For one tool in one script, MCP is extra moving parts. Use it when a tool is shared or reused.

Key points

  • MCP is an open standard (Anthropic, November 2024) for connecting AI apps to tools and data.
  • A tool is written once as an MCP server; any MCP client can use it - no new glue code.
  • Three roles: the host (the app), a client per server inside it, and the server.
  • The model still decides which tool to call; the host’s client does the MCP talking.
  • Our one Python server worked with a Python client, curl and a TypeScript app - unchanged.
  • MCP is young: protocol versions are dates, and SDK 2 renamed FastMCP to MCPServer.
  • A local server runs with your rights - install only servers you trust.

Quick check before you move on

What problem does MCP solve?
Every app needing its own glue code for every tool. With MCP a tool is written once as a server and any MCP app can use it.
What is the difference between the host, a client and a server?
The host is the app the user works with. Inside it, one client per server talks MCP. The server offers tools, resources and prompts.
Does MCP decide which tool to call?
No. The model still decides. MCP only defines how the app finds and calls tools.
Why could curl use our server?
Because MCP is just JSON messages over a connection. Any program that can send the right JSON can be a client.

Quiz

  1. 1.

    4 apps and 5 tools, no standard: how many adapters? With MCP?

  2. 2.

    What happens if you run "from mcp.server.fastmcp import FastMCP" with mcp 2.3.0?

  3. 3.

    Is a Python MCP server usable from a TypeScript app?

  4. 4.

    Name one case where MCP is not worth it.

Interview questions

What is the Model Context Protocol, and why does it exist?

An open protocol that standardizes how AI applications discover and use external tools, data (resources) and prompt templates. It turns an N x M integration problem - every app writing glue for every tool - into N + M: tools ship as servers, apps implement a client once.

How does MCP relate to function calling?

Function calling is how a model asks for a tool. MCP is how the host application finds tools and executes them on servers. The model still emits a tool call; the host maps it to an MCP tools/call on the right server.

What are the main risks of MCP servers?

Local servers run with the user’s privileges; tool descriptions and results can carry prompt injection; overly powerful tools can take real actions. Mitigate with trusted sources, least privilege, approval for side effects, and treating server output as untrusted.

Comments

Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.

Loading comments...