
- BLOG
MCP Clients Explained: How AI Applications Connect to MCP Servers
Published: October 29, 2026
Route Optimization API
Optimize routing, task allocation and dispatch
Distance Matrix API
Calculate accurate ETAs, distances and directions
Directions API
Compute routes between two locations
Navigation API & SDK
Turn by Turn Instructions for Drivers & Technicians
Route Optimization Software
Plan optimized routes with 50+ Constraints
Product Demos
See NextBillion.ai APIs & SDKs In action
Location Reasoning AI
Help your AI agents answer location-based questions
AI Route Optimization
Learns from Your Fleet’s Past Performance
Platform Overview
Learn about how Nextbillion.ai's platform is designed
On-Premise Deployments
Take Full Control of Your Maps and Routing
Table of Contents
Why can your AI assistant suddenly read a support ticket, query a database or open a pull request, when the model behind it has never seen those systems? Part of the answer is a small piece of software most people never notice: the MCP client.
The protocol it speaks now sees more than 97 million SDK downloads a month and counts upwards of 10,000 active servers, according to figures reported by the MCP project and Anthropic. Yet most explainers spend their time on servers and skip the side that actually lives inside your app.
So what does an MCP client do all day, and how is it different from the server on the other end?
An MCP client is the component inside an AI application that connects to one MCP server, finds out what that server offers, and passes requests and results between the server and the application’s model. It is not the app itself. It is not the model. It is the connector in the middle.
Take a code editor with an AI assistant built in. The editor wants the assistant to read a ticket tracker and query a database. It does not hard-code either integration. Instead, it starts one client per server, and each client speaks the same protocol (JSON-RPC underneath) to its own server. Add a new server and the editor gains new abilities. No new release needed.
Three roles are easy to blur together, so it helps to see them side by side.
Role | What it is | Examples | Main jobs |
Host | The AI application the user actually sees | A desktop AI assistant, an IDE with a coding assistant, a custom agent | Creates clients, enforces consent and security rules, coordinates the model, pulls context together from every client |
Client | A connector the host creates, one per server | The client class in an MCP SDK | Sends requests with its version and capabilities, routes messages both ways, manages subscriptions, keeps servers apart |
Server | A program or service that exposes capabilities | A file-system server, a database server, a hosted API | Offers tools, resources and prompts; can ask the client for input while it handles a request |
The architecture follows four design principles set out in the specification:
The effect is deliberate. The hard parts of an AI integration, such as consent, context and model coordination, sit on the host and client side. That is why a basic server can be a small project, while a good client is a bigger one.
For a while, the conversation was all about servers. Directories such as Glama list more than 23,000 of them, and Pulse MCP estimates that local servers were downloaded 67 million times in April 2026 alone. But every one of those servers is useless until a client connects to it. As more teams build their own agents and internal assistants, the client side has become the part they actually have to write, test and secure.
If you only remember one thing from this guide, make it this table. Most confusion about MCP comes from mixing up which side does what.
Question | MCP client | MCP server |
Where does it live? | Inside the host application | A local process or a remote service |
Who usually builds it? | AI app makers, IDE vendors, teams building agents | Anyone with a system worth exposing |
What does it send? | Requests: list, call, read, get | Responses, and sometimes requests for user input |
What does it offer? | Handling for things like user prompts and subscriptions | Tools, resources and prompts |
How many connections? | Exactly one server per client | Many clients can connect to it |
Who decides a tool gets used? | The model proposes; the host and user approve | Nobody. It waits to be called |
What does it carry on each request? | Protocol version, client info, capabilities | Its own capabilities, shared on request |
Where does it usually go wrong? | Stale tool lists, unsafe retries, version mismatches | Poor schemas, slow responses, weak authorisation |
A connection follows five steps. The details below match the 2026-07-28 revision of the specification, the newest at the time of writing, with notes where older versions differ.
The transport is simply how messages travel. The current specification defines two, and lists a third as deprecated.
Transport | Typical server | How messages move | Worth knowing |
stdio | A local program the host launches | One JSON-RPC message per line over standard input and output | No HTTP headers. Suits desktop apps and command-line tools |
Streamable HTTP | A remote or shared service | One HTTP POST per request to a single endpoint | Requires an Mcp-Method header, plus Mcp-Name on calls that target a named tool, resource or prompt. Suits hosted servers |
HTTP+SSE (older) | Legacy remote servers | A long-lived event stream | Deprecated. Expect it only in older servers |
The choice usually makes itself. If the server runs on the same machine as the host, use stdio. If it runs somewhere else, use Streamable HTTP.
Older versions of MCP opened every connection with an initialize handshake. The 2026-07-28 revision removed it. Now every request carries the protocol version, client details and client capabilities in a _meta field, and the client can call server/discover whenever it wants the server’s supported versions, capabilities and identity up front. Calling it is optional for the client. Implementing it is not optional for the server.
Area | Before (2025-11-25 and earlier) | After (2026-07-28) |
Opening move | initialize, then notifications/initialized | No handshake required |
Session | Mcp-Session-Id header on later requests | No protocol-level session |
Client capabilities | Sent once, at connection time | Sent in _meta on every request |
Server capabilities | Returned in the initialize response | Fetched with server/discover when needed |
Server asks for input | Over a held-open event stream | Returned as an input-required result |
The practical gain is that any request can land on any server instance. Hosted servers no longer need sticky routing or a shared session store, and can sit behind an ordinary round-robin load balancer.
There is a catch. The change is breaking, and plenty of servers still expect the old handshake. A common approach is to send a modern request first and fall back to the legacy handshake if the server rejects it. Any production client should plan for both.
A server can expose three kinds of building blocks. The client asks for each with a list call.
Primitive | What it is | Normally controlled by | Client calls |
Tools | Actions the model can invoke | The model | tools/list, tools/call |
Resources | Data the application can read | The application | resources/list, resources/read |
Prompts | Reusable message templates | The user | prompts/list, prompts/get |
List results now include two fields, ttlMs and cacheScope, modelled on HTTP cache control. In plain terms:
Once the client knows what exists, the model can start using it. Each kind of building block has its own request, and every request follows the same pattern:
What the client wants | Method it sends | Name header |
To run a tool | tools/call | Mcp-Name, set to the tool’s name |
To read a resource | resources/read | Mcp-Name, set to the resource’s identifier |
To fetch a prompt | prompts/get | Mcp-Name, set to the prompt’s name |
Whichever one you send, remember the following points:
Sometimes a server cannot finish a call without more information, such as a confirmation from the user. In the new design, it returns an input-required result with its questions and a requestState value. The client collects the answers through the host, then sends the original call again with the answers and the echoed state. A server may only ask while it is actively handling a client request, so a user is never prompted out of nowhere.
A support agent calls a tool that issues refunds. The server replies that it needs approval for a £40 refund. The host shows the user a prompt, the user clicks approve, and the client resends the call with that answer attached. Because everything the server needs is inside the payload, any server instance can finish the job.
Clients declare which extra features they handle, and servers only use what a client has declared. Here is where each stands in the latest revision:
Client feature | What it does | Status in 2026-07-28 |
Elicitation | Lets a server ask the user for input or confirmation during a call | Active |
Subscriptions | Streams list changes and resource updates to the client | Active |
Roots | Tells a server which folders or scope the client is working in | Deprecated, still works |
Sampling | Lets a server request a model completion through the client | Deprecated, still works |
MCP Apps | Renders a server-supplied interface in a sandboxed frame | Official extension |
Tasks | Tracks long-running work through a task handle | Official extension |
The deprecations are annotation-only. The methods keep working in this release and in every version published within a year of it. The suggested replacements are tool parameters or resource URIs for roots, direct calls to a model provider for sampling, and stderr or OpenTelemetry for logging.
Clients carry real security work when a server sits behind OAuth. Under the latest revision, they should expect to:
Mix-up attacks matter more in MCP than in a typical app, because one client often talks to many servers, each with its own authorisation setup.
The MCP project says first-class client support now spans ChatGPT, Claude, Cursor, Gemini, Microsoft Copilot and Visual Studio Code. The clients look different on the surface but follow the same pattern.
Assistants such as Claude and ChatGPT act as hosts. When a user connects a server, the host starts a client for it. The user never sees the client, only the new abilities that appear in the chat.
Editors such as Cursor, Zed and Visual Studio Code connect to servers for repositories, issue trackers, documentation and databases. Local stdio servers suit editors well, since the editor can launch the process itself.
Teams building their own agents use an SDK to write the client. The scenarios below are illustrative, not drawn from a specific deployment:
In the logistics case, the host runs three separate clients. Each talks to exactly one server and cannot see the others. The host gathers the results, hands them to the model, and decides what the user must approve. That isolation is the point. If the telemetry server misbehaves, it cannot reach into the order database.
Not every team needs to write a client. This quick guide shows where the line usually falls:
Your situation | Likely best route |
You want staff to use MCP tools inside an assistant or IDE they already have | Use an existing host and just add servers |
You are shipping an AI product that must reach customer systems | Build a client with an official SDK |
You need tight control over consent, logging and routing | Build the client inside your own host application |
You are still experimenting | Start from an SDK’s sample client and grow from there |
Mistake | Why it hurts | Better approach |
Assuming every server speaks the newest revision | Older servers still expect the handshake and may error or misroute | Try a modern request first, fall back to the legacy handshake |
Ignoring ttlMs | Stale tool lists, or pointless re-fetching | Cache within the window and refresh on notification |
Retrying every failed call | Broken streams cannot resume, and a retry may repeat a side effect | Retry only safe calls, and pass explicit handles for stateful work |
Matching the old not-found code | Missing resources now return -32602, not -32002 | Update your error handling |
Trusting tool descriptions | They come from the server, not from you | Treat them as untrusted input and show users what will run |
Letting headers and body drift apart | Servers reject mismatched Mcp-Method and Mcp-Name values | Generate both from one object |
With sessions gone, a server that needs to remember something between calls mints an explicit handle, such as a basket ID, and the model passes it back as an ordinary argument. For a client builder, the rule is simple: carry those handles through faithfully and never strip them from tool results. The project maintainers have even described this pattern as often more powerful than hidden session state, since the model can reason about the handle directly.
The specification puts consent and enforcement on the host. A few habits follow from that:
The MCP client is easy to overlook precisely because it runs in the background. The client connects to one server, discovers what it does, keeps lists up-to-date, handles traffic between servers, and makes a user participate in the decision-making process. Although servers are the ones who get all the attention, it is actually the clients who decide on the security, speed, and usability.
With the shift to the stateless protocol, responsibilities of the client become more obvious. Knowing these responsibilities will greatly simplify the development and selection of the client. Begin with the simple principle that one client should connect to one server, and much of the rest follows from it.
It is a protocol for an AI application that connects to one MCP server, discovers its tools and resources, and relays requests and results to the model.
The client initiates connections and sends requests. The server exposes tools, resources, and prompts and responds to those requests. The client lives inside the AI application; the server is an external process the application connects to.
Yes. Most host applications maintain one client instance per server and merge the discovered capabilities into a unified tool registry. When two servers expose tools with the same name, the client needs a way to differentiate them, typically by prefixing tool names with the server identifier.
Not if you use an existing host such as an AI assistant or IDE. You only build a client when creating your own app or agent.
Use stdio for local servers you control as a subprocess. It is the simplest option and the default for most desktop applications. Use HTTP + SSE or Streamable HTTP for remote or cloud-hosted servers.
The client is capable of managing authorization via OAuth flows. Clients should ensure validation of the iss parameter from authorization requests and bind credentials to the respective server.
Bhavisha Bhatia is a Computer Science graduate with a passion for writing technical blogs that make complex technical concepts engaging and easy to understand. She is intrigued by the technological developments shaping the course of the world and the beautiful nature around us.