Tool calling / function calling
The model can't run anything itself. It emits a request naming a function plus arguments, your code runs it, and the result goes back in.
See it
What it is
The model never runs anything. You send it a list of tools (a name, a description written for the model to read, and a JSON Schema for the arguments) and instead of prose it can reply with a tool call: 'run get_order with id 4471'. Your code executes that, sends the result back as another message, and the model keeps going. That request, execute, return, continue cycle is the whole mechanism, and every provider ships its own flavour of it. MCP sits one layer out: it standardizes how a host app discovers tools from an outside server and talks to it, then hands those tools to the model in whatever tool calling format the provider expects. The loop stays yours either way.
Reach for it whenever the answer depends on something the model cannot know or cannot do: live data, your database, math you want to be right, sending the email. Keep the tool set small and the boundaries obvious. Three sharp tools beat fifteen overlapping ones, because the model picks off the names, the descriptions, the parameter schemas and whatever the conversation has said so far, which makes those strings part of your prompt, not documentation.
Gotcha: arguments arriving from the model are untrusted input, exactly like a query string from a stranger. Anything reaching the context (a web page, a support ticket, a PDF) can talk the model into calling delete_account. Validate, authorize, and scope every call server side, and put a human confirmation in front of anything destructive or expensive.
Ask AI for it
Add tool calling to this app. Define each tool as a name, a one-sentence description written for the model, and a JSON Schema for its parameters (generate the schema from Zod so the types stay in one place). Send the tool list with every request and run a loop: if the response contains tool calls, execute each handler, append the results as tool-result messages keyed by the call id, then call the model again; stop when it returns plain text or after 10 rounds. Treat the model as an untrusted caller: validate arguments against the schema, check the current user's permissions inside every handler, and return errors as normal tool results so the model can retry. Start with three tools: search_orders, get_order, and cancel_order, where cancel_order requires explicit user confirmation before it runs.