calculator
Provides a Streamlit-based chat UI that acts as an AI host, allowing users to chat with MCP servers and drive real MCP tools through an LLM agent loop.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@calculatorWhat is 27 * 43?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Learn MCP by Building an MCP Server
The hands-on guide to the Model Context Protocol. Build a calculator server, test it the way real AI apps do, upgrade it into a live weather server, and finally build your own AI host — a chat UI where an LLM calls your tools for real.
📖 Full docs: tharunramavath.github.io/learn-mcp-by-building
MCP (Model Context Protocol) is the open standard that lets AI apps (Claude, ChatGPT, VS Code, Cursor) talk to your tools and data — "USB-C for AI". This repo is a from-zero, build-it-yourself tutorial: every concept becomes a file you write, run, and break on purpose. No AI/ML background needed.
Who this is for
Developers who want to understand MCP by building, not just reading.
Python users comfortable with functions, async, and JSON.
People who learn best when they can see the protocol wire traffic fly by.
You do not need any AI/ML background, an API key, or an LLM for Steps 1–6.
Related MCP server: MCP Server Demo
What you'll build
Step | You build | You learn |
0 | Your environment | The Python MCP SDK |
1 |
| The 3 primitives: tools, resources, prompts |
2 |
| The whole JSON-RPC conversation |
3 | MCP Inspector | Visual tool-calling + raw protocol traffic |
4 | A real AI app (Claude / VS Code / Cursor) | What a host and client configs look like |
5 |
| Async tools, external APIs, geocoding |
6 | — | The two layers & stateless discovery |
7 |
| Function calling driving real MCP tools |
Quickstart (60 seconds)
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python server_basic.pyThat server does nothing visible — by design. It waits for a client. Open a second terminal and talk to it:
python test_client_basic.pyIf you see discovery, tools, resources, prompts, and add(2, 3) → 5.0 — you
just ran a full MCP conversation. Now go do the steps below.
Table of contents
Read these docs first
docs/00-learning-path.md— start here: the recommended reading/doing order
docs/01-concepts.md— the theory: what MCP is, architecture, primitives
docs/02-glossary.md— a cheat-sheet of every term
docs/03-inspector-v2-guide.md— how the new Inspector v2 UI maps to the classic (v1) layout
docs/04-mcp-vs-alternatives.md— how MCP compares to plain function calling, provider tools, and REST APIs
docs/05-faq.md— a deeper FAQ than the short one at the bottom of this README
💡 Prefer reading in the browser? The same docs are hosted at tharunramavath.github.io/learn-mcp-by-building.
Project layout
mcp-tutorial/
├── server_basic.py STEP 1 - your first (offline) server
├── test_client_basic.py STEP 2 - a tiny client that tests it
├── server_weather.py STEP 5 - the real-world weather server
├── test_client_weather.py STEP 5 - a client for the weather server
├── mcp_host.py STEP 7 - the MCP host/client wrapper (sync bridge)
├── chat_engine.py STEP 7 - the LLM agent loop (Groq function calling)
├── app.py STEP 7 - the Streamlit chat UI
├── run-chat.cmd STEP 7 - double-click to launch the chat UI
├── claude_desktop_config.json STEP 4 - config for Claude Desktop (edit the path)
├── .vscode/mcp.json STEP 4 - config for VS Code
├── inspector.json STEP 3 - Inspector catalog (launch config for both servers)
├── run-inspector.cmd STEP 3 - double-click to launch the Inspector
├── requirements.txt
└── docs/
├── 00-learning-path.md START HERE - the sequential reading order
├── 01-concepts.md
├── 02-glossary.md
├── 03-inspector-v2-guide.md
├── 04-mcp-vs-alternatives.md
└── 05-faq.mdStep 0 — Setup (one time)
# From inside the mcp-tutorial/ folder:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txtThat installs the official Python MCP SDK (mcp) plus httpx2 (the HTTP client
the weather server uses). Verify:
python -c "from mcp.server import MCPServer; print('MCP SDK OK')"Prefer uv? (faster, modern alternative)
If you have uv installed, you can skip the venv
setup entirely — the project has a pyproject.toml:
uv sync # creates .venv and installs all deps from pyproject.toml
uv run server_basic.py # run the server
uv run test_client_basic.py # run the test clientWindows note: use
uvfor running scripts, but launch the Inspector withnpx @modelcontextprotocol/inspector --catalog inspector.jsoninstead ofuv run mcp dev— see Step 3. If a GUI app says'uv' is not recognized, add uv's folder to your PATH permanently:[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path","User") + ";$env:USERPROFILE\.local\bin", "User")then fully restart the app.
Step 1 — Your first server: server_basic.py
Open server_basic.py and read it top to bottom. It is ~90 lines and shows all
three primitives at once.
from mcp.server import MCPServer
mcp = MCPServer("calculator") # 1 line to create a serverThe 3 tools (what the AI can call)
@mcp.tool()
def add(a: float, b: float) -> float:
"""Add two numbers together.
Args:
a: The first number.
b: The second number.
"""
return a + bThree magic things happen here:
@mcp.tool()registers the function as an MCP tool.The type hints (
a: float, b: float) become the tool's input schema.The docstring becomes the tool's description — this is what the AI model reads to decide when to call it. Write it like the model will read it.
The 1 resource (read-only data)
@mcp.resource("config://app", mime_type="application/json")
def get_app_config() -> dict:
return APP_CONFIGResources have a URI (config://app). The app loads them to give the model
context — like opening a file.
The 1 prompt (a template)
@mcp.prompt()
def math_help(problem: str) -> list[dict]:
return [{"role": "user", "content": f"You are a math tutor. Problem: {problem}"}]Prompts are templates the user invokes explicitly (like a slash command).
Run it
python server_basic.pyIt prints a log line and then just sits there. That is normal — a stdio server waits for a client to spawn it and talk to it.
Why no output? Over the
stdiotransport, your server's stdout is the protocol. If youprint()anything, you corrupt the JSON-RPC messages and the server silently breaks. That's why we uselogging(which goes to stderr). This is the golden rule of stdio MCP servers — seedocs/01-concepts.md.
Step 2 — Test it with a tiny client: test_client_basic.py
You don't need an AI app yet. This script is a minimal stand-in client that connects to your server over stdio and drives the whole protocol.
python test_client_basic.pyYou'll see, in order:
Discovery — the client asks what the server supports (
server/discover).List tools — notice each tool's auto-generated
inputSchema.List resources — the
config://appURI.List prompts —
math_help.Call tools —
add(2, 3)returns5.0.Read the resource — your config JSON comes back.
Get the prompt — the template comes back.
That's the entire MCP conversation, end to end. The client code:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async with stdio_client(server_params) as (read, write): # spawn server
async with ClientSession(read, write) as session: # open conversation
await session.initialize() # handshake
await session.list_tools()
await session.call_tool("add", {"a": 2, "b": 3})Step 3 — Explore with the MCP Inspector (visual UI)
The official MCP Inspector is a web UI for poking at servers and watching the raw JSON-RPC messages.
This project ships an inspector.json catalog that tells the Inspector how to
launch both servers using paths relative to this folder (no uv, no PATH
lookup, no machine-specific paths).
Easiest way — double-click run-inspector.cmd, or run it from the terminal:
.\run-inspector.cmdOr invoke npx directly:
npx @modelcontextprotocol/inspector --catalog "<your-path>\mcp-tutorial\inspector.json"The web UI opens at http://localhost:6274 (the browser auto-launches; the URL
may carry an MCP_INSPECTOR_API_TOKEN= query param — keep it if you
bookmark the page). Pick a server (calculator or weather) from the catalog
and click Connect. Click around:
Tools / Resources / Prompts tabs — browse what your server exposes.
Call a tool — try
addwith{"a": 10, "b": 5}.Protocol tab — watch the actual JSON-RPC requests and responses fly by. This is where you see what Step 2 did programmatically.
If the UI looks different from YouTube tutorials, that's because this project runs the new Inspector v2. See
docs/03-inspector-v2-guide.mdfor a feature-by-feature map (transport type, command/args, pings, sampling, roots, protocol routes, etc.) to the v2 tabs.
Windows note: avoid
mcp dev/uv run mcp dev— it forces the Inspector to spawn your server viauv, which often fails on Windows (the Inspector's spawned process can't seeuvon PATH). The--catalogapproach above avoids that entirely by using relative paths to the venv Python. Also launch the Inspector from PowerShell or cmd (double-clickrun-inspector.cmd) rather than from Git Bash — the MSYS environment mis-resolvesnodefor child processes and the Inspector dies withspawn node ENOENT. Only one Inspector can run at a time — if you see "PORT IS IN USE", close the existing tab/instance instead of starting another. First run downloads the Inspector vianpxand takes a minute.
Step 4 — Attach to a real AI app
Now the payoff: plug your server into an AI assistant you already use.
Claude Desktop
Copy claude_desktop_config.json to your real config file:
C:\Users\<you>\AppData\Roaming\Claude\claude_desktop_config.json, then fully
restart Claude Desktop. Your calculator server will appear. Ask:
"Use the calculator server to multiply 17 by 23."
The config tells Claude Desktop: launch this server by running this Python script, then talk to it over stdio.
VS Code
VS Code reads project-scoped MCP servers from .vscode/mcp.json (already
included). Open this folder in VS Code, then:
Open the command palette → "MCP: List Servers" / "MCP: Add Server".
Or open Copilot Chat and use the MCP tools that appear.
Cursor
Settings → MCP → Add new global MCP server, and paste the same JSON
shape from claude_desktop_config.json.
Paths in the config files:
inspector.jsonand.vscode/mcp.jsonuse relative paths (.venv\Scripts\python.exe), so they work as long as you open the project folder.claude_desktop_config.jsonis a copy-paste example and uses a<YOUR-PATH>placeholder — replace it with the absolute path to your checkout before copying (Claude Desktop doesn't resolve relative paths). On Windows use double backslashes\\in JSON.
Step 5 — The real-world upgrade: server_weather.py
Now you take what you learned and build something genuinely useful: a weather server for India backed by the free Open-Meteo API (no API key required).
Read server_weather.py. The MCP part is identical to Step 1 — what's new:
Async tools —
async defbecause we do I/O.External API calls —
httpx2fetches live data;make_requestwraps it with error handling so a network failure returns a friendly message instead of crashing.City name geocoding — users just type
Mumbai, not coordinates.geocode_cityresolves the name to a latitude/longitude internally via Open-Meteo's geocoding API. A classic real-world API pattern.Heuristic alerts —
get_alertsderives advisories from current and near-term conditions (thunderstorm, heavy rain, fog, extreme heat), since India has no free keyless official alert feed.
Test it (needs internet):
python test_client_weather.pyThen explore it in the Inspector (the weather server is already in the catalog):
npx @modelcontextprotocol/inspector --catalog "<your-path>\mcp-tutorial\inspector.json"Then plug it into VS Code / Claude Desktop using the weather entry already in
.vscode/mcp.json / claude_desktop_config.json, and ask:
"What's the weather like in Mumbai?"
Step 6 — Under the hood (recommended reading)
Read docs/01-concepts.md fully. The two ideas that make everything click:
Two layers. Data layer = the JSON-RPC 2.0 messages (what). Transport layer = how messages travel (stdio locally, Streamable HTTP remotely). Same messages, different plumbing.
Stateless + discovery. Every request carries the protocol version and capabilities; the client discovers what the server supports before using it.
Then try the challenges below.
Step 7 — Become the host: chat with your servers (Streamlit UI)
So far your servers just sit and wait for a client. Now you build the other half of MCP — the host (the AI app). This is a real chat UI in your browser that spawns your servers, discovers their tools, and lets an LLM call them through function calling.
Three files, each a distinct layer:
mcp_host.py— a reusable MCP client/host. It spawns a server over stdio and exposes plain synchronous methods (list_tools,call_tool,read_resource,get_prompt, ...). MCP's Python SDK is async but Streamlit is sync, so it runs a real asyncio event loop on a background thread and bridges the two.chat_engine.py— the agent loop. It sends your message plus the discovered tool schemas to Groq. If the model decides it needs a tool, the engine executes it on the server and feeds the result back, repeating until the model answers in plain text. That loop is function calling driving real MCP tools.app.py— the Streamlit UI. Pick a server, paste a Groq API key, connect, and chat. Every reply can show an agent trace of the real MCP tool calls that produced it.
Run it — double-click run-chat.cmd, or:
python -m streamlit run app.pyThe UI opens at http://localhost:8501. You need a free Groq API key
(https://console.groq.com/keys). Then:
Paste the key in the sidebar.
Pick the calculator server → Connect. The sidebar lists its discovered 3 tools, 1 resource, and 1 prompt.
Ask "What is 17 * 23?". The agent trace under the reply shows the LLM called your real
multiplytool and used its answer.Switch to the weather server and ask "What's the weather in Mumbai?" — it geocodes the city and fetches live data, all via MCP.
Why this is the big finale: every AI app is a host. Claude Desktop, VS Code, and Cursor do exactly what
app.pydoes — spawn servers, discover tools, and call them on the model's behalf. You just built one from scratch.
Challenges (do these yourself)
Add a
dividetool toserver_basic.py. What happens whenb == 0?Add a resource template — a resource with a URI like
weather://city/{city}instead of a fixed URI.Make
server_basic.pya remote server — change the last line tomcp.run(transport="streamable-http")and see what URL it prints. (You'll need to configure a client for HTTP transport to talk to it.)Write your own tiny client that takes a math question in English, extracts numbers, and calls your calculator tools.
Add a tool to
server_basic.pyand re-connect the chat UI — the host should discover it automatically. What happens if the LLM divides by zero?Swap the Groq model in the chat sidebar. Which models call tools more reliably? (Watch the agent trace to see.)
FAQ
Do I need an API key or an AI model to follow along? No. Steps 1–6 need only Python. The only key in the whole project is the free Groq key used in Step 7 (the host). You can go through the entire protocol without ever touching an LLM.
Why does my server "do nothing" when I run it? It's working. A stdio server doesn't run on its own — it waits for a client to spawn it and speak JSON-RPC over stdin/stdout. See Step 2 / Step 3.
What's the difference between a tool, a resource, and a prompt?
Short version: tools do something (the model calls them), resources are data
to read (the app loads them), prompts are recipes (the user invokes them).
Full details in docs/01-concepts.md.
Isn't this just "function calling"?
Function calling is how an LLM decides to use a tool — MCP is the standard for
transporting tools and data between apps and models. They're complementary,
not the same thing. The whole comparison is in docs/04-mcp-vs-alternatives.md.
stdio vs Streamable HTTP — which do I use?
Same JSON-RPC messages, different plumbing. stdio for local servers you run
yourself; Streamable HTTP for remote/deployed servers. See docs/01-concepts.md.
Can I plug my server into ChatGPT? Claude Desktop, VS Code, and Cursor are the easy wins in Step 4. Support varies by app — any app that speaks MCP can use your server; that's the whole point.
Do I have to learn JSON-RPC? No. The SDK generates and parses it for you — but Step 3 shows you the raw traffic so you understand what's happening underneath.
More questions answered in docs/05-faq.md.
Where to go next
Official docs: https://modelcontextprotocol.io
MCP specification: https://modelcontextprotocol.io/specification/latest
Reference servers: https://github.com/modelcontextprotocol/servers
Troubleshooting
Symptom | Fix |
| Activate the venv first, or run with |
LSP/editor red squiggles on | Your editor is using system Python. Select the interpreter at |
Server starts then exits instantly | Something printed to stdout. Search for |
Weather returns "Unable to fetch" | No internet, or you hit the Open-Meteo rate limit. Wait a minute and retry. |
Client hangs | The server isn't on your |
| Avoid non-ASCII characters in tool output, or run with |
| The venv isn't active — run |
Chat shows | The API key is missing or wrong — get one at https://console.groq.com/keys. |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- -license-quality-maintenanceA calculator server that exposes mathematical functions as tools (add, subtract, multiply, divide, square, power, square root), enabling language models to perform calculations through Model Context Protocol (MCP).Last updated
- Flicense-quality-maintenanceA demonstration MCP server that provides calculator tools for arithmetic operations, personalized greeting resources, and code review prompt templates. Enables users to perform basic math calculations, generate dynamic greetings, and access reusable code review templates through the Model Context Protocol.Last updated
- Flicense-qualityDmaintenanceA simple demonstration MCP server built with FastMCP that exposes basic calculator operations (add, subtract, multiply, divide) as tools for MCP clients like GitHub Copilot Agent mode.Last updated
Related MCP Connectors
This MCP server enables users to perform scientific computations regarding linear algebra and vect…
Educational MCP server with 17 math/stats tools, visualizations, and persistent workspace
MCP server for generating rough-draft project plans from natural-language prompts.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tharunramavath/learn-mcp-by-building'
If you have feedback or need assistance with the MCP directory API, please join our Discord server