UNPKG

@nvhien20vn/git-mcp-server

Version:
88 lines (87 loc) • 5.09 kB
/** * Handles the setup and connection for the Stdio MCP transport. * Implements the MCP Specification 2025-03-26 for stdio transport. * This transport communicates directly over standard input (stdin) and * standard output (stdout), typically used when the MCP server is launched * as a child process by a host application. * * Specification Reference: * https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/transports.mdx#stdio * * --- Authentication Note --- * As per the MCP Authorization Specification (2025-03-26, Section 1.2), * STDIO transports SHOULD NOT implement HTTP-based authentication flows. * Authorization is typically handled implicitly by the host application * controlling the server process. This implementation follows that guideline. * * @see {@link https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/authorization.mdx | MCP Authorization Specification} */ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // Import core utilities: ErrorHandler for centralized error management and logger for logging. import { ErrorHandler, logger } from '../../utils/index.js'; // --- Stdio Session State --- // Since stdio typically involves a single, persistent connection managed by a parent, // we manage a single working directory state for the entire process. let currentWorkingDirectory = undefined; // Initialize as undefined /** * Gets the current working directory set for the stdio session. * @returns {string | undefined} The current working directory path or undefined if not set. */ export function getStdioWorkingDirectory() { return currentWorkingDirectory; } /** * Sets the working directory for the stdio session. * @param {string} dir - The new working directory path. */ export function setStdioWorkingDirectory(dir) { currentWorkingDirectory = dir; logger.info(`Stdio working directory set to: ${dir}`, { operation: 'setStdioWorkingDirectory' }); } /** * Connects a given McpServer instance to the Stdio transport. (Asynchronous) * Initializes the SDK's StdioServerTransport, which handles reading newline-delimited * JSON-RPC messages from process.stdin and writing corresponding messages to process.stdout, * adhering to the MCP stdio transport specification. * * MCP Spec Points Covered by SDK's StdioServerTransport: * - Reads JSON-RPC messages (requests, notifications, responses, batches) from stdin. * - Writes JSON-RPC messages to stdout. * - Handles newline delimiters and ensures no embedded newlines in output messages. * - Ensures only valid MCP messages are written to stdout. * * Note: Logging via the `logger` utility MAY result in output to stderr, which is * permitted by the spec for logging purposes. * * @param {McpServer} server - The McpServer instance containing the core logic (tools, resources). * @param {Record<string, any>} context - Logging context for correlation. * @returns {Promise<void>} A promise that resolves when the connection is successfully established. * @throws {Error} Throws an error if the connection fails during setup (e.g., issues connecting server to transport). */ export async function connectStdioTransport(server, context) { // Add a specific operation name to the context for better log filtering. const operationContext = { ...context, operation: 'connectStdioTransport', transportType: 'Stdio' }; logger.debug('Attempting to connect stdio transport...', operationContext); try { logger.debug('Creating StdioServerTransport instance...', operationContext); // Instantiate the transport provided by the SDK for standard I/O communication. // This class encapsulates the logic for reading from stdin and writing to stdout // according to the MCP stdio spec. const transport = new StdioServerTransport(); logger.debug('Connecting McpServer instance to StdioServerTransport...', operationContext); // Establish the link between the server's core logic and the transport layer. // This internally starts the necessary listeners on process.stdin. await server.connect(transport); // Log successful connection. The server is now ready to process messages via stdio. logger.info('MCP Server connected and listening via stdio transport.', operationContext); // Use logger.notice for startup message to ensure MCP compliance and proper handling by clients. logger.notice(`\nšŸš€ MCP Server running in STDIO mode.\n (MCP Spec: 2025-03-26 Stdio Transport)\n`, operationContext); } catch (err) { // Catch and handle any critical errors during the transport connection setup. // Mark as critical because the server cannot function without a connected transport. ErrorHandler.handleError(err, { ...operationContext, critical: true }); // Rethrow the error to signal the failure to the calling code (e.g., the main server startup). throw err; } }