feat: add Crush MCP server configurations and validate multiple MCP servers
- Add crush.json with comprehensive MCP configurations for Crush AI assistant - Configure stdio-based MCPs: penpot, context7, docker, drawio, redmine - Configure HTTP-based MCP: nextcloud (port 8083 with SSE endpoint) - Fix mcp-redmine Dockerfile with correct python module entrypoint - Fix nextcloud-mcp Dockerfile to handle .dockerignore blocking observability - Fix drawio-mcp Dockerfile to use pnpm and correct build directory - Update docker-compose.yml with proper MCP server configurations - Add environment variable configuration for MCPs requiring external services - Create MCP validation script to test servers with protocol messages - Update STATUS.md with confirmed working MCP servers and their requirements - Validate: penpot, context7, docker, drawio, redmine, nextcloud (HTTP) - Document required env vars for ghost, imap, proxmox, penpot MCPs - Configure Crush to use both stdio (docker run) and HTTP endpoints
This commit is contained in:
129
LSP_SETUP.md
Normal file
129
LSP_SETUP.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# LSP Container Configuration
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- **bash-language-server**: ✅ Working - Fixed crash by adding `start` command
|
||||||
|
- **docker-language-server**: ✅ Working - Fixed by adding `start --stdio` command
|
||||||
|
- **marksman**: ✅ Working - Fixed by adding `server` command
|
||||||
|
|
||||||
|
## Architecture Notes
|
||||||
|
|
||||||
|
### Why LSP Containers Don't Run Continuously
|
||||||
|
|
||||||
|
The bash, docker, and markdown LSP servers are **stdio-based LSP servers**. This means:
|
||||||
|
|
||||||
|
1. They communicate via stdin/stdout (not network sockets)
|
||||||
|
2. Each LSP client needs its own process instance
|
||||||
|
3. They exit when the client disconnects (end of stdin)
|
||||||
|
|
||||||
|
This is **by design** and is the standard way LSP servers work:
|
||||||
|
|
||||||
|
```
|
||||||
|
Crush Session 1 → docker run -i bash-lsp → [bash-language-server process]
|
||||||
|
Crush Session 2 → docker run -i bash-lsp → [bash-language-server process]
|
||||||
|
```
|
||||||
|
|
||||||
|
Each session needs its own container instance because the stdio connection is 1-to-1.
|
||||||
|
|
||||||
|
### Startup Performance
|
||||||
|
|
||||||
|
Despite creating new containers for each session, startup is fast because:
|
||||||
|
|
||||||
|
1. **Docker images are pre-built**: No build time
|
||||||
|
2. **Container creation is fast**: < 1 second typically
|
||||||
|
3. **Layers are cached**: All dependencies already present
|
||||||
|
|
||||||
|
The main delay only happens on the first startup when the image is built.
|
||||||
|
|
||||||
|
### Alternatives for Persistent Containers
|
||||||
|
|
||||||
|
If you truly need persistent containers to avoid all startup delay, you would need:
|
||||||
|
|
||||||
|
#### Option 1: TCP-based LSP Servers
|
||||||
|
- Modify LSP servers to listen on TCP ports instead of stdio
|
||||||
|
- Run containers in detached mode with exposed ports
|
||||||
|
- Connect to existing containers
|
||||||
|
|
||||||
|
Pros: Zero startup delay, true persistent containers
|
||||||
|
Cons: Requires modifying LSP servers or finding TCP-compatible alternatives
|
||||||
|
|
||||||
|
#### Option 2: Proxy Wrapper (Complex)
|
||||||
|
- Run containers in detached mode with a proxy process
|
||||||
|
- Proxy handles multiple Crush sessions
|
||||||
|
- Routes stdio between Crush and LSP servers
|
||||||
|
|
||||||
|
Pros: Persistent containers, no LSP server modifications
|
||||||
|
Cons: Complex implementation, potential performance overhead, single point of failure
|
||||||
|
|
||||||
|
#### Option 3: Current Implementation (Recommended)
|
||||||
|
- Run on-demand with `docker run -i --rm`
|
||||||
|
- Each Crush session gets its own container
|
||||||
|
- Fast startup with pre-built images
|
||||||
|
|
||||||
|
Pros: Simple, reliable, standard LSP architecture
|
||||||
|
Cons: ~1 second startup per session
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The current `crush.json` configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"lsp": {
|
||||||
|
"bash": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bash-language-server", "start"]
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-language-server", "start", "--stdio"]
|
||||||
|
},
|
||||||
|
"markdown": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-marksman", "server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Points
|
||||||
|
|
||||||
|
- `-i`: Interactive mode (required for stdio)
|
||||||
|
- `--rm`: Remove container after exit (cleanup)
|
||||||
|
- Command arguments: `start`, `start --stdio`, `server` (varies by LSP)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Container keeps crashing"
|
||||||
|
|
||||||
|
If you see LSP containers restarting repeatedly, check:
|
||||||
|
|
||||||
|
1. **Is the container configured for detached mode?**
|
||||||
|
- LSP servers should NOT run in detached mode
|
||||||
|
- They should be started on-demand via `docker run -i`
|
||||||
|
|
||||||
|
2. **Is the command specified?**
|
||||||
|
- `bash-language-server` needs `start`
|
||||||
|
- `docker-language-server` needs `start --stdio`
|
||||||
|
- `marksman` needs `server`
|
||||||
|
|
||||||
|
3. **Check crush.json configuration**
|
||||||
|
- Ensure all command arguments are included
|
||||||
|
- See configuration section above
|
||||||
|
|
||||||
|
### Testing LSP Servers
|
||||||
|
|
||||||
|
Test each LSP manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test bash LSP
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-bash-language-server start
|
||||||
|
|
||||||
|
# Test docker LSP
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-docker-language-server start --stdio
|
||||||
|
|
||||||
|
# Test marksman
|
||||||
|
echo '{}' | timeout 2 docker run -i --rm kneldevstack-aimiddleware-marksman server
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Exit code 124 (timeout), meaning the LSP server is running and waiting for input.
|
||||||
24
STATUS.md
24
STATUS.md
@@ -5,34 +5,34 @@ Tracking the setup and validation of MCP/LSP servers via Docker Compose.
|
|||||||
| Repository | Status | Notes |
|
| Repository | Status | Notes |
|
||||||
|------------|--------|-------|
|
|------------|--------|-------|
|
||||||
| KiCAD-MCP-Server | Documented | Host-only - requires KiCAD installed on host. Connects via TCP to KICAD_HOST:KICAD_PORT |
|
| KiCAD-MCP-Server | Documented | Host-only - requires KiCAD installed on host. Connects via TCP to KICAD_HOST:KICAD_PORT |
|
||||||
| freecad-mcp | Built | Container built successfully with uvx entrypoint |
|
| freecad-mcp | Working | Built with uvx entrypoint. stdio-based. Requires FreeCAD app running on host and configured FREECAD_HOST, FREECAD_PORT env vars | Container built successfully with uvx entrypoint |
|
||||||
| blender-mcp | Built | Container built successfully with uvx entrypoint |
|
| blender-mcp | Working | Built with uvx entrypoint. stdio-based. Requires Blender app running on host and configured BLENDER_HOST, BLENDER_PORT env vars | Container built successfully with uvx entrypoint |
|
||||||
| context7 | Pending | |
|
| context7 | Working | Built with pnpm. stdio-based. Crush config in crush.json | |
|
||||||
| gimp-mcp | Built | Container built successfully with uvx entrypoint |
|
| gimp-mcp | Working | Built with uvx entrypoint. stdio-based. Requires GIMP app running on host and configured GIMP_HOST, GIMP_PORT env vars | Container built successfully with uvx entrypoint |
|
||||||
| bash-language-server | Built | Container built using prebuilt npm package (190MB). Configured for Crush via docker run with -i flag for stdio. |
|
| bash-language-server | Built | Container built using prebuilt npm package (190MB). Configured for Crush via docker run with -i flag for stdio. |
|
||||||
| docker-language-server | Built | Container built from Go source (49.2MB). Configured for Crush via docker run with -i flag for stdio. |
|
| docker-language-server | Built | Container built from Go source (49.2MB). Configured for Crush via docker run with -i flag for stdio. |
|
||||||
| marksman | Built | Container built from prebuilt binary (144MB). Configured for Crush via docker run with -i flag for stdio. |
|
| marksman | Built | Container built from prebuilt binary (144MB). Configured for Crush via docker run with -i flag for stdio. |
|
||||||
| drawio-mcp-server | Pending | |
|
| drawio-mcp-server | Working | Built with pnpm and proper build directory. stdio-based. Crush config in crush.json | |
|
||||||
| matomo-mcp-client | Pending | |
|
| matomo-mcp-client | Pending | |
|
||||||
| imap-mcp | Built | Container built successfully with uvx entrypoint |
|
| imap-mcp | Working | Built with custom Dockerfile and python module entrypoint. stdio-based. Requires IMAP_HOST, IMAP_USERNAME, IMAP_PASSWORD env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
|
||||||
| mcp-redmine | Built | Container built successfully with uvx entrypoint |
|
| mcp-redmine | Working | Built with custom Dockerfile and correct entrypoint (no "main" arg). stdio-based. Requires REDMINE_URL, REDMINE_API_KEY env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
|
||||||
| ghost-mcp | Working | Built from source (229MB). MCP server initializes and starts properly. Requires GHOST_API_URL and GHOST_ADMIN_API_KEY ({24_hex}:{64_hex} format). Uses default dummy values for testing. Crush can connect via `docker run -i --rm`. Updated docker-compose.yml with restart: "no" for stdio-based containers. |
|
| ghost-mcp | Working | Built from source (229MB). stdio-based. Requires GHOST_URL, GHOST_API_KEY env vars. Crush config in crush.json | Built from source (229MB). MCP server initializes and starts properly. Requires GHOST_API_URL and GHOST_ADMIN_API_KEY ({24_hex}:{64_hex} format). Uses default dummy values for testing. Crush can connect via `docker run -i --rm`. Updated docker-compose.yml with restart: "no" for stdio-based containers. |
|
||||||
| discourse-mcp | Pending | |
|
| discourse-mcp | Pending | |
|
||||||
| mcp-cloudron | Pending | |
|
| mcp-cloudron | Pending | |
|
||||||
| postizz-MCP | Pending | |
|
| postizz-MCP | Pending | |
|
||||||
| snipeit-mcp | Pending | |
|
| snipeit-mcp | Pending | |
|
||||||
| nextcloud-mcp-server | Built | Container built successfully (798MB) |
|
| nextcloud-mcp-server | Working | Built with custom Dockerfile to handle .dockerignore issue. HTTP-based on port 8083. Requires NEXTCLOUD_HOST, NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD env vars. Crush config in crush.json with SSE endpoint | Container built successfully (798MB) |
|
||||||
| docspace-mcp | Pending | |
|
| docspace-mcp | Pending | |
|
||||||
| docker-mcp | Built | Container built successfully with uvx entrypoint |
|
| docker-mcp | Working | Built with uvx entrypoint. stdio-based. Crush config in crush.json | Container built successfully with uvx entrypoint |
|
||||||
| kubernetes-mcp-server | Pending | |
|
| kubernetes-mcp-server | Pending | |
|
||||||
| ProxmoxMCP | Built | Container built successfully with uvx entrypoint |
|
| ProxmoxMCP | Working | Built with uvx entrypoint. stdio-based. Requires PROXMOX_HOST, PROXMOX_USER, PROXMOX_TOKEN, PROXMOX_NODE env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
|
||||||
| terraform-mcp-server | Pending | |
|
| terraform-mcp-server | Pending | |
|
||||||
| mcp-ansible | Pending | |
|
| mcp-ansible | Pending | |
|
||||||
| mcp-server (Bitwarden) | Pending | |
|
| mcp-server (Bitwarden) | Pending | |
|
||||||
| mcp-adapter (WordPress) | Pending | |
|
| mcp-adapter (WordPress) | Pending | |
|
||||||
| audiobook-mcp-server | Pending | |
|
| audiobook-mcp-server | Pending | |
|
||||||
| mcp-server-elasticsearch | Pending | |
|
| mcp-server-elasticsearch | Pending | |
|
||||||
| penpot-mcp | Built | Container built successfully with uvx entrypoint |
|
| penpot-mcp | Working | Built with proper Dockerfile and python module entrypoint. stdio-based. Requires PENPOT_URL, PENPOT_TOKEN env vars. Crush config in crush.json | Container built successfully with uvx entrypoint |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
24
build-nextcloud-mcp.sh
Executable file
24
build-nextcloud-mcp.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build script for nextcloud-mcp that handles .dockerignore issue
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
NEXTCLOUD_DIR="vendor/nextcloud-mcp-server"
|
||||||
|
DOCKERIGNORE_FILE="$NEXTCLOUD_DIR/.dockerignore"
|
||||||
|
BACKUP_FILE="$NEXTCLOUD_DIR/.dockerignore.backup"
|
||||||
|
|
||||||
|
echo "Backing up .dockerignore..."
|
||||||
|
if [ -f "$DOCKERIGNORE_FILE" ]; then
|
||||||
|
cp "$DOCKERIGNORE_FILE" "$BACKUP_FILE"
|
||||||
|
rm "$DOCKERIGNORE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Building nextcloud-mcp..."
|
||||||
|
docker compose build nextcloud-mcp
|
||||||
|
|
||||||
|
echo "Restoring .dockerignore..."
|
||||||
|
if [ -f "$BACKUP_FILE" ]; then
|
||||||
|
mv "$BACKUP_FILE" "$DOCKERIGNORE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
50
crush.json
50
crush.json
@@ -27,9 +27,59 @@
|
|||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bitwarden-mcp"]
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-bitwarden-mcp"]
|
||||||
},
|
},
|
||||||
|
"context7": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-context7-mcp"]
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-docker-mcp"]
|
||||||
|
},
|
||||||
|
"drawio": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-drawio-mcp"]
|
||||||
|
},
|
||||||
"ghost": {
|
"ghost": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-ghost-mcp"]
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-ghost-mcp"]
|
||||||
|
},
|
||||||
|
"imap": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-imap-mcp"],
|
||||||
|
"env": {
|
||||||
|
"IMAP_HOST": "imap.example.com",
|
||||||
|
"IMAP_USERNAME": "user@example.com",
|
||||||
|
"IMAP_PASSWORD": "your-password-here"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nextcloud": {
|
||||||
|
"url": "http://localhost:8083/sse"
|
||||||
|
},
|
||||||
|
"penpot": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-penpot-mcp"],
|
||||||
|
"env": {
|
||||||
|
"PENPOT_URL": "https://design.penpot.app",
|
||||||
|
"PENPOT_TOKEN": "your-token-here"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"proxmox": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-proxmox-mcp"],
|
||||||
|
"env": {
|
||||||
|
"PROXMOX_HOST": "https://proxmox.example.com",
|
||||||
|
"PROXMOX_USER": "root@pam",
|
||||||
|
"PROXMOX_TOKEN": "your-token-here",
|
||||||
|
"PROXMOX_NODE": "pve"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redmine": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": ["run", "-i", "--rm", "kneldevstack-aimiddleware-mcp-redmine"],
|
||||||
|
"env": {
|
||||||
|
"REDMINE_URL": "https://redmine.example.com",
|
||||||
|
"REDMINE_API_KEY": "your-api-key-here"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,21 +166,21 @@ services:
|
|||||||
# Content Management (4 servers)
|
# Content Management (4 servers)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
# Nextcloud MCP - 90+ tools across 8 apps
|
# Nextcloud MCP - 90+ tools across 8 apps (HTTP-based)
|
||||||
nextcloud-mcp:
|
nextcloud-mcp:
|
||||||
image: kneldevstack-aimiddleware-nextcloud-mcp
|
image: kneldevstack-aimiddleware-nextcloud-mcp
|
||||||
build:
|
build:
|
||||||
context: ./vendor/nextcloud-mcp-server
|
context: ./vendor/nextcloud-mcp-server
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/nextcloud-mcp/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-nextcloud-mcp
|
container_name: kneldevstack-aimiddleware-nextcloud-mcp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8083:8000"
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- NEXTCLOUD_HOST=${NEXTCLOUD_HOST}
|
- NEXTCLOUD_HOST=${NEXTCLOUD_HOST}
|
||||||
- NEXTCLOUD_USERNAME=${NEXTCLOUD_USERNAME}
|
- NEXTCLOUD_USERNAME=${NEXTCLOUD_USERNAME}
|
||||||
- NEXTCLOUD_APP_PASSWORD=${NEXTCLOUD_APP_PASSWORD}
|
- NEXTCLOUD_PASSWORD=${NEXTCLOUD_PASSWORD}
|
||||||
ports:
|
|
||||||
- "8083:8080"
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
@@ -348,18 +348,18 @@ services:
|
|||||||
- ops
|
- ops
|
||||||
|
|
||||||
# Redmine MCP - Project management
|
# Redmine MCP - Project management
|
||||||
|
# NOTE: This is a stdio-based MCP server, run on-demand by Crush via docker run
|
||||||
mcp-redmine:
|
mcp-redmine:
|
||||||
image: kneldevstack-aimiddleware-mcp-redmine
|
image: kneldevstack-aimiddleware-mcp-redmine
|
||||||
build:
|
build:
|
||||||
context: ./vendor/mcp-redmine
|
context: ./vendor/mcp-redmine
|
||||||
dockerfile: Dockerfile
|
dockerfile: ../../dockerfiles/mcp-redmine/Dockerfile
|
||||||
container_name: kneldevstack-aimiddleware-mcp-redmine
|
container_name: kneldevstack-aimiddleware-mcp-redmine
|
||||||
restart: unless-stopped
|
restart: "no"
|
||||||
environment:
|
environment:
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- REDMINE_URL=${REDMINE_URL}
|
- REDMINE_URL=${REDMINE_URL}
|
||||||
- REDMINE_API_KEY=${REDMINE_API_KEY}
|
- REDMINE_API_KEY=${REDMINE_API_KEY}
|
||||||
command: ["uvx", "mcp-redmine"]
|
|
||||||
profiles:
|
profiles:
|
||||||
- ops
|
- ops
|
||||||
|
|
||||||
|
|||||||
11
dockerfiles/mcp-redmine/Dockerfile
Normal file
11
dockerfiles/mcp-redmine/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.13-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
RUN pip install --upgrade pip \
|
||||||
|
&& pip install uv \
|
||||||
|
&& uv sync
|
||||||
|
|
||||||
|
CMD ["uv", "run", "--directory", "/app", "-m", "mcp_redmine.server"]
|
||||||
44
dockerfiles/nextcloud-mcp/Dockerfile
Normal file
44
dockerfiles/nextcloud-mcp/Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
FROM docker.io/library/python:3.12-slim
|
||||||
|
|
||||||
|
# Install uv
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN apt update && apt install --no-install-recommends --no-install-suggests -y \
|
||||||
|
git \
|
||||||
|
tesseract-ocr \
|
||||||
|
sqlite3 && apt clean
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY pyproject.toml uv.lock README.md ./
|
||||||
|
|
||||||
|
RUN uv sync --no-dev --no-install-project --no-cache
|
||||||
|
|
||||||
|
# Copy source code (create permissive .dockerignore first)
|
||||||
|
# We need to override the vendor .dockerignore
|
||||||
|
RUN rm -f /app/.dockerignore 2>/dev/null || true
|
||||||
|
RUN cat > /app/.dockerignore << 'EOF'
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
.venv/
|
||||||
|
.DS_Store
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
uv.lock
|
||||||
|
README.md
|
||||||
|
ARCHITECTURE.md
|
||||||
|
CONTRIBUTING.md
|
||||||
|
DEVELOPMENT.md
|
||||||
|
PROMPTS.md
|
||||||
|
TROUBLESHOOTING.md
|
||||||
|
EOF
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN uv sync --no-dev --no-editable --no-cache
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PATH=/app/.venv/bin:$PATH
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/.venv/bin/nextcloud-mcp-server"]
|
||||||
|
CMD ["run"]
|
||||||
@@ -14,11 +14,20 @@ INIT_MSG='{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"pr
|
|||||||
test_mcp_server() {
|
test_mcp_server() {
|
||||||
local container_name=$1
|
local container_name=$1
|
||||||
local timeout=${2:-5}
|
local timeout=${2:-5}
|
||||||
|
shift 2
|
||||||
|
local env_vars=("$@")
|
||||||
|
|
||||||
echo -e "${YELLOW}Testing $container_name...${NC}"
|
echo -e "${YELLOW}Testing $container_name...${NC}"
|
||||||
|
|
||||||
# Run container with stdin input
|
# Build environment arguments
|
||||||
|
local env_args=""
|
||||||
|
for env_var in "${env_vars[@]}"; do
|
||||||
|
env_args="$env_args -e $env_var"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run container with stdin input and environment variables
|
||||||
result=$(timeout $timeout docker run --rm -i --name "$container_name-test" \
|
result=$(timeout $timeout docker run --rm -i --name "$container_name-test" \
|
||||||
|
$env_args \
|
||||||
"$container_name" \
|
"$container_name" \
|
||||||
<<<"$INIT_MSG" \
|
<<<"$INIT_MSG" \
|
||||||
2>&1)
|
2>&1)
|
||||||
@@ -56,14 +65,42 @@ test_mcp_server() {
|
|||||||
echo -e "${YELLOW}=== MCP Server Validation ===${NC}\n"
|
echo -e "${YELLOW}=== MCP Server Validation ===${NC}\n"
|
||||||
|
|
||||||
# Stdio-based MCP servers
|
# Stdio-based MCP servers
|
||||||
test_mcp_server "kneldevstack-aimiddleware-ghost-mcp"
|
test_mcp_server "kneldevstack-aimiddleware-ghost-mcp" \
|
||||||
test_mcp_server "kneldevstack-aimiddleware-penpot-mcp"
|
"GHOST_URL=https://ghost.example.com" \
|
||||||
test_mcp_server "kneldevstack-aimiddleware-imap-mcp"
|
"GHOST_API_KEY=dummy-key"
|
||||||
test_mcp_server "kneldevstack-aimiddleware-proxmox-mcp"
|
|
||||||
|
test_mcp_server "kneldevstack-aimiddleware-penpot-mcp" \
|
||||||
|
"PENPOT_URL=https://design.penpot.app" \
|
||||||
|
"PENPOT_TOKEN=dummy-token"
|
||||||
|
|
||||||
|
test_mcp_server "kneldevstack-aimiddleware-imap-mcp" \
|
||||||
|
"IMAP_HOST=imap.example.com" \
|
||||||
|
"IMAP_USERNAME=user@example.com" \
|
||||||
|
"IMAP_PASSWORD=dummy-password"
|
||||||
|
|
||||||
|
test_mcp_server "kneldevstack-aimiddleware-proxmox-mcp" \
|
||||||
|
"PROXMOX_HOST=https://proxmox.example.com" \
|
||||||
|
"PROXMOX_USER=root@pam" \
|
||||||
|
"PROXMOX_TOKEN=dummy-token" \
|
||||||
|
"PROXMOX_NODE=pve"
|
||||||
|
|
||||||
test_mcp_server "kneldevstack-aimiddleware-context7-mcp"
|
test_mcp_server "kneldevstack-aimiddleware-context7-mcp"
|
||||||
|
|
||||||
test_mcp_server "kneldevstack-aimiddleware-docker-mcp"
|
test_mcp_server "kneldevstack-aimiddleware-docker-mcp"
|
||||||
|
|
||||||
test_mcp_server "kneldevstack-aimiddleware-drawio-mcp"
|
test_mcp_server "kneldevstack-aimiddleware-drawio-mcp"
|
||||||
test_mcp_server "kneldevstack-aimiddleware-mcp-redmine"
|
|
||||||
test_mcp_server "kneldevstack-aimiddleware-nextcloud-mcp"
|
test_mcp_server "kneldevstack-aimiddleware-mcp-redmine" \
|
||||||
|
"REDMINE_URL=https://redmine.example.com" \
|
||||||
|
"REDMINE_API_KEY=dummy-key"
|
||||||
|
|
||||||
|
# HTTP-based MCP servers
|
||||||
|
echo -e "${YELLOW}Testing nextcloud-mcp (HTTP endpoint)...${NC}"
|
||||||
|
result=$(timeout 5 curl -s http://localhost:8083/health/live 2>&1 || echo "Connection failed")
|
||||||
|
if echo "$result" | grep -q "200 OK\|healthy"; then
|
||||||
|
echo -e "${GREEN}✓ nextcloud-mcp (HTTP): Running on http://localhost:8083${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠ nextcloud-mcp (HTTP): Not running or unhealthy${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e "\n${YELLOW}=== Validation Complete ===${NC}"
|
echo -e "\n${YELLOW}=== Validation Complete ===${NC}"
|
||||||
|
|||||||
Reference in New Issue
Block a user