Hosts, clients, servers, and transports — how the pieces of an MCP system fit together.
MCP organizes the connection between an AI model and an external tool into three distinct roles. Understanding these roles is essential before you start building.
┌─────────────────────────────────┐
│ MCP Host │
│ (Claude Desktop, Cursor, etc.) │
│ │
│ ┌───────────────────────────┐ │
│ │ MCP Client │ │
│ │ (manages connections) │ │
│ └──────────┬────────────────┘ │
└─────────────┼───────────────────┘
│ MCP Protocol
│ (JSON-RPC 2.0)
▼
┌─────────────────────────────────┐
│ MCP Server │
│ (filesystem, GitHub, DB, etc.) │
└─────────────────────────────────┘
The MCP Host is the application that contains — or is connected to — the AI model. Examples include Claude Desktop, Cursor, VS Code with an AI extension, or a custom application you build yourself using an MCP client library.
The host is responsible for the user-facing experience. It decides which MCP servers to connect to, manages the overall context of a conversation, and presents tool results back to the user. A single host can connect to multiple MCP servers simultaneously.
The MCP Client lives inside the host. It's the protocol-level component that handles the actual communication with MCP servers — sending requests, receiving responses, and managing the connection lifecycle.
In practice, you rarely build an MCP client from scratch. The official SDKs (TypeScript and Python) include client implementations. If you're building a custom MCP host, you instantiate the client from the SDK and configure it to connect to your servers.
The MCP Server is a lightweight, standalone process that exposes capabilities — tools, resources, or prompt templates — to any MCP-compatible host. This is where most developers spend their time when building MCP integrations.
An MCP server for GitHub might expose tools like list_issues, create_pull_request, and get_file_contents. An MCP server for a PostgreSQL database might expose run_query and list_tables. The server handles the actual logic; the protocol handles the communication.
Servers can be written in any language capable of handling stdio or HTTP. The official SDKs cover TypeScript and Python. Community implementations exist for Go, Rust, Java, and others.
MCP supports two transport mechanisms, chosen based on whether the server is local or remote.
The stdio transport is used for local servers — processes running on the same machine as the host. The host launches the server as a subprocess and communicates with it over standard input and output streams.
This is the most common transport for developer tooling. Claude Desktop, for example, launches MCP servers as local subprocesses defined in its configuration file. stdio is simple, requires no network configuration, and is appropriate for tools that access local resources like the file system.
The SSE transport runs over HTTP and is used for remote servers. The client connects to an HTTP endpoint; the server pushes messages using Server-Sent Events; the client sends messages back via HTTP POST.
SSE transport is appropriate when your MCP server needs to run remotely — for example, a shared team server, a cloud-hosted integration, or a service you want to expose to multiple users.
MCP servers expose three types of capabilities, called primitives.
Tools are functions the AI model can call. They're the most commonly used primitive. A tool has a name, a description (which the model reads to decide when to use it), and a JSON Schema defining its input parameters.
json
{
"name": "search_documents",
"description": "Search the document store for relevant content",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"limit": { "type": "integer", "default": 10 }
},
"required": ["query"]
}
}
Resources are data the AI model can read. Unlike tools (which perform actions), resources expose content — files, database records, API responses — that the model can incorporate into its context. Resources are identified by URIs and can be static or dynamic.
Prompts are reusable prompt templates that a server can expose. They let server authors package useful prompt patterns — for example, a "summarize this document" prompt that already knows how to format output for a specific use case. Hosts can surface these to users as slash commands or quick-access options.
All MCP communication uses JSON-RPC 2.0, a lightweight remote procedure call protocol encoded in JSON. If you've worked with language server protocols (like LSP in VS Code), the pattern will be familiar.
A request looks like this:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_documents",
"arguments": { "query": "quarterly revenue" }
}
}
The server responds with either a result or an error object. The protocol supports request/response pairs for synchronous calls and notifications for one-way messages.
The key interaction sequences are:
- tools/list — host asks server what tools are available
- tools/call — host asks server to execute a specific tool
- resources/list and resources/read — for reading data
- prompts/list and prompts/get — for retrieving prompt templates
Understanding this message flow is enough to debug most MCP integration issues and to build servers without relying entirely on the SDK abstractions.
Have a follow-up question about this topic?
Ask AI