Hosts, clients and servers
Explain MCP roles and lifecycle and trace a tool-discovery and tool-call exchange under a pinned protocol version.
THE IDEA
Hosts, clients and servers
The Model Context Protocol (MCP) standardises how applications connect models to external capabilities. It defines three roles. The host is the application the user talks to; it manages the experience and the connections. For each server it opens a client; and each server exposes capabilities such as tools. These are roles, not necessarily three machines: all of them can run on one laptop. MCP standardises the exchange. It does not give a server authority over everything, nor make every discovered tool right for every request.
The host application owns the user experience and the connections. For each server it opens a client connection. These are roles, not necessarily three separate machines.
Predict first. Can one host connect to several MCP servers?
Chapter context
MCP defines a protocol for applications to connect models with external capabilities. It standardizes exchanges; it does not grant a server universal authority or make every discovered tool appropriate for every user request.
TRY IT YOURSELF
Part 1. Do it hands-on
Count connections and tools by hand, then write a host that routes calls to the right server.
The host application owns the user experience and the connections. For each server it opens a client connection. These are roles, not necessarily three separate machines.
- To do: A host application connects to three MCP servers (files, web, calendar), one client connection per server. How many client connections does the host manage?
- To do: files offers 2 tools, web 3 and calendar 1. How many tools can the host put in front of the model in total?
- To do: Both files and web offer a tool called search. How many tool names are offered by more than one server?
- To do: Can one host connect to several MCP servers? Type yes or no
Part 2. Do it in code
- A Host (PROVIDED skeleton) keeps one client connection per MCP server. Servers are described as {server name: [tool names]}.
- connect(name, tools): add a server. ValueError if the name is already connected.
- all_tools(): the qualified names "server.tool" of every tool, servers in connection order, tools in their listed order. (Qualified names are this host's own policy for telling servers apart; they are not part of the protocol.)
- collisions(): the sorted list of unqualified tool names offered by more than one server.
- route(qualified): return (server, tool) for a qualified name; KeyError if the server or tool is unknown.
- disconnect(name): remove a server; KeyError if it is not connected.
Stuck, or something not working? You can come back to it any time.
CHECK YOUR UNDERSTANDING
Can one host connect to several MCP servers?
Chapter reference: math, worked example & code
This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.
Math and notation
The MCP specification revision examined here is 2026-07-28. Request envelopes use JSON-RPC 2.0, an ID for response correlation, a method, and method-specific parameters that include _meta with the required io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. A successful result carries resultType, here "complete". Do not treat this date as a claim about every installed client or SDK.
Worked example
A tools/call request with id 7 names add, supplies a=2,b=3 and carries the protocol version and client capabilities in _meta. The server runs the permitted operation and answers with the same id and a content array holding the text 5. The offline example below checks envelope fields and arithmetic; a production server must also implement discovery, schema validation, errors and transport behavior.
Reference code
The following example uses the Python standard library and does not call a remote service.
meta={'io.modelcontextprotocol/protocolVersion':'2026-07-28','io.modelcontextprotocol/clientCapabilities':{}}
request={'jsonrpc':'2.0','id':7,'method':'tools/call','params':{'name':'add','arguments':{'a':2,'b':3},'_meta':meta}}
args=request['params']['arguments']
total=args['a']+args['b']
response={'jsonrpc':'2.0','id':request['id'],'result':{'resultType':'complete','content':[{'type':'text','text':str(total)}],'isError':False}}
assert request['method'] == 'tools/call'
assert request['params']['_meta']['io.modelcontextprotocol/protocolVersion'] == '2026-07-28'
assert response['id'] == 7
assert response['result']['content'][0]['text'] == '5'
assert response['result']['isError'] is False
Python examples are provided for study and local execution; this page does not execute Python.
Common mistakes
MCP is not a language model or an automatic permission system. Resource, prompt and tool capabilities differ. Do not assume an initialize handshake: that belongs to revisions before 2026-07-28. Protocol versions and SDK releases must be matched when turning this draft into runnable setup instructions.