MCP client architecture showing an AI host managing client connections A, B, and C to CRM, data, and files MCP servers.
|

MCP Client Architecture

MCP client architecture showing an AI host managing client connections A, B, and C to CRM, data, and files MCP servers.
The host coordinates policy and user experience; each protocol client communicates with one server.

The client is the host’s protocol adapter—not the model, the router, or the agent itself.

MCP client architecture is often drawn as one box between an AI application and every available tool. That shortcut hides the decisions that make a production integration dependable: which server is trusted, which capabilities enter model context, which operations require approval, how names are resolved, and what happens when a server becomes slow or unavailable.

In the Model Context Protocol, a host is the AI application. The host creates and manages MCP clients, typically one client for each server connection. Each client speaks MCP to its server. The host owns the model interaction, user experience, security policy, capability selection, and orchestration around those connections.

This distinction is the foundation for a multi-server design.

Host, client, and server responsibilities

The three roles cooperate, but they are not interchangeable.

The host application:

  • manages the conversation or workflow;
  • decides which servers may be connected;
  • creates a client for each server;
  • combines selected capabilities for the model or user;
  • enforces consent, approval, and product policy;
  • decides whether to retry, fall back, or stop.

The MCP client:

  • establishes transport communication with one server;
  • sends protocol and client capability metadata;
  • discovers supported server features;
  • invokes tools, reads resources, and retrieves prompts;
  • receives results, notifications, and errors;
  • exposes connection state to the host.

The MCP server:

  • advertises its supported features;
  • defines and executes tools;
  • exposes resources and prompt templates;
  • validates operations and enforces server-side permissions;
  • adapts backend systems into bounded results.

A client does not independently decide the user’s goal. It does not become a universal tool router merely because it lists tools. It is a protocol participant managed by a larger product.

One client per server

Suppose a research host connects to three servers:

  1. a CRM server;
  2. an analytics server;
  3. a file server.

The host maintains three MCP client instances. That structure isolates transport state, server identity, supported features, failures, and authorization material. If the file server disconnects, the analytics connection does not need to fail with it.

One-client-per-server does not mean one operating-system process per client. Implementations may multiplex network connections, use connection pools, or run local child processes. The architectural rule is about protocol relationships and state ownership: each client represents a distinct server connection.

This separation also keeps server-provided names from becoming global truth. Two servers may both expose a tool named search. The host can preserve server identity with an internal key such as crm.search and files.search, while showing clearer descriptions to the model.

The capability lifecycle

MCP client flow from connect and discover capabilities to make available, select or approve, invoke, receive result, and continue.
Capability discovery is not tool selection; the host or model still makes a policy-governed choice.

A reliable client architecture treats capability use as a lifecycle:

  1. Connect. The host selects a server configuration and establishes the appropriate transport.
  2. Discover. The client learns protocol support and available server features.
  3. Normalize. The host converts server metadata into its internal capability representation.
  4. Filter. Policy removes capabilities the user, tenant, or workflow cannot use.
  5. Present. A bounded set becomes available to the model or user.
  6. Select. The host, model, workflow, or user chooses an operation.
  7. Approve. Consequential actions pass through any required consent step.
  8. Invoke. The client sends the operation to the correct server.
  9. Observe. The host records timing, result status, and correlation data.
  10. Continue. The application uses the result, retries safely, asks a question, or terminates.

Discovery answers “what does this server say it supports?” It does not answer “what should this agent do?” Selection remains a host-level decision, informed by model behavior and constrained by policy.

Discovery in current MCP

The current MCP revision is protocol-stateless. Requests carry protocol-version, client-identity, and client-capability metadata rather than relying on a mandatory long-lived protocol session. A server may implement server/discover so a client can retrieve server identity and capability information before normal feature operations.

Feature-specific list operations then expose tools, resources, resource templates, or prompts. The client should use negotiated feature support instead of assuming every server implements every operation.

Older MCP revisions used an initialize handshake and protocol-level session lifecycle. That remains relevant when interoperating with legacy servers, but it should not be presented as the current architecture. A compatibility layer should identify the server revision explicitly and keep legacy behavior out of the host’s core domain model.

Transport is below the capability model

MCP can use stdio for a client-launched local server or Streamable HTTP for a remote server. The client’s transport adapter handles framing, connection behavior, authentication material where applicable, and transport errors.

Above it, the same host concepts should remain stable:

  • server identity;
  • protocol revision;
  • supported features;
  • discovered capabilities;
  • permission state;
  • operation request and result;
  • connection health.

This boundary makes it possible to replace a local development server with a remote deployment without rewriting the host’s capability-selection logic.

Capability registries and caching

