Add SSE transport fallback to basic-host
Implement the conventional MCP pattern for transport backward compatibility: try `StreamableHTTPClientTransport` first (modern), then fall back to `SSEClientTransport` (deprecated but needed for older servers). This follows the approach documented in the MCP TypeScript SDK's `streamableHttpWithSseFallbackClient.ts` example. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8c3b1daf7e
commit
7ce5504f9f
1 changed files with 24 additions and 4 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport, type McpUiResourceCsp, type McpUiResourcePermissions, buildAllowAttribute, type McpUiUpdateModelContextRequest, type McpUiMessageRequest } from "@modelcontextprotocol/ext-apps/app-bridge";
|
import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport, type McpUiResourceCsp, type McpUiResourcePermissions, buildAllowAttribute, type McpUiUpdateModelContextRequest, type McpUiMessageRequest } from "@modelcontextprotocol/ext-apps/app-bridge";
|
||||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||||
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
||||||
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
||||||
import type { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
import type { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
||||||
|
|
||||||
|
|
@ -24,11 +25,8 @@ export interface ServerInfo {
|
||||||
|
|
||||||
|
|
||||||
export async function connectToServer(serverUrl: URL): Promise<ServerInfo> {
|
export async function connectToServer(serverUrl: URL): Promise<ServerInfo> {
|
||||||
const client = new Client(IMPLEMENTATION);
|
|
||||||
|
|
||||||
log.info("Connecting to server:", serverUrl.href);
|
log.info("Connecting to server:", serverUrl.href);
|
||||||
await client.connect(new StreamableHTTPClientTransport(serverUrl));
|
const client = await connectWithFallback(serverUrl);
|
||||||
log.info("Connection successful");
|
|
||||||
|
|
||||||
const name = client.getServerVersion()?.name ?? serverUrl.href;
|
const name = client.getServerVersion()?.name ?? serverUrl.href;
|
||||||
|
|
||||||
|
|
@ -39,6 +37,28 @@ export async function connectToServer(serverUrl: URL): Promise<ServerInfo> {
|
||||||
return { name, client, tools, appHtmlCache: new Map() };
|
return { name, client, tools, appHtmlCache: new Map() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function connectWithFallback(serverUrl: URL): Promise<Client> {
|
||||||
|
// Try Streamable HTTP first (modern transport)
|
||||||
|
try {
|
||||||
|
const client = new Client(IMPLEMENTATION);
|
||||||
|
await client.connect(new StreamableHTTPClientTransport(serverUrl));
|
||||||
|
log.info("Connected via Streamable HTTP transport");
|
||||||
|
return client;
|
||||||
|
} catch (streamableError) {
|
||||||
|
log.info("Streamable HTTP failed:", streamableError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to SSE (deprecated but needed for older servers)
|
||||||
|
try {
|
||||||
|
const client = new Client(IMPLEMENTATION);
|
||||||
|
await client.connect(new SSEClientTransport(serverUrl));
|
||||||
|
log.info("Connected via SSE transport");
|
||||||
|
return client;
|
||||||
|
} catch (sseError) {
|
||||||
|
throw new Error(`Could not connect with any transport. SSE error: ${sseError}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface UiResourceData {
|
interface UiResourceData {
|
||||||
html: string;
|
html: string;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue