Patterns Strategy / Adapter Pattern See in Code Tour

Strategy Pattern

Swappable implementations for transports (MCP), sandboxes, and auth providers behind unified interfaces.

Strategy Pattern — Architecture Diagram
graph TD
    A[MCP Client] --> B{Transport Strategy}
    B --> C[StdioTransport]
    B --> D[SSETransport]
    B --> E[HTTPTransport]
    B --> F[WebSocketTransport]
    G[Permission Check] --> H{Sandbox Strategy}
    H --> I[No Sandbox]
    H --> J[bwrap sandbox]
    H --> K[VM sandbox]

Mermaid diagram definition

Deep Dive

The Strategy pattern appears in two critical places: MCP transports and execution sandboxes. In both cases, the consuming code is identical regardless of which strategy is active — only the concrete implementation differs.

🔑Key Insight

MCP supports 6 transports (stdio, SSE, HTTP, WebSocket, SDK, claudeai-proxy). Switching from a local stdio server to a remote HTTP server requires only a config change — no code change. The transport is the strategy; the client is unchanged.

ℹ️Info

The sandbox adapter (`src/utils/sandbox/sandbox-adapter.ts`) abstracts over `bwrap` (Linux), `vm` (macOS), and no-sandbox (fallback). The bash tool doesn't know which sandbox it's running in.

KEY TAKEAWAYS
  • Strategy pattern decouples algorithm from context
  • Config-driven strategy selection enables zero-code switching
  • Adapters unify incompatible interfaces (6 transports → 1 client)
  • Testing is simpler: swap the SDK transport for unit tests

Source Code

MCP config schema showing the transport type discriminated union — the Strategy interface.

import type { Client } from '@modelcontextprotocol/sdk/client/index.js'
import type {
  Resource,
  ServerCapabilities,
} from '@modelcontextprotocol/sdk/types.js'
import { z } from 'zod/v4'
import { lazySchema } from '../../utils/lazySchema.js'

// Configuration schemas and types
export const ConfigScopeSchema = lazySchema(() =>
  z.enum([
    'local',
    'user',
    'project',
    'dynamic',
    'enterprise',
    'claudeai',
    'managed',
  ]),
)
export type ConfigScope = z.infer<ReturnType<typeof ConfigScopeSchema>>

export const TransportSchema = lazySchema(() =>
  z.enum(['stdio', 'sse', 'sse-ide', 'http', 'ws', 'sdk']),
)
export type Transport = z.infer<ReturnType<typeof TransportSchema>>

export const McpStdioServerConfigSchema = lazySchema(() =>
  z.object({
    type: z.literal('stdio').optional(), // Optional for backwards compatibility
    command: z.string().min(1, 'Command cannot be empty'),
    args: z.array(z.string()).default([]),
    env: z.record(z.string(), z.string()).optional(),
  }),
)

// Cross-App Access (XAA / SEP-990): just a per-server flag. IdP connection
// details (issuer, clientId, callbackPort) come from settings.xaaIdp — configured
// once, shared across all XAA-enabled servers. clientId/clientSecret (parent
// oauth config + keychain slot) are for the MCP server's AS.
const McpXaaConfigSchema = lazySchema(() => z.boolean())

const McpOAuthConfigSchema = lazySchema(() =>
  z.object({
    clientId: z.string().optional(),
    callbackPort: z.number().int().positive().optional(),
    authServerMetadataUrl: z
      .string()
      .url()
      .startsWith('https://', {
AI Assistant

Ask anything about Strategy Pattern

Powered by Groq · Enter to send, Shift+Enter for newline