We added the last of the three MCP building blocks to the Charminar Cafe server, then zoomed out to what MCP is really for in a company.
1. The Three Primitives, Complete
| What it is | Who triggers it | What comes back | |
|---|---|---|---|
| Tool | An action | The model decides | A result |
| Resource | Information | The application surfaces it | Content |
| Prompt | A ready-made request | The user picks it | Messages that start a chat |
Examples from the cafe:
- Tool: place an order
- Resource: the menu card
- Prompt: a daily sales summary
Why prompts exist: some requests are common and fiddly. A prompt packages one so nobody has to type the same complex instructions every day. In Claude Desktop it shows up as something the user selects. The model doesn’t call it on its own.
2. Building the Daily Sales Summary Prompt
@mcp.prompt(title="daily sales summary")
def daily_sales_summary() -> str:
"""Summarise today's sales so far."""
if not orders:
return "No orders placed so far."
total = sum(o["total_rupees"] for o in orders.values())
return f"Sales so far today: ₹{total}. Please summarise."
- Defined with the
@mcp.prompt()decorator, the same pattern as tools and resources. - No orders yet? It says so plainly.
- Orders present? It walks the order IDs, adds up
total_rupees, and hands the model a starting message.
Test it in the Inspector:
uv run mcp dev cafe_server.py
3. Debugging: Why It Said “No Orders”
The summary kept reporting no orders placed so far even after we’d placed some. Three causes, and the third is the one worth remembering:
- The table number was missing from the order request, so
place_orderfailed and nothing was recorded. total_rupeeswas missing from the stored order, so the summary crashed when it tried to read it.- The orders live in memory, in one process. The MCP Inspector and Claude Desktop each start their own copy of the server. An order placed in one simply doesn’t exist in the other, and every restart wipes the dictionary.
That third one isn’t a code bug. It’s what “in-memory” means, and it’s exactly why real servers use a database. Expect to see it again.
We fixed the first two, stabilised the VS Code launch.json and the Python debugger, and confirmed place_order across several customers and table numbers.
4. Running It in Claude Desktop
We registered the cafe server in Claude Desktop’s config and ran both the prompt and the tools from the Claude interface. The MCP Inspector remained the tool for seeing exactly what the server exposes during development.
5. From Local to Cloud
stdio is a development transport. One user, one machine, one process.
For a business, the server needs to live at a URL, so many agents and many users can reach one centralised layer of business logic. That’s Streamable HTTP, and it’s where the course goes next.
6. What MCP Really Is in a Company: Glue Code
The point of MCP is for agents to do things in systems you already have, not to describe how they might be done.
Most enterprise systems already expose a REST API: Jira, GitHub, Azure, AWS. So an MCP server is usually:
- A REST client that calls the existing API
- An adapter that presents those calls as tools, resources and prompts a model can understand
Examples:
| Goal | The MCP tool calls |
|---|---|
| Send an SMS | Twilio’s API |
| Send an email | SendGrid’s API |
| Restart Linux servers in a cluster | The vSphere SDK |
You’re not rebuilding the system. You’re giving an agent a handle on it, which is the bridge-not-rewrite rule from yesterday, applied at company scale.
7. Enterprise Reality
- Write custom servers for internal tools. Public servers exist for Jira and GitHub. Nobody has written one for your company’s own systems.
- Authentication is the missing piece in everything we’ve built so far. For remote HTTP servers, the MCP specification builds on OAuth 2.1.
- Enterprise MCP servers usually aren’t public. They’re deployed inside the organisation and listed in an internal MCP registry so the right teams and projects can find them.
✅ Action Items
- Add the daily sales summary prompt to your cafe server with
@mcp.prompt(). - Reproduce the in-memory problem on purpose. Place an order in the Inspector, then ask Claude Desktop for the summary. Explain to yourself why it says “no orders”.
- Move beyond dummy data. Today’s orders are fixed at ₹100. Calculate a real total from the menu prices.
- Pick one REST API you already use and sketch which of its calls would become tools and which resources.
⏭️ Next up: authentication, and taking MCP servers off your laptop.
