Skip to content

MCP Core Architecture

Understanding MCP’s Connection: Clients, Servers, and LLMs

Section titled “Understanding MCP’s Connection: Clients, Servers, and LLMs”

MCP facilitates a sophisticated interplay between Clients (acting on behalf of users or host applications), Servers (providing access to context and capabilities), and LLMs (consuming context and driving interactions). The core idea is to create a structured communication channel where an LLM, through a Client, can dynamically query for relevant information or invoke tools exposed by a Server. This is a departure from simply stuffing large amounts of static text into a prompt; instead, MCP enables a more interactive and targeted way for LLMs to gather what they need, when they need it.

For example, an LLM attempting to help a developer debug code in an IDE (the Host) might use an MCP Client to query an MCP Server for the contents of a specific file, a list of compiler errors (Resources), or request the execution of a test script (a Tool).

MCP leverages JSON-RPC 2.0 as its foundational messaging protocol. JSON-RPC is a lightweight remote procedure call protocol that uses JSON for its data format. This choice offers several advantages:

  • Simplicity and Readability: JSON is human-readable and easy for machines to parse.
  • Widespread Support: Numerous libraries exist for JSON and JSON-RPC across various programming languages, simplifying implementation.
  • Clear Specification: JSON-RPC has a well-defined structure for requests, responses, notifications, and error handling.
  • Transport Agnostic: While MCP often uses WebSockets, JSON-RPC can be transported over other mechanisms like HTTP or IPC (Inter-Process Communication) channels.

In MCP, client requests to list resources, get prompt suggestions, or execute tools, and the server’s replies, are all formatted as JSON-RPC messages.

A key architectural characteristic of MCP is its emphasis on stateful connections. This means that once a Client connects to a Server, the connection is typically maintained for the duration of an interaction session. This is often achieved using WebSockets.

Statefulness is crucial because:

  • Reduced Latency: Eliminates the overhead of establishing a new connection for each request.
  • Efficient Context Management: The Server can maintain session-specific context about the Client or the ongoing task, allowing for more intelligent responses and suggestions.
  • Bidirectional Communication: Servers can proactively send updates or notifications to Clients (e.g., a file has changed, a long-running tool has completed). This is harder to achieve efficiently with traditional stateless request-response models like HTTP.
  • Streaming: Facilitates streaming of data, which can be useful for large resources or continuous updates.

MCP includes mechanisms for capability negotiation between the Client and the Server. This is important because not all Clients may support every feature a Server offers, and vice-versa. Additionally, new versions of the protocol or specific extensions might introduce new capabilities.

During the initial handshake or at specific interaction points, the Client and Server can exchange information about:

  • Supported MCP protocol versions.
  • Available methods (e.g., for Resources, Prompts, Tools).
  • Data formats or schemas they can handle.
  • Security protocols or authentication mechanisms supported.

This negotiation ensures smoother interoperability and allows the ecosystem to evolve. For instance, a Server might declare it supports a specific version of a ‘code-indexing’ Tool, and the Client can then decide if and how to use it based on its own capabilities.