# How mksglu/context-mode Auto-Detects Platforms via MCP Protocol Handshake

> Learn how mksglu/context-mode auto-detects platforms using the MCP protocol handshake. Discover the clientInfo.name mapping and adapter instantiation process for reliable platform detection.

- Repository: [Mert Köseoğlu/context-mode](https://github.com/mksglu/context-mode)
- Tags: how-to-guide
- Published: 2026-04-24

---

**mksglu/context-mode detects the client platform during the MCP initialization handshake by reading the `clientInfo.name` field from the `initialize` request, mapping it to an internal `PlatformId` via the `CLIENT_NAME_TO_PLATFORM` registry in [`src/adapters/client-map.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/client-map.ts), and instantiating the matching adapter with high confidence.**

The `mksglu/context-mode` repository implements a Model Context Protocol (MCP) server that seamlessly identifies which IDE or CLI tool is connecting—whether Claude Code, Gemini CLI, Cursor, or OpenCode. This auto-detection occurs instantly during the protocol handshake, eliminating the need for manual platform configuration.

## The MCP Handshake Detection Flow

Platform detection follows a strict sequence that begins when the transport connects and ends with a cached, platform-specific adapter ready to handle requests.

### Server Initialization

In [`src/server.ts`](https://github.com/mksglu/context-mode/blob/main/src/server.ts), the `main()` function (lines 29-35) instantiates an `MCPServer` and opens a **stdio** transport. This establishes the low-level communication channel that will carry the MCP protocol messages between the client and server.

### Client Identification via the initialize Request

When an MCP client connects, the protocol mandates an **`initialize`** request containing a `clientInfo` object with `name` and `version` properties. According to the source code in [`src/server.ts`](https://github.com/mksglu/context-mode/blob/main/src/server.ts) (lines 302-305), the server retrieves this metadata immediately after the transport attaches by calling `server.server.getClientVersion()`.

### Platform Resolution Core Logic

The `detectPlatform()` function in [`src/adapters/detect.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/detect.ts) (lines 33-44) receives the client metadata and performs a lookup against `CLIENT_NAME_TO_PLATFORM`. This mapping table—curated from the *Apify MCP Client Capabilities Registry*—links standard MCP client names to internal `PlatformId` values.

When a match is found, the function returns a **`DetectionSignal`** object containing:
- `platform`: The resolved `PlatformId` (e.g., `"cursor"`, `"claude-code"`)
- `confidence`: `"high"` 
- `reason`: A descriptive string including the original `clientInfo.name`

### Adapter Selection and Caching

With a valid `DetectionSignal`, the server invokes `getAdapter(signal.platform)` from [`src/adapters/detect.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/detect.ts) (lines 24-28). This utility uses dynamic `import()` to lazily load only the platform-specific adapter code, keeping the server memory footprint minimal.

The instantiated adapter is then stored in the module-level `_detectedAdapter` variable (lines 1000-1006 in [`src/server.ts`](https://github.com/mksglu/context-mode/blob/main/src/server.ts)), making it available for the remainder of the session for operations like session-path calculation.

## Fallback Detection Chain

If the MCP handshake lacks `clientInfo` or the client name is unrecognized, the detection logic degrades gracefully through a predefined hierarchy implemented in [`src/adapters/detect.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/detect.ts) (lines 46-62):

1. **Environment variable checks** – Searches for platform-specific environment markers
2. **Config directory heuristics** – Inspects filesystem paths for known configuration directories
3. **Default platform** – Returns `"claude-code"` with low confidence, ensuring the server remains operational

This fallback chain guarantees that `context-mode` remains functional even when receiving connections from non-compliant or unidentified MCP clients.

## Practical Implementation Example

When a client such as Cursor initiates a connection, the handshake data flows through the detection pipeline:

```typescript
// Client sends during MCP initialization
const clientInfo = { name: "cursor-vscode", version: "2.3.1" };
await mcpConnection.sendRequest("initialize", { clientInfo });

// Server-side processing in context-mode:
// 1. server.server.getClientVersion() returns clientInfo
// 2. detectPlatform(clientInfo) checks CLIENT_NAME_TO_PLATFORM
// 3. Returns { platform: "cursor", confidence: "high", ... }
// 4. getAdapter("cursor") dynamically imports cursor adapter

```

## Summary

- **Handshake-driven detection**: Platform identification relies on the `clientInfo.name` field sent in the MCP `initialize` request, extracted via `getClientVersion()` in [`src/server.ts`](https://github.com/mksglu/context-mode/blob/main/src/server.ts).
- **Zero-configuration**: The `CLIENT_NAME_TO_PLATFORM` mapping in [`src/adapters/client-map.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/client-map.ts) enables instant recognition without user intervention.
- **High-confidence signals**: Valid matches return a `DetectionSignal` with `confidence: "high"` and detailed reasoning for debugging.
- **Lazy loading**: `getAdapter()` uses dynamic imports to load only the required platform adapter, optimizing startup performance.
- **Robust fallbacks**: If handshake data is unavailable, the system checks environment variables and config directories before defaulting to the Claude Code adapter.

## Frequently Asked Questions

### How does context-mode extract client information from the MCP protocol?

The server retrieves the `clientInfo` object by calling `server.server.getClientVersion()` immediately after the transport connects, as implemented in [`src/server.ts`](https://github.com/mksglu/context-mode/blob/main/src/server.ts) at lines 302-305. This method extracts the `name` and `version` fields that the client sent in the `initialize` request.

### What happens if an unknown MCP client connects?

If `clientInfo.name` is not found in `CLIENT_NAME_TO_PLATFORM`, the `detectPlatform` function in [`src/adapters/detect.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/detect.ts) (lines 46-62) falls back to environment variable inspection and configuration directory heuristics. If these fail, it defaults to the Claude Code adapter with low confidence, ensuring the server remains functional.

### Where is the platform-to-adapter mapping defined?

The mapping from MCP client names to internal platform IDs is maintained in [`src/adapters/client-map.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/client-map.ts). This registry is derived from the *Apify MCP Client Capabilities Registry* and maps strings like `"cursor-vscode"` to the `PlatformId` `"cursor"`.

### Why does context-mode use lazy loading for adapters?

The `getAdapter` function in [`src/adapters/detect.ts`](https://github.com/mksglu/context-mode/blob/main/src/adapters/detect.ts) uses dynamic `import()` statements to load platform-specific code only when a matching client is detected. This approach minimizes the initial startup time and memory footprint of the MCP server, as unnecessary adapter code is never loaded into memory.