Discovery metadata can be expensive to retrieve repeatedly, so hosts commonly maintain an in-memory capability registry. Cache entries should be keyed by server identity and connection configuration, not merely by a display name.

A useful registry tracks:

  • the source server;
  • capability type and name;
  • description and schemas;
  • protocol revision;
  • discovery timestamp;
  • required scopes or local policy labels;
  • availability and health state;
  • a fingerprint or version for change detection.

Caching creates a stale-metadata problem. A server can remove a tool, narrow a schema, or change its description after the host cached it. Treat cached metadata as a performance aid, not an authorization grant. Refresh on reconnect, honor change notifications where supported, set an appropriate time-to-live, and handle “capability not found” without blindly repeating the same request.

Selecting capabilities for model context

Giving every discovered tool to a model is rarely good architecture. Large catalogs increase context use, tool-name collisions, selection ambiguity, and the blast radius of a mistaken choice.

The host should narrow the candidate set using stable information before the model sees it:

  • tenant and user permissions;
  • current workflow or page;
  • server trust level;
  • read, write, or destructive risk;
  • capability tags or domains;
  • recent health and latency;
  • task routing rules.

Semantic retrieval can help choose relevant tool descriptions from a large registry, but retrieval is not permission enforcement. A capability excluded by policy must stay excluded even if it is semantically relevant.

Permissions belong at multiple layers

The client may hold credentials or attach authorization information for a remote server, but transport authorization is only one layer.

The host still needs product-level controls:

  • whether a server is approved for the organization;
  • whether the current user can access it;
  • which capabilities may enter the workflow;
  • whether an action requires confirmation;
  • which arguments and results may be shown to the model.

The server independently validates the caller and enforces backend permissions. The host cannot safely “pre-approve” an operation on the server’s behalf, and the server cannot know every piece of user-interface intent.

For more detail, see [MCP Security and Permissions](/mcp-security-and-permissions/).

Failure isolation and recovery

Multi-server hosts need explicit failure categories.

Connection failure: mark that server unavailable and preserve other connections.

Unsupported feature: remove or suppress the capability instead of retrying.

Invalid arguments: return actionable validation detail to the application; do not retry unchanged input.

Authorization failure: trigger reauthorization or explain that the operation is unavailable.

Rate limit or transient backend failure: honor retry guidance, use bounded backoff, and retry only when the operation is safe.

Timeout: cancel if possible, record uncertainty for side effects, and avoid duplicate execution without an idempotency mechanism.

Malformed or oversized result: reject or truncate at a defined boundary rather than injecting uncontrolled content into model context.

A circuit breaker can temporarily suppress a repeatedly failing server. Health state should influence availability, but it should not silently redirect an operation to another server with different data or permissions.

Results are observations, not instructions

Tool and resource results may contain external text. A client should preserve structured content types, size limits, provenance, and annotations rather than flattening every result into a trusted prompt.

The host should treat server output as an observation from a particular source. External content must not be allowed to rewrite system policy, grant permissions, or trigger a second tool merely because its text requests one.

Result handling may include:

  • schema validation;
  • content-type checks;
  • redaction;
  • attachment isolation;
  • provenance labels;
  • context-size limits;
  • user-visible citations;
  • storage and retention policy.

Observability for the client layer

Instrument each operation with a trace that links:

  • host run or task ID;
  • server identity;
  • capability name and type;
  • request attempt;
  • approval decision;
  • start and end time;
  • result or error category;
  • retry and cancellation state.

Do not log secrets or unrestricted argument and result bodies. Structured metadata is usually more useful for aggregate reliability than indiscriminate payload capture.

Useful client metrics include connection success, discovery latency, tool-call latency, error rate by server and capability, approval outcomes, retry rate, and result-size distribution.

Architecture review checklist

Before shipping an MCP-enabled host, ask:

  • Is the host distinct from its client instances?
  • Does each client have one clear server identity?
  • Are current and legacy protocol lifecycles separated?
  • Are capabilities namespaced and filtered before model exposure?
  • Can metadata refresh without restarting the host?
  • Are approval and server authorization both enforced?
  • Can one server fail without taking down the workflow?
  • Are retries bounded and safe for side effects?
  • Are results treated as untrusted, provenance-bearing observations?
  • Can a trace identify the server and capability behind every operation?

My Take

The hardest part of MCP client architecture is not sending protocol messages. It is maintaining a trustworthy capability view as servers, permissions, and workflow context change.

A strong host keeps a small internal model: dedicated server connections, normalized capabilities with provenance, explicit policy decisions, and observable operation lifecycles. That model scales much better than a single global “tools” array. It also keeps an important truth visible: MCP makes capabilities interoperable, while the host remains responsible for deciding how those capabilities participate in an agent experience.

Sources

Similar Posts