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, and logging (currently empty objects serving as placeholders for future extensions)
  • serverInfo: An object with name: "desktop-commander" and version set to the VERSION constant

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 the Server instantiation and the initialize request handler (lines 209–268)
  • src/version.ts – Exports the VERSION constant used in the handshake response
  • src/utils/system-info.ts – Gathers system information referenced during the onboarding phase
  • package.json – Declares @modelcontextprotocol/sdk as the core dependency providing the Server class and InitializeRequestSchema

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.ts using the @modelcontextprotocol/sdk package
  • The server registers a handler for InitializeRequestSchema at lines 209–264 to process incoming initialization requests
  • Client identity is captured via updateCurrentClient and stored for telemetry and feature detection
  • Protocol version negotiation checks SUPPORTED_PROTOCOL_VERSIONS and falls back to LATEST_PROTOCOL_VERSION if 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →