MCP: one protocol between AI apps and the world
Monday, 9:05: the PMS team renamed one field on Friday, and two of StayHub's three AI apps broke all weekend: 1,900 failed tool calls. Each app had its own copy of the hotel-system integration, and partner hotels want to plug in their own AI too.
Every AI app used to wire up every tool by hand. MCP is one shared plug, so each tool is wired once and every app can use it.
- Problem
A hotel group wants its chat assistant, its staff IDE copilot and its voice agent to all read reservations and update room status.
- Why the simple system fails
Each AI app writes its own glue for each system: N apps × M tools integrations, each with its own auth, schema and bugs.
- Engineering concept
Wrap each system once in a server that speaks a shared protocol; any compliant AI app can discover and call it.
- Technology
Model Context Protocol: host → client → server, JSON-RPC messages, stdio or streamable HTTP transports, tools/resources/prompts.
- Trade-offs
Reuse and decoupling vs an extra process, an extra hop and a new supply-chain attack surface. Overkill for one app with three tools.
The problem
2 min- Omar · On-call SRE1,900 failed tool calls since Friday 17:00. The PMS team renamed
room_statustohousekeeping_status. Two of our three AI apps broke. - Maya · Product managerAnd 140 partner hotels want to connect their own AI assistants to our availability.
- Lina · Senior engineer, your mentorGuess the real problem before we fix anything.
The big idea
4 minWrap each system once; every AI app plugs into the same server. MCP standardises the wiring, not the trust.
A shared code library would help our three apps, but not 140 partners whose assistants are written by other companies. That needs a protocol: 3 hosts + 6 servers = 9 pieces, and a PMS change touches one place.
How it works
5 min(Model Context Protocol) is an open standard for connecting AI apps to tools and data. The host is the AI app the user talks to; it holds the model and decides what runs. An wraps one system and exposes its tools. An inside the host holds one session with one server.
- 1Connect
The host starts one client per server. Each says hello (
initialize) and agrees a protocol version. - 2Discover
The client asks
tools/list; the server answers with names, descriptions and JSON Schemas. The PMS team writes them once. - 3The model picks
The host hands those tools to the model, which emits an ordinary tool call. MCP is invisible to the model.
- 4The host checks
Allowed for this app? Needs the user's confirmation (a write like
updateRoomStatus)? Decided in host code. - 5Call and result
The client sends
tools/callas ; the server runs it with its own scoped credential and replies with the same id. The result goes back into the model's context. - 6Transports
when the host launches a local server; with real authorization for a shared remote one, like our PMS server for many apps.
Watch a decision being made
4 minLina traces one MCP session end to end
The front-desk assistant must answer "Who's arriving today?" through the new PMS server. Trace every message and say where each check belongs.
- 1Open the session
"The client sends
initialize; the server says it offers tools and resources."json{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "clientInfo": { "name": "front-desk-assistant" } } }Why: A mismatch fails here, loudly, not halfway through a guest request.
- 2Discover, let the model choose
"
tools/listreturnsgetReservations(read,daterequired) andupdateRoomStatus(write). The model callsgetReservations({ date: "2026-10-01", status: "arriving" })."Why: This replaces the tool definitions every app hand-wrote. For the model, it's ordinary tool calling.
- 3Check in the host
"Allowed for this app? Read-only, so no confirmation. For
updateRoomStatus, the host would ask the staff member first."Why: The protocol carries the call; it doesn't decide whether the call is a good idea.
- 4Call with a scoped credential
"The server queries the PMS with its own narrow credential and replies: 3 arrivals,
isError: false."Why: The server enforces whatever host calls it or whatever the model was tricked into asking.
In real life
3 minOpenAI's custom GPT Actions: describe the API to one app
- Publicly described as giving a custom GPT an OpenAPI description
- Easy if you have a documented REST API
- Configured per GPT, inside one product
Quick for one app; every other app needs its own setup.
MCP: one server, many hosts
- Introduced by Anthropic in late 2024 as an open protocol
- One server works in any compliant host
- The system's team ships and owns the server
More to build and run, built once for every app.
What goes wrong
3 minA server is code running with your permissions, and your model reads its descriptions.
An approved list, pinned versions, a human review of descriptions on every update.
One injected instruction can do anything the credential allows.
Narrow, task-shaped tools with strict schemas.
A new process, a hop and a security boundary, with no reuse.
Plain in-process tools; extract a server when a second consumer appears.
Trade-offs
3 min| Option | Choose when | You pay |
|---|---|---|
| In-process tools | One AI app, a few tools, one team | No reuse; every app re-implements |
| Local MCP servers (stdio) | Developer tools, local files | Full local permissions; supply-chain risk |
| Remote MCP server (HTTP) | Many hosts, including outside ones | A service to run, real auth, a network hop |
- Karim · CTOA remote server is a new service, new auth, a hop per call. A shared PMS library fixes Friday for a tenth of the work.
- Lina · Senior engineer, your mentorIt fixes it for us. 140 partner hotels can't import our library.
- Karim · CTOPartners are a maybe. The ops cost is a certainty.
Your job as tech lead
4 minClaude Code can write the code for this. You still own the decisions, and you have to know what good looks like to accept or reject its work.
- Whether MCP is worth it: 18 integrations versus 9 pieces here; for one app with three functions, plain tool calling is simpler.
- Which team owns each server (the PMS team owns the PMS server), and which transport: stdio locally, streamable HTTP with real auth when shared.
- Which third-party servers are allowed, who reviews their descriptions, and where consent for writes lives (in the host).
Two of our AI apps broke when the PMS renamed `room_status` (1,900 failed calls), because each app has its own PMS integration. Build a PMS MCP server owned by the PMS team, exposing `getReservations` (read) and `updateRoomStatus` (write) with JSON Schemas and clear descriptions, over streamable HTTP with per-app scoped tokens checked by the server. Switch the front-desk assistant to it; the host asks staff before forwarding `updateRoomStatus`. Plan first, then show `tools/list` and a test proving a renamed field only changes the server.
- Read
tools/listyourself: it is exactly what the model sees. Anything odd in a description? - Authorization happens in the server (per-app tokens and scopes), not the model or prompt.
- The server uses a scoped PMS credential, not an admin password copied into each app.
- A community server connected without showing its descriptions or pinning its version.
- Confirmation for writes dropped "because it's a compliant MCP server".
- Three in-app functions wrapped in three servers for one app "because MCP is the standard".
Check yourself
2 minNext episode: Karim wants the PMS server live for partner hotels by Friday, and the first prototype exposes 46 tools behind one shared admin key. You lead.
Mark it complete to update your skill map.
Go deeper (optional)You don't need this to understand the lesson. Open it when a project needs the details: Technical deep dive, Interactive simulation, Visual diagram, Analogy, Why it matters, Check your understanding, Practice ladder, Explain it yourself.
Technical deep dive
Lina traces one MCP session end to end
The front-desk assistant must answer "Who's arriving today?" using the new PMS MCP server. Trace every message, and say where each check belongs.
- 1Open the session
The host's client sends
initializewith its name and a protocol version. The server answers with its capabilities (it offers tools and resources, no prompts). The client confirms with anotifications/initializednotification.json{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "clientInfo": { "name": "front-desk-assistant", "version": "1.4.0" } } }Why: Both sides must agree on what they support before anything else. A mismatch fails here, loudly, not halfway through a guest request.
- 2Discover the tools
The client calls
tools/list. The server returnsgetReservations(read-only,daterequired,statusenum) andupdateRoomStatus(write,roompattern,statusenum).Why: This replaces the tool definitions we hand-wrote in every app. The PMS team writes them once, with the tight schemas from the last module.
- 3Let the model choose
The host passes these definitions to the model with the staff member's question. The model emits a tool call:
getReservations({ date: "2026-10-01", status: "arriving" }).Why: Nothing new for the model: it's ordinary tool calling. MCP is invisible to it.
- 4Check in the host
The host checks: is this tool allowed for this app? Read-only, so no confirmation. (For
updateRoomStatus, the host would ask the staff member first.)Why: The protocol carries the call; it doesn't decide whether the call is a good idea. That stays in our code.
- 5Call and return
The client sends
tools/callwith id 3. The server queries the PMS with its own scoped credential and replies with the same id:contentwith 3 arrivals,isError: false. The host adds it to the model's context.Why: The server owns the PMS credentials and can enforce least privilege. A failure comes back as
isError: true, so the model can react.
| Primitive | Who decides to use it | Hotel example | Typical risk |
|---|---|---|---|
| Tool | The model (host may require approval) | getReservations, updateRoomStatus | Side effects, abuse via injected instructions |
| Resource | The app or the user selects it | cancellation-policy.md, today's occupancy | Leaking sensitive data into context |
| Prompt | The user picks it (e.g. a slash command) | "Draft apology for late check-in" | Low: it's a template |
| Transport | How it runs | Auth | Use for |
|---|---|---|---|
| stdio | The host launches the server as a local process; messages over stdin/stdout | Inherits the local user's permissions | Local tools: files, a local database, developer machines |
| Streamable HTTP | The server runs as a web service; clients POST messages, the server can stream replies | Real authorization needed (the spec builds on OAuth) | Shared remote servers, like our PMS server for many apps |
Interactive simulation
Visual diagram
One host, two MCP clients, two servers: a remote PMS server and a local file server. Start the walkthrough to follow one tool call.
Analogy
- USB-CEvery device had its own chargerMCPEvery app wired every tool
- USB-COne standard portMCPOne standard protocol
- USB-CThe laptopMCPThe host (the AI app)
- USB-CA charger or a hard driveMCPA server wrapping a system
Where the analogy breaks: a cable is passive, but an MCP server is running code you trust with data. And its tool descriptions are read by the model, so a bad server can slip in instructions. Plugging one in is more like installing an app.
Why it matters
StayHub has 3 AI apps and 6 systems. Without a standard, every app connects to every system: up to 18 separate integrations. When the booking system changes, three places break.
With MCP, each system is wrapped once (6 servers) and each app learns the protocol once (3). That's 9 pieces. A new AI app gets all six systems for free.
It also changes who owns what. The team that owns the booking system can own its server, its permissions and its tests.
Custom wiring
- Every app × every system
- Each with its own quirks
- One change breaks many
Up to 18 integrations
With MCP
- Wrap each system once
- Each app speaks MCP once
- New apps plug straight in
9 pieces
Check your understanding
Practice ladder
Trace a session that goes wrong
Debugging Warm-upThe housekeeping chatbot connects to the PMS MCP server. Here is its message log (shortened):
→ { "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", ... } }
← { "id": 1, "result": { "capabilities": { "tools": {} }, ... } }
→ { "method": "notifications/initialized" }
→ { "id": 2, "method": "tools/list" }
← { "id": 2, "result": { "tools": [ getReservations, updateRoomStatus ] } }
(model emits: updateRoomStatus({ room: "204", status: "clean" }))
→ { "id": 3, "method": "tools/call", "params": { "name": "updateRoomStatus", "arguments": { "room": "204", "status": "clean" } } }
← { "id": 3, "result": { "content": [{ "type": "text", "text": "Room 204 is locked: guest in-house." }], "isError": true } }Trace what each step does, and what the chatbot's model should do with the last message. Is the last message a protocol error?
Pick the primitive
Design PracticeThe PMS team is designing the PMS MCP server. Lina has filled in two rows. Fill in the primitive (tool, resource or prompt) and a one-line reason for the other four.
| Capability | Primitive | Why |
|---|---|---|
| List today's arrivals | Tool | The model decides when it needs them; read-only |
| The hotel's cancellation policy document | Resource | Read-only data the app loads into context |
| Set room 204 to "clean" | ___ | ___ |
| A template: "Draft an apology for a late check-in" | ___ | ___ |
| Today's occupancy report (a file regenerated hourly) | ___ | ___ |
| Look up one reservation by number | ___ | ___ |
Loyalty for partner assistants
Design PracticeThe loyalty team wants partner hotels' AI assistants to check a guest's StayHub points and redeem points for a room upgrade. Partners use different AI products. Sketch the loyalty MCP server: transport, the tools (and any resources or prompts), what each tool's credential may do, and where confirmation happens.
Does the revenue agent need MCP?
Decision StretchThe revenue team's nightly agent uses two tools: read yesterday's bookings, and write a pricing suggestion to a spreadsheet. It's one script, run by one team, used by nobody else. The PMS MCP server now exists. Options:
- A: switch the agent to the PMS MCP server for bookings, keep the spreadsheet tool in-process.
- B: convert both tools to MCP servers "for consistency".
- C: leave everything in-process.
Write a short decision: "We chose X over Y because…, accepting the risk of…".
Explain it yourself
Explain to a product manager what MCP is, what problem it solves for StayHub, and why the security team wants a say in which MCP servers are used.