Tools and the Model Context Protocol
With tools, the Mangrove app's product assistant can check live stock at the customer's store and list real delivery slots. This lesson shows how the tool-calling loop works, how to keep every call inside the customer's own permissions, and how the Model Context Protocol lets you write a stock tool once and use it from many AI apps.
By the end you can
- Explain the tool-calling loop step by step, and say who runs each step
- Write tool definitions with clear names, honest descriptions and narrow JSON Schema parameters
- Build a dispatcher that validates arguments, adds session facts, enforces permissions and timeouts, and returns errors the model can explain
- Decide which tools are read-only, which need the customer's confirmation, and which you leave out on purpose
- Describe MCP hosts, clients and servers, its two transports and how it is authorized, and name its main security risks
The everyday picture
Picture a new phone-support worker at a grocery chain. She is quick and friendly, and she has never set foot in a stockroom. When a caller asks "do you have oat milk at my store?", she can't walk to the shelf. She fills in a printed request slip from a small pad, "Stock check, product: oat milk 1 litre", and passes it through a hatch to the stockroom clerk.
The clerk does not trust the slip blindly. He checks that it is a real form, filled in properly, and he writes the caller's store on it himself, from the caller's account card. A slip that would spend the caller's money waits until the caller says yes. Then the answer goes back through the hatch. The worker is the model, the pad of forms is your tool list, and the clerk is your code. If every branch used the same printed forms, one stockroom desk could serve the phone line, the shop floor and the warehouse. That shared standard is what the Model Context Protocol is for.
The tool-calling loop
In How LLM APIs work you wrapped your provider's API in a small callModel function, and in Prompts and structured output you made it return JSON your app can trust. Tool calling adds one more thing to the request: a list of tools. Each tool has a name, a description and a JSON Schema for its parameters. Every provider supports this, with different field names; the idea is the same everywhere.
The loop works like this:
- Your server calls the model with the system prompt, the conversation and the tool list.
- The model replies in one of two ways. Either it writes text, which is the answer, or it returns one or more tool calls: a tool name, JSON arguments and a call id.
- Your code validates each call and runs it. The model runs nothing. A tool call is a request written in JSON, and your code is free to refuse it.
- You add the model's tool calls and one tool result message per call, matched by call id, to the conversation, and call the model again.
- The model reads the results and either answers or asks for more tools. You repeat, with a hard limit on the number of rounds.
Three details matter. A model may return several tool calls in one reply, such as stock and slots at once; you return one result per call id. Every round is a full model call: the conversation, the tool list and all earlier results are input tokens again, so three rounds cost roughly three times a plain answer. And the loop needs a step limit, because a confused model can keep asking for the same tool. Mangrove's assistant stops after 5 rounds with a polite fallback.
Quick check
The model's reply is a tool call, check_stock with {"article_id": "A-30417"}. What has happened in Mangrove's systems at that moment?
The model has no access to anything. It returned text shaped like a function call, and only your server can turn that into a real stock lookup. That is exactly why your server is the place to put validation and permissions.