UNPKG

@mcp-shark/mcp-shark

Version:

Aggregate multiple Model Context Protocol (MCP) servers into a single unified interface with a powerful monitoring UI. Prov deep visibility into every request and response.

118 lines (103 loc) 3.21 kB
import { getMcpConfigPath } from 'mcp-shark-common/configs/index.js'; import { readFileSync, existsSync } from 'node:fs'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { convertMcpServersToServers } from '../../utils/config.js'; import { createTransport } from './transport.js'; /** * Discover a single MCP server */ async function discoverServer(serverName, serverConfig) { const transport = createTransport(serverConfig, serverName); const client = new Client( { name: 'mcp-shark-smart-scan', version: '1.0.0' }, { capabilities: { tools: {}, resources: {}, prompts: {}, }, } ); try { await client.connect(transport); const [toolsResult, resourcesResult, promptsResult] = await Promise.allSettled([ client.listTools(), client.listResources(), client.listPrompts(), ]); const tools = toolsResult.status === 'fulfilled' ? toolsResult.value?.tools || [] : []; const resources = resourcesResult.status === 'fulfilled' ? resourcesResult.value?.resources || [] : []; const prompts = promptsResult.status === 'fulfilled' ? promptsResult.value?.prompts || [] : []; await client.close(); if (transport.close) { await transport.close(); } return { name: serverName, tools, resources, prompts, }; } catch (error) { try { await client.close(); if (transport.close) { await transport.close(); } } catch (closeError) { // Ignore close errors } throw error; } } /** * Discover all MCP servers from config * GET /api/smartscan/discover */ export async function discoverServers(req, res) { try { const configPath = getMcpConfigPath(); if (!existsSync(configPath)) { return res.status(404).json({ error: 'MCP config file not found', message: `Config file not found at: ${configPath}`, }); } const configContent = readFileSync(configPath, 'utf-8'); const parsedConfig = JSON.parse(configContent); const convertedConfig = convertMcpServersToServers(parsedConfig); const servers = convertedConfig.servers || {}; if (Object.keys(servers).length === 0) { return res.status(400).json({ error: 'No servers found in config', message: 'The config file does not contain any MCP servers', }); } const discoveryPromises = Object.entries(servers).map(async ([serverName, serverConfig]) => { try { return await discoverServer(serverName, serverConfig); } catch (error) { console.error(`Error discovering server ${serverName}:`, error); return { name: serverName, tools: [], resources: [], prompts: [], error: error.message, }; } }); const discoveredServers = await Promise.all(discoveryPromises); return res.json({ success: true, servers: discoveredServers, }); } catch (error) { console.error('Error discovering servers:', error); return res.status(500).json({ error: 'Failed to discover servers', message: error.message, }); } }