Skip to main content
Glama

MCPMan

by semistrict
proxy.ts4.94 kB
import type { UpstreamServerManager } from "../mcp/upstream-server-manager.js"; import type { MacroManager } from "../mcp/macros.js"; import type { EvalRuntime } from "./runtime.js"; /** * Converts dash-case or snake_case to camelCase * Example: agent-debugger -> agentDebugger, list_targets -> listTargets */ function toCamelCase(str: string): string { return str .replace(/[-_]([a-z])/g, (_, letter) => letter.toUpperCase()) .replace(/^[a-z]/, (letter) => letter.toLowerCase()); } export interface ToolProxy { [toolName: string]: (args?: unknown) => Promise<unknown>; } export interface ServerProxies { [serverName: string]: ToolProxy; } export async function createServerProxies( upstreamServerManager: UpstreamServerManager ): Promise<ServerProxies> { const proxies: ServerProxies = {}; // Create proxies for ALL connected servers (both 'connected' and 'enabled' states) // The proxy will check state when tools are called for (const managedServer of upstreamServerManager.getAllServers()) { if (managedServer.state !== "not-connected") { try { proxies[managedServer.name] = await managedServer.createProxy(); } catch (error) { console.error(`Failed to create proxy for server ${managedServer.name}:`, error); } } } return proxies; } function createMacrosProxy(macroManager: MacroManager, evalRuntime: EvalRuntime): ToolProxy { // Create a lazy proxy that loads macros on-demand return new Proxy( {}, { get(_target, prop, _receiver) { if (typeof prop === "string") { // Return a function that will execute the macro return async (args?: unknown) => { return await macroManager.executeMacro(prop, args || {}, evalRuntime); }; } return undefined; }, } ); } export function createGlobalContext( proxies: ServerProxies, upstreamServerManager: UpstreamServerManager, macroManager: MacroManager | null, evalRuntime: EvalRuntime | null ): Record<string, unknown> { // Create the global context that will be available in eval'd code const context: Record<string, unknown> = {}; // Add each server as a global variable (with both original and camelCase names) for (const [serverName, toolProxy] of Object.entries(proxies)) { context[serverName] = toolProxy; // Also add camelCase version (e.g., agent-debugger -> agentDebugger) const camelCaseName = toCamelCase(serverName); if (camelCaseName !== serverName) { context[camelCaseName] = toolProxy; } } // Add macros proxy if MacroManager is available if (macroManager && evalRuntime) { context.macros = createMacrosProxy(macroManager, evalRuntime); } // Add utility functions context.listServers = () => Object.keys(proxies); context.listTools = (serverName?: string) => { if (serverName) { const server = proxies[serverName]; return server ? Object.keys(server) : []; } const allTools: Record<string, string[]> = {}; for (const [name, proxy] of Object.entries(proxies)) { allTools[name] = Object.keys(proxy); } return allTools; }; context.help = async (serverName: string, toolName?: string) => { // Get managed server const managedServer = upstreamServerManager.getManagedServer(serverName); if (!managedServer || managedServer.state !== "enabled") { throw new Error( `Server '${serverName}' not found or not enabled. Available servers: ${Object.keys(proxies).join(", ")}` ); } try { // Get all tools for the server const result = await managedServer.listTools(); const tools = result.tools || []; if (toolName) { // Show help for specific tool const tool = tools.find((t: { name: string }) => t.name === toolName); if (!tool) { throw new Error( `Tool '${toolName}' not found in server '${serverName}'. Available tools: ${tools.map((t: { name: string }) => t.name).join(", ")}` ); } return { server: serverName, tool: { name: tool.name, description: tool.description, inputSchema: tool.inputSchema || {}, }, }; } else { // Show help for all tools in server return { server: serverName, tools: tools.map( (tool: { name: string; description?: string; inputSchema?: unknown }) => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema || {}, }) ), }; } } catch (error) { throw new Error( `Error getting tools from server '${serverName}': ${error instanceof Error ? error.message : String(error)}` ); } }; // Add vars object for persisting state across eval calls context.vars = {}; return context; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/semistrict/mcpman'

If you have feedback or need assistance with the MCP directory API, please join our Discord server