How Desktop Commander MCP Server Negotiates Protocol Versions with Clients
The Desktop Commander MCP server negotiates protocol versions by reading the client's requested version from the initialize request, validating it against the SDK's SUPPORTED_PROTOCOL_VERSIONS array, and falling back to LATEST_PROTOCOL_VERSION if unsupported.
The Model Context Protocol (MCP) enables standardized communication between AI assistants and external tools. When a client connects to an MCP server, both sides must agree on which protocol version to use before exchanging capabilities or executing commands. This article explains how the Desktop Commander MCP server (wonderwhy-er/DesktopCommanderMCP) handles this negotiation based on its actual implementation.
Protocol Version Negotiation Flow
The negotiation occurs entirely within the initialize request handler in src/server.ts. The server follows a strict server-driven selection process to ensure compatibility.
Step 1: Extract Client's Requested Version
When the client sends its initialize request, it may include a protocolVersion field in the request parameters. The server extracts this value to determine what the client prefers.
Step 2: Validate Against Supported Versions
The server imports SUPPORTED_PROTOCOL_VERSIONS from the MCP SDK. This array contains all protocol versions the server is capable of speaking. The server checks whether the client's requested version exists in this list.
Step 3: Select or Fall Back
If the client's version is found in SUPPORTED_PROTOCOL_VERSIONS, that version is selected. Otherwise, the server enforces LATEST_PROTOCOL_VERSION as the fallback. This prevents unsupported protocol mismatches that could cause communication failures.
Step 4: Return Negotiated Version
The server includes the final protocolVersion in its response, confirming to the client which protocol version will govern the session.
Code Implementation in src/server.ts
The following implementation shows the version negotiation logic as found in the server's initialization handler:
// src/server.ts - initialize request handler (around line 253-260)
const requestedVersion = request.params?.protocolVersion;
const protocolVersion = (requestedVersion && SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion))
? requestedVersion // Client's version is supported — use it
: LATEST_PROTOCOL_VERSION; // Unsupported or missing — fall back to latest
return {
protocolVersion, // Negotiated version sent back to client
capabilities: {
tools: {},
// ... other capabilities
},
serverInfo: {
name: "desktop-commander",
version: VERSION
},
};
This pattern ensures backward compatibility: older clients requesting valid legacy versions continue to work, while newer clients or those with unknown versions default to the server's latest supported protocol.
Key Files and Constants
| File | Role |
|---|---|
src/server.ts |
Contains the initialize handler and version negotiation logic (lines 253-260) |
@modelcontextprotocol/sdk (imported) |
Defines SUPPORTED_PROTOCOL_VERSIONS and LATEST_PROTOCOL_VERSION constants |
test/test-welcome-onboarding-legacy-config.js |
Test file demonstrating initialize requests with explicit protocolVersion (lines 76-78) |
The SUPPORTED_PROTOCOL_VERSIONS and LATEST_PROTOCOL_VERSION constants originate from the official MCP SDK, not the Desktop Commander repository itself. The server imports these values rather than defining its own, ensuring alignment with SDK standards.
Why Server-Driven Negotiation Matters
Client-proposed, server-validated version selection offers critical advantages:
- Predictability: Clients cannot force unsupported protocol versions that might crash the server
- Security: Prevents downgrade attacks where malicious clients might attempt to use vulnerable legacy protocols
- Simplicity: Clients need only attempt their preferred version; the server handles fallback transparently
This approach follows the MCP specification's recommendation that servers maintain authoritative control over protocol compatibility.
Summary
- The Desktop Commander MCP server negotiates protocol versions during the
initializerequest handshake - The server validates the client's requested version against
SUPPORTED_PROTOCOL_VERSIONSfrom the MCP SDK - Supported versions are accepted; unsupported versions trigger fallback to
LATEST_PROTOCOL_VERSION - Implementation resides in
src/server.tswith logic concentrated around lines 253-260 - This server-driven model ensures robust, secure, and backward-compatible client connections
Frequently Asked Questions
What happens if a client doesn't send a protocolVersion in the initialize request?
The server treats missing protocolVersion as unsupported due to falsy value checking. The expression (requestedVersion && SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion)) evaluates to false when requestedVersion is undefined, triggering fallback to LATEST_PROTOCOL_VERSION.
Where are SUPPORTED_PROTOCOL_VERSIONS and LATEST_PROTOCOL_VERSION defined?
These constants are defined in the @modelcontextprotocol/sdk package, specifically in the SDK's types module. The Desktop Commander server imports them rather than defining local versions, ensuring automatic compatibility updates when the SDK is upgraded.
Can I force the server to use a specific protocol version?
No. While you can request a specific version in your client's initialize call, the server ultimately decides based on its supported versions list. If your requested version is unsupported, the server will override it with LATEST_PROTOCOL_VERSION in its response.
How can I test protocol version negotiation?
The repository includes test coverage in test/test-welcome-onboarding-legacy-config.js. Lines 76-78 demonstrate sending an initialize request with an explicit protocolVersion field, allowing you to verify server behavior with different version strings.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →