Skip to main content
Glama

pluggedin-mcp-proxy

call-pluggedin-tool.ts8.8 kB
import { z } from "zod"; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { CompatibilityCallToolResultSchema, ListToolsResultSchema, Tool, } from "@modelcontextprotocol/sdk/types.js"; import { getMcpServers } from "../fetch-pluggedinmcp.js"; import { getSessionKey, sanitizeName, getPluggedinMCPApiKey, getPluggedinMCPApiBaseUrl } from "../utils.js"; // Import API utils import axios from "axios"; // Import axios import { getSession } from "../sessions.js"; import { ConnectedClient } from "../client.js"; // Assuming ConnectedClient holds the session/client // import { // getProfileCapabilities, // ProfileCapability, // } from "../fetch-capabilities.js"; // Removed unused import // import { getInactiveTools, ToolParameters } from "../fetch-tools.js"; // Removed unused import // import { container } from "../di-container.js"; // Removed DI // import { Logger } from "../logging.js"; // Removed Logger // import { ToolPlugin, pluginRegistry } from "../plugin-system.js"; // Removed Plugin System import { ToolExecutionResult } from "../types.js"; // import { getSessionKeyForTool } from '../tool-registry.js'; // Removed Tool Registry const toolName = "tool_call"; // Renamed to match veyrax-mcp convention const toolDescription = ` Executes a specific proxied MCP tool managed by PluggedinMCP. Use 'get_tools' first to find the correct 'tool_name' (e.g., 'github__create_issue'). Requires a valid PluggedinMCP API key configured in the environment. The API key is used implicitly by the server based on its environment configuration. `; // Define the input schema for this tool const CallPluggedinToolSchema = z.object({ tool_name: z .string() .describe( "The prefixed name of the proxied tool to call (e.g., 'github__create_issue', 'google_calendar__list_events'). Get this from 'get_tools'." ), arguments: z // Renamed input parameter to match veyrax-mcp .record(z.any()) .optional() .default({}) .describe( "The arguments object required by the specific proxied tool being called." ), }); // Removed logger /** * Implementation for the 'tool_call' static tool. * Proxies a tool call to the appropriate downstream MCP server based on the prefixed tool name. */ // Removed ToolPlugin interface implementation export class CallPluggedinToolTool { readonly name = toolName; readonly description = toolDescription; readonly inputSchema = CallPluggedinToolSchema; // Removed findClientForTool static method as it relied on removed tool-registry /** * Executes the 'tool_call' logic. * Finds the correct downstream server based on the prefixed tool name, * extracts the original tool name, and proxies the 'tools/call' request. * @param args - Validated input arguments containing 'tool_name' and 'arguments'. * @param meta - Optional request metadata containing progress tokens etc. * @returns A promise resolving to the ToolExecutionResult from the downstream server. */ async execute( args: z.infer<typeof CallPluggedinToolSchema>, meta?: any ): Promise<ToolExecutionResult> { const { tool_name: toolName, arguments: toolArgs } = args; // Find the client session directly let clientForTool: ConnectedClient | null = null; let serverName = "unknown"; // Default server name let serverUuid: string | null = null; try { // First, check if the tool arguments contain a _serverUuid field // This would be the case if the tool was called directly from the get_tools response if (toolArgs && '_serverUuid' in toolArgs) { serverUuid = toolArgs._serverUuid; // Remove the _serverUuid field from the arguments before passing to the downstream server delete toolArgs._serverUuid; } // If we don't have a serverUuid from the arguments, try to get it from the API if (!serverUuid) { // Fetch tools from the API to find the server UUID for this tool const apiKey = getPluggedinMCPApiKey(); const apiBaseUrl = getPluggedinMCPApiBaseUrl(); if (apiKey && apiBaseUrl) { try { const response = await axios.get( `${apiBaseUrl}/api/tools`, { headers: { Authorization: `Bearer ${apiKey}`, }, } ); let tools: any[] = []; if (response.data && response.data.tools && Array.isArray(response.data.tools)) { tools = response.data.tools; } else if (response.data && Array.isArray(response.data)) { tools = response.data; } // Find the tool with the matching name const matchingTool = tools.find((tool: any) => tool.name === toolName); if (matchingTool) { serverUuid = matchingTool.mcp_server_uuid || matchingTool._serverUuid; } } catch (error) { // Ignore API errors and fall back to the old method } } } // If we have a serverUuid, get the server params and session if (serverUuid) { const serverParamsMap = await getMcpServers(); // Fetch server configs const params = serverParamsMap[serverUuid]; if (params) { serverName = params.name || serverUuid; const sessionKey = getSessionKey(serverUuid, params); // Attempt to get the session const session = await getSession(sessionKey, serverUuid, params); if (session) { clientForTool = session; } } } // If we still don't have a client, fall back to the old method of checking all servers if (!clientForTool) { const serverParamsMap = await getMcpServers(); // Fetch server configs for (const [uuid, params] of Object.entries(serverParamsMap)) { serverName = params.name || uuid; const sessionKey = getSessionKey(uuid, params); // Attempt to get the session const session = await getSession(sessionKey, uuid, params); if (session) { // Try to check if this server has the tool try { const toolsResponse = await session.client.request( { method: "tools/list", params: {} }, ListToolsResultSchema ); if (toolsResponse.tools.some((tool: Tool) => tool.name === toolName)) { clientForTool = session; break; // Found the matching server and session } } catch (error) { // Ignore errors and continue to the next server } } } } } catch (error) { // logger.error("Error finding client session for tool call:", error); // Removed logging return { isError: true, content: [{ type: "text", text: `Error finding origin server for tool: ${toolName}` }], }; } // Handle cases where client wasn't found if (!clientForTool) { // logger.warn(`Could not find active session for tool: ${toolName}`); // Removed logging return { isError: true, content: [{ type: "text", text: `Error: Tool not found or origin server unavailable: ${toolName}` }], }; } // Proceed with the tool call using the found client try { // logger.debug( // Removed logging // `Proxying call to tool '${toolName}' on server '${serverName}' with args:`, // toolArgs // ); // Call the actual tool on the downstream client return await clientForTool.client.request( { method: "tools/call", params: { name: toolName, arguments: toolArgs || {}, _meta: { progressToken: meta?.progressToken, // Use meta here }, }, }, CompatibilityCallToolResultSchema // Use the schema that expects content/isError ) as ToolExecutionResult; // Explicitly cast the result // The result from client.request should match ToolExecutionResult structure after type update // return result; // Removed extraneous return } catch (error) { // logger.error( // Removed logging // `Error calling tool '${toolName}' through ${serverName}:`, // error // ); // Return error structure matching ToolExecutionResult const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: "text", text: `Error executing proxied tool: ${errorMessage}` }], }; } } } // Removed plugin registration

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/VeriTeknik/pluggedin-mcp'

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