Primitives, transports and the client-server handshake
MCP standardises how an AI application connects to external context and tools, so one server works with every compatible client.
| Primitive | Is | Controlled by |
|---|---|---|
| Tools | Actions the model may invoke | The model, at its discretion |
| Resources | Readable context — files, records, pages | The application, which chooses what to attach |
| Prompts | Reusable templates the user can trigger | The user, usually from a menu |
| Transport | Runs | Use for |
|---|---|---|
stdio |
As a local subprocess | Local tools, filesystem access, developer machines |
Streamable HTTP |
As a remote service | Shared and hosted servers |
SSE |
Remote, server-sent events | Legacy deployments; superseded by streamable HTTP |
| Message | Direction |
|---|---|
initialize |
client → server: protocol version and capabilities |
initialize result |
server → client: its own capabilities |
notifications/initialized |
client → server: ready |
tools/list |
client → server: discover available tools |
tools/call |
client → server: invoke one |
resources/list, resources/read |
client → server: discover and fetch context |
prompts/list, prompts/get |
client → server: discover and expand templates |
The client config that starts a server as a subprocess and speaks JSON-RPC over stdin/stdout.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/srv/data"],
"env": { "LOG_LEVEL": "info" }
},
"internal-api": {
"type": "http",
"url": "https://tools.internal.example/mcp",
"headers": { "Authorization": "Bearer ${API_TOKEN}" }
}
}
}
Function calling is per-application: you define tools inside your own code. MCP is a protocol, so one server works with every compatible client, and it adds resources and prompts alongside tools.
Treat it like a browser extension. It runs with the access you grant it, and its tool descriptions become part of the model instructions. Prefer least privilege and read what it does first.