/** * CapabilityNegotiator — client capability detection and negotiation * * Encapsulates the logic for detecting what an MCP client supports * (UI rendering, elicitation, etc.) based on the initialize handshake. * * The MCP SDK's Zod schema strips unknown fields like `extensions` * (protocol 2025-11-25+), so we also capture raw capabilities from * the JSON-RPC initialize message before Zod parsing occurs. */ import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; export declare class CapabilityNegotiator { /** * Raw client capabilities captured from the initialize request BEFORE Zod parsing. * * The MCP SDK uses Zod to validate incoming requests, which strips unknown fields * from ClientCapabilities. Notably, `extensions` (protocol 2025-11-25+) is not in * the SDK's Zod schema yet, so `getClientCapabilities()` returns an object without * it. Real clients like Claude Desktop and ChatGPT send UI capability under * `extensions`, not `experimental`. We intercept the raw JSON-RPC message to * capture the full capabilities before Zod strips them. * * Key: Server instance → Value: raw capabilities object from initialize request */ /** * Public so PhotonServer can expose a back-compat alias for tests that * seed raw capabilities directly. Prefer `setRawCapabilities()` in * non-test code paths. */ rawClientCapabilities: WeakMap, Record>; /** * Store raw capabilities for a server instance. * Called from the transport message interceptor. */ setRawCapabilities(server: Server, capabilities: Record): void; /** * Check if client supports MCP Apps UI (structuredContent + _meta.ui) * * Looks for the "io.modelcontextprotocol/ui" capability in the client's * initialize handshake. Any MCP client that advertises this capability * gets rich UI responses — Claude Desktop, ChatGPT, MCPJam, etc. * * The capability may appear under `experimental` (older SDK types) or * `extensions` (protocol version 2025-11-25+). We check both so it * just works regardless of which field the client uses. * * Beam is special-cased because it's our own SSE transport where the * capability is implicit. */ supportsUI(server: Server): boolean; /** * ChatGPT's Apps connector currently identifies as OpenAI-owned clients such * as `openai-mcp` in live traffic. Treat those as UI-capable even when the * SDK-normalized capabilities object does not retain the app extension. */ /** * ChatGPT/OpenAI app hosts need a couple of compatibility shims beyond plain * UI support, notably slashless tool names for the app connector layer. */ isOpenAIAppHost(server: Server): boolean; private isOpenAIClientName; /** * Check if client supports elicitation * * Elicitation is a client capability declared during initialization. * The server can use elicitInput() when the client supports it. */ supportsElicitation(server: Server): boolean; /** * Check if client supports sampling (server-driven LLM requests). * * Sampling is a client capability declared during initialization. * When present, the server can call `createMessage()` on the client * to ask its LLM to generate text — used by photons that call * `this.sample()` to delegate inference to the caller's model. */ supportsSampling(server: Server): boolean; /** * Intercept a transport to capture raw client capabilities before Zod strips them. * * The MCP SDK's Zod schema for ClientCapabilities doesn't include `extensions` * (protocol 2025-11-25+), so getClientCapabilities() returns an object without it. * We intercept the transport's onmessage to capture the raw `initialize` request * and store capabilities before Zod parsing occurs. * * @param onMessage Optional additional message interceptor (e.g. for channel permissions) */ interceptTransportForRawCapabilities(transport: { onmessage?: (...args: any[]) => void; }, targetServer: Server, onMessage?: (message: any) => void): void; } //# sourceMappingURL=capability-negotiator.d.ts.map