|
|
@@ -7,6 +7,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 { spawn, ChildProcess } from 'child_process';
|
|
|
import { MCPServerConfig } from './types.js';
|
|
|
|
|
|
@@ -49,13 +50,17 @@ export class ToolDiscovery {
|
|
|
for (const serverName of serverNames) {
|
|
|
const serverConfig = mcpConfig.mcpServers[serverName];
|
|
|
|
|
|
- if (serverConfig.type !== 'stdio') {
|
|
|
- console.warn(`Warning: MCP server '${serverName}' uses type '${serverConfig.type}' - only 'stdio' type is supported for tool discovery. Skipping.`);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
try {
|
|
|
- const tools = await this.discoverServerTools(serverName, serverConfig);
|
|
|
+ let tools: string[];
|
|
|
+
|
|
|
+ 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 {
|
|
|
+ console.warn(`Warning: MCP server '${serverName}' uses unsupported type '${serverConfig.type}'. Skipping.`);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
console.log(` - ${serverName}: discovered ${tools.length} tool(s)`);
|
|
|
|
|
|
@@ -73,9 +78,9 @@ export class ToolDiscovery {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Discover tools from a single MCP server
|
|
|
+ * Discover tools from a single stdio-based MCP server
|
|
|
*/
|
|
|
- private static async discoverServerTools(
|
|
|
+ private static async discoverStdioServerTools(
|
|
|
serverName: string,
|
|
|
serverConfig: { command?: string; args?: string[]; env?: Record<string, string> }
|
|
|
): Promise<string[]> {
|
|
|
@@ -167,4 +172,66 @@ export class ToolDiscovery {
|
|
|
throw error;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Discover tools from a single HTTP/SSE-based MCP server
|
|
|
+ */
|
|
|
+ private static async discoverHttpServerTools(
|
|
|
+ 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 SSE transport with optional headers
|
|
|
+ const transport = new SSEClientTransport(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;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|