Model Context Protocol — fundamentals
MCP standardises how applications supply context and tools to LLMs. The pitch is the one that matters: M×N integrations become M+N. Without it, every AI app writes bespoke glue for every data source. With it, any MCP client talks to any MCP server.
Think “LSP for AI tooling” — the Language Server Protocol analogy is exact, and it’s the fastest way to explain MCP to an engineer.
The three primitives
| Primitive | Controlled by | Analogy | Use for |
|---|---|---|---|
| Tools | the model | POST — has effects |
actions: query a DB, send a message, call an API |
| Resources | the application | GET — read-only |
context: files, records, schemas |
| Prompts | the user | a slash command | reusable templates the user invokes |
The distinction is about who decides, and it’s the most commonly missed part of MCP.
- A tool is invoked by the model as part of reasoning.
- A resource is selected by the client application (or user) and injected as context — the model doesn’t choose to fetch it.
- A prompt is deliberately triggered by a human.
Getting this wrong — exposing everything as tools — produces an agent with fifty tools that picks badly. Read-only context usually belongs as a resource.
A server
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("orders")
@mcp.tool()
def refund_order(order_id: str, reason: str) -> str:
"""Refund an order. Requires a reason for the audit log."""
return process_refund(order_id, reason)
@mcp.resource("order://{order_id}")
def get_order(order_id: str) -> str:
"""Read-only order details."""
return json.dumps(load_order(order_id))
@mcp.prompt()
def investigate(order_id: str) -> str:
return f"Investigate order {order_id}. Check status, payments and shipping."
The docstring is the tool description the model sees. Vague docstrings produce wrong tool calls, and that’s the single highest-leverage thing to get right — the same discipline as writing a good function-calling schema. See ../10_agents_orchestration/08_function_calling_and_structured_output.md.
Transports
| Transport | Where the server runs | Use |
|---|---|---|
| stdio | subprocess on the same machine | local tools, filesystem, developer tooling |
| Streamable HTTP | remote service | hosted servers, multi-user, production |
Streamable HTTP replaced the older HTTP+SSE transport. As of the 2026-07-28 revision the protocol core is stateless, which changes how remote servers scale — covered in 02_spec_2026_stateless.md.
Why not just function calling
A fair question, and the answer is about the boundary, not the capability.
Function calling is a model API feature: you pass JSON schemas in the request, the model returns a call, your code executes it. It’s per-application and per-vendor.
MCP is a protocol between processes. The consequences:
- Reusable. One MCP server serves Claude Desktop, your IDE, your own agent, and a colleague’s app.
- Independently deployed. The server team ships without touching the AI app.
- Discoverable. A client lists tools at runtime rather than hardcoding schemas.
- Composable. Add a server, gain its tools, no code change in the client.
Underneath, MCP tools still become function-calling schemas when sent to the model. MCP doesn’t replace function calling — it standardises where the definitions come from. That’s the precise answer to the interview question.
Use plain function calling for two or three app-specific tools. Use MCP when tools are reused across applications, owned by another team, or you want an ecosystem.
Where servers run
- Local (stdio) — full access to the user’s filesystem and environment. The trust model is “the user’s own machine”.
- Remote (HTTP) — a network service with authentication, multi-tenancy and the usual API concerns.
The security posture is entirely different between the two, and conflating them is how MCP deployments go wrong. See 03_building_and_securing.md.
Interview angle
- “What problem does MCP solve?” — the M×N integration explosion. Standardising the client-server contract turns it into M+N, so any MCP-speaking application can use any MCP server. LSP is the right analogy.
- “Tools vs resources vs prompts?” — who controls invocation. Tools are model-controlled and may have effects; resources are application-controlled read-only context; prompts are user-triggered templates. Exposing read-only context as tools bloats the tool list and degrades selection.
- “Isn’t this just function calling?” — function calling is a model API feature scoped to one application; MCP is a process-to-process protocol that makes tool definitions reusable, independently deployable and discoverable at runtime. MCP tools are still converted into function-calling schemas — it standardises their source, not the mechanism.
- “When would you not use MCP?” — a handful of app-specific tools with no reuse. The protocol, transport and server lifecycle are overhead you don’t need for three internal functions.
- “What determines whether the model calls your tool correctly?” — the name, description and parameter schema. The docstring is the prompt. Vague descriptions are the main cause of wrong or missed tool calls.