UNPKG

pocketsmith-mcp

Version:

MCP server for managing budgets via PocketSmith API

68 lines (67 loc) 3.92 kB
/** * @fileoverview Provides functions for creating and configuring MCP StdioClientTransport. * This module is responsible for instantiating and setting up the StdioClientTransport * from the @modelcontextprotocol/sdk, which is used to communicate with local MCP * server processes via their standard input/output streams. * @module src/mcp-client/transports/stdioClientTransport */ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { BaseErrorCode, McpError } from "../../types-global/errors.js"; import { logger, requestContextService, } from "../../utils/index.js"; // Centralized internal imports /** * Creates and configures a `StdioClientTransport` instance (from the `@modelcontextprotocol/sdk`) * for launching and communicating with an MCP server process via its standard input and output streams. * * @param transportConfig - Configuration containing the command, arguments, * and environment variables for the server process. * @param parentContext - Optional parent request context for logging and tracing. * @returns A configured `StdioClientTransport` instance, ready to be connected. * @throws {McpError} If the provided `transportConfig` is invalid (e.g., missing command) * or if the transport fails to initialize for other reasons. */ export function createStdioClientTransport(transportConfig, parentContext) { const baseContext = parentContext ? { ...parentContext } : {}; const context = requestContextService.createRequestContext({ ...baseContext, operation: "createStdioClientTransport", transportType: "stdio", command: transportConfig.command, }); logger.debug("Creating StdioClientTransport", context); if (!transportConfig.command || typeof transportConfig.command !== "string") { logger.error("Invalid command provided for StdioClientTransport", context); throw new McpError(BaseErrorCode.CONFIGURATION_ERROR, "Invalid command for StdioClientTransport: command must be a non-empty string.", context); } // Args validation (Array.isArray) is handled by TypeScript and Zod schema at config load time. // If individual arg string validation (e.g., non-empty) is needed, // it should be part of the Zod schema in configLoader.ts. try { // Only pass through environment variables explicitly defined in the server's configuration. // Inheriting all of process.env is a security risk. // If specific variables from process.env are needed, they should be explicitly // listed in the mcp-config.json for that server or handled by an allowlist mechanism. const serverSpecificEnv = { ...(transportConfig.env || {}), // Only use explicitly defined env vars from config }; logger.debug("Creating StdioClientTransport with merged environment", { ...context, envKeysCount: Object.keys(serverSpecificEnv).length, envVarNames: Object.keys(serverSpecificEnv).join(", ") || "None", }); const transport = new StdioClientTransport({ command: transportConfig.command, args: transportConfig.args, // Assumed to be string[] by this point env: serverSpecificEnv, }); logger.info("StdioClientTransport created successfully", context); return transport; } catch (error) { logger.error("Failed to create StdioClientTransport", { ...context, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }); throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Failed to create StdioClientTransport: ${error instanceof Error ? error.message : String(error)}`, { originalError: error, ...context }); } }