UNPKG

mcp-uni

Version:

A unified gateway for managing multiple MCP servers

98 lines (97 loc) 4.37 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import z from 'zod'; import { mcpHost, transportConfigSchema } from './host.js'; import { toZodRawShape } from './utils/schema-converter.js'; const connectMcpInputSchema = { name: z.string().describe('The name of the MCP server to connect to'), transportConfig: transportConfigSchema.describe('The transport config of the MCP server to connect to'), }; const disconnectMcpInputSchema = { name: z.string().describe('The name of the MCP server to disconnect from'), }; export const createServer = async (config) => { const server = new McpServer({ name: 'mcp-uni', version: '0.1.0', capabilities: { resources: {}, tools: {}, }, }); if (config?.mcpServers) { console.log('Loading MCP servers from config...'); for (const [name, transportConfig] of Object.entries(config.mcpServers)) { console.log(`Loading MCP server: ${name}`); await mcpHost.addClient(name, transportConfig); } } server.tool('connect_mcp', 'Connect a MCP server to the host', connectMcpInputSchema, async (args) => { const { name, transportConfig } = args; await mcpHost.addClient(name, transportConfig); server.sendToolListChanged(); return { content: [{ type: 'text', text: `Connected MCP server: ${name}` }], }; }); server.tool('disconnect_mcp', 'Disconnect a MCP server from the host', disconnectMcpInputSchema, async (args) => { const { name } = args; await mcpHost.removeClient(name); return { content: [{ type: 'text', text: `Disconnected MCP server: ${name}` }], }; }); server.tool('list_mcp', 'List all MCP servers', {}, async () => { const clients = mcpHost.getClients(); return { content: [{ type: 'text', text: `List of MCP servers: ${clients.map(c => c.name).join(', ')}` }], }; }); for (const tool of mcpHost.getClients().flatMap(c => c.tools)) { const inputSchema = toZodRawShape(tool.inputSchema); server.tool(tool.name, tool.description || '', inputSchema, async (args) => { try { const client = mcpHost.getClients().find(c => c.tools.find(t => t.name === tool.name)); if (!client) { throw new Error(`Unknown tool: ${tool.name}`); } return (await client.client.callTool({ name: tool.name, arguments: args, })); } catch (error) { console.error(`Error calling tool ${tool.name}:`, error); throw error; } }); } for (const prompt of mcpHost.getClients().flatMap(c => c.prompts)) { const inputSchema = toZodRawShape(prompt.arguments); server.prompt(prompt.name, prompt.description || '', inputSchema, async (args) => { const client = mcpHost.getClients().find(c => c.prompts.find(p => p.name === prompt.name)); if (!client) { throw new Error(`Unknown prompt: ${prompt.name}`); } return client.client.getPrompt({ name: prompt.name }); }); } for (const resource of mcpHost.getClients().flatMap(c => c.resources)) { server.resource(resource.name, resource.uri, resource, async (args) => { const client = mcpHost.getClients().find(c => c.resources.find(r => r.name === resource.name)); if (!client) { throw new Error(`Unknown resource: ${resource.name}`); } return client.client.readResource({ uri: resource.uri }); }); } for (const resourceTemplate of mcpHost.getClients().flatMap(c => c.resourceTemplates)) { server.resource(resourceTemplate.name, resourceTemplate.uriTemplate, resourceTemplate, async (args) => { const client = mcpHost.getClients().find(c => c.resourceTemplates.find(r => r.name === resourceTemplate.name)); if (!client) { throw new Error(`Unknown resource template: ${resourceTemplate.name}`); } return client.client.readResource({ uri: resourceTemplate.uriTemplate }); }); } return server; };