Forráskód Böngészése

fix: use StreamableHTTPClientTransport for HTTP MCP servers

The previous implementation used SSEClientTransport for both 'http' and 'sse'
type MCP servers, which caused a 405 Method Not Allowed error for HTTP servers.

Changes:
- Added StreamableHTTPClientTransport import from MCP SDK
- Split HTTP and SSE discovery into separate methods
- discoverStreamableHttpServerTools() for 'http' type (uses StreamableHTTPClientTransport)
- discoverSseServerTools() for 'sse' type (uses SSEClientTransport)
- Updated routing logic to use the correct transport based on server type

StreamableHTTPClientTransport uses HTTP POST for sending messages and HTTP GET
with Server-Sent Events for receiving messages, which is the correct protocol
for HTTP-based MCP servers like Supabase.

This fixes the tool discovery error:
"Error discovering tools from MCP server 'supabase': SSE error: Non-200 status code (405)"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Claude 9 hónapja
szülő
commit
0d656c0f75
1 módosított fájl, 69 hozzáadás és 4 törlés
  1. 69 4
      client/src/toolDiscovery.ts

+ 69 - 4
client/src/toolDiscovery.ts

@@ -8,6 +8,7 @@
 import { Client } from '@modelcontextprotocol/sdk/client/index.js';
 import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
 import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
+import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
 import { spawn, ChildProcess } from 'child_process';
 import { MCPServerConfig } from './types.js';
 
@@ -55,8 +56,10 @@ export class ToolDiscovery {
 
         if (serverConfig.type === 'stdio') {
           tools = await this.discoverStdioServerTools(serverName, serverConfig);
-        } else if (serverConfig.type === 'http' || serverConfig.type === 'sse') {
-          tools = await this.discoverHttpServerTools(serverName, serverConfig);
+        } else if (serverConfig.type === 'http') {
+          tools = await this.discoverStreamableHttpServerTools(serverName, serverConfig);
+        } else if (serverConfig.type === 'sse') {
+          tools = await this.discoverSseServerTools(serverName, serverConfig);
         } else {
           console.warn(`Warning: MCP server '${serverName}' uses unsupported type '${serverConfig.type}'. Skipping.`);
           continue;
@@ -174,9 +177,71 @@ export class ToolDiscovery {
   }
 
   /**
-   * Discover tools from a single HTTP/SSE-based MCP server
+   * Discover tools from a single Streamable HTTP-based MCP server
    */
-  private static async discoverHttpServerTools(
+  private static async discoverStreamableHttpServerTools(
+    serverName: string,
+    serverConfig: { url?: string; headers?: Record<string, string> }
+  ): Promise<string[]> {
+    if (!serverConfig.url) {
+      throw new Error(`MCP server '${serverName}' is missing 'url' field`);
+    }
+
+    let client: Client | null = null;
+
+    try {
+      // Parse the URL
+      const url = new URL(serverConfig.url);
+
+      // Create Streamable HTTP transport with optional headers
+      const transport = new StreamableHTTPClientTransport(url, {
+        requestInit: serverConfig.headers ? {
+          headers: serverConfig.headers
+        } : undefined
+      });
+
+      // Create MCP client
+      client = new Client({
+        name: `tool-discovery-${serverName}`,
+        version: '1.0.0'
+      }, {
+        capabilities: {}
+      });
+
+      // Connect to the server
+      await client.connect(transport);
+
+      // List available tools
+      const toolsResponse = await client.listTools();
+
+      // Format tool names with mcp__ prefix
+      const tools = toolsResponse.tools.map(tool =>
+        `mcp__${serverName}__${tool.name}`
+      );
+
+      // Close the connection
+      await client.close();
+
+      return tools;
+
+    } catch (error) {
+      // Ensure cleanup
+      if (client) {
+        try {
+          await client.close();
+        } catch (closeError) {
+          // Ignore close errors
+        }
+      }
+
+      throw error;
+    }
+  }
+
+  /**
+   * Discover tools from a single SSE-based MCP server
+   */
+  private static async discoverSseServerTools(
     serverName: string,
     serverConfig: { url?: string; headers?: Record<string, string> }
   ): Promise<string[]> {