mcp-client-capabilities-gap image

December 23, 2025

Mind the MCP Client Capability Gap: and How To Work Around It

From time to time we feature guest posts from folks in the MCP ecosystem doing interesting things. This post comes from Jan Čurn, co-founder of Apify, whose team is helping to nudge the MCP client - MCP server ecosystem forward by building tooling to empower servers to progressively enhance into less-adopted MCP features.

The Model Context Protocol (MCP) is poised to become the standard protocol for connecting AI agents and tools. It promises rich, flexible interactions between apps/agents (MCP clients) and services (MCP servers).

Despite this promise, many server maintainers find themselves stuck in the protocol's first gear. Much of the MCP ecosystem is stuck catering to the lowest common denominator - the simplest components of the protocol. And that's largely because of the client capability gap.

Most MCP clients support only the most basic protocol features:

MCP client capabilities comparison table

As a result, MCP servers don't have the motivation to implement those features either. Not necessarily because nobody would use them (some clients would), but because they'd entirely break the functionality of those that don't.

When an MCP client connects to a server, it declares its capabilities during the initialize handshake — but the list is incomplete. The server learns some of what the client supports (e.g., tools, prompts, or resources). But still missing from the initialization sequence are several nuanced but important features: whether the client supports instructions, dynamic tool updates using list_changed notifications, and subscribing to resource changes.

As a result, servers are forced to adopt the lowest common denominator design, implementing only the minimal MCP features that all clients are guaranteed to understand. When they do that, the MCP clients have no incentive to adopt all the new MCP protocol features; the vicious cycle continues.

The lowest common denominator

Here's what the handshake looks like today. First, the MCP client sends a message like this:

CLIENT REQUEST
{
  "method": "initialize",
  "params": {
    "clientInfo": { "name": "ExampleClient" },
    "capabilities": { "roots": { "listChanged": true } }
  }
}

And the server responds:

SERVER RESPONSE
{
  "result": {
    "capabilities": {
      "resources": { "listChanged": true, "subscribe": true },
      "tools": { "listChanged": true }
    }
  }
}

But this doesn't tell the server if the client actually supports notifications/tools/list_changed, the instructions directive, or how it handles updates. Without that context, both sides play it safe, and the entire MCP ecosystem stagnates.

While proposals like SEP-1381 aim to improve capability negotiation, those changes take time to propagate across all clients and SDKs. We need a solution now.

Introducing mcp-client-capabilities

To work around this capability gap, at Apify, we've created the open source mcp-client-capabilities package, which provides a simple, community-maintained database of known MCP clients and their capabilities.

For maximum compatibility, it's really just a single JSON file mcp-clients.json listing each client's name, metadata, and supported features. The structure mirrors MCP's ClientCapabilities type, so it integrates naturally into existing MCP servers.

Node.js example

JAVASCRIPT
import { mcpClients } from "mcp-client-capabilities";
console.log(mcpClients["cursor-vscode"].tools?.listChanged);

Python example

PYTHON
from mcp_client_capabilities import mcp_clients
value = (
    mcp_clients
        .get("cursor-vscode", {})
        .get("tools", {})
        .get("listChanged")
)
print(value)

Each record in the JSON file represents the latest known release of the client. If the client's reported protocolVersion doesn't match the one in the registry, the server can safely ignore it, ensuring correctness without overreliance.

Why it matters

The new mcp-client-capabilities package helps MCP servers adapt intelligently to different clients. A server can:

  • Leverage dynamic tool discovery to save context window and tokens by dynamically registering only the necessary tools in the current situation (read Anthropic's post about Tool Search to see why this is beneficial)
  • Simplify the tool descriptions for MCP clients who read instructions
  • Use MCP resources to share results with the clients.

The package is not a replacement for the handshake. It complements it by providing servers with the missing information.

By bridging this information gap, MCP servers can start adopting newer MCP features, and MCP clients get a growing incentive to support them too. Until the protocol-level negotiation improves, this registry gives the ecosystem a shared source of truth.

We're already using this today in production

Apify is a marketplace for 10K+ tools (called Actors) for web data extraction and automation, which AI agents and apps can access using the Apify MCP server (mcp.apify.com). There is simply no way we could expose all these tools on the MCP server, but it can be easily solved using dynamic tool discovery as follows:

  1. Client calls the search-actors tool to find Actors relevant for its use case based on a search query like "google maps scraper".
  2. The MCP server returns a list of suitable Actors, including compass/google-maps-scraper.
  3. The MCP client decides to use this specific Actor, and calls the add-actor tool with the parameter "compass/google-maps-scraper" to register it.
  4. The MCP server adds the new tool to the context and sends the client the notifications/tools/list_changed to update its list of tools.
  5. The MCP client updates the list of tools and is ready to call the new tool, with JSON schema validation.

But if the client doesn't support the notifications/tools/list_changed notification, the above will not work, and the MCP server instead needs to expose a generic tool called call-actor that can run arbitrary Actors. However, this method is less precise, lacks schema validation, and yields worse results.

Without the mcp-client-capabilities package, we always had to fall back to the second, less precise method.

How to contribute to mcp-client-capabilities

The MCP ecosystem is evolving quickly, and this registry relies on community input. If you maintain an MCP client, you can add or update its record by editing src/mcp_client_capabilities/mcp-clients.json and submitting a pull request. Just include a small piece of evidence, such as a screenshot, a snippet, or a documentation link showing the client's capabilities.

Closing the gap

MCP is one of the most exciting efforts in making agents and tools truly interoperable. But for that to happen, servers need to understand their clients better. The mcp-client-capabilities package is a small but practical step in that direction, enabling MCP servers to implement more advanced MCP features and thus motivating clients to do the same, thereby helping the entire MCP ecosystem evolve.

Also, this is a gentle nudge to the MCP committee to improve the protocol to make this package obsolete - let's get SEPs like this and this moved forward!

Subscribe to The Agentic Loop

Bi-weekly, high-signal insights on agentic engineering and AI-enabled knowledge work.

Jan Čurn image

Jan Čurn

Jan Čurn is a co-founder and CEO of Apify, a web scraping and automation platform that enables you to automate any workflow that a person can do manually in a web browser, and then run it at scale.