diff --git a/mcontainer/drivers/goose/Dockerfile b/mcontainer/drivers/goose/Dockerfile index 2ae48d8..dc5f774 100644 --- a/mcontainer/drivers/goose/Dockerfile +++ b/mcontainer/drivers/goose/Dockerfile @@ -37,11 +37,12 @@ COPY mc-init.sh /mc-init.sh COPY entrypoint.sh /entrypoint.sh COPY mc-driver.yaml /mc-driver.yaml COPY init-status.sh /init-status.sh +COPY update-goose-config.sh /usr/local/bin/update-goose-config.sh # Extend env via bashrc # Make scripts executable -RUN chmod +x /mc-init.sh /entrypoint.sh /init-status.sh +RUN chmod +x /mc-init.sh /entrypoint.sh /init-status.sh /usr/local/bin/update-goose-config.sh # Set up initialization status check on login RUN echo 'export PATH=/root/.local/bin:$PATH' >> /etc/bash.bashrc diff --git a/mcontainer/drivers/goose/mc-init.sh b/mcontainer/drivers/goose/mc-init.sh index 09b4793..c8cb34f 100755 --- a/mcontainer/drivers/goose/mc-init.sh +++ b/mcontainer/drivers/goose/mc-init.sh @@ -54,6 +54,17 @@ if [ -n "$LANGFUSE_INIT_PROJECT_SECRET_KEY" ] && [ -n "$LANGFUSE_INIT_PROJECT_PU export LANGFUSE_URL="${LANGFUSE_URL:-https://cloud.langfuse.com}" fi +# Update Goose configuration with available MCP servers +if [ -f "/usr/local/bin/update-goose-config.sh" ]; then + echo "Updating Goose configuration with MCP servers..." + bash /usr/local/bin/update-goose-config.sh +elif [ -f "$(dirname "$0")/update-goose-config.sh" ]; then + echo "Updating Goose configuration with MCP servers..." + bash "$(dirname "$0")/update-goose-config.sh" +else + echo "Warning: update-goose-config.sh script not found. Goose configuration will not be updated." +fi + echo "MC driver initialization complete" # Mark initialization as complete diff --git a/mcontainer/drivers/goose/update-goose-config.sh b/mcontainer/drivers/goose/update-goose-config.sh new file mode 100644 index 0000000..4d7220a --- /dev/null +++ b/mcontainer/drivers/goose/update-goose-config.sh @@ -0,0 +1,145 @@ +#!/bin/bash +# Script to update Goose configuration with MCP servers using Python standard library + +# Define config path +GOOSE_CONFIG="$HOME/.config/goose/config.yaml" +CONFIG_DIR="$(dirname "$GOOSE_CONFIG")" + +# Create config directory if it doesn't exist +mkdir -p "$CONFIG_DIR" + +# Function to update config using Python without yaml module +update_config() { + python3 - << 'EOF' +import os +import json +import re + +# Path to goose config +config_path = os.path.expanduser('~/.config/goose/config.yaml') + +# Check if file exists, create if not +if not os.path.exists(config_path): + with open(config_path, 'w') as f: + f.write("extensions:\n") + +# Read the entire file +with open(config_path, 'r') as f: + content = f.read() + +# Get MCP information from environment variables +mcp_count = int(os.environ.get('MCP_COUNT', '0')) +mcp_names_str = os.environ.get('MCP_NAMES', '[]') + +try: + mcp_names = json.loads(mcp_names_str) + print(f"Found {mcp_count} MCP servers: {', '.join(mcp_names)}") +except: + mcp_names = [] + print("Error parsing MCP_NAMES environment variable") + +# Check if extensions key exists, add if not +if 'extensions:' not in content: + content = "extensions:\n" + content + +# Process each MCP - we'll collect the mcp configs to add or update +mcp_configs = [] +for idx in range(mcp_count): + mcp_name = os.environ.get(f'MCP_{idx}_NAME') + mcp_type = os.environ.get(f'MCP_{idx}_TYPE') + mcp_host = os.environ.get(f'MCP_{idx}_HOST') + + # Always use container's SSE port (8080) not the host-bound port + if mcp_name and mcp_host: + # Use standard MCP SSE port (8080) + mcp_url = f"http://{mcp_host}:8080/sse" + print(f"Processing MCP extension: {mcp_name} ({mcp_type}) - {mcp_url}") + mcp_configs.append((mcp_name, mcp_url)) + elif mcp_name and os.environ.get(f'MCP_{idx}_URL'): + # For remote MCPs, use the URL provided in environment + mcp_url = os.environ.get(f'MCP_{idx}_URL') + print(f"Processing remote MCP extension: {mcp_name} ({mcp_type}) - {mcp_url}") + mcp_configs.append((mcp_name, mcp_url)) + +# Now we'll update the config file line by line, preserving all content +lines = content.split('\n') +output_lines = [] +in_extensions = False +current_ext = None +extension_added = set() # Track which extensions we've processed + +# First pass - update existing extensions and track them +for line in lines: + # Check if we're entering extensions section + if line.strip() == 'extensions:': + in_extensions = True + output_lines.append(line) + continue + + # Look for extension definition (2-space indentation) + if in_extensions and re.match(r'^ (\w+):', line): + match = re.match(r'^ (\w+):', line) + current_ext = match.group(1) + output_lines.append(line) + + # Mark as seen if this is one of our MCPs + for mcp_name, _ in mcp_configs: + if mcp_name == current_ext: + extension_added.add(mcp_name) + continue + + # If we're in an MCP extension that we need to update + if in_extensions and current_ext and current_ext in [n for n, _ in mcp_configs]: + # If this is a URI line, replace it with our URL + if line.strip().startswith('uri:'): + for mcp_name, mcp_url in mcp_configs: + if mcp_name == current_ext: + output_lines.append(f' uri: {mcp_url}') + break + # If this is a type line, ensure it's SSE + elif line.strip().startswith('type:'): + output_lines.append(' type: sse') + # If this is enabled line, ensure it's true + elif line.strip().startswith('enabled:'): + output_lines.append(' enabled: true') + # Otherwise keep the line + else: + output_lines.append(line) + continue + + # If we're moving to a non-2-space indented line, we're out of the current extension + if in_extensions and current_ext and not line.startswith(' ') and line.strip(): + current_ext = None + + # For any other line, just add it + output_lines.append(line) + +# Add any MCP extensions that weren't found in the existing config +if in_extensions: + for mcp_name, mcp_url in mcp_configs: + if mcp_name not in extension_added: + print(f"Adding new MCP extension: {mcp_name}") + output_lines.append(f' {mcp_name}:') + output_lines.append(f' enabled: true') + output_lines.append(f' name: {mcp_name}') + output_lines.append(f' timeout: 60') + output_lines.append(f' type: sse') + output_lines.append(f' uri: {mcp_url}') + output_lines.append(f' envs: {{}}') + +# Write the updated content back +with open(config_path, 'w') as f: + f.write('\n'.join(output_lines)) + +print(f"Updated Goose configuration at {config_path}") +EOF +} + +# Check if MCP servers are defined +if [ -n "$MCP_COUNT" ] && [ "$MCP_COUNT" -gt 0 ]; then + echo "Updating Goose configuration with MCP servers..." + update_config + echo "Goose configuration updated successfully!" +else + echo "No MCP servers found, using default Goose configuration." +fi \ No newline at end of file