Get startedGet started for free

MCP Client-Server Communications

1. MCP Client-Server Communications

Now you have your server set up, let's connect to it with a client.

2. Client-Server Communications

In MCP, the client’s main job is to start a session with the server and send it requests. It does this using a structured message format called JSON-RPC 2.0. JSON-RPC is a standardized way for programs to talk to each other using JSON messages. Every request, response, and function call between client and server follows this same structure, so communication is predictable and consistent across the entire system.

3. Client-Server Communications

When a client sends a message, it specifies which tool to use, and the required parameters for that tool. For our timezone converter server, the client sends: a datetime, its current timezone, and the target timezone. The server processes the request and sends back the converted datetime as a JSON-RPC response.

4. Transports: Standard I/O (stdio)

There are two ways to send and receive JSON-RPC messages in MCP, also called transport types. The first method is Standard Input/Output, or stdio. This is the simplest and most common setup when the client and server run on the same computer.

5. Transports: Standard I/O (stdio)

The client launches the MCP server as a subprocess.

6. Transports: Standard I/O (stdio)

The two exchange messages through the computer's standard input and output streams: stdin and stdout. You can think of stdio as message pipes between two programs. The client writes a message into stdin, and the server reads it. The server then writes its response to stdout, where the client reads it back.

7. Transports: Standard I/O (stdio)

As we mentioned before, the messages are formatted as JSON-RPC 2.0.

8. Transports: Standard I/O (stdio)

It's quick, local, and

9. Transports: Standard I/O (stdio)

requires no network connection — ideal for development, CLI tools, or agent plugins like Claude Desktop.

10. Transports: Standard I/O (stdio)

When the client exits, the server dies.

11. Transports: Streamable HTTP

The second method is Streamable HTTP, used when the client needs to connect to a remote server over the internet. Messages are still in JSON-RPC, but they're delivered using standard HTTP and received via server-sent events, or SSE.

12. MCP Server: timezone_server.py

We'll save our server code to a Python file called timezone_server.py. This is the code we wrote before, with just one addition: at the bottom of the script, the server is run using the mcp.run() function, and specifying the transport type we'll be using: stdio. With the server available, let's create the client to connect to it!

13. MCP Client: Listing Server Tools

To start with, we'll define a function to connect to our server and list the tools available. First, we create server parameters telling Python which script to run. Then we launch the server using stdio_client(), which gives us a connection. We wrap that connection in a ClientSession to handle the MCP protocol. We then initialize the session with the .initialize() method. Finally, we can extract tools from the session with the .list_tools() method. Notice the "async with"/"await" pattern throughout. Each await—like initialize and list_tools—pauses while waiting for the server to respond. The "async with" blocks manage connections, automatically closing them when done. This prevents freezing during operations, and means that operations can be run concurrently rather than sequentially.

14. MCP Client: Listing Server Tools

From this response, we'll print each tool and description using their respective attributes, and return the response's .tools attribute, which can be used by an LLM downstream. Finally, asyncio.run() starts the event loop, enabling all these async operations to work together seamlessly.

15. MCP Client: Listing Server Tools

Here's the result! This dynamic tool discovery is a major benefit of MCP applications, and the quality of our server docstrings will determine if the correct tools are used, for example, by an LLM. Let's now actually call these server tools from the client.

16. MCP Client: Calling Server Tools

We'll create a call_mcp_tool() function, starting with exactly the same code as before: running the server script, connecting to it, and opening a session. The only difference is that this function takes the tool_name to call, and the tool arguments to pass to it as a dictionary. These are passed to the .call_tool() method, which is called on the session. Finally, we extract the text content from the tool result object, then print and return it.

17. MCP Client: Calling Server Tools

From here, we can run our function using asyncio again, passing it the tool name and a datetime, initial timezone, and target timezone to convert to.

18. Let's practice!

Time to give this a go!

Create Your Free Account

or

By continuing, you accept our Terms of Use, our Privacy Policy and that your data is stored in the USA.