### Install MCP Globally (Bash) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/README.md Installs an MCP (Micro Code Package) globally on the system using the `roo.py` script. ```bash python roo.py install username/my-cool-mcp ``` -------------------------------- ### Installing Bun on Windows (PowerShell) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/mcp_servers_registration.md This PowerShell command downloads and executes the Bun installation script from bun.sh. It is used to install the Bun runtime, which includes the 'bunx' command, recommended for running local MCP servers on Windows. ```PowerShell iwr https://bun.sh/install | iex ``` -------------------------------- ### Python Function Start for Listing Installed MCPs Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Defines the beginning of the `list_installed` Python function, including its docstring which describes its purpose to list installed MCPs across scopes and scan for unregistered ones, and initializes a boolean flag. ```python def list_installed(): """Lists all installed MCPs, checking both global and project scopes, and scans for potential unregistered MCPs.""" print("--- Installed MCPs ---") found_any = False ``` -------------------------------- ### Checking and Installing Tool - TypeScript Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Provides functions to check for the existence of a command-line tool and to prompt the user to install it if missing. `checkCommandExists` verifies if a command is available in the system's PATH, while `checkAndInstallTool` uses VS Code's warning messages to guide the user on installing required dependencies. ```TypeScript import * as child_process from 'child_process'; import * as vscode from 'vscode'; import { promisify } from 'util'; const execPromise = promisify(child_process.exec); async function checkCommandExists(command: string): Promise { try { // Use a command that should always succeed if the tool exists (e.g., --version, or just the command itself) // 'which' or 'where' are more reliable for checking existence const checkCmd = process.platform === 'win32' ? `where ${command}` : `which ${command}`; await execPromise(checkCmd); return true; } catch (error) { // Command not found or execution failed return false; } } async function checkAndInstallTool( toolName: string, installCommandSuggestion: string | null, progress: vscode.Progress<{ message?: string; increment?: number }> ): Promise { progress.report({ message: `Checking for tool: ${toolName}` }); const exists = await checkCommandExists(toolName); if (exists) { progress.report({ message: `${toolName} found.` }); return true; } else { const message = `Tool '${toolName}' not found.`; const options: vscode.MessageOptions = { modal: true }; const items: vscode.MessageItem[] = [{ title: 'OK' }]; // Default option let fullPrompt = message; if (installCommandSuggestion) { fullPrompt += ` Would you like to attempt installation? (Suggested command: ${installCommandSuggestion})`; items.unshift({ title: 'Attempt Install' }); // Add install option } else { fullPrompt += ` Please install it manually to proceed.`; } const selection = await vscode.window.showWarningMessage(fullPrompt, options, ...items); if (selection && selection.title === 'Attempt Install' && installCommandSuggestion) { progress.report({ message: `Attempting to install ${toolName}...` }); try { // WARNING: Running arbitrary install commands is risky. // A safer approach is to provide instructions or links. // This is just illustrative based on the prompt. // await runCommand(installCommandSuggestion, process.cwd(), progress); // Requires runCommand // Check again after attempt // return await checkCommandExists(toolName); vscode.window.showInformationMessage(`Please run the suggested command manually: ${installCommandSuggestion}`); return false; // Assume manual step required } catch (installError) { vscode.window.showErrorMessage(`Failed to attempt installation of ${toolName}: ${installError}`); return false; } } else { // User clicked OK or closed the dialog, or no install suggestion return false; // Tool not handled/installed } } } ``` -------------------------------- ### Reading Installed MCP Database - Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Resolves the path to the installed database, initializes a set for efficient tracking of registered MCPs, and safely opens and loads the database content using JSON. ```Python db_path = get_installed_db(scope) # Returns resolved Path object registered_mcps = set() # Efficient tracking structure # Safe database reading with open(db_path, "r", encoding='utf-8') as f: installed_list = json.load(f) ``` -------------------------------- ### Installing Dependencies Based on Project Type Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Determines the appropriate dependency installation command based on the detected project type (npm, pip, poetry, go, cargo) and executes it within the cloned repository directory. It also ensures the necessary build tool is installed beforehand. ```Shell # Example commands based on detected type: # npm: npm install # pip: pip install -r requirements.txt # poetry: poetry install # go: go mod download # cargo: cargo build ``` -------------------------------- ### Configuring a Local STDIO MCP Server (JSON) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/mcp_servers_registration.md This JSON snippet provides an example configuration for a local MCP server that communicates via standard I/O (STDIO). It specifies the command to run, arguments, optional environment variables, auto-approval settings, and disabled status. This example uses 'bunx' as the command. ```JSON { "mcpServers": { "gitlab-mcp": { "command": "bunx", "args": ["@modelcontextprotocol/server-gitlab", "--port", "3000"], "env": { "GITLAB_TOKEN": "your-token-here" }, "alwaysAllow": [], "disabled": false } } } ``` -------------------------------- ### Detecting Run Command for MCP Server Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Identifies the command needed to start the MCP server process for a given project type and directory. It checks common entry points and scripts (like package.json scripts, main files) and may involve running build steps if necessary. ```TypeScript async function detectRunCommand(mcpDirUri: vscode.Uri, projectType: string): Promise { const fsPath = mcpDirUri.fsPath; switch (projectType) { case 'npm': // Check package.json scripts (start:mcp, start) // Default to 'node dist/index.js stdio' or 'node index.js stdio' // Consider build scripts ('build', 'compile') if source exists but dist doesn't break; case 'pip': case 'poetry': // Look for main.py, app.py, run.py // Default to 'python main.py stdio' or similar break; case 'go': // Check for main.go // Default to 'go run . stdio' // Consider 'go build -o . stdio' and './ stdio' break; case 'cargo': // Check for src/main.rs // Default to 'cargo run -- stdio' // Consider 'cargo build --release' and './target/release/ stdio' break; default: return null; } // Return the detected command string or null return null; // Placeholder } ``` ```Shell # Example run commands: node dist/index.js stdio python main.py stdio go run . stdio ./ stdio cargo run -- stdio ./target/release/ stdio ``` -------------------------------- ### List Installed and Scan for Unregistered MCPs (Python) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Iterates through 'global' and 'project' scopes. For each scope, it attempts to read a list of registered MCPs from a JSON database file. It prints the details of registered MCPs and tracks their names. Subsequently, it scans the base installation directory for the scope, identifies directories whose names are not in the registered list, attempts to read their manifest, and prints details for these unregistered MCPs. Includes error handling for file operations and JSON parsing. ```python # Iterate through both installation scopes for scope in ["global", "project"]: print(f"\nScope: {scope}") try: # Get base installation directory for this scope base_install_dir = get_global_install_dir() if scope == "global" else get_project_install_dir() # Get the path to the database file for this scope db_path = get_installed_db(scope) # Ensures DB file exists (may be empty list) registered_mcps = set() # Track registered MCP names # Check if the DB file actually exists and has content if not db_path.is_file() or db_path.stat().st_size == 0: # Special message for project scope if .roo dir doesn't exist if scope == "project" and not (Path.cwd() / ".roo").exists(): print(" (No project found in current directory)") else: print(f" No MCPs installed in {scope} scope.") # Continue with directory scan even if no registered MCPs # --- Load and Display Registered MCPs --- print(" Registered MCPs:") with open(db_path, "r", encoding='utf-8') as f: installed_list = json.load(f) if isinstance(installed_list, list): # Sort MCPs by name for consistent output installed_list.sort(key=lambda x: x.get("name", "").lower() if isinstance(x, dict) else "") # Track registered MCPs and print their details for mcp in installed_list: found_any = True # Check if item is a dictionary before accessing keys if not isinstance(mcp, dict): log_event(f"Warning: Found non-dictionary item in {scope} DB: {mcp}") continue # Extract details with defaults for robustness name = mcp.get("name", "Unknown Name") registered_mcps.add(name) # Track this MCP as registered mcp_type = mcp.get("type", "unknown") source = mcp.get("source", "Unknown Source") subdir = mcp.get("subdir", "") location = mcp.get("installed_at", "Unknown Location") entry = mcp.get("entry", "N/A") # Format source display to include subdirectory if present source_display = f"{source}{':' + subdir if subdir else ''}" # Print formatted details print(f" - {name}") print(f" Type : {mcp_type}") print(f" Source : {source_display}") print(f" Installed At : {location}") print(f" Entry Point : {entry}") # --- Scan for Unregistered MCPs --- if base_install_dir.exists(): print("\n Scanning for unregistered MCPs...") try: for item in base_install_dir.iterdir(): if item.is_dir() and item.name not in registered_mcps: # Try to read manifest from unregistered directory try: manifest = read_manifest(item) found_any = True print(f" ! {item.name} (Unregistered)") print(f" Type : {manifest.get('type', 'unknown')}") print(f" Location : {item}") print(f" Entry Point : {manifest.get('main', 'N/A')}") print(" Note: Use 'roo install' to properly register this MCP") except (FileNotFoundError, ValueError): # Not a valid MCP directory, skip it continue except Exception as e: log_event(f"Error reading potential unregistered MCP at {item}: {e}") continue except Exception as e: log_event(f"Error scanning for unregistered MCPs in {base_install_dir}: {e}") print(f" Warning: Error scanning for unregistered MCPs: {e}", file=sys.stderr) except (json.JSONDecodeError, IOError, UnicodeDecodeError) as e: # Handle errors reading or parsing the database file log_event(f"ERROR reading MCP database for scope '{scope}' ({db_path}): {e}") print(f" Error reading installation data for {scope} scope: {e}", file=sys.stderr) except Exception as e: # Catch any other unexpected errors during listing log_event(f"Unexpected error listing MCPs for scope '{scope}': {e}") print(f" An unexpected error occurred while listing {scope} MCPs: {e}", file=sys.stderr) ``` -------------------------------- ### Registering MCP Server Configuration Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Updates the extension's configuration file (mcp_settings.json) with the details of the newly installed server, including its name, installation path, detected run command, and references to where environment variables are stored. ```JSON // Example mcp_settings.json structure entry: { "servers": [ { "name": "my-mcp-server", "installPath": "/path/to/installed/server", "runCommand": "node dist/index.js stdio", "envVars": { "source": "secrets", // or ".env" or "config" "keys": ["API_KEY", "DB_URL"], // List of keys stored (e.g., in secrets) "filePath": ".env" // If source is .env } } ] } ``` -------------------------------- ### Scanning Installation Directory - Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Determines the base installation directory (global or project) and iterates through its contents to identify potential unregistered MCP directories, skipping those already marked as registered. ```Python # Base directory determination base_install_dir = get_global_install_dir() if scope == "global" else get_project_install_dir() # Safe iteration for item in base_install_dir.iterdir(): if item.is_dir() and item.name not in registered_mcps: # Process potential unregistered MCP ``` -------------------------------- ### Determining Installation Directory - TypeScript Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Calculates the target installation directory based on the specified scope ('global' or 'project') and the repository name. It uses VS Code's extension context for global storage or the workspace folder for project scope, ensuring the necessary parent directories exist. ```TypeScript import * as vscode from 'vscode'; import * as path from 'path'; import * as fs from 'fs/promises'; async function getInstallDir(scope: 'global' | 'project', repoName: string, context: vscode.ExtensionContext): Promise { let baseDir: string; if (scope === 'global') { baseDir = path.join(context.globalStorageUri.fsPath, 'mcps'); await fs.mkdir(baseDir, { recursive: true }); // Ensure directory exists } else { // project scope if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { throw new Error('Project scope selected but no workspace folder is open.'); } baseDir = path.join(vscode.workspace.workspaceFolders[0].uri.fsPath, '.roo', 'mcps'); await fs.mkdir(baseDir, { recursive: true }); // Ensure directory exists } const installPath = path.join(baseDir, repoName); return vscode.Uri.file(installPath); } ``` -------------------------------- ### Roo Code Request (use_tool) - JSON Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a JSON-RPC request sent from Roo Code to the MCP server via stdin to invoke a specific tool with arguments. ```json {"jsonrpc": "2.0", "id": 1, "method": "use_tool", "params": {"tool_name": "do_something", "arguments": {"param1": "hello"}}} ``` -------------------------------- ### Displaying MCP Server List in VS Code (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Explains how the final list of MCP servers is presented to the user in VS Code. Options include appending text to a 'vscode.OutputChannel' using 'appendLine' or formatting the list for interactive selection via 'vscode.window.showQuickPick'. ```Node.js vscode.OutputChannel.appendLine ``` ```Node.js vscode.window.showQuickPick ``` -------------------------------- ### Parsing Environment Variables from Files Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Implements functions to extract potential environment variable names from common configuration files like `.env.example` or by parsing JSON code blocks within `README.md` files. ```TypeScript async function parseEnvExample(filePath: string): Promise { try { const content = await fs.promises.readFile(filePath, 'utf-8'); const lines = content.split('\n'); const varNames: string[] = []; const envVarRegex = /^\s*([a-zA-Z_][a-zA-Z0-9_]*)=/; for (const line of lines) { const match = line.match(envVarRegex); if (match && match[1]) { varNames.push(match[1]); } } return varNames; } catch (error) { console.error(`Error reading or parsing ${filePath}:`, error); return []; } } async function parseReadmeForEnvVars(readmePath: string): Promise { try { const content = await fs.promises.readFile(readmePath, 'utf-8'); const jsonBlockRegex = /```json\n([\s\S]*?)\n```/g; let match; const allKeys: Set = new Set(); while ((match = jsonBlockRegex.exec(content)) !== null) { try { const jsonContent = match[1]; const parsed = JSON.parse(jsonContent); _findEnvKeysRecursive(parsed, allKeys); } catch (parseError) { console.warn('Failed to parse JSON block in README:', parseError); } } return Array.from(allKeys); } catch (error) { console.error(`Error reading ${readmePath}:`, error); return []; } } function _findEnvKeysRecursive(obj: any, keys: Set) { if (typeof obj !== 'object' || obj === null) { return; } if (Array.isArray(obj)) { for (const item of obj) { _findEnvKeysRecursive(item, keys); } } else { for (const key in obj) { if (typeof obj[key] === 'string') { // Simple heuristic: assume string keys might be env vars keys.add(key); } _findEnvKeysRecursive(obj[key], keys); } } } ``` ```Regex ^\s*([a-zA-Z_][a-zA-Z0-9_]*)=/ /```json\n([\s\S]*?)\n```/g ``` -------------------------------- ### Streaming New Log Content (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md When 'fs.watchFile' detects new content, 'fs.createReadStream' is used to efficiently read only the new bytes added to the file since the last check. The stream starts reading from the previous file size. ```Node.js fs.createReadStream ``` -------------------------------- ### Implementing listInstalledMcps Function (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Defines the asynchronous function 'listInstalledMcps' responsible for gathering and validating the list of installed MCP servers. It reads settings from global and project scopes, validates paths using 'fs.promises.stat', and returns a structured array. ```TypeScript listInstalledMcps(context: vscode.ExtensionContext): Promise> ``` -------------------------------- ### Parsing Repository Input - TypeScript Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Implements the logic to parse a repository input string, which can be a full Git URL or a `owner/repo[:subdir]` slug. It extracts the full Git URL, the repository name, and an optional subdirectory. ```TypeScript function parseRepoInput(repoInput: string): { gitUrl: string; subdir: string | null; repoName: string } { // Implementation using regex or string manipulation // Example: owner/repo[:subdir] or full URL const slugMatch = repoInput.match(/^([^/]+)/([^/:]+)(?::(.+))?$/); if (slugMatch) { const owner = slugMatch[1]; const repo = slugMatch[2]; const subdir = slugMatch[3] || null; return { gitUrl: `https://github.com/${owner}/${repo}.git`, subdir, repoName: repo }; } // Handle full URL case const urlMatch = repoInput.match(/^(https?://.*/([^/]+).git)(?::(.+))?$/); if (urlMatch) { const gitUrl = urlMatch[1]; const repoName = urlMatch[2]; const subdir = urlMatch[3] || null; return { gitUrl, subdir, repoName }; } // Basic fallback or error handling throw new Error(`Invalid repository input format: ${repoInput}`); } ``` -------------------------------- ### Detecting Project Type for MCP Server Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Implements the logic to identify the programming language and build system used in a given repository directory by checking for the presence of specific marker files like package.json, requirements.txt, etc. This helps determine subsequent installation and run commands. ```TypeScript async function detectProjectType(repoDirUri: vscode.Uri): Promise<'npm' | 'pip' | 'poetry' | 'cargo' | 'go' | 'unknown'> { const fsPath = repoDirUri.fsPath; // Use fs.promises.stat or fs.promises.access to check for files if (await fileExists(path.join(fsPath, 'package.json'))) return 'npm'; if (await fileExists(path.join(fsPath, 'requirements.txt'))) return 'pip'; // Check pyproject.toml for [tool.poetry] if (await checkPoetry(path.join(fsPath, 'pyproject.toml'))) return 'poetry'; if (await fileExists(path.join(fsPath, 'Cargo.toml'))) return 'cargo'; if (await fileExists(path.join(fsPath, 'go.mod'))) return 'go'; return 'unknown'; } async function fileExists(filePath: string): Promise { try { await fs.promises.access(filePath); return true; } catch { return false; } } ``` ```Shell package.json requirements.txt pyproject.toml Cargo.toml go.mod ``` -------------------------------- ### Implementing showLogs Function (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Defines the main asynchronous function 'showLogs' responsible for reading, processing, and displaying log file content. It handles options like specifying the number of lines and enabling 'follow' mode using file watching. ```TypeScript showLogs(logFilePath: string, follow: boolean, lines: number | undefined, outputChannel: vscode.OutputChannel, context: vscode.ExtensionContext) ``` -------------------------------- ### Displaying Log Content in Output Channel (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Displays the processed log content to the user by appending lines to a dedicated 'vscode.OutputChannel' using 'appendLine'. The channel is made visible using the '.show()' method. ```Node.js outputChannel.appendLine ``` ```Node.js outputChannel.show() ``` -------------------------------- ### Reading MCP Settings Configuration (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Describes the process of reading MCP server configuration settings from files located at paths determined by 'getSettingsPath'. The actual reading is done by a 'readSettings' function, which loads server details from both global and project scopes. ```Node.js readSettings ``` -------------------------------- ### Validating MCP Server Paths (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Uses 'fs.promises.stat' to check if the directory paths specified for each configured MCP server still exist on the file system. This step ensures that only valid, accessible server installations are included in the list. ```Node.js fs.promises.stat ``` -------------------------------- ### MCP Server Success Response - JSON Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a successful JSON-RPC response sent from the MCP server to Roo Code via stdout, indicating the successful completion of a request. ```json {"jsonrpc": "2.0", "id": 1, "result": {"message": "Action completed successfully!"}} ``` -------------------------------- ### Registering 'roo.showLogs' Command (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Registers the VS Code command 'roo.showLogs' using 'vscode.commands.registerCommand'. This command is the user-facing trigger for the log viewing functionality within the extension. ```Node.js vscode.commands.registerCommand('roo.showLogs') ``` -------------------------------- ### Collecting Environment Variables from User Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Prompts the user to enter values for required environment variables discovered from configuration files, using VS Code's input box API. It handles sensitive inputs by masking them. ```TypeScript async function collectEnvVars(requiredVars: string[]): Promise> { const collectedVars = new Map(); for (const varName of requiredVars) { const value = await vscode.window.showInputBox({ prompt: `Enter value for ${varName}:`, ignoreFocusOut: true, password: varName.toLowerCase().includes('secret') || varName.toLowerCase().includes('key') || varName.toLowerCase().includes('token') }); if (value !== undefined) { // User didn't cancel collectedVars.set(varName, value); } } return collectedVars; } ``` -------------------------------- ### Defining MCP Server Configuration with mcp.json (JSON) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md The `mcp.json` file is a crucial manifest located at the root of your server's Git repository. Roo Code reads this file after cloning to understand the server's identity, how to run it, its dependencies, and the tools/resources it provides. This example demonstrates the structure and common fields required. ```JSON { "name": "my-feature-server", "version": "1.0.0", "displayName": "My Awesome Feature", "description": "Provides awesome features via MCP.", "author": "Your Name ", "repository": { "type": "git", "url": "https://github.com/your-username/my-feature-server.git" }, "run": { }, "environment": [ { "name": "API_KEY", "description": "API Key for accessing the awesome service.", "secret": true }, { "name": "FEATURE_FLAG_X", "description": "Enable experimental feature X.", "secret": false, "default": "false" } ], "tools": [ { "name": "do_something", "description": "Performs an awesome action.", "inputSchema": { "type": "object", "properties": { "param1": { "type": "string", "description": "First parameter." }, "count": { "type": "number", "default": 1 } }, "required": ["param1"] } } ], "resources": [ { "uri": "myfeature://data/{id}", "description": "Access specific data item by ID." } ], "uiContributions": { "buttons": [ {"id": "myfeature.refresh", "label": "Refresh Data"} ], "initialLayout": [ {"type": "text", "content": "Welcome to My Feature!"}, {"type": "button", "id": "myfeature.refresh"} ] } } ``` -------------------------------- ### Registering 'roo.listMcps' Command (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Registers the VS Code command 'roo.listMcps' using 'vscode.commands.registerCommand'. This command serves as the entry point from the VS Code command palette to trigger the MCP server listing feature. ```Node.js vscode.commands.registerCommand('roo.listMcps') ``` -------------------------------- ### Safely Removing Directory - TypeScript Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Provides a utility function to safely remove a directory using Node.js `fs.promises.rm` with recursive and force options. Includes basic logging for success or failure. ```TypeScript import * as vscode from 'vscode'; import * as fs from 'fs/promises'; async function safeRemoveDirectory(dirUri: vscode.Uri): Promise { try { await fs.rm(dirUri.fsPath, { recursive: true, force: true }); console.log(`Successfully removed directory: ${dirUri.fsPath}`); // Add logging } catch (error) { console.error(`Error removing directory ${dirUri.fsPath}:`, error); // Decide how to handle errors - maybe rethrow or just log } } ``` -------------------------------- ### MCP Server Error Response - JSON Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a JSON-RPC error response sent from the MCP server to Roo Code via stdout, indicating that a request failed. ```json {"jsonrpc": "2.0", "id": 1, "error": {"code": -32000, "message": "Something went wrong", "data": { ... }}} ``` -------------------------------- ### Sending mcp/uiAction JSON-RPC Request Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a JSON-RPC request sent from the Roo Code Extension to the MCP Server when a user interacts with a UI element (e.g., clicks a button). It specifies the method `mcp/uiAction` and includes parameters identifying the specific action via `actionId`. ```JSON-RPC {"jsonrpc": "2.0", "id": 5, "method": "mcp/uiAction", "params": {"actionId": "myfeature.refresh"}} ``` -------------------------------- ### Executing Shell Command - TypeScript Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Implements an asynchronous function to execute shell commands using `child_process.spawn`. It captures stdout and stderr, updates a VS Code progress indicator, and can optionally log output to a VS Code output channel. Returns a promise resolving with the command's output and exit code. ```TypeScript import * as child_process from 'child_process'; import * as vscode from 'vscode'; interface RunCommandResult { stdout: string; stderr: string; code: number | null; } async function runCommand( command: string, cwd: string, progress: vscode.Progress<{ message?: string; increment?: number }>, options?: { env?: NodeJS.ProcessEnv, logOutput?: boolean, outputChannel?: vscode.OutputChannel } ): Promise { return new Promise((resolve, reject) => { progress.report({ message: `Running command: ${command}`, increment: 0 }); const [cmd, ...args] = command.split(/\s+/); // Simple split, might need more robust parsing const proc = child_process.spawn(cmd, args, { cwd, env: options?.env }); let stdout = ''; let stderr = ''; proc.stdout.on('data', (data) => { stdout += data.toString(); if (options?.logOutput && options.outputChannel) { options.outputChannel.append(data.toString()); } }); proc.stderr.on('data', (data) => { stderr += data.toString(); if (options?.logOutput && options.outputChannel) { options.outputChannel.append(data.toString()); } }); proc.on('error', (err) => { console.error(`Failed to start command ${command}:`, err); if (options?.logOutput && options.outputChannel) { options.outputChannel.appendLine(`Failed to start command: ${err.message}`); } reject(err); }); proc.on('close', (code) => { progress.report({ message: `Command finished with code ${code}`, increment: 100 }); if (options?.logOutput && options.outputChannel) { options.outputChannel.appendLine(`Command finished with code ${code}`); } resolve({ stdout, stderr, code }); }); }); } ``` -------------------------------- ### Watching Log File for Changes (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Implements the 'follow' mode by using 'fs.watchFile' to monitor the log file for size changes. When changes are detected, new content is read and appended to the output channel. The watcher needs to be managed for disposal. ```Node.js fs.watchFile(logFilePath, { interval: 500 }, (curr, prev) => { ... }) ``` -------------------------------- ### Reading Log File Content (Node.js) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Reads the content of the specified log file using 'fs.promises.readFile'. This asynchronous operation retrieves the full file content as a string, which is then typically split into lines for processing. ```Node.js fs.promises.readFile(logFilePath, 'utf-8') ``` -------------------------------- ### MCP Server Notification (mcp/log) - JSON Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a JSON-RPC notification sent from the MCP server to Roo Code via stdout, typically used for logging or events that do not require a response. ```json {"jsonrpc": "2.0", "method": "mcp/log", "params": {"level": "info", "message": "Processing data..."}} ``` -------------------------------- ### MCP Server Notification (mcp/updateUI) - JSON Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Another example of a JSON-RPC notification sent from the MCP server to Roo Code via stdout, potentially used to trigger UI updates in the Roo Code client. ```json {"jsonrpc": "2.0", "method": "mcp/updateUI", "params": {"elements": [{"type": "text", "content": "Data refreshed!"}]}} ``` -------------------------------- ### Sending mcp/updateUI JSON-RPC Notification Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Example of a JSON-RPC notification sent from the MCP Server back to the Roo Code Extension to dynamically update the UI in the MCP tab. It uses the `mcp/updateUI` method and provides an array of UI element descriptions in the `params`. ```JSON-RPC {"jsonrpc": "2.0", "method": "mcp/updateUI", "params": {"elements": [{"type": "text", "content": "Data refreshed successfully at " + new Date()}]}} ``` -------------------------------- ### Configuring Winston Logging in VS Code Extension (TypeScript) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md This snippet provides a function to configure the Winston logger for a VS Code extension. It sets up logging to a rotating file using the extension's log directory and a custom transport to write messages to a dedicated VS Code Output Channel. It requires the 'winston' and 'vscode' dependencies. ```TypeScript // src/logging.ts import * as winston from 'winston'; import * as path from 'path'; import * as vscode from 'vscode'; let logger: winston.Logger; let outputChannel: vscode.OutputChannel; export function configureLogging(context: vscode.ExtensionContext, level: string = 'info') { if (logger) return logger; // Already configured outputChannel = vscode.window.createOutputChannel("Roo Extension Logs"); context.subscriptions.push(outputChannel); // Dispose channel on deactivation const logFilePath = vscode.Uri.joinPath(context.logUri, 'roo-extension.log').fsPath; // Ensure log directory exists vscode.workspace.fs.createDirectory(context.logUri); // Custom transport for VS Code Output Channel const outputChannelTransport = new winston.transports.Console({ level: 'warn', // Only show warnings and errors in the channel by default format: winston.format.combine( winston.format.timestamp(), winston.format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level.toUpperCase()}]: ${message}`; }) ), log: (info, callback) => { outputChannel.appendLine(info[Symbol.for('message')]); callback(); } }); logger = winston.createLogger({ level: level, // 'info' or 'debug' format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), // Log stack traces winston.format.json() // Log as JSON to file ), transports: [ new winston.transports.File({ filename: logFilePath, maxsize: 5 * 1024 * 1024, // 5MB maxFiles: 3, tailable: true, }), outputChannelTransport // Add the custom transport ], }); // Optional: Capture console.log/warn/error // console.log = (...args) => logger.info(args.join(' ')); // console.warn = (...args) => logger.warn(args.join(' ')); // console.error = (...args) => logger.error(args.join(' ')); logger.info('Logging configured.'); return logger; } // Helper like Python's log_event export function logEvent(level: 'info' | 'warn' | 'error' | 'debug', message: string, data?: any) { if (!logger) { console.error("Logger not configured!"); return; } logger.log(level, message, data); } export function getLogger(): winston.Logger { if (!logger) { throw new Error("Logger not configured!"); } return logger; } ``` -------------------------------- ### Saving Environment Variables Securely Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_porting_guide.md Describes methods for storing collected environment variables, favoring the VS Code Secrets API for sensitive data and potentially a `.env` file for non-sensitive variables required by the server process. ```TypeScript // Using VS Code Secrets API for sensitive data async function storeSecret(context: vscode.ExtensionContext, serverName: string, varName: string, value: string): Promise { const secretKey = `roo.mcp.${serverName}.${varName}`; await context.secrets.store(secretKey, value); } // Writing to a .env file (less secure for secrets) async function writeEnvFile(installDirUri: vscode.Uri, envVars: Map): Promise { const envFilePath = path.join(installDirUri.fsPath, '.env'); const lines: string[] = []; for (const [key, value] of envVars.entries()) { lines.push(`${key}=${value}`); } await fs.promises.writeFile(envFilePath, lines.join('\n')); } ``` -------------------------------- ### Using File System Promises Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Accesses the promise-based API for file system operations provided by `fs.promises` in Node.js. Recommended for asynchronous file operations to avoid callback hell. ```javascript fs.promises ``` -------------------------------- ### Loading Dotenv Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses the `config()` method from the `dotenv` library to load environment variables from a `.env` file into `process.env`. Typically called early in the application startup. ```javascript require('dotenv').config() ``` -------------------------------- ### Loading Dotenv Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses the `load_dotenv()` function from the `python-dotenv` library to load environment variables from a `.env` file into `os.environ`. Useful if the application environment is configured via a file. ```python load_dotenv() ``` -------------------------------- ### Spawning Child Process Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Refers to the `spawn` method from the built-in `child_process` module in Node.js. Used for launching new processes with more control over input/output streams. ```javascript child_process.spawn ``` -------------------------------- ### Executing Child Process Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Refers to the `exec` method from the built-in `child_process` module in Node.js. Used for running shell commands in a child process and buffering their output. Simpler than `spawn` for basic command execution. ```javascript child_process.exec ``` -------------------------------- ### Flushing Stdout Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `sys.stdout.flush()` from the standard `sys` library to ensure that all buffered output is immediately written to standard output. Crucial after writing messages with `sys.stdout.write()` to guarantee delivery. ```python sys.stdout.flush() ``` -------------------------------- ### Python Try-Except Indentation Pattern Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Illustrates the recommended indentation pattern for a try-except block nested within an if statement in Python, emphasizing the importance of correct indentation for proper control flow and avoiding potential errors. ```python if condition: try: # Operation code here except Exception as e: # Exception handling here ``` -------------------------------- ### Defining MCP Servers in JSON Configuration Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/mcp_servers_registration.md This JSON snippet shows the basic structure required for an MCP server configuration file. It defines the top-level object containing the 'mcpServers' property, which is a dictionary where keys are server names and values are server configuration objects. ```JSON { "mcpServers": { "my-server": { // server configuration } } } ``` -------------------------------- ### Reading Stdin Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `sys.stdin.readline()` from the standard `sys` library to read a single line of input from standard input. Useful for receiving line-delimited messages like JSON-RPC over stdio. ```python sys.stdin.readline() ``` -------------------------------- ### Iterating Directories Safely (Python) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md This Python snippet demonstrates a safe way to iterate through items in a directory. It checks if each item is a directory and filters out items whose names are present in a list of registered MCPs before processing. ```python for item in base_install_dir.iterdir(): if item.is_dir() and item.name not in registered_mcps: # Process potential unregistered MCP ``` -------------------------------- ### Writing Stdout Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `sys.stdout.write()` from the standard `sys` library to write a string to standard output. Used for sending messages, typically followed by `sys.stdout.flush()`. Ensure a trailing newline (`\n`) is included for line-delimited protocols. ```python sys.stdout.write() ``` -------------------------------- ### Writing Stdout Console Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `console.log()` to write output to standard output (`stdout`). Should be used sparingly for non-JSON-RPC messages when communicating over stdio, as `stdout` is typically reserved for the protocol. ```javascript console.log ``` -------------------------------- ### Layered Error Handling - Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md Implements a layered error handling strategy using nested try/except blocks to gracefully handle expected errors (like missing files) by skipping, log unexpected errors, and catch critical errors affecting the entire scope. ```Python try: # Main operation block try: # Specific operation (e.g., manifest reading) except (FileNotFoundError, ValueError): # Expected errors (skip quietly) continue except Exception as e: # Unexpected errors (log and continue) log_event(f"Error: {e}") except Exception as e: # Critical errors (affect entire scope) print(f"Error processing scope {scope}: {e}", file=sys.stderr) ``` -------------------------------- ### Configuring a Remote SSE/HTTP MCP Server (JSON) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/mcp_servers_registration.md This JSON snippet demonstrates how to configure a remote MCP server that connects via Server-Sent Events (SSE) or HTTP. It requires a URL endpoint and can include optional headers for authentication or other purposes, along with auto-approval and disabled settings. ```JSON { "mcpServers": { "remote-server": { "url": "https://your-server-url.com/mcp", "headers": { "Authorization": "Bearer your-token" }, "alwaysAllow": ["tool3"], "disabled": false } } } ``` -------------------------------- ### Accessing Environment Variables Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `os.environ.get()` from the standard `os` library to safely retrieve the value of an environment variable by name. Returns `None` if the variable is not set. ```python os.environ.get('VAR_NAME') ``` -------------------------------- ### Layered Exception Handling (Python) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md This Python code illustrates a layered approach to exception handling. It uses nested try-except blocks to differentiate between expected errors (like FileNotFoundError or ValueError) that can be skipped quietly and unexpected errors that should be logged, with an outer block catching critical errors affecting the entire scope. ```python try: # Main operation block try: # Specific operation (e.g., manifest reading) except (FileNotFoundError, ValueError): # Expected errors (skip quietly) continue except Exception as e: # Unexpected errors (log and continue) log_event(f"Error: {e}") except Exception as e: # Critical errors (affect entire scope) print(f"Error processing scope {scope}: {e}", file=sys.stderr) ``` -------------------------------- ### Serializing JSON Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses the standard `json` library to serialize a Python object into a JSON string. Used for formatting outgoing JSON-RPC responses or notifications. ```python json.dumps ``` -------------------------------- ### Accessing Environment Variables Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Accesses environment variables directly using the built-in `process.env` object in Node.js. The value is retrieved by accessing the property corresponding to the variable name. ```javascript process.env.VAR_NAME ``` -------------------------------- ### Parsing JSON Python Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses the standard `json` library to parse a JSON string into a Python object. Essential for processing incoming JSON-RPC messages. ```python json.loads ``` -------------------------------- ### Writing Stderr Console Node.js Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/roo_mcp_integration_guide.md Uses `console.error()` to write output to standard error (`stderr`). This is the recommended channel for logging and debugging information when communicating over stdio, as it is separate from the protocol channel (`stdout`). ```javascript console.error ``` -------------------------------- ### Printing MCP Not Found Messages (Python) Source: https://github.com/robertheadley/roo-code-mcp-installer/blob/main/rooinstallerlearnings.md This snippet checks if any MCPs were found during a scan. If none were found, it prints a user-friendly message tailored to whether the current directory is within a Roo project context (indicated by the presence of a '.roo' directory). ```python # Print a summary message if no MCPs were found in any scope if not found_any: # Check again if a project context exists to refine the message if not (Path.cwd() / ".roo").exists(): print("\nNo MCPs installed globally or in the current project.") else: print("\nNo MCPs installed globally. Project MCPs might be listed above if any exist.") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.