From 35575241e610b35be1cf44ff7a6a655ffe927878 Mon Sep 17 00:00:00 2001 From: steev Date: Wed, 17 Sep 2025 11:23:37 +0100 Subject: [PATCH 1/6] removes unnecessary locale copy in build --- containers/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/containers/Dockerfile b/containers/Dockerfile index d8bb182..2d24c0f 100644 --- a/containers/Dockerfile +++ b/containers/Dockerfile @@ -20,7 +20,6 @@ RUN npm ci --only=production # Copy built application and necessary resources COPY --from=builder /app/dist ./dist -COPY --from=builder /app/src/locales ./src/locales RUN mkdir -p /workspace From 844dd08f2e91a114e78a0df699f8ab1bb938341b Mon Sep 17 00:00:00 2001 From: steev Date: Wed, 17 Sep 2025 11:24:15 +0100 Subject: [PATCH 2/6] use json parameters for cmdline signals --- containers/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/Dockerfile b/containers/Dockerfile index 2d24c0f..69279fd 100644 --- a/containers/Dockerfile +++ b/containers/Dockerfile @@ -33,4 +33,4 @@ WORKDIR /workspace EXPOSE 3000 -CMD node /app/dist/index.js ${SPEC_WORKFLOW_PATH:-/workspace} --dashboard --port ${DASHBOARD_PORT:-3000} +CMD ["sh", "-c", "node /app/dist/index.js ${SPEC_WORKFLOW_PATH:-/workspace} --dashboard --port ${DASHBOARD_PORT:-3000}"] From 70f22174e73f02aaa2f94e916646a3b4b3c13e88 Mon Sep 17 00:00:00 2001 From: steev Date: Wed, 17 Sep 2025 15:01:03 +0100 Subject: [PATCH 3/6] changes for better permissions when mounting --- containers/Dockerfile | 19 ++++-- containers/README.md | 39 +++++++++-- containers/setup-mcp.sh | 141 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 12 deletions(-) create mode 100755 containers/setup-mcp.sh diff --git a/containers/Dockerfile b/containers/Dockerfile index 69279fd..bd5b6ec 100644 --- a/containers/Dockerfile +++ b/containers/Dockerfile @@ -23,11 +23,20 @@ COPY --from=builder /app/dist ./dist RUN mkdir -p /workspace -# Change ownership of the app directory to the node user (uid=1000) -RUN chown -R node:node /app /workspace - -# Switch to the node user to match host user permissions -USER node +# Create a user with matching UID/GID (can be overridden at runtime) +ARG USER_ID=1000 +ARG GROUP_ID=1000 + +# Use existing node user/group if UID/GID is 1000, otherwise create new user +RUN if [ "$USER_ID" = "1000" ] && [ "$GROUP_ID" = "1000" ]; then \ + echo "Using existing node user"; \ + else \ + addgroup -g $GROUP_ID appgroup && \ + adduser -D -u $USER_ID -G appgroup appuser; \ + fi + +# Switch to the appropriate user (node for 1000:1000, appuser otherwise) +USER ${USER_ID} WORKDIR /workspace diff --git a/containers/README.md b/containers/README.md index 5f2aef8..22cfe7e 100644 --- a/containers/README.md +++ b/containers/README.md @@ -12,17 +12,38 @@ This directory contains Docker configuration files to run the Spec-Workflow MCP ### Building the Container -From the containers directory, build the Docker image: +From the containers directory, build the Docker image with your user ID to avoid permission issues: ```bash -docker build -t spec-workflow-mcp . +docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t spec-workflow-mcp . +``` + +For systems where `id` command is not available: + +```bash +docker build --build-arg USER_ID=1000 --build-arg GROUP_ID=1000 -t spec-workflow-mcp . ``` ## MCP Server Configuration -### For Claude Desktop or other MCP clients +### Automated Setup (Recommended) + +The easiest way to configure the MCP server is to use the provided setup script: + +```bash +# From your project directory (where you want to use spec-workflow) +/path/to/spec-workflow-mcp/containers/setup-mcp.sh +``` + +This script will: +- Detect your user ID and group ID automatically +- Create or update `.mcp.json` with the correct configuration +- Handle existing MCP configurations safely +- Provide clear next steps -Create or update the `.mcp.json` file in your project root with the following configuration: +### Manual Configuration + +If you prefer to configure manually, create or update the `.mcp.json` file in your project root: ```json { @@ -31,10 +52,11 @@ Create or update the `.mcp.json` file in your project root with the following co "command": "docker", "args": [ "run", "--rm", "-i", - "-v", "./.spec-workflow:/home/username/project/.spec-workflow:rw", + "--user", "1000:1000", + "-v", "/full/path/to/project/.spec-workflow:/full/path/to/project/.spec-workflow:rw", "--entrypoint=node", "spec-workflow-mcp:latest", - "/app/dist/index.js", "./" + "/app/dist/index.js", "/full/path/to/project" ] } } @@ -42,6 +64,8 @@ Create or update the `.mcp.json` file in your project root with the following co ``` +**Important**: Replace `1000:1000` with your actual user ID and group ID (get them with `id -u` and `id -g`). + ## Important Configuration Notes ### Path Mapping Requirements @@ -112,10 +136,11 @@ docker-compose down ### Common Issues -1. **Permission Denied**: Ensure the `.spec-workflow` directory has proper permissions +1. **Permission Denied**: Ensure the container was built with your user ID using the `--build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)` flags 2. **Port Already in Use**: Choose a different port using the `DASHBOARD_PORT` variable 3. **Path Not Found**: Verify that your `SPEC_WORKFLOW_PATH` matches your actual project location 4. **SELinux Issues**: On SELinux-enabled systems, add `:z` to volume mounts +5. **File Ownership Issues**: Rebuild the container with the correct user/group IDs if `.spec-workflow` files are created with wrong ownership ### Logs and Debugging diff --git a/containers/setup-mcp.sh b/containers/setup-mcp.sh new file mode 100755 index 0000000..5108e61 --- /dev/null +++ b/containers/setup-mcp.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +# Spec-Workflow MCP Setup Script +# This script configures .mcp.json for use with spec-workflow-mcp container + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Get current directory and user info +PROJECT_DIR=$(pwd) +USER_ID=$(id -u) +GROUP_ID=$(id -g) +MCP_FILE=".mcp.json" + +echo -e "${BLUE}Spec-Workflow MCP Container Setup${NC}" +echo "==================================" +echo "Project directory: $PROJECT_DIR" +echo "User ID: $USER_ID" +echo "Group ID: $GROUP_ID" +echo "" + +# Check if Docker is available +if ! command -v docker &> /dev/null; then + echo -e "${RED}Error: Docker is not installed or not in PATH${NC}" + exit 1 +fi + +# Check if the spec-workflow-mcp image exists +if ! docker image inspect spec-workflow-mcp:latest &> /dev/null; then + echo -e "${YELLOW}Warning: spec-workflow-mcp:latest image not found${NC}" + echo "Please build the image first:" + echo " cd containers/" + echo " docker build --build-arg USER_ID=$USER_ID --build-arg GROUP_ID=$GROUP_ID -t spec-workflow-mcp ." + echo "" + read -p "Continue anyway? (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Create MCP configuration +MCP_CONFIG=$(cat < /dev/null; then + NEW_CONFIG=$(echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"') + jq --argjson newconfig "$NEW_CONFIG" '.mcpServers."spec-workflow" = $newconfig' "$MCP_FILE" > "$MCP_FILE.tmp" && \ + mv "$MCP_FILE.tmp" "$MCP_FILE" + echo -e "${GREEN}Updated existing $MCP_FILE${NC}" + else + echo -e "${YELLOW}jq not found. Please manually merge the following configuration:${NC}" + echo "" + echo "$MCP_CONFIG" + exit 1 + fi + else + # Add to existing file + if command -v jq &> /dev/null; then + echo -e "${BLUE}Adding spec-workflow to existing $MCP_FILE${NC}" + NEW_CONFIG=$(echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"') + jq --argjson newconfig "$NEW_CONFIG" '.mcpServers."spec-workflow" = $newconfig' "$MCP_FILE" > "$MCP_FILE.tmp" && \ + mv "$MCP_FILE.tmp" "$MCP_FILE" + echo -e "${GREEN}Added spec-workflow to existing $MCP_FILE${NC}" + else + echo -e "${YELLOW}jq not found. Please manually add the spec-workflow section to your existing $MCP_FILE:${NC}" + echo "" + echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"' + exit 1 + fi + fi +else + # Create new file + echo -e "${BLUE}Creating new $MCP_FILE${NC}" + echo "$MCP_CONFIG" > "$MCP_FILE" + echo -e "${GREEN}Created $MCP_FILE${NC}" +fi + +# Create .spec-workflow directory if it doesn't exist +SPEC_WORKFLOW_DIR="$PROJECT_DIR/.spec-workflow" +if [ ! -d "$SPEC_WORKFLOW_DIR" ]; then + echo -e "${BLUE}Creating .spec-workflow directory${NC}" + mkdir -p "$SPEC_WORKFLOW_DIR" + echo -e "${GREEN}Created $SPEC_WORKFLOW_DIR${NC}" +else + echo -e "${BLUE}.spec-workflow directory already exists${NC}" +fi + +echo "" +echo -e "${GREEN}Setup complete!${NC}" +echo "" +echo "Next steps:" +echo "1. Make sure the Docker image is built:" +echo " cd containers/" +echo " docker build --build-arg USER_ID=$USER_ID --build-arg GROUP_ID=$GROUP_ID -t spec-workflow-mcp ." +echo "" +echo "2. Restart Claude Desktop to pick up the new MCP configuration" +echo "" +echo "3. Test the connection by asking Claude to use spec-workflow tools" \ No newline at end of file From 894b0298074fadbf8a0ad9f537e0297125b0ecaa Mon Sep 17 00:00:00 2001 From: steev Date: Sun, 5 Oct 2025 18:26:03 +0100 Subject: [PATCH 4/6] improves dx, fixes unreliable permissions --- containers/Dockerfile | 19 +- containers/README.md | 37 +--- containers/setup-mcp.sh | 441 ++++++++++++++++++++++++++++++---------- 3 files changed, 343 insertions(+), 154 deletions(-) diff --git a/containers/Dockerfile b/containers/Dockerfile index bd5b6ec..6576a8c 100644 --- a/containers/Dockerfile +++ b/containers/Dockerfile @@ -8,7 +8,7 @@ WORKDIR /app RUN git clone --depth 1 https://github.com/Pimzino/spec-workflow-mcp.git . # Install dependencies and build -RUN npm ci && npm run build +RUN npm install && npm run build # Runtime stage FROM node:24-alpine @@ -23,20 +23,9 @@ COPY --from=builder /app/dist ./dist RUN mkdir -p /workspace -# Create a user with matching UID/GID (can be overridden at runtime) -ARG USER_ID=1000 -ARG GROUP_ID=1000 - -# Use existing node user/group if UID/GID is 1000, otherwise create new user -RUN if [ "$USER_ID" = "1000" ] && [ "$GROUP_ID" = "1000" ]; then \ - echo "Using existing node user"; \ - else \ - addgroup -g $GROUP_ID appgroup && \ - adduser -D -u $USER_ID -G appgroup appuser; \ - fi - -# Switch to the appropriate user (node for 1000:1000, appuser otherwise) -USER ${USER_ID} +# Ensure application files are readable by any UID +# This is necessary because we run the container with --user flag at runtime +RUN chmod -R a+rX /app WORKDIR /workspace diff --git a/containers/README.md b/containers/README.md index 22cfe7e..2958cdf 100644 --- a/containers/README.md +++ b/containers/README.md @@ -12,17 +12,13 @@ This directory contains Docker configuration files to run the Spec-Workflow MCP ### Building the Container -From the containers directory, build the Docker image with your user ID to avoid permission issues: +From the containers directory, build the Docker image: ```bash -docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t spec-workflow-mcp . +docker build -t spec-workflow-mcp . ``` -For systems where `id` command is not available: - -```bash -docker build --build-arg USER_ID=1000 --build-arg GROUP_ID=1000 -t spec-workflow-mcp . -``` +The container will run with your host user's UID/GID at runtime using the `--user` flag, ensuring proper file permissions. ## MCP Server Configuration @@ -53,7 +49,7 @@ If you prefer to configure manually, create or update the `.mcp.json` file in yo "args": [ "run", "--rm", "-i", "--user", "1000:1000", - "-v", "/full/path/to/project/.spec-workflow:/full/path/to/project/.spec-workflow:rw", + "-v", "/full/path/to/project:/full/path/to/project:rw", "--entrypoint=node", "spec-workflow-mcp:latest", "/app/dist/index.js", "/full/path/to/project" @@ -70,31 +66,18 @@ If you prefer to configure manually, create or update the `.mcp.json` file in yo ### Path Mapping Requirements -The container requires the `.spec-workflow` directory to be mounted at the **exact same path** inside the container as it exists on your host system. This is critical for the MCP server to function correctly. +The container requires the entire project directory to be mounted at the **exact same path** inside the container as it exists on the host system. This is so the MCP server can reliably create and manage the `.spec-workflow` directory -**Example:** If your project is at `/home/steev/tabletopsentinel.com`, your configuration would be: -```json -{ - "mcpServers": { - "spec-workflow": { - "command": "docker", - "args": [ - "run", "--rm", "-i", - "-v", "./.spec-workflow:/home/steev/tabletopsentinel.com/.spec-workflow:rw", - "--entrypoint=node", - "spec-workflow-mcp:latest", - "/app/dist/index.js", "./" - ] - } - } -} +**Example:** If your project is at `/home/steev/myproject`, your configuration would mount: +``` +-v /home/steev/myproject:/home/steev/myproject:rw ``` ### Key Configuration Points - **Path Consistency**: The container path must match your host path exactly -- **Volume Mount**: Only the `.spec-workflow` directory needs to be mounted +- **Volume Mount**: The entire project directory must be mounted for the MCP server to access source code - **Auto-creation**: The `.spec-workflow` directory will be created if it doesn't exist - **SELinux Note**: If you're using SELinux, you may need to add `:z` to the volume mount (e.g., `:rw,z`) @@ -136,7 +119,7 @@ docker-compose down ### Common Issues -1. **Permission Denied**: Ensure the container was built with your user ID using the `--build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)` flags +1. **Permission Denied**: The container runs with your host user ID/GID via the `--user` flag. Ensure `.mcp.json` includes the correct user ID from `id -u` and group ID from `id -g` 2. **Port Already in Use**: Choose a different port using the `DASHBOARD_PORT` variable 3. **Path Not Found**: Verify that your `SPEC_WORKFLOW_PATH` matches your actual project location 4. **SELinux Issues**: On SELinux-enabled systems, add `:z` to volume mounts diff --git a/containers/setup-mcp.sh b/containers/setup-mcp.sh index 5108e61..9cffd72 100755 --- a/containers/setup-mcp.sh +++ b/containers/setup-mcp.sh @@ -5,137 +5,354 @@ set -e -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Get current directory and user info -PROJECT_DIR=$(pwd) -USER_ID=$(id -u) -GROUP_ID=$(id -g) -MCP_FILE=".mcp.json" - -echo -e "${BLUE}Spec-Workflow MCP Container Setup${NC}" -echo "==================================" -echo "Project directory: $PROJECT_DIR" -echo "User ID: $USER_ID" -echo "Group ID: $GROUP_ID" -echo "" - -# Check if Docker is available -if ! command -v docker &> /dev/null; then - echo -e "${RED}Error: Docker is not installed or not in PATH${NC}" - exit 1 -fi - -# Check if the spec-workflow-mcp image exists -if ! docker image inspect spec-workflow-mcp:latest &> /dev/null; then - echo -e "${YELLOW}Warning: spec-workflow-mcp:latest image not found${NC}" - echo "Please build the image first:" - echo " cd containers/" - echo " docker build --build-arg USER_ID=$USER_ID --build-arg GROUP_ID=$GROUP_ID -t spec-workflow-mcp ." +############################################# +# CONSTANTS +############################################# +readonly SCRIPT_NAME="$(basename "$0")" +readonly IMAGE_NAME="spec-workflow-mcp:latest" +readonly MCP_FILENAME=".mcp.json" +readonly SPEC_WORKFLOW_DIRNAME=".spec-workflow" +readonly MCP_SERVER_NAME="spec-workflow" +readonly PACKAGE_JSON_IDENTIFIER="spec-workflow-mcp" + +# Colours +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly NC='\033[0m' + +# Exit codes +readonly EXIT_SUCCESS=0 +readonly EXIT_ERROR=1 +readonly EXIT_USER_CANCEL=2 + +############################################# +# HELPER FUNCTIONS +############################################# + +log_info() { + echo -e "${BLUE}$1${NC}" +} + +log_success() { + echo -e "${GREEN}$1${NC}" +} + +log_warning() { + echo -e "${YELLOW}$1${NC}" +} + +log_error() { + echo -e "${RED}$1${NC}" +} + +show_help() { + cat << EOF +Spec-Workflow MCP Container Setup Script + +USAGE: + $SCRIPT_NAME [OPTIONS] [PROJECT_DIRECTORY] + +DESCRIPTION: + Configures $MCP_FILENAME for use with the $IMAGE_NAME Docker container. + Creates the necessary $SPEC_WORKFLOW_DIRNAME directory with correct permissions. + +OPTIONS: + -h, --help Show this help message and exit + +ARGUMENTS: + PROJECT_DIRECTORY Target directory for spec-workflow setup (default: current directory) + +USAGE EXAMPLES: + # Setup in current directory (run from your project directory): + $SCRIPT_NAME + + # Setup in a specific project directory (run from anywhere): + $SCRIPT_NAME /path/to/your/project + + # Setup in a specific directory (run from spec-workflow-mcp repo): + ./containers/setup-mcp.sh /path/to/your/project + +IMPORTANT: + - Run this script FROM your project directory, OR + - Run this script with your project directory as an argument + - DO NOT run this in the spec-workflow-mcp source directory unless you want to + configure spec-workflow for development purposes +EOF +} + +confirm_action() { + local prompt="$1" echo "" - read -p "Continue anyway? (y/N): " -n 1 -r + read -p "$prompt (y/N): " -n 1 -r echo "" - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - exit 1 + [[ $REPLY =~ ^[Yy]$ ]] +} + +check_docker_available() { + if ! command -v docker &> /dev/null; then + log_error "Error: Docker is not installed or not in PATH" + exit $EXIT_ERROR + fi +} + +check_image_exists() { + if ! docker image inspect "$IMAGE_NAME" &> /dev/null; then + log_warning "Warning: $IMAGE_NAME image not found" + echo "Please build the image first:" + echo " cd containers/" + echo " docker build -t ${IMAGE_NAME%:*} ." + echo "" + + if ! confirm_action "Continue anyway?"; then + exit $EXIT_USER_CANCEL + fi + fi +} + +is_in_source_directory() { + [[ -f "$(pwd)/package.json" ]] && grep -q "$PACKAGE_JSON_IDENTIFIER" "$(pwd)/package.json" 2>/dev/null +} + +warn_if_source_directory() { + local project_dir="$1" + + if is_in_source_directory && [[ "$project_dir" == "$(pwd)" ]]; then + log_warning "Warning: You appear to be running this script in the $PACKAGE_JSON_IDENTIFIER source directory" + echo "This will configure spec-workflow for the source code directory itself." + echo "If you want to configure a different project, run:" + echo " $0 /path/to/your/project" + + if ! confirm_action "Continue with current directory?"; then + echo "Cancelled. Run the script with your target project directory as an argument." + exit $EXIT_USER_CANCEL + fi fi -fi +} + +generate_mcp_config() { + local project_dir="$1" + local user_id="$2" + local group_id="$3" -# Create MCP configuration -MCP_CONFIG=$(cat < /dev/null +} + +backup_file() { + local file="$1" + local backup_file="${file}.backup" + + log_info "Creating backup: $backup_file" + cp "$file" "$backup_file" +} + +update_existing_mcp_config() { + local mcp_file="$1" + local new_config="$2" + + if ! has_jq; then + log_warning "jq not found. Please manually merge the following configuration:" echo "" - if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "$new_config" + exit $EXIT_ERROR + fi + + local server_config + server_config=$(echo "$new_config" | jq ".mcpServers.\"$MCP_SERVER_NAME\"") + + jq --argjson newconfig "$server_config" ".mcpServers.\"$MCP_SERVER_NAME\" = \$newconfig" "$mcp_file" > "${mcp_file}.tmp" + mv "${mcp_file}.tmp" "$mcp_file" +} + +handle_existing_mcp_file() { + local mcp_file="$1" + local mcp_config="$2" + + log_warning "Found existing $mcp_file" + + if grep -q "\"$MCP_SERVER_NAME\"" "$mcp_file"; then + log_warning "$MCP_SERVER_NAME configuration already exists" + + if ! confirm_action "Overwrite existing $MCP_SERVER_NAME configuration?"; then echo "Setup cancelled." - exit 0 - fi - - # Remove existing spec-workflow config and add new one - # This is a simple approach - for complex cases, users should edit manually - echo -e "${BLUE}Creating backup: $MCP_FILE.backup${NC}" - cp "$MCP_FILE" "$MCP_FILE.backup" - - # Use jq if available, otherwise warn user - if command -v jq &> /dev/null; then - NEW_CONFIG=$(echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"') - jq --argjson newconfig "$NEW_CONFIG" '.mcpServers."spec-workflow" = $newconfig' "$MCP_FILE" > "$MCP_FILE.tmp" && \ - mv "$MCP_FILE.tmp" "$MCP_FILE" - echo -e "${GREEN}Updated existing $MCP_FILE${NC}" - else - echo -e "${YELLOW}jq not found. Please manually merge the following configuration:${NC}" - echo "" - echo "$MCP_CONFIG" - exit 1 + exit $EXIT_USER_CANCEL fi + + backup_file "$mcp_file" + update_existing_mcp_config "$mcp_file" "$mcp_config" + log_success "Updated existing $mcp_file" else - # Add to existing file - if command -v jq &> /dev/null; then - echo -e "${BLUE}Adding spec-workflow to existing $MCP_FILE${NC}" - NEW_CONFIG=$(echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"') - jq --argjson newconfig "$NEW_CONFIG" '.mcpServers."spec-workflow" = $newconfig' "$MCP_FILE" > "$MCP_FILE.tmp" && \ - mv "$MCP_FILE.tmp" "$MCP_FILE" - echo -e "${GREEN}Added spec-workflow to existing $MCP_FILE${NC}" - else - echo -e "${YELLOW}jq not found. Please manually add the spec-workflow section to your existing $MCP_FILE:${NC}" + log_info "Adding $MCP_SERVER_NAME to existing $mcp_file" + update_existing_mcp_config "$mcp_file" "$mcp_config" + log_success "Added $MCP_SERVER_NAME to existing $mcp_file" + fi +} + +create_new_mcp_file() { + local mcp_file="$1" + local mcp_config="$2" + + log_info "Creating new $mcp_file" + echo "$mcp_config" > "$mcp_file" + log_success "Created $mcp_file" +} + +ensure_spec_workflow_directory() { + local spec_workflow_dir="$1" + local user_id="$2" + local group_id="$3" + + if [[ ! -d "$spec_workflow_dir" ]]; then + log_info "Creating $SPEC_WORKFLOW_DIRNAME directory" + mkdir -p "$spec_workflow_dir" + log_success "Created $spec_workflow_dir with user permissions (UID:$user_id, GID:$group_id)" + else + log_info "$SPEC_WORKFLOW_DIRNAME directory already exists" + + # Check if directory is owned by root + local dir_owner_id=$(stat -c "%u" "$spec_workflow_dir" 2>/dev/null || stat -f "%u" "$spec_workflow_dir" 2>/dev/null) + local dir_group_id=$(stat -c "%g" "$spec_workflow_dir" 2>/dev/null || stat -f "%g" "$spec_workflow_dir" 2>/dev/null) + + if [[ "$dir_owner_id" == "0" ]] || [[ "$dir_group_id" == "0" ]]; then + log_warning "Warning: $SPEC_WORKFLOW_DIRNAME is owned by root (UID:$dir_owner_id, GID:$dir_group_id)" + echo "This likely means the Docker container was run before this setup script." + echo "The container may not be able to write to this directory." + echo "" + echo "To fix this, run:" + echo " sudo chown -R $user_id:$group_id $spec_workflow_dir" + echo "" + + if ! confirm_action "Continue anyway?"; then + exit $EXIT_USER_CANCEL + fi + elif [[ "$dir_owner_id" != "$user_id" ]] || [[ "$dir_group_id" != "$group_id" ]]; then + log_warning "Warning: $SPEC_WORKFLOW_DIRNAME ownership (UID:$dir_owner_id, GID:$dir_group_id) doesn't match current user (UID:$user_id, GID:$group_id)" + echo "The container may have permission issues." echo "" - echo "$MCP_CONFIG" | jq '.mcpServers."spec-workflow"' - exit 1 + echo "To fix this, run:" + echo " sudo chown -R $user_id:$group_id $spec_workflow_dir" + echo "" + + if ! confirm_action "Continue anyway?"; then + exit $EXIT_USER_CANCEL + fi + else + log_success "$SPEC_WORKFLOW_DIRNAME directory has correct permissions" fi fi -else - # Create new file - echo -e "${BLUE}Creating new $MCP_FILE${NC}" - echo "$MCP_CONFIG" > "$MCP_FILE" - echo -e "${GREEN}Created $MCP_FILE${NC}" -fi - -# Create .spec-workflow directory if it doesn't exist -SPEC_WORKFLOW_DIR="$PROJECT_DIR/.spec-workflow" -if [ ! -d "$SPEC_WORKFLOW_DIR" ]; then - echo -e "${BLUE}Creating .spec-workflow directory${NC}" - mkdir -p "$SPEC_WORKFLOW_DIR" - echo -e "${GREEN}Created $SPEC_WORKFLOW_DIR${NC}" -else - echo -e "${BLUE}.spec-workflow directory already exists${NC}" -fi - -echo "" -echo -e "${GREEN}Setup complete!${NC}" -echo "" -echo "Next steps:" -echo "1. Make sure the Docker image is built:" -echo " cd containers/" -echo " docker build --build-arg USER_ID=$USER_ID --build-arg GROUP_ID=$GROUP_ID -t spec-workflow-mcp ." -echo "" -echo "2. Restart Claude Desktop to pick up the new MCP configuration" -echo "" -echo "3. Test the connection by asking Claude to use spec-workflow tools" \ No newline at end of file +} + +show_next_steps() { + local user_id="$1" + local group_id="$2" + + echo "" + log_success "Setup complete!" + echo "" + + local script_dir + script_dir=$(dirname "$(realpath "$0")") + + if [[ "$script_dir" == */$PACKAGE_JSON_IDENTIFIER/containers* ]] || is_in_source_directory; then + echo "Next steps:" + echo "1. Build the Docker image:" + echo " docker build -t ${IMAGE_NAME%:*} ." + else + echo "Next steps:" + echo "1. Build the Docker image (run from the $PACKAGE_JSON_IDENTIFIER repository):" + echo " cd /path/to/$PACKAGE_JSON_IDENTIFIER/containers/" + echo " docker build -t ${IMAGE_NAME%:*} ." + fi + + cat << EOF + +2. Restart Claude to pick up the new MCP configuration + +3. Test the connection by asking Claude to use spec-workflow tools +EOF +} + +parse_arguments() { + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit $EXIT_SUCCESS + ;; + *) + if [[ -z "${PROJECT_DIR:-}" ]]; then + PROJECT_DIR="$1" + else + echo "Error: Multiple project directories specified" + exit $EXIT_ERROR + fi + shift + ;; + esac + done +} + +############################################# +# MAIN FUNCTION +############################################# + +main() { + parse_arguments "$@" + + # Get project directory and user info + PROJECT_DIR=${PROJECT_DIR:-$(pwd)} + PROJECT_DIR=$(realpath "$PROJECT_DIR") + readonly USER_ID=$(id -u) + readonly GROUP_ID=$(id -g) + readonly MCP_FILE="$PROJECT_DIR/$MCP_FILENAME" + readonly SPEC_WORKFLOW_DIR="$PROJECT_DIR/$SPEC_WORKFLOW_DIRNAME" + + log_info "Spec-Workflow MCP Container Setup" + echo "==================================" + echo "Project directory: $PROJECT_DIR" + echo "User ID: $USER_ID" + echo "Group ID: $GROUP_ID" + echo "" + + check_docker_available + check_image_exists + warn_if_source_directory "$PROJECT_DIR" + + # Create .spec-workflow directory early with correct permissions + ensure_spec_workflow_directory "$SPEC_WORKFLOW_DIR" "$USER_ID" "$GROUP_ID" + + local mcp_config + mcp_config=$(generate_mcp_config "$PROJECT_DIR" "$USER_ID" "$GROUP_ID") + + if [[ -f "$MCP_FILE" ]]; then + handle_existing_mcp_file "$MCP_FILE" "$mcp_config" + else + create_new_mcp_file "$MCP_FILE" "$mcp_config" + fi + + show_next_steps "$USER_ID" "$GROUP_ID" +} + +# Execute main function with all arguments +main "$@" From 7087fb7b81ac4f8d0bb490722c36ef4320d39f7d Mon Sep 17 00:00:00 2001 From: steev Date: Fri, 7 Nov 2025 14:30:49 +0000 Subject: [PATCH 5/6] Update containers/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- containers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/README.md b/containers/README.md index 2958cdf..3c0b743 100644 --- a/containers/README.md +++ b/containers/README.md @@ -66,7 +66,7 @@ If you prefer to configure manually, create or update the `.mcp.json` file in yo ### Path Mapping Requirements -The container requires the entire project directory to be mounted at the **exact same path** inside the container as it exists on the host system. This is so the MCP server can reliably create and manage the `.spec-workflow` directory +The container requires the entire project directory to be mounted at the **exact same path** inside the container as it exists on the host system. This is so the MCP server can reliably create and manage the `.spec-workflow` directory. **Example:** If your project is at `/home/steev/myproject`, your configuration would mount: From 9ac85979290068a37d246de348e5e363cef28859 Mon Sep 17 00:00:00 2001 From: steev Date: Fri, 7 Nov 2025 14:31:06 +0000 Subject: [PATCH 6/6] Update containers/setup-mcp.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- containers/setup-mcp.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/containers/setup-mcp.sh b/containers/setup-mcp.sh index 9cffd72..7d6fe83 100755 --- a/containers/setup-mcp.sh +++ b/containers/setup-mcp.sh @@ -298,6 +298,7 @@ parse_arguments() { case $1 in -h|--help) show_help + shift exit $EXIT_SUCCESS ;; *)