How DesktopCommanderMCP Implements the MCP Protocol Handshake During Initialization
TLDR: The Desktop Commander server implements the MCP protocol handshake in src/server.ts by registering an initialize request handler that negotiates protocol versions, captures client metadata, and returns capability descriptors to establish the client-server session.
The DesktopCommanderMCP repository provides a Model Context Protocol (MCP) server that enables desktop automation through a standardized JSON-RPC interface. Understanding how this server handles the MCP protocol handshake during initialization is critical for developers building compatible clients or debugging connection issues. The handshake implementation follows the official MCP specification by processing initialize requests in src/server.ts, where it validates client information and negotiates mutually supported protocol versions.
Step-by-Step Handshake Implementation in src/server.ts
The initialization sequence spans lines 209–268 in src/server.ts, following the official MCP specification for server initialization.
Server Instantiation and SDK Setup
The process begins at lines 98–103 where the server constructs a new Server instance imported from @modelcontextprotocol/sdk. The constructor receives the plugin identifier and the VERSION constant defined in src/version.ts, establishing the server's identity before any client connects.
Registering the Initialize Request Handler
At lines 209–264, the server registers the core handshake logic using server.setRequestHandler(InitializeRequestSchema, async (request) => { ... }). This method binds the initialization logic to the MCP initialize method, which clients must call immediately after establishing a transport connection.
Client Identity Extraction and Onboarding
Upon receiving the initialize request, the handler extracts clientInfo from request.params?.clientInfo (lines 211–215) and persists it via updateCurrentClient. This captures the caller's name and version for telemetry and feature-flag decisions.
Between lines 216–226, the server conditionally triggers handleWelcomePageOnboarding if the client is not the Desktop Commander app itself or a remote-device wrapper. This ensures first-time users see the welcome interface without interfering with programmatic clients.
Telemetry and Environment Capture
At lines 238–243, the server records initialization telemetry using capture('run_server_mcp_initialized', ...), logging environment variables such as entrypoint, agent, and plugin ID. This analytics call excludes PII while providing diagnostic context for server usage patterns.
Protocol Version Negotiation
The critical version negotiation occurs at lines 245–250. The server inspects request.params?.protocolVersion and validates it against the SUPPORTED_PROTOCOL_VERSIONS array. If the requested version is supported, the server adopts it; otherwise, it falls back to LATEST_PROTOCOL_VERSION. This ensures backward compatibility while allowing modern clients to leverage newer protocol features.
Returning the Handshake Payload
Lines 252–264 construct and return the handshake response object containing:
- protocolVersion: The agreed-upon version string
- capabilities: An object declaring support for
tools,resources,prompts, andlogging(currently empty objects serving as placeholders for future extensions) - serverInfo: An object with
name: "desktop-commander"andversionset to theVERSIONconstant
Error Handling and Logging
The handler wraps all logic in a try-catch block at lines 265–268. Any exceptions are logged to stderr and re-thrown, ensuring the MCP SDK transmits an appropriate error response to the client rather than failing silently.
Key Source Files and Dependencies
The handshake implementation relies on several files within the repository:
src/server.ts– Contains theServerinstantiation and the initialize request handler (lines 209–268)src/version.ts– Exports theVERSIONconstant used in the handshake responsesrc/utils/system-info.ts– Gathers system information referenced during the onboarding phasepackage.json– Declares@modelcontextprotocol/sdkas the core dependency providing theServerclass andInitializeRequestSchema
Practical Implementation Examples
The following examples demonstrate the handshake from both client and server perspectives.
Client-Side Initialization
import { ServerClient } from "@modelcontextprotocol/sdk/client";
const client = new ServerClient({
url: "http://localhost:PORT",
name: "my-app",
version: "1.2.3",
});
const initResponse = await client.initialize({
clientInfo: { name: "my-app", version: "1.2.3" },
protocolVersion: "1.0",
});
console.log(initResponse.protocolVersion);
console.log(initResponse.serverInfo);
Server-Side Handler
server.setRequestHandler(InitializeRequestSchema, async (request) => {
const clientInfo = request.params?.clientInfo;
if (clientInfo) await updateCurrentClient(clientInfo);
const requested = request.params?.protocolVersion;
const protocolVersion = (requested && SUPPORTED_PROTOCOL_VERSIONS.includes(requested))
? requested
: LATEST_PROTOCOL_VERSION;
return {
protocolVersion,
capabilities: { tools: {}, resources: {}, prompts: {}, logging: {} },
serverInfo: { name: "desktop-commander", version: VERSION },
};
});
Summary
- The MCP protocol handshake is implemented in
src/server.tsusing the@modelcontextprotocol/sdkpackage - The server registers a handler for
InitializeRequestSchemaat lines 209–264 to process incoming initialization requests - Client identity is captured via
updateCurrentClientand stored for telemetry and feature detection - Protocol version negotiation checks
SUPPORTED_PROTOCOL_VERSIONSand falls back toLATEST_PROTOCOL_VERSIONif needed - The handshake response includes the agreed protocol version, empty capability placeholders, and server metadata
- Errors during initialization are logged to stderr and re-thrown to ensure proper error propagation to the client
Frequently Asked Questions
Where is the MCP protocol handshake implemented in DesktopCommanderMCP?
The handshake logic is implemented in src/server.ts between lines 209 and 268. This file contains the setRequestHandler call for InitializeRequestSchema that processes the initial client request and returns the protocol configuration.
How does the server handle protocol version mismatches during the handshake?
The server checks the requested protocol version against SUPPORTED_PROTOCOL_VERSIONS at lines 245–250. If the client requests a version not in the supported list, the server automatically falls back to LATEST_PROTOCOL_VERSION, ensuring the connection succeeds while maintaining compatibility.
What information does the server capture during initialization?
The server captures clientInfo (name and version) via updateCurrentClient and records telemetry using capture('run_server_mcp_initialized', ...) with environment variables like entrypoint and agent. This data is used for analytics and conditional onboarding flows, but excludes personally identifiable information.
What capabilities does the server advertise during the MCP handshake?
The server returns an empty object for each capability type—tools, resources, prompts, and logging—at lines 252–264. These serve as placeholders indicating protocol support while the actual capability implementations are registered separately after the handshake completes.
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 →